Skip to content

Commit c9c7ecc

Browse files
authored
Merge pull request #50 from BitOne/GIT-49_pipe_char_in_json
Fixes #49 by escaping control chars
2 parents 120ed99 + 652434d commit c9c7ecc

9 files changed

+239
-13
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ Options:
148148
### Example
149149

150150
```bash
151-
$ bin/analyzer ref-path 0x7f94a1877068 /tmp/php_mem_dump.json
151+
$ bin/analyzer ref-path -v 0x7f94a1877068 /tmp/php_mem_dump.json
152152
Found 1 paths
153153
Path from 0x7f94a1856260
154154
+--------------------+
@@ -223,6 +223,24 @@ Check the PHP Info output and look for the MemInfo data.
223223

224224
To see the PHP Info output, just create a page calling the `phpinfo();` function, and load it from your browser, or call `php -i` from the command line.
225225

226+
## Why most tests are "skipped"?
227+
228+
While doing a `make test`, some test will need JSON capabilities. But The
229+
compilation system generates a clean env by removing all configuration
230+
directives that load extension.
231+
So if JSON capabilites are packaged as a separate extension (instead of
232+
being compiled directly in the PHP runtime), the tests will be skipped.
233+
234+
You may run them with the `run-tests.php` generated after the `make test`
235+
command, by providing the `php` executable:
236+
237+
```bash
238+
$ TEST_PHP_EXECUTABLE=/usr/bin/php php run-tests.php
239+
240+
```
241+
In this case, your tests will run with your local PHP configuration,
242+
including the loading of the JSON extension.
243+
226244
Credits
227245
-------
228246
Thanks to Derick Rethans for his inspirational work on the essential XDebug. See http://www.xdebug.org/

extension/php5/meminfo.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,21 +416,33 @@ void meminfo_build_frame_label(char* frame_label, int frame_label_len, zend_exec
416416
}
417417

418418
/**
419-
* Escape the \ and " characters for JSON encoding
419+
* Escape for JSON encoding
420420
*/
421421
char * meminfo_escape_for_json(const char *s TSRMLS_DC)
422422
{
423-
int new_str_len;
424-
char *s1, *s2;
423+
int new_str_len, i;
424+
char unescaped_char[2];
425+
char escaped_char[7]; // \uxxxx format
426+
char *s1, *s2, *s3 = NULL;
425427

426428
s1 = php_str_to_str((char *) s, strlen(s), "\\", 1, "\\\\", 2, &new_str_len);
427429
s2 = php_str_to_str(s1, strlen(s1), "\"", 1, "\\\"", 2, &new_str_len);
428430

429-
if (s1) {
430-
efree(s1);
431+
for (i = 0; i <= 0x1f; i++) {
432+
unescaped_char[0] = (char) i;
433+
sprintf(escaped_char, "\\u%04x", i);
434+
if (s3) {
435+
s2 = s3;
436+
}
437+
s3 = php_str_to_str(s2, strlen(s2), unescaped_char, 1, escaped_char, 6, &new_str_len);
438+
if (s2) {
439+
efree(s2);
440+
}
431441
}
432442

433-
return s2;
443+
efree(s1);
444+
445+
return s3;
434446
}
435447

436448
/**
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Check that control character in array key are properly escaped for json
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('json')) die('skip json ext not loaded');
6+
?>
7+
--FILE--
8+
<?php
9+
$myArray = [
10+
"1|\x1f" => "My data"
11+
];
12+
13+
$dump = fopen('php://memory', 'rw');
14+
15+
meminfo_dump($dump);
16+
17+
rewind($dump);
18+
$meminfoData = json_decode(stream_get_contents($dump), true);
19+
fclose($dump);
20+
21+
if (is_array($meminfoData)) {
22+
echo "meminfo_dump JSON decode ok\n";
23+
} else {
24+
echo "meminfo_dump JSON decode fail\n";
25+
}
26+
27+
?>
28+
--EXPECT--
29+
meminfo_dump JSON decode ok
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Check JSON proper escaping (see http://json.org)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('json')) die('skip json ext not loaded');
6+
?>
7+
--FILE--
8+
<?php
9+
$jsonCharactersToEscape = [
10+
'"' => 'quotation mark',
11+
'\\' => "reverse solidus",
12+
'/' => "solidus"
13+
];
14+
15+
for ($i = 0; $i <= 0x1f; $i++) {
16+
$jsonCharactersToEscape[chr($i)] = "control character $i";
17+
}
18+
19+
$dump = fopen('php://memory', 'rw');
20+
21+
meminfo_dump($dump);
22+
23+
rewind($dump);
24+
$meminfoData = json_decode(stream_get_contents($dump), true);
25+
fclose($dump);
26+
27+
if (is_array($meminfoData)) {
28+
echo "meminfo_dump JSON decode ok\n";
29+
} else {
30+
echo "meminfo_dump JSON decode fail\n";
31+
}
32+
33+
?>
34+
--EXPECT--
35+
meminfo_dump JSON decode ok
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Check JSON proper escaping (see http://json.org)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('json')) die('skip json ext not loaded');
6+
?>
7+
--FILE--
8+
<?php
9+
$myArrayWithUnicodeKey = [
10+
'' => 'plane character'
11+
];
12+
13+
$dump = fopen('php://memory', 'rw');
14+
15+
meminfo_dump($dump);
16+
17+
rewind($dump);
18+
$meminfoData = json_decode(stream_get_contents($dump), true);
19+
fclose($dump);
20+
21+
if (is_array($meminfoData)) {
22+
echo "meminfo_dump JSON decode ok\n";
23+
} else {
24+
echo "meminfo_dump JSON decode fail\n";
25+
}
26+
27+
?>
28+
--EXPECT--
29+
meminfo_dump JSON decode ok

extension/php7/meminfo.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -405,21 +405,31 @@ void meminfo_build_frame_label(char* frame_label, int frame_label_len, zend_exec
405405
}
406406

407407
/**
408-
* Escape the \ and " characters for JSON encoding
408+
* Escape for JSON encoding
409409
*/
410410
zend_string * meminfo_escape_for_json(const char *s)
411411
{
412-
int new_str_len;
413-
zend_string *s1, *s2;
412+
int new_str_len, i;
413+
char unescaped_char[2];
414+
char escaped_char[7]; // \uxxxx format
415+
zend_string *s1, *s2, *s3 = NULL;
414416

415417
s1 = php_str_to_str((char *) s, strlen(s), "\\", 1, "\\\\", 2);
416418
s2 = php_str_to_str(ZSTR_VAL(s1), ZSTR_LEN(s1), "\"", 1, "\\\"", 2);
417419

418-
if (s1) {
419-
zend_string_release(s1);
420+
for (i = 0; i <= 0x1f; i++) {
421+
unescaped_char[0] = (char) i;
422+
sprintf(escaped_char, "\\u%04x", i);
423+
if (s3) {
424+
s2 = s3;
425+
}
426+
s3 = php_str_to_str(ZSTR_VAL(s2), ZSTR_LEN(s2), unescaped_char, 1, escaped_char, 6);
427+
zend_string_release(s2);
420428
}
421429

422-
return s2;
430+
zend_string_release(s1);
431+
432+
return s3;
423433
}
424434

425435
/**
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Check that control character in array key are properly escaped for json
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('json')) die('skip json ext not loaded');
6+
?>
7+
--FILE--
8+
<?php
9+
$myArray = [
10+
"1|\x1f" => "My data"
11+
];
12+
13+
$dump = fopen('php://memory', 'rw');
14+
15+
meminfo_dump($dump);
16+
17+
rewind($dump);
18+
$meminfoData = json_decode(stream_get_contents($dump), true);
19+
fclose($dump);
20+
21+
if (is_array($meminfoData)) {
22+
echo "meminfo_dump JSON decode ok\n";
23+
} else {
24+
echo "meminfo_dump JSON decode fail\n";
25+
}
26+
27+
?>
28+
--EXPECT--
29+
meminfo_dump JSON decode ok
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Check JSON proper escaping (see http://json.org)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('json')) die('skip json ext not loaded');
6+
?>
7+
--FILE--
8+
<?php
9+
$jsonCharactersToEscape = [
10+
'"' => 'quotation mark',
11+
'\\' => "reverse solidus",
12+
'/' => "solidus"
13+
];
14+
15+
for ($i = 0; $i <= 0x1f; $i++) {
16+
$jsonCharactersToEscape[chr($i)] = "control character $i";
17+
}
18+
19+
$dump = fopen('php://memory', 'rw');
20+
21+
meminfo_dump($dump);
22+
23+
rewind($dump);
24+
$meminfoData = json_decode(stream_get_contents($dump), true);
25+
fclose($dump);
26+
27+
if (is_array($meminfoData)) {
28+
echo "meminfo_dump JSON decode ok\n";
29+
} else {
30+
echo "meminfo_dump JSON decode fail\n";
31+
}
32+
33+
?>
34+
--EXPECT--
35+
meminfo_dump JSON decode ok
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Check JSON proper escaping (see http://json.org)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('json')) die('skip json ext not loaded');
6+
?>
7+
--FILE--
8+
<?php
9+
$myArrayWithUnicodeKey = [
10+
'' => 'plane character'
11+
];
12+
13+
$dump = fopen('php://memory', 'rw');
14+
15+
meminfo_dump($dump);
16+
17+
rewind($dump);
18+
$meminfoData = json_decode(stream_get_contents($dump), true);
19+
fclose($dump);
20+
21+
if (is_array($meminfoData)) {
22+
echo "meminfo_dump JSON decode ok\n";
23+
} else {
24+
echo "meminfo_dump JSON decode fail\n";
25+
}
26+
27+
?>
28+
--EXPECT--
29+
meminfo_dump JSON decode ok

0 commit comments

Comments
 (0)