From 2524428504ec9e154b01db7f6040e42c1bc89ada Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Tue, 10 Sep 2013 21:22:06 +0000 Subject: [PATCH 1/3] Fixed whitespace part of bug #64874 ("json_decode handles whitespace and case-sensitivity incorrectly") --- ext/json/json.c | 30 +++++++++++++----- ext/json/tests/bug64874_part1.phpt | 51 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 ext/json/tests/bug64874_part1.phpt diff --git a/ext/json/json.c b/ext/json/json.c index 8c8963db8cc5b..a786fef45c744 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -684,21 +684,35 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, double d; int type, overflow_info; long p; + char *trim = str; + int trim_len = str_len; + + /* Increment trimmed string pointer to strip leading whitespace */ + /* JSON RFC says to consider as whitespace: space, tab, LF or CR */ + while (trim_len && (*trim == ' ' || *trim == '\t' || *trim == '\n' || *trim == '\r')) { + trim++; + trim_len--; + } + + /* Decrement trimmed string length to strip trailing whitespace */ + while (trim_len && (trim[trim_len - 1] == ' ' || trim[trim_len - 1] == '\t' || trim[trim_len - 1] == '\n' || trim[trim_len - 1] == '\r')) { + trim_len--; + } RETVAL_NULL(); - if (str_len == 4) { - if (!strcasecmp(str, "null")) { + if (trim_len == 4) { + if (!strncasecmp(trim, "null", trim_len)) { /* We need to explicitly clear the error because its an actual NULL and not an error */ jp->error_code = PHP_JSON_ERROR_NONE; RETVAL_NULL(); - } else if (!strcasecmp(str, "true")) { + } else if (!strncasecmp(trim, "true", trim_len)) { RETVAL_BOOL(1); } - } else if (str_len == 5 && !strcasecmp(str, "false")) { + } else if (trim_len == 5 && !strncasecmp(trim, "false", trim_len)) { RETVAL_BOOL(0); } - if ((type = is_numeric_string_ex(str, str_len, &p, &d, 0, &overflow_info)) != 0) { + if ((type = is_numeric_string_ex(trim, trim_len, &p, &d, 0, &overflow_info)) != 0) { if (type == IS_LONG) { RETVAL_LONG(p); } else if (type == IS_DOUBLE) { @@ -711,10 +725,10 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, int i; zend_bool is_float = 0; - for (i = (str[0] == '-' ? 1 : 0); i < str_len; i++) { + for (i = (trim[0] == '-' ? 1 : 0); i < trim_len; i++) { /* Not using isdigit() because it's locale specific, * but we expect JSON input to always be UTF-8. */ - if (str[i] < '0' || str[i] > '9') { + if (trim[i] < '0' || trim[i] > '9') { is_float = 1; break; } @@ -723,7 +737,7 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, if (is_float) { RETVAL_DOUBLE(d); } else { - RETVAL_STRINGL(str, str_len, 1); + RETVAL_STRINGL(trim, trim_len, 1); } } else { RETVAL_DOUBLE(d); diff --git a/ext/json/tests/bug64874_part1.phpt b/ext/json/tests/bug64874_part1.phpt new file mode 100644 index 0000000000000..4047eb895c1e5 --- /dev/null +++ b/ext/json/tests/bug64874_part1.phpt @@ -0,0 +1,51 @@ +--TEST-- +Whitespace part of bug #64874 ("json_decode handles whitespace and case-sensitivity incorrectly") +--SKIPIF-- + +--FILE-- + Date: Tue, 15 Oct 2013 20:42:31 +0000 Subject: [PATCH 2/3] Better test: Check combined leading/trailing --- ext/json/tests/bug64874_part1.phpt | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/ext/json/tests/bug64874_part1.phpt b/ext/json/tests/bug64874_part1.phpt index 4047eb895c1e5..6b79b8dc047ed 100644 --- a/ext/json/tests/bug64874_part1.phpt +++ b/ext/json/tests/bug64874_part1.phpt @@ -22,6 +22,24 @@ decode("true\t"); decode("true\n"); decode("true\r"); +// And so should the combination of both +decode(" true "); +decode(" true\t"); +decode(" true\n"); +decode(" true\r"); +decode("\ttrue "); +decode("\ttrue\t"); +decode("\ttrue\n"); +decode("\ttrue\r"); +decode("\ntrue "); +decode("\ntrue\t"); +decode("\ntrue\n"); +decode("\ntrue\r"); +decode("\rtrue "); +decode("\rtrue\t"); +decode("\rtrue\n"); +decode("\rtrue\r"); + echo "Done\n"; --EXPECT-- bool(true) @@ -48,4 +66,52 @@ bool(false) bool(true) bool(false) +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + +bool(true) +bool(false) + Done From 872ef919ca665d632d55410ef2ff066659af4769 Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Tue, 15 Oct 2013 22:44:23 +0000 Subject: [PATCH 3/3] UPGRADING and NEWS --- NEWS | 4 ++++ UPGRADING | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/NEWS b/NEWS index fcf34c3fb9ec9..0fe7e6825af5a 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ PHP NEWS - FTP: . Fixed bug #65667 (ftp_nb_continue produces segfault). (Philip Hofstetter) +- JSON + . Fixed whitespace part of bug #64874 ("json_decode handles whitespace and + case-sensitivity incorrectly") + - Sockets: . Fixed bug #65808 (the socket_connect() won't work with IPv6 address). (Mike) diff --git a/UPGRADING b/UPGRADING index e6f582a4a8b13..edcaa17b30524 100755 --- a/UPGRADING +++ b/UPGRADING @@ -492,6 +492,16 @@ b. Extensions with changed behavior - the output of the tiger hash family has been corrected, see https://bugs.php.net/61307 + - JSON extension + - Fixed whitespace part of bug #64874 ("json_decode handles whitespace and + case-sensitivity incorrectly") + This means that leading and trailing whitespace when deserialising lone + JSON null, true, false, string and number values no longer causes an + error. Please note that this only applies to the deserialising of strings + containing only a null, true, false, string or number value. Leading and + trailing whitespace around and inside objects and arrays has never caused + an error. + =========================== 10. Changes in SAPI support ===========================