summaryrefslogtreecommitdiff
path: root/ext/json
diff options
context:
space:
mode:
authorMark A. Hershberger <mah@debian.(none)>2009-03-25 00:37:27 -0400
committerMark A. Hershberger <mah@debian.(none)>2009-03-25 00:37:27 -0400
commit2d4e5b09576bb4f0ba716cc82cdf29ea04d9184b (patch)
tree41ccc042009cba53e4ce43e727fcba4c1cfbf7f3 /ext/json
parentd29a4fd2dd3b5d4cf6e80b602544d7b71d794e76 (diff)
downloadphp-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.c29
-rw-r--r--ext/json/json.c73
-rw-r--r--ext/json/php_json.h4
-rw-r--r--ext/json/tests/001.phpt12
-rw-r--r--ext/json/tests/002.phpt2
-rw-r--r--ext/json/tests/bug40503.phpt21
-rw-r--r--ext/json/tests/bug41034.phpt12
-rw-r--r--ext/json/tests/bug41067.phpt23
-rw-r--r--ext/json/tests/fail001.phpt6
-rw-r--r--ext/json/tests/pass001.1.phpt40
-rw-r--r--ext/json/tests/pass001.phpt2
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');