diff --git a/UPGRADING b/UPGRADING index 46cf4cafab12..2071afdd4278 100644 --- a/UPGRADING +++ b/UPGRADING @@ -44,6 +44,16 @@ PHP 8.7 UPGRADE NOTES A ValueError is thrown if the array is empty or contains an invalid locale, and a TypeError if it contains a non-string value. +- JSON: + . json_decode() and json_validate() can now accept comments and trailing + commas. JSON_ALLOW_COMMENTS accepts "//" line comments and "/* */" + block comments wherever whitespace is allowed. Block comments do not + nest. A line comment ends at LF, CR, CRLF, or the end of the input. + A NUL byte in a comment is a control character error. + JSON_ALLOW_TRAILING_COMMAS accepts one comma after the last element of + a non-empty array or the last member of a non-empty object. Without + these flags, parsing does not change. + - Streams: . The so_linger, so_rcvbuf and so_sndbuf stream socket context options are now also applied to unix and unix datagram sockets. @@ -60,6 +70,13 @@ PHP 8.7 UPGRADE NOTES 5. Changed Functions ======================================== +- JSON: + . json_decode() now accepts the JSON_ALLOW_COMMENTS and + JSON_ALLOW_TRAILING_COMMAS flags. + . json_validate() now accepts the JSON_ALLOW_COMMENTS and + JSON_ALLOW_TRAILING_COMMAS flags, in addition to + JSON_INVALID_UTF8_IGNORE. + ======================================== 6. New Functions ======================================== @@ -80,6 +97,10 @@ PHP 8.7 UPGRADE NOTES 10. New Global Constants ======================================== +- JSON: + . JSON_ALLOW_COMMENTS. + . JSON_ALLOW_TRAILING_COMMAS. + ======================================== 11. Changes to INI File Handling ======================================== diff --git a/ext/json/json.c b/ext/json/json.c index dbae11c98f40..982e1fb5faac 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -350,8 +350,11 @@ PHP_FUNCTION(json_validate) ZEND_PARSE_PARAMETERS_END(); - if ((options != 0) && (options != PHP_JSON_INVALID_UTF8_IGNORE)) { - zend_argument_value_error(3, "must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE)"); + if ((options & ~(PHP_JSON_INVALID_UTF8_IGNORE + | PHP_JSON_ALLOW_COMMENTS + | PHP_JSON_ALLOW_TRAILING_COMMAS)) != 0) { + zend_argument_value_error(3, "must be a valid flag (allowed flags: " + "JSON_INVALID_UTF8_IGNORE, JSON_ALLOW_COMMENTS, JSON_ALLOW_TRAILING_COMMAS)"); RETURN_THROWS(); } diff --git a/ext/json/json.stub.php b/ext/json/json.stub.php index a805c3893dd1..737d341e9ca2 100644 --- a/ext/json/json.stub.php +++ b/ext/json/json.stub.php @@ -90,6 +90,17 @@ */ const JSON_THROW_ON_ERROR = UNKNOWN; +/** + * @var int + * @cvalue PHP_JSON_ALLOW_COMMENTS + */ +const JSON_ALLOW_COMMENTS = UNKNOWN; +/** + * @var int + * @cvalue PHP_JSON_ALLOW_TRAILING_COMMAS + */ +const JSON_ALLOW_TRAILING_COMMAS = UNKNOWN; + /** * @var int * @cvalue PHP_JSON_ERROR_NONE diff --git a/ext/json/json_arginfo.h b/ext/json/json_arginfo.h index 01ebf40727c3..02ed604f5f22 100644 --- a/ext/json/json_arginfo.h +++ b/ext/json/json_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit json.stub.php instead. - * Stub hash: 0ceb50047401c4b9e878c09cc518eacc274f7fff */ + * Stub hash: 405dc5ea03cb0ed560c3717cad38203b2f55d870 */ #include "zend_constants.h" @@ -70,6 +70,8 @@ static void register_json_symbols(int module_number) REGISTER_LONG_CONSTANT("JSON_INVALID_UTF8_IGNORE", PHP_JSON_INVALID_UTF8_IGNORE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("JSON_INVALID_UTF8_SUBSTITUTE", PHP_JSON_INVALID_UTF8_SUBSTITUTE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("JSON_THROW_ON_ERROR", PHP_JSON_THROW_ON_ERROR, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ALLOW_COMMENTS", PHP_JSON_ALLOW_COMMENTS, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ALLOW_TRAILING_COMMAS", PHP_JSON_ALLOW_TRAILING_COMMAS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH, CONST_PERSISTENT); diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y index 0fd3e2c4e364..50b5c71b4c72 100644 --- a/ext/json/json_parser.y +++ b/ext/json/json_parser.y @@ -119,6 +119,7 @@ members: } } | member + | member trailing_comma ; member: @@ -175,6 +176,7 @@ elements: } } | element + | element trailing_comma ; element: @@ -190,6 +192,18 @@ element: } ; +trailing_comma: + ',' + { + if (!(parser->scanner.options & PHP_JSON_ALLOW_TRAILING_COMMAS)) { + /* This rule also reduces on an error token from the scanner, + * so keep the scanner's error code. */ + php_json_yyerror(parser, NULL); + YYERROR; + } + } +; + key: PHP_JSON_T_STRING | PHP_JSON_T_ESTRING diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re index be62875a00e0..7681fb9ed771 100644 --- a/ext/json/json_scanner.re +++ b/ext/json/json_scanner.re @@ -102,6 +102,11 @@ void php_json_scanner_init(php_json_scanner *s, const char *str, size_t str_len, int php_json_scan(php_json_scanner *s) { + /* Line of the last block comment opener, for an unterminated comment. + * s->token keeps the opener position while in COMMENT_BLOCK. */ + php_json_ctype *comment_line_start = s->line_start; + uint64_t comment_line = s->line; + ZVAL_NULL(&s->value); std: @@ -203,6 +208,22 @@ std: goto std; } WS { goto std; } + "//" { + if (!(s->options & PHP_JSON_ALLOW_COMMENTS)) { + s->errcode = PHP_JSON_ERROR_SYNTAX; + return PHP_JSON_T_ERROR; + } + PHP_JSON_CONDITION_SET_AND_GOTO(COMMENT_LINE); + } + "/*" { + if (!(s->options & PHP_JSON_ALLOW_COMMENTS)) { + s->errcode = PHP_JSON_ERROR_SYNTAX; + return PHP_JSON_T_ERROR; + } + comment_line_start = s->line_start; + comment_line = s->line; + PHP_JSON_CONDITION_SET_AND_GOTO(COMMENT_BLOCK); + } EOI { if (s->limit < s->cursor) { return PHP_JSON_T_EOI; @@ -230,6 +251,65 @@ std: s->errcode = PHP_JSON_ERROR_UTF8; return PHP_JSON_T_ERROR; } + NL { + s->line++; + s->line_start = s->cursor; + PHP_JSON_CONDITION_SET(JS); + goto std; + } + "\r" { + /* A bare CR ends the comment but is whitespace, as in the JS condition. */ + PHP_JSON_CONDITION_SET(JS); + goto std; + } + EOI { + if (s->limit < s->cursor) { + s->token = s->limit; + PHP_JSON_CONDITION_SET(JS); + return PHP_JSON_T_EOI; + } + s->token = s->cursor - 1; + s->errcode = PHP_JSON_ERROR_CTRL_CHAR; + return PHP_JSON_T_ERROR; + } + UTF8 { PHP_JSON_CONDITION_GOTO(COMMENT_LINE); } + ANY { + if (s->options & (PHP_JSON_INVALID_UTF8_IGNORE | PHP_JSON_INVALID_UTF8_SUBSTITUTE)) { + PHP_JSON_CONDITION_GOTO(COMMENT_LINE); + } + s->token = s->cursor - 1; + s->errcode = PHP_JSON_ERROR_UTF8; + return PHP_JSON_T_ERROR; + } + "*/" { + PHP_JSON_CONDITION_SET(JS); + goto std; + } + NL { + s->line++; + s->line_start = s->cursor; + PHP_JSON_CONDITION_GOTO(COMMENT_BLOCK); + } + EOI { + if (s->limit < s->cursor) { + s->line_start = comment_line_start; + s->line = comment_line; + s->errcode = PHP_JSON_ERROR_SYNTAX; + return PHP_JSON_T_ERROR; + } + s->token = s->cursor - 1; + s->errcode = PHP_JSON_ERROR_CTRL_CHAR; + return PHP_JSON_T_ERROR; + } + UTF8 { PHP_JSON_CONDITION_GOTO(COMMENT_BLOCK); } + ANY { + if (s->options & (PHP_JSON_INVALID_UTF8_IGNORE | PHP_JSON_INVALID_UTF8_SUBSTITUTE)) { + PHP_JSON_CONDITION_GOTO(COMMENT_BLOCK); + } + s->token = s->cursor - 1; + s->errcode = PHP_JSON_ERROR_UTF8; + return PHP_JSON_T_ERROR; + } EOI { if (s->limit < s->cursor) { s->errcode = PHP_JSON_ERROR_SYNTAX; diff --git a/ext/json/php_json.h b/ext/json/php_json.h index f20b20964a71..0145a0dfaa6c 100644 --- a/ext/json/php_json.h +++ b/ext/json/php_json.h @@ -89,6 +89,10 @@ static inline void php_json_error_details_clear(php_json_error_details *out) { #define PHP_JSON_INVALID_UTF8_SUBSTITUTE (1<<21) #define PHP_JSON_THROW_ON_ERROR (1<<22) +/* json_validate() and json_decode() common options */ +#define PHP_JSON_ALLOW_COMMENTS (1<<23) +#define PHP_JSON_ALLOW_TRAILING_COMMAS (1<<24) + /* default depth */ #define PHP_JSON_PARSER_DEFAULT_DEPTH 512 diff --git a/ext/json/tests/json_decode_allow_comments.phpt b/ext/json/tests/json_decode_allow_comments.phpt new file mode 100644 index 000000000000..065b057f9138 --- /dev/null +++ b/ext/json/tests/json_decode_allow_comments.phpt @@ -0,0 +1,90 @@ +--TEST-- +json_decode() and json_validate() with JSON_ALLOW_COMMENTS +--FILE-- + +--EXPECT-- +{"a":[1,2],"b":3} +bool(true) +[1,2] +bool(true) +[] +bool(true) +[] +bool(true) +1 +bool(true) +2 +bool(true) +3 +bool(true) +4 +bool(true) +6 +bool(true) +7 +bool(true) +1 +bool(true) +1 +bool(true) +1 +bool(true) +1.5 +bool(true) +100000 +bool(true) +["//","/* not a comment */","https://php.net/a/*b*/"] +bool(true) +5 +bool(true) +8 +bool(true) diff --git a/ext/json/tests/json_decode_allow_comments_errors.phpt b/ext/json/tests/json_decode_allow_comments_errors.phpt new file mode 100644 index 000000000000..557f94cb1889 --- /dev/null +++ b/ext/json/tests/json_decode_allow_comments_errors.phpt @@ -0,0 +1,112 @@ +--TEST-- +JSON_ALLOW_COMMENTS rejects malformed or misplaced comments +--FILE-- +getCode(), ': ', $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:16 +NULL +4: Syntax error near location 1:19 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:2 +NULL +4: Syntax error near location 1:2 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:26 +NULL +4: Syntax error near location 1:22 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 1:1 +NULL +4: Syntax error near location 3:3 +NULL +3: Control character error, possibly incorrectly encoded near location 1:9 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:9 +NULL +3: Control character error, possibly incorrectly encoded near location 1:9 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:9 +NULL +3: Control character error, possibly incorrectly encoded near location 2:3 +bool(false) +3: Control character error, possibly incorrectly encoded near location 2:3 +NULL +3: Control character error, possibly incorrectly encoded near location 1:9 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:9 +NULL +3: Control character error, possibly incorrectly encoded near location 1:9 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:9 +NULL +3: Control character error, possibly incorrectly encoded near location 1:9 +NULL +3: Control character error, possibly incorrectly encoded near location 1:9 +JsonException: 4: Syntax error near location 2:2 diff --git a/ext/json/tests/json_decode_allow_comments_utf8.phpt b/ext/json/tests/json_decode_allow_comments_utf8.phpt new file mode 100644 index 000000000000..8bcd13157df8 --- /dev/null +++ b/ext/json/tests/json_decode_allow_comments_utf8.phpt @@ -0,0 +1,68 @@ +--TEST-- +JSON_ALLOW_COMMENTS interactions with malformed UTF-8 flags +--FILE-- +getCode(), ': ', $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +NULL +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:9 +array(1) { + [0]=> + string(2) "ab" +} +0: No error +array(1) { + [0]=> + string(2) "ab" +} +0: No error +bool(false) +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:9 +bool(true) +0: No error +NULL +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:9 +array(1) { + [0]=> + string(2) "ab" +} +0: No error +array(1) { + [0]=> + string(2) "ab" +} +0: No error +bool(false) +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:9 +bool(true) +0: No error +JsonException: 5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:9 diff --git a/ext/json/tests/json_decode_allow_trailing_commas.phpt b/ext/json/tests/json_decode_allow_trailing_commas.phpt new file mode 100644 index 000000000000..83a5550381bc --- /dev/null +++ b/ext/json/tests/json_decode_allow_trailing_commas.phpt @@ -0,0 +1,96 @@ +--TEST-- +json_decode() and json_validate() with JSON_ALLOW_TRAILING_COMMAS +--FILE-- +getCode(), ': ', $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +[1] +[1] +[1] +{"a":1} +[[1],{"a":2}] +error 4: Syntax error near location 1:2 +error 4: Syntax error near location 1:2 +error 4: Syntax error near location 1:4 +error 4: Syntax error near location 1:4 +error 4: Syntax error near location 1:8 +error 4: Syntax error near location 1:4 +error 4: Syntax error near location 1:4 +error 4: Syntax error near location 1:4 +[1] +{"a":1} +error 2: State mismatch (invalid or malformed JSON) near location 1:4 +error 2: State mismatch (invalid or malformed JSON) near location 1:8 +bool(true) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +JsonException: 4: Syntax error near location 1:4 diff --git a/ext/json/tests/json_decode_relaxed_syntax_interactions.phpt b/ext/json/tests/json_decode_relaxed_syntax_interactions.phpt new file mode 100644 index 000000000000..89129c8e6a9f --- /dev/null +++ b/ext/json/tests/json_decode_relaxed_syntax_interactions.phpt @@ -0,0 +1,110 @@ +--TEST-- +JSON comment and trailing-comma flags interact correctly with existing behavior +--FILE-- + 1], RELAXED)); + +/* Association, bigint conversion, and duplicate-key behavior are unchanged. */ +var_dump(json_decode( + '/* before */{"n":9223372036854775808,"same":1,"same":2,}', + null, + 512, + RELAXED | JSON_OBJECT_AS_ARRAY | JSON_BIGINT_AS_STRING +)); +var_dump(json_decode('{"a":1,}', false, 512, JSON_ALLOW_TRAILING_COMMAS)); + +/* Comments and trailing commas do not consume nesting depth. */ +$nested = '/* before */[[0,],]'; +var_dump(json_decode($nested, true, 2, RELAXED)); +echo json_last_error(), ': ', json_last_error_msg(), "\n"; +var_dump(json_validate($nested, 3, RELAXED)); + +/* A trailing-comma reduction must not replace a more specific scanner error. + * Without the flag, the reduction also runs when the scanner reports an error. */ +foreach ([0, RELAXED] as $flags) { + foreach ([ + "[1,\x01]", + "[1,\x80]", + '[1,"\\ud834"]', + "{\"a\":1,\x01}", + ] as $json) { + var_dump(json_decode($json, true, 512, $flags)); + echo json_last_error(), ': ', json_last_error_msg(), "\n"; + var_dump(json_validate($json, 512, $flags)); + echo json_last_error(), ': ', json_last_error_msg(), "\n"; + } +} + +/* json_validate() accepts only its documented combinations. */ +var_dump(json_validate('/* comment */[1,]', 512, RELAXED)); +var_dump(json_validate( + "/* \x80 */[1,]", + 512, + RELAXED | JSON_INVALID_UTF8_IGNORE +)); +foreach ([JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_SUBSTITUTE] as $invalidFlag) { + try { + json_validate('{}', flags: RELAXED | $invalidFlag); + } catch (Throwable $e) { + echo $e::class, ': ', $e->getCode(), ': ', $e->getMessage(), "\n"; + } +} + +?> +--EXPECTF-- +int(8388608) +int(16777216) +string(7) "{"x":1}" +array(2) { + ["n"]=> + string(19) "9223372036854775808" + ["same"]=> + int(2) +} +object(stdClass)#%d (1) { + ["a"]=> + int(1) +} +NULL +1: Maximum stack depth exceeded near location 1:14 +bool(true) +NULL +3: Control character error, possibly incorrectly encoded near location 1:4 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:4 +NULL +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:4 +bool(false) +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:4 +NULL +10: Single unpaired UTF-16 surrogate in unicode escape near location 1:4 +bool(false) +10: Single unpaired UTF-16 surrogate in unicode escape near location 1:4 +NULL +3: Control character error, possibly incorrectly encoded near location 1:8 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:8 +NULL +3: Control character error, possibly incorrectly encoded near location 1:4 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:4 +NULL +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:4 +bool(false) +5: Malformed UTF-8 characters, possibly incorrectly encoded near location 1:4 +NULL +10: Single unpaired UTF-16 surrogate in unicode escape near location 1:4 +bool(false) +10: Single unpaired UTF-16 surrogate in unicode escape near location 1:4 +NULL +3: Control character error, possibly incorrectly encoded near location 1:8 +bool(false) +3: Control character error, possibly incorrectly encoded near location 1:8 +bool(true) +bool(true) +ValueError: 0: json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE, JSON_ALLOW_COMMENTS, JSON_ALLOW_TRAILING_COMMAS) +ValueError: 0: json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE, JSON_ALLOW_COMMENTS, JSON_ALLOW_TRAILING_COMMAS) diff --git a/ext/json/tests/json_last_error_msg_error_location_comments.phpt b/ext/json/tests/json_last_error_msg_error_location_comments.phpt new file mode 100644 index 000000000000..c74642f07a82 --- /dev/null +++ b/ext/json/tests/json_last_error_msg_error_location_comments.phpt @@ -0,0 +1,64 @@ +--TEST-- +JSON comment and trailing-comma errors preserve original source locations +--FILE-- + +--EXPECT-- +bool(false) +4: Syntax error near location 3:17 +bool(false) +4: Syntax error near location 3:2 +bool(false) +4: Syntax error near location 1:12 +bool(false) +4: Syntax error near location 1:12 +bool(false) +4: Syntax error near location 1:12 +bool(false) +4: Syntax error near location 2:6 +bool(false) +4: Syntax error near location 2:6 +bool(false) +4: Syntax error near location 2:6 +bool(false) +4: Syntax error near location 1:22 +bool(false) +4: Syntax error near location 3:3 +bool(false) +4: Syntax error near location 1:19 diff --git a/ext/json/tests/json_validate_002.phpt b/ext/json/tests/json_validate_002.phpt index 423564c4ad7c..c3b003ea57b3 100644 --- a/ext/json/tests/json_validate_002.phpt +++ b/ext/json/tests/json_validate_002.phpt @@ -36,10 +36,10 @@ string(8) "No error" Error: 0 json_validate(): Argument #2 ($depth) must be greater than 0 int(0) string(8) "No error" -Error: 0 json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE) +Error: 0 json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE, JSON_ALLOW_COMMENTS, JSON_ALLOW_TRAILING_COMMAS) int(0) string(8) "No error" -Error: 0 json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE) +Error: 0 json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE, JSON_ALLOW_COMMENTS, JSON_ALLOW_TRAILING_COMMAS) int(0) string(8) "No error" bool(false) diff --git a/sapi/fuzzer/fuzzer-json.c b/sapi/fuzzer/fuzzer-json.c index 0407a895835e..a36f768cbf23 100644 --- a/sapi/fuzzer/fuzzer-json.c +++ b/sapi/fuzzer/fuzzer-json.c @@ -37,7 +37,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { memcpy(data, Data, Size); data[Size] = '\0'; - int options[12] = { + static const int options[] = { 0, PHP_JSON_OBJECT_AS_ARRAY, PHP_JSON_OBJECT_AS_ARRAY | PHP_JSON_BIGINT_AS_STRING, @@ -49,13 +49,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { PHP_JSON_BIGINT_AS_STRING | PHP_JSON_INVALID_UTF8_IGNORE, PHP_JSON_BIGINT_AS_STRING | PHP_JSON_INVALID_UTF8_SUBSTITUTE, PHP_JSON_INVALID_UTF8_IGNORE, - PHP_JSON_INVALID_UTF8_SUBSTITUTE + PHP_JSON_INVALID_UTF8_SUBSTITUTE, + PHP_JSON_ALLOW_COMMENTS, + PHP_JSON_ALLOW_TRAILING_COMMAS, + PHP_JSON_ALLOW_COMMENTS | PHP_JSON_ALLOW_TRAILING_COMMAS, + PHP_JSON_OBJECT_AS_ARRAY | PHP_JSON_BIGINT_AS_STRING + | PHP_JSON_ALLOW_COMMENTS | PHP_JSON_ALLOW_TRAILING_COMMAS, + PHP_JSON_ALLOW_COMMENTS | PHP_JSON_ALLOW_TRAILING_COMMAS | PHP_JSON_INVALID_UTF8_IGNORE, + PHP_JSON_ALLOW_COMMENTS | PHP_JSON_ALLOW_TRAILING_COMMAS | PHP_JSON_INVALID_UTF8_SUBSTITUTE, }; - for (int index = 0; index < 12; ++index) { + for (size_t i = 0; i < sizeof(options) / sizeof(options[0]); ++i) { zval result; php_json_parser parser; - php_json_parser_init(&parser, &result, data, Size, options[index], 10); + php_json_parser_init(&parser, &result, data, Size, options[i], 10); if (php_json_yyparse(&parser) == SUCCESS) { zval_ptr_dtor(&result); } diff --git a/sapi/fuzzer/json.dict b/sapi/fuzzer/json.dict index e08245a2194f..adfd4dd4407b 100644 --- a/sapi/fuzzer/json.dict +++ b/sapi/fuzzer/json.dict @@ -50,3 +50,8 @@ "\"\":0" "//" "/**/" +"/*" +"*/" +",]" +",}" +"\x0d"