Skip to content

Commit f3df3df

Browse files
committed
Fix bug #68546 (json_decode cannot access property started with \0)
1 parent 115e928 commit f3df3df

File tree

6 files changed

+62
-11
lines changed

6 files changed

+62
-11
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ PHP NEWS
199199
(JSON extension includes a problematic license statement). (Jakub Zelenka)
200200
. Fixed bug #68938 (json_decode() decodes empty string without error).
201201
(jeremy at bat-country dot us)
202+
. Fixed bug #68546 (json_decode() Fatal error: Cannot access property
203+
started with '\0'). (Jakub Zelenka)
202204

203205
- LDAP
204206
. Fixed bug #47222 (Implement LDAP_OPT_DIAGNOSTIC_MESSAGE). (Andreas Heigl)

ext/json/json.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ static PHP_MINIT_FUNCTION(json)
121121
REGISTER_LONG_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION, CONST_CS | CONST_PERSISTENT);
122122
REGISTER_LONG_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN, CONST_CS | CONST_PERSISTENT);
123123
REGISTER_LONG_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE, CONST_CS | CONST_PERSISTENT);
124+
REGISTER_LONG_CONSTANT("JSON_ERROR_INVALID_PROPERTY_NAME", PHP_JSON_ERROR_INVALID_PROPERTY_NAME, CONST_CS | CONST_PERSISTENT);
124125

125126
REGISTER_LONG_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY, CONST_CS | CONST_PERSISTENT);
126127
REGISTER_LONG_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING, CONST_CS | CONST_PERSISTENT);
@@ -300,6 +301,8 @@ static PHP_FUNCTION(json_last_error_msg)
300301
RETURN_STRING("Inf and NaN cannot be JSON encoded");
301302
case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
302303
RETURN_STRING("Type is not supported");
304+
case PHP_JSON_ERROR_INVALID_PROPERTY_NAME:
305+
RETURN_STRING("The decoded property name is invalid");
303306
default:
304307
RETURN_STRING("Unknown error");
305308
}

ext/json/json_parser.tab.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ int php_json_yyparse (php_json_parser *parser);
204204
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
205205
void php_json_yyerror(php_json_parser *parser, char const *msg);
206206
void php_json_parser_object_init(php_json_parser *parser, zval *object);
207-
void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
207+
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
208208
void php_json_parser_array_init(zval *object);
209209
void php_json_parser_array_append(zval *array, zval *zvalue);
210210

@@ -515,9 +515,9 @@ static const yytype_uint8 yytranslate[] =
515515
static const yytype_uint8 yyrline[] =
516516
{
517517
0, 92, 92, 98, 105, 105, 113, 114, 123, 126,
518-
130, 135, 140, 147, 152, 159, 159, 167, 168, 177,
519-
180, 184, 189, 194, 201, 202, 206, 207, 208, 209,
520-
210, 211, 212, 213, 214, 215, 219
518+
130, 136, 142, 149, 154, 161, 161, 169, 170, 179,
519+
182, 186, 191, 196, 203, 204, 208, 209, 210, 211,
520+
212, 213, 214, 215, 216, 217, 221
521521
};
522522
#endif
523523

@@ -1499,15 +1499,17 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
14991499

15001500
{
15011501
php_json_parser_object_init(parser, &(yyval.value));
1502-
php_json_parser_object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val);
1502+
if (php_json_parser_object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE)
1503+
YYERROR;
15031504
}
15041505

15051506
break;
15061507

15071508
case 11:
15081509

15091510
{
1510-
php_json_parser_object_update(parser, &(yyvsp[-2].value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val);
1511+
if (php_json_parser_object_update(parser, &(yyvsp[-2].value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE)
1512+
YYERROR;
15111513
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value));
15121514
}
15131515

@@ -1860,7 +1862,7 @@ void php_json_parser_object_init(php_json_parser *parser, zval *object)
18601862
}
18611863
}
18621864

1863-
void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
1865+
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
18641866
{
18651867
/* if JSON_OBJECT_AS_ARRAY is set */
18661868
if (Z_TYPE_P(object) == IS_ARRAY) {
@@ -1870,6 +1872,12 @@ void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_s
18701872
if (key->len == 0) {
18711873
zend_string_release(key);
18721874
key = zend_string_init("_empty_", sizeof("_empty_") - 1, 0);
1875+
} else if (key->val[0] == '\0') {
1876+
parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME;
1877+
zend_string_release(key);
1878+
zval_dtor(zvalue);
1879+
zval_dtor(object);
1880+
return FAILURE;
18731881
}
18741882
ZVAL_NEW_STR(&zkey, key);
18751883
zend_std_write_property(object, &zkey, zvalue, NULL);
@@ -1879,6 +1887,8 @@ void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_s
18791887
}
18801888
}
18811889
zend_string_release(key);
1890+
1891+
return SUCCESS;
18821892
}
18831893

18841894
void php_json_parser_array_init(zval *array)

ext/json/json_parser.y

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ int json_yydebug = 1;
7373
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
7474
void php_json_yyerror(php_json_parser *parser, char const *msg);
7575
void php_json_parser_object_init(php_json_parser *parser, zval *object);
76-
void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
76+
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
7777
void php_json_parser_array_init(zval *object);
7878
void php_json_parser_array_append(zval *array, zval *zvalue);
7979

@@ -130,11 +130,13 @@ member:
130130
pair
131131
{
132132
php_json_parser_object_init(parser, &$$);
133-
php_json_parser_object_update(parser, &$$, $1.key, &$1.val);
133+
if (php_json_parser_object_update(parser, &$$, $1.key, &$1.val) == FAILURE)
134+
YYERROR;
134135
}
135136
| member ',' pair
136137
{
137-
php_json_parser_object_update(parser, &$1, $3.key, &$3.val);
138+
if (php_json_parser_object_update(parser, &$1, $3.key, &$3.val) == FAILURE)
139+
YYERROR;
138140
ZVAL_COPY_VALUE(&$$, &$1);
139141
}
140142
| member errlex
@@ -248,7 +250,7 @@ void php_json_parser_object_init(php_json_parser *parser, zval *object)
248250
}
249251
}
250252

251-
void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
253+
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
252254
{
253255
/* if JSON_OBJECT_AS_ARRAY is set */
254256
if (Z_TYPE_P(object) == IS_ARRAY) {
@@ -258,6 +260,12 @@ void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_s
258260
if (key->len == 0) {
259261
zend_string_release(key);
260262
key = zend_string_init("_empty_", sizeof("_empty_") - 1, 0);
263+
} else if (key->val[0] == '\0') {
264+
parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME;
265+
zend_string_release(key);
266+
zval_dtor(zvalue);
267+
zval_dtor(object);
268+
return FAILURE;
261269
}
262270
ZVAL_NEW_STR(&zkey, key);
263271
zend_std_write_property(object, &zkey, zvalue, NULL);
@@ -267,6 +275,8 @@ void php_json_parser_object_update(php_json_parser *parser, zval *object, zend_s
267275
}
268276
}
269277
zend_string_release(key);
278+
279+
return SUCCESS;
270280
}
271281

272282
void php_json_parser_array_init(zval *array)

ext/json/php_json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ typedef enum {
5151
PHP_JSON_ERROR_RECURSION,
5252
PHP_JSON_ERROR_INF_OR_NAN,
5353
PHP_JSON_ERROR_UNSUPPORTED_TYPE,
54+
PHP_JSON_ERROR_INVALID_PROPERTY_NAME,
5455
PHP_JSON_ERROR_UTF16
5556
} php_json_error_code;
5657

ext/json/tests/bug68546.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #68546 (json_decode() Fatal error: Cannot access property started with '\0')
3+
--SKIPIF--
4+
<?php
5+
6+
if (!extension_loaded('json')) die('skip');
7+
?>
8+
--FILE--
9+
<?php
10+
11+
var_dump(json_decode('{"key": {"\u0000": "aa"}}'));
12+
var_dump(json_last_error() === JSON_ERROR_INVALID_PROPERTY_NAME);
13+
var_dump(json_decode('[{"key1": 0, "\u0000": 1}]'));
14+
var_dump(json_last_error() === JSON_ERROR_INVALID_PROPERTY_NAME);
15+
var_dump(json_last_error_msg());
16+
17+
echo "Done\n";
18+
?>
19+
--EXPECTF--
20+
NULL
21+
bool(true)
22+
NULL
23+
bool(true)
24+
string(36) "The decoded property name is invalid"
25+
Done

0 commit comments

Comments
 (0)