Skip to content

Commit 2524428

Browse files
Fixed whitespace part of bug #64874 ("json_decode handles whitespace and case-sensitivity incorrectly")
1 parent 7beef74 commit 2524428

File tree

2 files changed

+73
-8
lines changed

2 files changed

+73
-8
lines changed

ext/json/json.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -684,21 +684,35 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
684684
double d;
685685
int type, overflow_info;
686686
long p;
687+
char *trim = str;
688+
int trim_len = str_len;
689+
690+
/* Increment trimmed string pointer to strip leading whitespace */
691+
/* JSON RFC says to consider as whitespace: space, tab, LF or CR */
692+
while (trim_len && (*trim == ' ' || *trim == '\t' || *trim == '\n' || *trim == '\r')) {
693+
trim++;
694+
trim_len--;
695+
}
696+
697+
/* Decrement trimmed string length to strip trailing whitespace */
698+
while (trim_len && (trim[trim_len - 1] == ' ' || trim[trim_len - 1] == '\t' || trim[trim_len - 1] == '\n' || trim[trim_len - 1] == '\r')) {
699+
trim_len--;
700+
}
687701

688702
RETVAL_NULL();
689-
if (str_len == 4) {
690-
if (!strcasecmp(str, "null")) {
703+
if (trim_len == 4) {
704+
if (!strncasecmp(trim, "null", trim_len)) {
691705
/* We need to explicitly clear the error because its an actual NULL and not an error */
692706
jp->error_code = PHP_JSON_ERROR_NONE;
693707
RETVAL_NULL();
694-
} else if (!strcasecmp(str, "true")) {
708+
} else if (!strncasecmp(trim, "true", trim_len)) {
695709
RETVAL_BOOL(1);
696710
}
697-
} else if (str_len == 5 && !strcasecmp(str, "false")) {
711+
} else if (trim_len == 5 && !strncasecmp(trim, "false", trim_len)) {
698712
RETVAL_BOOL(0);
699713
}
700714

701-
if ((type = is_numeric_string_ex(str, str_len, &p, &d, 0, &overflow_info)) != 0) {
715+
if ((type = is_numeric_string_ex(trim, trim_len, &p, &d, 0, &overflow_info)) != 0) {
702716
if (type == IS_LONG) {
703717
RETVAL_LONG(p);
704718
} 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,
711725
int i;
712726
zend_bool is_float = 0;
713727

714-
for (i = (str[0] == '-' ? 1 : 0); i < str_len; i++) {
728+
for (i = (trim[0] == '-' ? 1 : 0); i < trim_len; i++) {
715729
/* Not using isdigit() because it's locale specific,
716730
* but we expect JSON input to always be UTF-8. */
717-
if (str[i] < '0' || str[i] > '9') {
731+
if (trim[i] < '0' || trim[i] > '9') {
718732
is_float = 1;
719733
break;
720734
}
@@ -723,7 +737,7 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
723737
if (is_float) {
724738
RETVAL_DOUBLE(d);
725739
} else {
726-
RETVAL_STRINGL(str, str_len, 1);
740+
RETVAL_STRINGL(trim, trim_len, 1);
727741
}
728742
} else {
729743
RETVAL_DOUBLE(d);

ext/json/tests/bug64874_part1.phpt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
Whitespace part of bug #64874 ("json_decode handles whitespace and case-sensitivity incorrectly")
3+
--SKIPIF--
4+
<?php if (!extension_loaded("json")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
function decode($json) {
8+
var_dump(json_decode($json));
9+
var_dump(json_last_error() !== 0);
10+
echo "\n";
11+
}
12+
13+
// Leading whitespace should be ignored
14+
decode(" true");
15+
decode("\ttrue");
16+
decode("\ntrue");
17+
decode("\rtrue");
18+
19+
// So should trailing whitespace
20+
decode("true ");
21+
decode("true\t");
22+
decode("true\n");
23+
decode("true\r");
24+
25+
echo "Done\n";
26+
--EXPECT--
27+
bool(true)
28+
bool(false)
29+
30+
bool(true)
31+
bool(false)
32+
33+
bool(true)
34+
bool(false)
35+
36+
bool(true)
37+
bool(false)
38+
39+
bool(true)
40+
bool(false)
41+
42+
bool(true)
43+
bool(false)
44+
45+
bool(true)
46+
bool(false)
47+
48+
bool(true)
49+
bool(false)
50+
51+
Done

0 commit comments

Comments
 (0)