diff options
| author | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:37:27 -0400 |
|---|---|---|
| committer | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:37:27 -0400 |
| commit | 2d4e5b09576bb4f0ba716cc82cdf29ea04d9184b (patch) | |
| tree | 41ccc042009cba53e4ce43e727fcba4c1cfbf7f3 /ext/json | |
| parent | d29a4fd2dd3b5d4cf6e80b602544d7b71d794e76 (diff) | |
| download | php-upstream/5.2.2.tar.gz | |
Imported Upstream version 5.2.2upstream/5.2.2
Diffstat (limited to 'ext/json')
| -rw-r--r-- | ext/json/JSON_parser.c | 29 | ||||
| -rw-r--r-- | ext/json/json.c | 73 | ||||
| -rw-r--r-- | ext/json/php_json.h | 4 | ||||
| -rw-r--r-- | ext/json/tests/001.phpt | 12 | ||||
| -rw-r--r-- | ext/json/tests/002.phpt | 2 | ||||
| -rw-r--r-- | ext/json/tests/bug40503.phpt | 21 | ||||
| -rw-r--r-- | ext/json/tests/bug41034.phpt | 12 | ||||
| -rw-r--r-- | ext/json/tests/bug41067.phpt | 23 | ||||
| -rw-r--r-- | ext/json/tests/fail001.phpt | 6 | ||||
| -rw-r--r-- | ext/json/tests/pass001.1.phpt | 40 | ||||
| -rw-r--r-- | ext/json/tests/pass001.phpt | 2 |
11 files changed, 165 insertions, 59 deletions
diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index dce42d37e..b57d65174 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -169,7 +169,7 @@ static const int ascii_class[128] = { accepted if the end of the text is in state 9 and mode is MODE_DONE. */ static const int state_transition_table[30][31] = { -/* 0*/ { 0, 0,-8,-1,-6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +/* 0*/ { 0, 0,-8,-1,-6,-1,-1,-1, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, /* 1*/ { 1, 1,-1,-9,-1,-1,-1,-1, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, /* 2*/ { 2, 2,-8,-1,-6,-5,-1,-1, 3,-1,-1,-1,20,-1,21,22,-1,-1,-1,-1,-1,13,-1,17,-1,-1,10,-1,-1,-1,-1}, /* 3*/ { 3,-1, 3, 3, 3, 3, 3, 3,-4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, @@ -316,6 +316,25 @@ static void utf16_to_utf8(smart_str *buf, unsigned short utf16) smart_str_appendc(buf, 0xc0 | (utf16 >> 6)); smart_str_appendc(buf, 0x80 | (utf16 & 0x3f)); } + else if ((utf16 & 0xfc00) == 0xdc00 + && buf->len >= 3 + && ((unsigned char) buf->c[buf->len - 3]) == 0xed + && ((unsigned char) buf->c[buf->len - 2] & 0xf0) == 0xa0 + && ((unsigned char) buf->c[buf->len - 1] & 0xc0) == 0x80) + { + /* found surrogate pair */ + unsigned long utf32; + + utf32 = (((buf->c[buf->len - 2] & 0xf) << 16) + | ((buf->c[buf->len - 1] & 0x3f) << 10) + | (utf16 & 0x3ff)) + 0x10000; + buf->len -= 3; + + smart_str_appendc(buf, 0xf0 | (utf32 >> 18)); + smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f)); + smart_str_appendc(buf, 0x80 | ((utf32 >> 6) & 0x3f)); + smart_str_appendc(buf, 0x80 | (utf32 & 0x3f)); + } else { smart_str_appendc(buf, 0xe0 | (utf16 >> 12)); @@ -577,6 +596,14 @@ JSON_parser(zval *z, unsigned short p[], int length, int assoc TSRMLS_DC) case MODE_OBJECT: the_state = 9; break; + case MODE_DONE: + if (type == IS_STRING) { + smart_str_0(&buf); + ZVAL_STRINGL(z, buf.c, buf.len, 1); + the_state = 9; + break; + } + /* fall through if not IS_STRING */ default: FREE_BUFFERS(); return false; diff --git a/ext/json/json.c b/ext/json/json.c index 097c0ad7d..c406522aa 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | + | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: json.c,v 1.9.2.6 2006/08/14 20:08:17 nlopess Exp $ */ +/* $Id: json.c,v 1.9.2.14 2007/04/13 21:34:12 andrei Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -35,9 +35,6 @@ static PHP_MINFO_FUNCTION(json); static PHP_FUNCTION(json_encode); static PHP_FUNCTION(json_decode); -/* If you declare any globals in php_json.h uncomment this: -ZEND_DECLARE_MODULE_GLOBALS(json) -*/ static const char digits[] = "0123456789abcdef"; /* {{{ json_functions[] @@ -91,14 +88,7 @@ static void json_escape_string(smart_str *buf, char *s, int len); static int json_determine_array_type(zval **val TSRMLS_DC) { int i; - HashTable *myht; - - if (Z_TYPE_PP(val) == IS_ARRAY) { - myht = HASH_OF(*val); - } else { - myht = Z_OBJPROP_PP(val); - return 1; - } + HashTable *myht = HASH_OF(*val); i = myht ? zend_hash_num_elements(myht) : 0; if (i > 0) { @@ -187,7 +177,7 @@ static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) { json_encode_r(buf, *data TSRMLS_CC); } else if (r == 1) { if (i == HASH_KEY_IS_STRING) { - if (key[0] == '\0') { + if (key[0] == '\0' && Z_TYPE_PP(val) == IS_OBJECT) { /* Skip protected and private members. */ continue; } @@ -249,7 +239,7 @@ static void json_escape_string(smart_str *buf, char *s, int len) return; } - utf16 = (unsigned short *) emalloc(len * sizeof(unsigned short)); + utf16 = (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0); len = utf8_to_utf16(utf16, s, len); if (len <= 0) @@ -313,7 +303,7 @@ static void json_escape_string(smart_str *buf, char *s, int len) break; default: { - if (us < ' ' || (us & 127) == us) + if (us >= ' ' && (us & 127) == us) { smart_str_appendc(buf, (unsigned char) us); } @@ -355,7 +345,7 @@ static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC) { } break; case IS_LONG: - smart_str_append_long(buf, Z_LVAL_P(val)); + smart_str_append_long(buf, Z_LVAL_P(val)); break; case IS_DOUBLE: { @@ -363,14 +353,16 @@ static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC) { int len; double dbl = Z_DVAL_P(val); - if (!zend_isinf(dbl) && !zend_isnan(dbl)) - { - len = spprintf(&d, 0, "%.9g", dbl); - if (d) - { - smart_str_appendl(buf, d, len); - efree(d); - } + if (!zend_isinf(dbl) && !zend_isnan(dbl)) { + len = spprintf(&d, 0, "%.9g", dbl); + if (d) { + if (dbl > LONG_MAX && !memchr(d, '.', len)) { + smart_str_append_unsigned(buf, (unsigned long)Z_DVAL_P(val)); + } else { + smart_str_appendl(buf, d, len); + } + efree(d); + } } else { @@ -428,7 +420,7 @@ static PHP_FUNCTION(json_decode) RETURN_NULL(); } - utf16 = (unsigned short *) emalloc((parameter_len+1) * sizeof(unsigned short)); + utf16 = (unsigned short *) safe_emalloc((parameter_len+1), sizeof(unsigned short), 1); utf16_len = utf8_to_utf16(utf16, parameter, parameter_len); if (utf16_len <= 0) @@ -451,10 +443,37 @@ static PHP_FUNCTION(json_decode) } else { + double d; + int type; + long p; + zval_dtor(z); FREE_ZVAL(z); efree(utf16); - RETURN_NULL(); + + if (parameter_len == 4) { + if (!strcasecmp(parameter, "null")) { + RETURN_NULL(); + } else if (!strcasecmp(parameter, "true")) { + RETURN_BOOL(1); + } + } else if (parameter_len == 5 && !strcasecmp(parameter, "false")) { + RETURN_BOOL(0); + } + if ((type = is_numeric_string(parameter, parameter_len, &p, &d, 0)) != 0) { + if (type == IS_LONG) { + RETURN_LONG(p); + } else if (type == IS_DOUBLE) { + RETURN_DOUBLE(d); + } + } + if (*parameter == '"' && parameter[parameter_len-1] == '"') { + RETURN_STRINGL(parameter+1, parameter_len-2, 1); + } else if (*parameter == '{' || *parameter == '[') { /* invalid JSON string */ + RETURN_NULL(); + } else { + RETURN_STRINGL(parameter, parameter_len, 1); + } } } diff --git a/ext/json/php_json.h b/ext/json/php_json.h index 64e4d5edc..e9e6395a0 100644 --- a/ext/json/php_json.h +++ b/ext/json/php_json.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | + | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_json.h,v 1.8.2.1 2006/08/14 20:08:17 nlopess Exp $ */ +/* $Id: php_json.h,v 1.8.2.2 2007/01/01 09:36:02 sebastian Exp $ */ #ifndef PHP_JSON_H #define PHP_JSON_H diff --git a/ext/json/tests/001.phpt b/ext/json/tests/001.phpt index 095aedf63..4c9f918b4 100644 --- a/ext/json/tests/001.phpt +++ b/ext/json/tests/001.phpt @@ -31,12 +31,12 @@ NULL NULL NULL NULL -NULL -NULL -NULL -NULL -NULL -NULL +string(1) "." +string(1) "." +string(3) "<?>" +string(1) ";" +string(12) "руссиш" +string(4) "blah" NULL object(stdClass)#1 (1) { ["test"]=> diff --git a/ext/json/tests/002.phpt b/ext/json/tests/002.phpt index 5bc29bc5b..87f57421f 100644 --- a/ext/json/tests/002.phpt +++ b/ext/json/tests/002.phpt @@ -21,7 +21,7 @@ echo "Done\n"; string(2) """" string(4) "null" string(4) "true" -string(2) "{}" +string(7) "{"":""}" string(5) "[[1]]" string(1) "1" string(38) ""\u0440\u0443\u0441\u0441\u0438\u0448"" diff --git a/ext/json/tests/bug40503.phpt b/ext/json/tests/bug40503.phpt new file mode 100644 index 000000000..48f18a4e0 --- /dev/null +++ b/ext/json/tests/bug40503.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #40503 (json_encode() value corruption on 32bit systems with overflown values) +--INI-- +precision=14 +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php +function show_eq($x,$y) { + echo "$x ". ($x==$y ? "==" : "!=") ." $y\n"; +} + +$value = 0x7FFFFFFF; #2147483647; +show_eq("$value", json_encode($value)); +$value++; +show_eq("$value", json_encode($value)); + +?> +--EXPECT-- +2147483647 == 2147483647 +2147483648 == 2147483648 diff --git a/ext/json/tests/bug41034.phpt b/ext/json/tests/bug41034.phpt new file mode 100644 index 000000000..cc7704122 --- /dev/null +++ b/ext/json/tests/bug41034.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #41034 (json_encode() ignores null byte started keys in arrays) +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php +echo json_encode(array(0,"\0ab"=>1,"\0null-prefixed value")); +echo "\nDone\n"; +?> +--EXPECT-- +{"0":0,"\u0000ab":1,"1":"\u0000null-prefixed value"} +Done diff --git a/ext/json/tests/bug41067.phpt b/ext/json/tests/bug41067.phpt new file mode 100644 index 000000000..b20e6e1b5 --- /dev/null +++ b/ext/json/tests/bug41067.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #41067 (json_encode() problem with UTF-16 input) +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php +$single_barline = "\360\235\204\200"; +$array = array($single_barline); +print bin2hex($single_barline) . "\n"; +// print $single_barline . "\n\n"; +$json = json_encode($array); +print $json . "\n\n"; +$json_decoded = json_decode($json, true); +// print $json_decoded[0] . "\n"; +print bin2hex($json_decoded[0]) . "\n"; +print "END\n"; +?> +--EXPECT-- +f09d8480 +["\ud834\udd00"] + +f09d8480 +END diff --git a/ext/json/tests/fail001.phpt b/ext/json/tests/fail001.phpt index f0e0afa38..2f0c41b90 100644 --- a/ext/json/tests/fail001.phpt +++ b/ext/json/tests/fail001.phpt @@ -45,9 +45,9 @@ foreach ($tests as $test) --EXPECT-- Testing: "A JSON payload should be an object or array, not a string." AS OBJECT -NULL +string(58) "A JSON payload should be an object or array, not a string." AS ARRAY -NULL +string(58) "A JSON payload should be an object or array, not a string." Testing: ["Unclosed array" AS OBJECT NULL @@ -162,4 +162,4 @@ Testing: ['single quote'] AS OBJECT NULL AS ARRAY -NULL +NULL
\ No newline at end of file diff --git a/ext/json/tests/pass001.1.phpt b/ext/json/tests/pass001.1.phpt index cdc68ab96..45eb5739a 100644 --- a/ext/json/tests/pass001.1.phpt +++ b/ext/json/tests/pass001.1.phpt @@ -1,5 +1,7 @@ --TEST-- JSON (http://www.crockford.com/JSON/JSON_checker/test/pass1.json) +--INI-- +precision=14 --SKIPIF-- <?php if (!extension_loaded('json')) die('skip: json extension not available'); @@ -101,7 +103,7 @@ $arr = json_decode($arr_enc, true); var_dump($arr); ?> ---EXPECT-- +--EXPECTF-- Testing: [ "JSON Test Pattern pass1", @@ -170,7 +172,7 @@ array(14) { [0]=> string(23) "JSON Test Pattern pass1" [1]=> - object(stdClass)#1 (1) { + object(stdClass)#%d (1) { ["object with 1 member"]=> array(1) { [0]=> @@ -178,7 +180,7 @@ array(14) { } } [2]=> - object(stdClass)#2 (0) { + object(stdClass)#%d (0) { } [3]=> array(0) { @@ -192,7 +194,7 @@ array(14) { [7]=> NULL [8]=> - object(stdClass)#3 (36) { + object(stdClass)#%d (36) { ["integer"]=> int(1234567890) ["real"]=> @@ -204,7 +206,7 @@ array(14) { ["_empty_"]=> float(INF) ["E no ."]=> - float(4.0E+12) + float(4000000000000) ["zero"]=> int(0) ["one"]=> @@ -246,14 +248,14 @@ array(14) { array(0) { } ["object"]=> - object(stdClass)#4 (0) { + object(stdClass)#%d (0) { } ["123"]=> - object(stdClass)#5 (1) { + object(stdClass)#%d (1) { ["456"]=> - object(stdClass)#6 (1) { + object(stdClass)#%d (1) { ["abc"]=> - object(stdClass)#7 (3) { + object(stdClass)#%d (3) { ["789"]=> string(3) "def" ["012"]=> @@ -383,7 +385,7 @@ array(14) { ["_empty_"]=> float(INF) ["E no ."]=> - float(4.0E+12) + float(4000000000000) ["zero"]=> int(0) ["one"]=> @@ -532,7 +534,7 @@ array(14) { [0]=> string(23) "JSON Test Pattern pass1" [1]=> - object(stdClass)#8 (1) { + object(stdClass)#%d (1) { ["object with 1 member"]=> array(1) { [0]=> @@ -540,7 +542,7 @@ array(14) { } } [2]=> - object(stdClass)#9 (0) { + object(stdClass)#%d (0) { } [3]=> array(0) { @@ -554,7 +556,7 @@ array(14) { [7]=> NULL [8]=> - object(stdClass)#10 (36) { + object(stdClass)#%d (36) { ["integer"]=> int(1234567890) ["real"]=> @@ -566,7 +568,7 @@ array(14) { ["_empty_"]=> int(0) ["E no ."]=> - float(4.0E+12) + float(4000000000000) ["zero"]=> int(0) ["one"]=> @@ -608,14 +610,14 @@ array(14) { array(0) { } ["object"]=> - object(stdClass)#11 (0) { + object(stdClass)#%d (0) { } ["123"]=> - object(stdClass)#12 (1) { + object(stdClass)#%d (1) { ["456"]=> - object(stdClass)#13 (1) { + object(stdClass)#%d (1) { ["abc"]=> - object(stdClass)#14 (3) { + object(stdClass)#%d (3) { ["789"]=> string(3) "def" ["012"]=> @@ -745,7 +747,7 @@ array(14) { ["_empty_"]=> int(0) ["E no ."]=> - float(4.0E+12) + float(4000000000000) ["zero"]=> int(0) ["one"]=> diff --git a/ext/json/tests/pass001.phpt b/ext/json/tests/pass001.phpt index 029e2f9ff..1decd546d 100644 --- a/ext/json/tests/pass001.phpt +++ b/ext/json/tests/pass001.phpt @@ -1,5 +1,7 @@ --TEST-- JSON (http://www.crockford.com/JSON/JSON_checker/test/pass1.json) +--INI-- +precision=14 --SKIPIF-- <?php if (!extension_loaded('json')) die('skip: json extension not available'); |
