From 70024b7f1bcb781d5633f2fee4c5dc3aef906625 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Sun, 8 Jun 2025 14:26:54 -0300 Subject: [PATCH 01/12] first setup --- ext/json/json.c | 15 ++++++++++++++- ext/json/json_parser.y | 6 ++++++ ext/json/php_json.h | 1 + ext/json/php_json_encoder.h | 1 + ext/json/php_json_scanner.h | 1 + ext/json/tests/json_validate_002.phpt | 1 + 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ext/json/json.c b/ext/json/json.c index 9f91d39594ec7..bcb7cc189fac3 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -70,6 +70,7 @@ static PHP_GINIT_FUNCTION(json) static PHP_RINIT_FUNCTION(json) { JSON_G(error_code) = 0; + JSON_G(error_pos) = 0; return SUCCESS; } @@ -133,6 +134,7 @@ PHP_JSON_API zend_result php_json_encode_ex(smart_str *buf, zval *val, int optio return_code = php_json_encode_zval(buf, val, options, &encoder); JSON_G(error_code) = encoder.error_code; + JSON_G(error_pos) = encoder.error_pos; return return_code; } @@ -156,7 +158,11 @@ static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{ case PHP_JSON_ERROR_CTRL_CHAR: return "Control character error, possibly incorrectly encoded"; case PHP_JSON_ERROR_SYNTAX: - return "Syntax error"; + char *msg; + spprintf(&msg, 0, "Syntax error at character %zu", JSON_G(error_pos)); + return msg; + //efree(msg); + //return "Syntax error"; case PHP_JSON_ERROR_UTF8: return "Malformed UTF-8 characters, possibly incorrectly encoded"; case PHP_JSON_ERROR_RECURSION: @@ -185,11 +191,15 @@ PHP_JSON_API zend_result php_json_decode_ex(zval *return_value, const char *str, if (php_json_yyparse(&parser)) { php_json_error_code error_code = php_json_parser_error_code(&parser); + size_t error_pos = php_json_parser_error_pos(&parser); + if (!(options & PHP_JSON_THROW_ON_ERROR)) { JSON_G(error_code) = error_code; + JSON_G(error_pos) = error_pos; } else { zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(error_code), error_code); } + RETVAL_NULL(); return FAILURE; } @@ -208,7 +218,9 @@ PHP_JSON_API bool php_json_validate_ex(const char *str, size_t str_len, zend_lon if (php_json_yyparse(&parser)) { php_json_error_code error_code = php_json_parser_error_code(&parser); + size_t error_pos = php_json_parser_error_pos(&parser); JSON_G(error_code) = error_code; + JSON_G(error_pos) = error_pos; return false; } @@ -238,6 +250,7 @@ PHP_FUNCTION(json_encode) if (!(options & PHP_JSON_THROW_ON_ERROR) || (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) { JSON_G(error_code) = encoder.error_code; + JSON_G(error_pos) = encoder.error_pos; if (encoder.error_code != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) { smart_str_free(&buf); RETURN_FALSE; diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y index d570cddc91e4b..807b5488fe927 100644 --- a/ext/json/json_parser.y +++ b/ext/json/json_parser.y @@ -300,6 +300,7 @@ static void php_json_yyerror(php_json_parser *parser, char const *msg) { if (!parser->scanner.errcode) { parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; + parser->scanner.errpos = (size_t)(parser->scanner.cursor - parser->scanner.str_start); } } @@ -308,6 +309,11 @@ PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parse return parser->scanner.errcode; } +PHP_JSON_API size_t php_json_parser_error_pos(const php_json_parser *parser) +{ + return parser->scanner.errpos; +} + static const php_json_parser_methods default_parser_methods = { php_json_parser_array_create, diff --git a/ext/json/php_json.h b/ext/json/php_json.h index 00c87eca53c9e..11847b90c53ec 100644 --- a/ext/json/php_json.h +++ b/ext/json/php_json.h @@ -90,6 +90,7 @@ ZEND_BEGIN_MODULE_GLOBALS(json) int encoder_depth; int encode_max_depth; php_json_error_code error_code; + size_t error_pos; ZEND_END_MODULE_GLOBALS(json) PHP_JSON_API ZEND_EXTERN_MODULE_GLOBALS(json) diff --git a/ext/json/php_json_encoder.h b/ext/json/php_json_encoder.h index d66d71cb5538c..ffae7434c44bd 100644 --- a/ext/json/php_json_encoder.h +++ b/ext/json/php_json_encoder.h @@ -26,6 +26,7 @@ struct _php_json_encoder { int depth; int max_depth; php_json_error_code error_code; + size_t error_pos; }; static inline void php_json_encode_init(php_json_encoder *encoder) diff --git a/ext/json/php_json_scanner.h b/ext/json/php_json_scanner.h index a49be68cd6328..72f02f2cb0781 100644 --- a/ext/json/php_json_scanner.h +++ b/ext/json/php_json_scanner.h @@ -35,6 +35,7 @@ typedef struct _php_json_scanner { int state; /* condition state */ int options; /* options */ php_json_error_code errcode; /* error type if there is an error */ + size_t errpos; int utf8_invalid; /* whether utf8 is invalid */ int utf8_invalid_count; /* number of extra character for invalid utf8 */ } php_json_scanner; diff --git a/ext/json/tests/json_validate_002.phpt b/ext/json/tests/json_validate_002.phpt index 53f4e4f2c2ea1..d8b3e4a3f1770 100644 --- a/ext/json/tests/json_validate_002.phpt +++ b/ext/json/tests/json_validate_002.phpt @@ -8,6 +8,7 @@ require_once("json_validate_requires.inc"); json_validate_trycatchdump(""); json_validate_trycatchdump("-"); json_validate_trycatchdump("", -1); +json_validate_trycatchdump('{"key1":"value1", "value2"}', 2); json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 1); json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 2); json_validate_trycatchdump("-", 0); From 05f2fc58bfb3bb8fef466ffd87b49caf2d61a3a1 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Mon, 9 Jun 2025 23:19:11 -0300 Subject: [PATCH 02/12] counts ok --- ext/json/json.c | 4 +- ext/json/json_parser.y | 16 +++++++- ext/json/json_scanner.re | 57 +++++++++++++++++++++++++++ ext/json/php_json_parser.h | 2 + ext/json/php_json_scanner.h | 1 + ext/json/tests/json_validate_002.phpt | 20 +++++----- 6 files changed, 86 insertions(+), 14 deletions(-) diff --git a/ext/json/json.c b/ext/json/json.c index bcb7cc189fac3..c6538d9332325 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -159,10 +159,8 @@ static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{ return "Control character error, possibly incorrectly encoded"; case PHP_JSON_ERROR_SYNTAX: char *msg; - spprintf(&msg, 0, "Syntax error at character %zu", JSON_G(error_pos)); + spprintf(&msg, 0, "Syntax error near character %zu", JSON_G(error_pos)); return msg; - //efree(msg); - //return "Syntax error"; case PHP_JSON_ERROR_UTF8: return "Malformed UTF-8 characters, possibly incorrectly encoded"; case PHP_JSON_ERROR_RECURSION: diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y index 807b5488fe927..c18aef155a4d3 100644 --- a/ext/json/json_parser.y +++ b/ext/json/json_parser.y @@ -35,6 +35,7 @@ int json_yydebug = 1; #define PHP_JSON_DEPTH_INC \ if (parser->max_depth && parser->depth >= parser->max_depth) { \ parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \ + parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ YYERROR; \ } \ ++parser->depth @@ -108,6 +109,7 @@ object_end: | ']' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; + parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ YYERROR; } ; @@ -164,6 +166,7 @@ array_end: | '}' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; + parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ YYERROR; } ; @@ -242,6 +245,7 @@ static int php_json_parser_object_update(php_json_parser *parser, zval *object, } else { if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') { parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME; + parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ zend_string_release_ex(key, 0); zval_ptr_dtor_nogc(zvalue); zval_ptr_dtor_nogc(object); @@ -300,7 +304,9 @@ static void php_json_yyerror(php_json_parser *parser, char const *msg) { if (!parser->scanner.errcode) { parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; - parser->scanner.errpos = (size_t)(parser->scanner.cursor - parser->scanner.str_start); + parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); + fprintf(stderr, "End of input: errpos=%zu, cursor=%p, str_start=%p\n", parser->scanner.errpos, parser->scanner.cursor, parser->scanner.str_start); + //parser->scanner.errpos = (size_t)(parser->scanner.cursor - parser->scanner.str_start); } } @@ -346,12 +352,20 @@ PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser, int max_depth, const php_json_parser_methods *parser_methods) { + memset(parser, 0, sizeof(php_json_parser)); php_json_scanner_init(&parser->scanner, str, str_len, options); parser->depth = 1; parser->max_depth = max_depth; parser->return_value = return_value; memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods)); + + if (!str || str_len == 0) { + parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; + parser->scanner.errpos = 0; + } + + fprintf(stderr, "Init: str_start=%p, cursor=%p, limit=%p, str_len=%zu\n", parser->scanner.str_start, parser->scanner.cursor, parser->scanner.limit, str_len); } PHP_JSON_API void php_json_parser_init(php_json_parser *parser, diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re index 0debb3b03cb22..852162065d273 100644 --- a/ext/json/json_scanner.re +++ b/ext/json/json_scanner.re @@ -93,9 +93,24 @@ static int php_json_ucs2_to_int(php_json_scanner *s, int size) void php_json_scanner_init(php_json_scanner *s, const char *str, size_t str_len, int options) { + s->token = NULL; + s->marker = NULL; + s->ctxmarker = NULL; + s->pstr = NULL; + s->str_esc = 0; + s->state = 0; + s->errcode = PHP_JSON_ERROR_NONE; + s->errpos = 0; /* Initialize errpos */ + s->utf8_invalid = 0; + s->utf8_invalid_count = 0; + s->str_start = (php_json_ctype *)str; /* Initialize str_start */ + s->input_start = (php_json_ctype *)str; /* Initialize str_start */ + s->cursor = (php_json_ctype *) str; s->limit = (php_json_ctype *) str + str_len; s->options = options; + s->errpos = 0; + s->errcode = 0; PHP_JSON_CONDITION_SET(JS); } @@ -106,6 +121,29 @@ int php_json_scan(php_json_scanner *s) std: s->token = s->cursor; + fprintf(stderr, "Scan: START=%p \n cursor=%p \n token=%p \n str_start=%p \n limit=%p \n value_START='%.*s' \n value_token='%.*s' \n value_cursor='%.*s' \n value_str_start='%.*s' \n", + s->input_start, + s->cursor, + s->token, + s->str_start, + s->limit, + (int)(s->limit - s->input_start), + s->input_start, + (int)(s->limit - s->token), + s->token, + (int)(s->limit - s->cursor), + s->cursor, + (int)(s->limit - s->str_start), + s->str_start + ); + + if (s->cursor >= s->limit) { + s->errcode = PHP_JSON_ERROR_SYNTAX; + s->errpos = (size_t)(s->str_start - s->input_start); + fprintf(stderr, "End of input: errpos=%zu, cursor=%p, str_start=%p\n", s->errpos, s->cursor, s->str_start); + return PHP_JSON_T_ERROR; + } + /*!re2c re2c:indent:top = 1; re2c:yyfill:enable = 0; @@ -201,6 +239,7 @@ std: return PHP_JSON_T_EOI; } else { s->errcode = PHP_JSON_ERROR_CTRL_CHAR; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } } @@ -213,19 +252,25 @@ std: } CTRL { s->errcode = PHP_JSON_ERROR_CTRL_CHAR; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } UTF8 { s->errcode = PHP_JSON_ERROR_SYNTAX; + s->errpos = (size_t)(s->str_start - s->input_start); + fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", + s->errpos, s->cursor, s->str_start); return PHP_JSON_T_ERROR; } ANY { s->errcode = PHP_JSON_ERROR_UTF8; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } CTRL { s->errcode = PHP_JSON_ERROR_CTRL_CHAR; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } UTF16_1 { @@ -246,6 +291,7 @@ std: } UCS2 { s->errcode = PHP_JSON_ERROR_UTF16; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } ESC { @@ -254,6 +300,9 @@ std: } ESCPREF { s->errcode = PHP_JSON_ERROR_SYNTAX; + s->errpos = (size_t)(s->str_start - s->input_start); + fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", + s->errpos, s->cursor, s->str_start); return PHP_JSON_T_ERROR; } ["] { @@ -283,6 +332,7 @@ std: if (s->options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) { if (s->utf8_invalid_count > INT_MAX - 2) { s->errcode = PHP_JSON_ERROR_UTF8; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } s->utf8_invalid_count += 2; @@ -293,6 +343,7 @@ std: PHP_JSON_CONDITION_GOTO(STR_P1); } s->errcode = PHP_JSON_ERROR_UTF8; + s->errpos = (size_t)(s->str_start - s->input_start); return PHP_JSON_T_ERROR; } @@ -358,6 +409,9 @@ std: break; default: s->errcode = PHP_JSON_ERROR_SYNTAX; + s->errpos = (size_t)(s->str_start - s->input_start); + fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", + s->errpos, s->cursor, s->str_start); return PHP_JSON_T_ERROR; } *(s->pstr++) = esc; @@ -386,6 +440,9 @@ std: <*>ANY { s->errcode = PHP_JSON_ERROR_SYNTAX; + s->errpos = (size_t)(s->str_start - s->input_start); + fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", + s->errpos, s->cursor, s->str_start); return PHP_JSON_T_ERROR; } */ diff --git a/ext/json/php_json_parser.h b/ext/json/php_json_parser.h index 8aedce9ac55d6..df375a29f1735 100644 --- a/ext/json/php_json_parser.h +++ b/ext/json/php_json_parser.h @@ -77,6 +77,8 @@ PHP_JSON_API void php_json_parser_init( PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser); +PHP_JSON_API size_t php_json_parser_error_pos(const php_json_parser *parser); + PHP_JSON_API int php_json_parse(php_json_parser *parser); int php_json_yyparse(php_json_parser *parser); diff --git a/ext/json/php_json_scanner.h b/ext/json/php_json_scanner.h index 72f02f2cb0781..8ec3b703a4fc4 100644 --- a/ext/json/php_json_scanner.h +++ b/ext/json/php_json_scanner.h @@ -29,6 +29,7 @@ typedef struct _php_json_scanner { php_json_ctype *marker; /* marker position for backtracking */ php_json_ctype *ctxmarker; /* marker position for context backtracking */ php_json_ctype *str_start; /* start position of the string */ + php_json_ctype *input_start; /* start position of the string */ php_json_ctype *pstr; /* string pointer for escapes conversion */ zval value; /* value */ int str_esc; /* number of extra characters for escaping */ diff --git a/ext/json/tests/json_validate_002.phpt b/ext/json/tests/json_validate_002.phpt index d8b3e4a3f1770..410449444fff4 100644 --- a/ext/json/tests/json_validate_002.phpt +++ b/ext/json/tests/json_validate_002.phpt @@ -5,17 +5,17 @@ json_validate() - Error handling require_once("json_validate_requires.inc"); -json_validate_trycatchdump(""); -json_validate_trycatchdump("-"); -json_validate_trycatchdump("", -1); +//json_validate_trycatchdump(""); +//json_validate_trycatchdump("-"); +//json_validate_trycatchdump("", -1); json_validate_trycatchdump('{"key1":"value1", "value2"}', 2); -json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 1); -json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 2); -json_validate_trycatchdump("-", 0); -json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING); -json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING | JSON_INVALID_UTF8_IGNORE); -json_validate_trycatchdump("-", 512, JSON_INVALID_UTF8_IGNORE); -json_validate_trycatchdump("{}", 512, JSON_INVALID_UTF8_IGNORE); +//json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 1); +//json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 2); +//json_validate_trycatchdump("-", 0); +//json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING); +//json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING | JSON_INVALID_UTF8_IGNORE); +//json_validate_trycatchdump("-", 512, JSON_INVALID_UTF8_IGNORE); +//json_validate_trycatchdump("{}", 512, JSON_INVALID_UTF8_IGNORE); ?> --EXPECTF-- From b4343011829a44af918d764a322bcdf950583030 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Mon, 9 Jun 2025 23:34:35 -0300 Subject: [PATCH 03/12] memory leak fixed with old school --- ext/json/json.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/json/json.c b/ext/json/json.c index c6538d9332325..d125cc98ec310 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -375,6 +375,11 @@ PHP_FUNCTION(json_last_error_msg) { ZEND_PARSE_PARAMETERS_NONE(); - RETURN_STRING(php_json_get_error_msg(JSON_G(error_code))); + char *msg = php_json_get_error_msg(JSON_G(error_code)); + RETVAL_STRING(msg); + if (JSON_G(error_code) == PHP_JSON_ERROR_SYNTAX) { + efree(msg); + } + //original:RETURN_STRING(php_json_get_error_msg(JSON_G(error_code))); } /* }}} */ From 73a671edbe7e2f11e42c5ed19fbea824e40187e0 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Wed, 11 Jun 2025 22:38:11 -0300 Subject: [PATCH 04/12] POC --- ext/json/json.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/json/json.c b/ext/json/json.c index d125cc98ec310..1f53b25a92d63 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -158,9 +158,7 @@ static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{ case PHP_JSON_ERROR_CTRL_CHAR: return "Control character error, possibly incorrectly encoded"; case PHP_JSON_ERROR_SYNTAX: - char *msg; - spprintf(&msg, 0, "Syntax error near character %zu", JSON_G(error_pos)); - return msg; + return "Syntax error"; case PHP_JSON_ERROR_UTF8: return "Malformed UTF-8 characters, possibly incorrectly encoded"; case PHP_JSON_ERROR_RECURSION: @@ -375,11 +373,13 @@ PHP_FUNCTION(json_last_error_msg) { ZEND_PARSE_PARAMETERS_NONE(); - char *msg = php_json_get_error_msg(JSON_G(error_code)); - RETVAL_STRING(msg); if (JSON_G(error_code) == PHP_JSON_ERROR_SYNTAX) { - efree(msg); - } - //original:RETURN_STRING(php_json_get_error_msg(JSON_G(error_code))); + char *msg; + spprintf(&msg, 0, "Syntax error near character %zu", JSON_G(error_pos)); + RETVAL_STRING(msg); + efree(msg); + } else { + RETURN_STRING(php_json_get_error_msg(JSON_G(error_code))); + } } /* }}} */ From 34439b8d92f9d7b11bbc73b25e456329dda0344b Mon Sep 17 00:00:00 2001 From: juan-morales Date: Thu, 12 Jun 2025 21:17:14 -0300 Subject: [PATCH 05/12] poc tests passed for json ext --- ext/json/json.c | 34 +++++++++++++++++----- ext/json/json_parser.y | 9 ------ ext/json/json_scanner.re | 33 ++++----------------- ext/json/tests/007.phpt | 4 +-- ext/json/tests/bug54058.phpt | 8 ++--- ext/json/tests/bug61537.phpt | 8 ++--- ext/json/tests/bug62010.phpt | 2 +- ext/json/tests/bug68546.phpt | 2 +- ext/json/tests/json_encode_exceptions.phpt | 10 +++---- ext/json/tests/json_validate_002.phpt | 31 +++++++++++--------- ext/json/tests/json_validate_004.phpt | 8 ++--- ext/json/tests/unsupported_type_error.phpt | 6 ++-- 12 files changed, 73 insertions(+), 82 deletions(-) diff --git a/ext/json/json.c b/ext/json/json.c index 1f53b25a92d63..e57f1b193e5a1 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -179,6 +179,29 @@ static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{ } /* }}} */ + +char *php_json_get_error_msg_wrapper(php_json_error_code error_code) /* {{{ */ +{ + char *final_message; + const char *error_message = php_json_get_error_msg(error_code); + + switch(error_code) { + case PHP_JSON_ERROR_SYNTAX: + case PHP_JSON_ERROR_UTF8: + case PHP_JSON_ERROR_CTRL_CHAR: + case PHP_JSON_ERROR_UNSUPPORTED_TYPE: + case PHP_JSON_ERROR_INVALID_PROPERTY_NAME: + case PHP_JSON_ERROR_UTF16: + spprintf(&final_message, 0, "%s near character %zu",error_message, JSON_G(error_pos)); + break; + default: + spprintf(&final_message, 0, "%s", error_message); + } + + return final_message; +} +/* }}} */ + PHP_JSON_API zend_result php_json_decode_ex(zval *return_value, const char *str, size_t str_len, zend_long options, zend_long depth) /* {{{ */ { php_json_parser parser; @@ -373,13 +396,8 @@ PHP_FUNCTION(json_last_error_msg) { ZEND_PARSE_PARAMETERS_NONE(); - if (JSON_G(error_code) == PHP_JSON_ERROR_SYNTAX) { - char *msg; - spprintf(&msg, 0, "Syntax error near character %zu", JSON_G(error_pos)); - RETVAL_STRING(msg); - efree(msg); - } else { - RETURN_STRING(php_json_get_error_msg(JSON_G(error_code))); - } + char *msg = php_json_get_error_msg_wrapper(JSON_G(error_code)); + RETVAL_STRING(msg); + efree(msg); } /* }}} */ diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y index c18aef155a4d3..f483841873fe2 100644 --- a/ext/json/json_parser.y +++ b/ext/json/json_parser.y @@ -305,8 +305,6 @@ static void php_json_yyerror(php_json_parser *parser, char const *msg) if (!parser->scanner.errcode) { parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); - fprintf(stderr, "End of input: errpos=%zu, cursor=%p, str_start=%p\n", parser->scanner.errpos, parser->scanner.cursor, parser->scanner.str_start); - //parser->scanner.errpos = (size_t)(parser->scanner.cursor - parser->scanner.str_start); } } @@ -359,13 +357,6 @@ PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser, parser->max_depth = max_depth; parser->return_value = return_value; memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods)); - - if (!str || str_len == 0) { - parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; - parser->scanner.errpos = 0; - } - - fprintf(stderr, "Init: str_start=%p, cursor=%p, limit=%p, str_len=%zu\n", parser->scanner.str_start, parser->scanner.cursor, parser->scanner.limit, str_len); } PHP_JSON_API void php_json_parser_init(php_json_parser *parser, diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re index 852162065d273..8585bad38c8df 100644 --- a/ext/json/json_scanner.re +++ b/ext/json/json_scanner.re @@ -121,28 +121,11 @@ int php_json_scan(php_json_scanner *s) std: s->token = s->cursor; - fprintf(stderr, "Scan: START=%p \n cursor=%p \n token=%p \n str_start=%p \n limit=%p \n value_START='%.*s' \n value_token='%.*s' \n value_cursor='%.*s' \n value_str_start='%.*s' \n", - s->input_start, - s->cursor, - s->token, - s->str_start, - s->limit, - (int)(s->limit - s->input_start), - s->input_start, - (int)(s->limit - s->token), - s->token, - (int)(s->limit - s->cursor), - s->cursor, - (int)(s->limit - s->str_start), - s->str_start - ); - - if (s->cursor >= s->limit) { + /*if (s->cursor >= s->limit) { s->errcode = PHP_JSON_ERROR_SYNTAX; s->errpos = (size_t)(s->str_start - s->input_start); - fprintf(stderr, "End of input: errpos=%zu, cursor=%p, str_start=%p\n", s->errpos, s->cursor, s->str_start); return PHP_JSON_T_ERROR; - } + }*/ /*!re2c re2c:indent:top = 1; @@ -258,8 +241,7 @@ std: UTF8 { s->errcode = PHP_JSON_ERROR_SYNTAX; s->errpos = (size_t)(s->str_start - s->input_start); - fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", - s->errpos, s->cursor, s->str_start); + return PHP_JSON_T_ERROR; } ANY { @@ -301,8 +283,7 @@ std: ESCPREF { s->errcode = PHP_JSON_ERROR_SYNTAX; s->errpos = (size_t)(s->str_start - s->input_start); - fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", - s->errpos, s->cursor, s->str_start); + return PHP_JSON_T_ERROR; } ["] { @@ -410,8 +391,7 @@ std: default: s->errcode = PHP_JSON_ERROR_SYNTAX; s->errpos = (size_t)(s->str_start - s->input_start); - fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", - s->errpos, s->cursor, s->str_start); + return PHP_JSON_T_ERROR; } *(s->pstr++) = esc; @@ -441,8 +421,7 @@ std: <*>ANY { s->errcode = PHP_JSON_ERROR_SYNTAX; s->errpos = (size_t)(s->str_start - s->input_start); - fprintf(stderr, "Syntax error: errpos=%zu, cursor=%p, str_start=%p\n", - s->errpos, s->cursor, s->str_start); + return PHP_JSON_T_ERROR; } */ diff --git a/ext/json/tests/007.phpt b/ext/json/tests/007.phpt index dea641317e97f..44eb10a864485 100644 --- a/ext/json/tests/007.phpt +++ b/ext/json/tests/007.phpt @@ -30,8 +30,8 @@ int(2) string(42) "State mismatch (invalid or malformed JSON)" NULL int(3) -string(53) "Control character error, possibly incorrectly encoded" +string(70) "Control character error, possibly incorrectly encoded near character 2" NULL int(4) -string(12) "Syntax error" +string(29) "Syntax error near character 0" Done diff --git a/ext/json/tests/bug54058.phpt b/ext/json/tests/bug54058.phpt index 25c5b6f5ceba7..48e21792a5ca1 100644 --- a/ext/json/tests/bug54058.phpt +++ b/ext/json/tests/bug54058.phpt @@ -29,10 +29,10 @@ var_dump(json_last_error(), json_last_error_msg()); ?> --EXPECT-- int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" diff --git a/ext/json/tests/bug61537.phpt b/ext/json/tests/bug61537.phpt index 32cae8c93dc26..cb8e65955926a 100644 --- a/ext/json/tests/bug61537.phpt +++ b/ext/json/tests/bug61537.phpt @@ -24,14 +24,14 @@ var_dump(json_last_error(), json_last_error_msg()); --EXPECT-- bool(false) int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" string(4) "null" int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" bool(false) int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" string(4) "null" int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" diff --git a/ext/json/tests/bug62010.phpt b/ext/json/tests/bug62010.phpt index 2591231dcdda1..10b0dd4daec18 100644 --- a/ext/json/tests/bug62010.phpt +++ b/ext/json/tests/bug62010.phpt @@ -10,4 +10,4 @@ var_dump(json_last_error_msg()); --EXPECT-- NULL bool(true) -string(50) "Single unpaired UTF-16 surrogate in unicode escape" +string(67) "Single unpaired UTF-16 surrogate in unicode escape near character 1" diff --git a/ext/json/tests/bug68546.phpt b/ext/json/tests/bug68546.phpt index 8835a72c5eac7..1ba57ba523056 100644 --- a/ext/json/tests/bug68546.phpt +++ b/ext/json/tests/bug68546.phpt @@ -16,5 +16,5 @@ NULL bool(true) NULL bool(true) -string(36) "The decoded property name is invalid" +string(54) "The decoded property name is invalid near character 20" Done diff --git a/ext/json/tests/json_encode_exceptions.phpt b/ext/json/tests/json_encode_exceptions.phpt index 2ca7ad4452d72..a0dd6c52680ac 100644 --- a/ext/json/tests/json_encode_exceptions.phpt +++ b/ext/json/tests/json_encode_exceptions.phpt @@ -26,17 +26,17 @@ object(JsonException)#1 (7) { ["code":protected]=> int(5) ["file":protected]=> - string(%d) "%s" + string(67) "/home/usuario/dev/php-src/ext/json/tests/json_encode_exceptions.php" ["line":protected]=> - int(%d) + int(4) ["trace":"Exception":private]=> array(1) { [0]=> array(4) { ["file"]=> - string(%d) "%s" + string(67) "/home/usuario/dev/php-src/ext/json/tests/json_encode_exceptions.php" ["line"]=> - int(%d) + int(4) ["function"]=> string(11) "json_encode" ["args"]=> @@ -53,4 +53,4 @@ object(JsonException)#1 (7) { } string(4) "null" int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 0" diff --git a/ext/json/tests/json_validate_002.phpt b/ext/json/tests/json_validate_002.phpt index 410449444fff4..9d514070a4ec0 100644 --- a/ext/json/tests/json_validate_002.phpt +++ b/ext/json/tests/json_validate_002.phpt @@ -5,29 +5,32 @@ json_validate() - Error handling require_once("json_validate_requires.inc"); -//json_validate_trycatchdump(""); -//json_validate_trycatchdump("-"); -//json_validate_trycatchdump("", -1); +json_validate_trycatchdump(""); +json_validate_trycatchdump("-"); +json_validate_trycatchdump("", -1); json_validate_trycatchdump('{"key1":"value1", "value2"}', 2); -//json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 1); -//json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 2); -//json_validate_trycatchdump("-", 0); -//json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING); -//json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING | JSON_INVALID_UTF8_IGNORE); -//json_validate_trycatchdump("-", 512, JSON_INVALID_UTF8_IGNORE); -//json_validate_trycatchdump("{}", 512, JSON_INVALID_UTF8_IGNORE); +json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 1); +json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 2); +json_validate_trycatchdump("-", 0); +json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING); +json_validate_trycatchdump("-", 512, JSON_BIGINT_AS_STRING | JSON_INVALID_UTF8_IGNORE); +json_validate_trycatchdump("-", 512, JSON_INVALID_UTF8_IGNORE); +json_validate_trycatchdump("{}", 512, JSON_INVALID_UTF8_IGNORE); ?> --EXPECTF-- bool(false) int(4) -string(12) "Syntax error" +string(29) "Syntax error near character 0" bool(false) int(4) -string(12) "Syntax error" +string(29) "Syntax error near character 0" bool(false) int(4) -string(12) "Syntax error" +string(29) "Syntax error near character 0" +bool(false) +int(4) +string(30) "Syntax error near character 19" bool(false) int(1) string(28) "Maximum stack depth exceeded" @@ -45,7 +48,7 @@ int(0) string(8) "No error" bool(false) int(4) -string(12) "Syntax error" +string(29) "Syntax error near character 0" bool(true) int(0) string(8) "No error" diff --git a/ext/json/tests/json_validate_004.phpt b/ext/json/tests/json_validate_004.phpt index d8a798d943278..6bf5720583f1c 100644 --- a/ext/json/tests/json_validate_004.phpt +++ b/ext/json/tests/json_validate_004.phpt @@ -23,16 +23,16 @@ json_validate_trycatchdump("[\"\xc1\xc1\",\"a\"]", 512, JSON_INVALID_UTF8_IGNORE Testing Invalid UTF-8 bool(false) int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 1" bool(false) int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 1" bool(false) int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 1" bool(false) int(5) -string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" +string(73) "Malformed UTF-8 characters, possibly incorrectly encoded near character 2" bool(true) int(0) string(8) "No error" diff --git a/ext/json/tests/unsupported_type_error.phpt b/ext/json/tests/unsupported_type_error.phpt index 449d423fd9d0c..507a842fd4497 100644 --- a/ext/json/tests/unsupported_type_error.phpt +++ b/ext/json/tests/unsupported_type_error.phpt @@ -15,10 +15,10 @@ var_dump(json_last_error(), json_last_error_msg()); ?> --EXPECTF-- -resource(%d) of type (stream) +resource(5) of type (stream) bool(false) int(8) -string(21) "Type is not supported" +string(38) "Type is not supported near character 0" string(4) "null" int(8) -string(21) "Type is not supported" +string(38) "Type is not supported near character 0" From a0764f309a749776f603d74114feb7abeb3f482f Mon Sep 17 00:00:00 2001 From: juan-morales Date: Mon, 16 Jun 2025 13:21:24 -0300 Subject: [PATCH 06/12] some cleanup --- ext/json/json_scanner.re | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re index 8585bad38c8df..fa06444ea33e8 100644 --- a/ext/json/json_scanner.re +++ b/ext/json/json_scanner.re @@ -104,7 +104,7 @@ void php_json_scanner_init(php_json_scanner *s, const char *str, size_t str_len, s->utf8_invalid = 0; s->utf8_invalid_count = 0; s->str_start = (php_json_ctype *)str; /* Initialize str_start */ - s->input_start = (php_json_ctype *)str; /* Initialize str_start */ + s->input_start = (php_json_ctype *)str; /* Initialize input_start */ s->cursor = (php_json_ctype *) str; s->limit = (php_json_ctype *) str + str_len; @@ -121,12 +121,6 @@ int php_json_scan(php_json_scanner *s) std: s->token = s->cursor; - /*if (s->cursor >= s->limit) { - s->errcode = PHP_JSON_ERROR_SYNTAX; - s->errpos = (size_t)(s->str_start - s->input_start); - return PHP_JSON_T_ERROR; - }*/ - /*!re2c re2c:indent:top = 1; re2c:yyfill:enable = 0; From 0593c4773d9c9f40b461b18d316759f33d311be6 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Mon, 16 Jun 2025 16:44:54 -0300 Subject: [PATCH 07/12] comments in php_json_scanner.h --- ext/json/php_json_scanner.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/json/php_json_scanner.h b/ext/json/php_json_scanner.h index 8ec3b703a4fc4..7acd8f5b66ce6 100644 --- a/ext/json/php_json_scanner.h +++ b/ext/json/php_json_scanner.h @@ -29,14 +29,14 @@ typedef struct _php_json_scanner { php_json_ctype *marker; /* marker position for backtracking */ php_json_ctype *ctxmarker; /* marker position for context backtracking */ php_json_ctype *str_start; /* start position of the string */ - php_json_ctype *input_start; /* start position of the string */ + php_json_ctype *input_start; /* start position of the string */ php_json_ctype *pstr; /* string pointer for escapes conversion */ zval value; /* value */ int str_esc; /* number of extra characters for escaping */ int state; /* condition state */ int options; /* options */ php_json_error_code errcode; /* error type if there is an error */ - size_t errpos; + size_t errpos; /* holds the aprox character number when an error occurs */ int utf8_invalid; /* whether utf8 is invalid */ int utf8_invalid_count; /* number of extra character for invalid utf8 */ } php_json_scanner; From f4f5e08b61e7d97dfce07fcdb8789a596e5616ba Mon Sep 17 00:00:00 2001 From: juan-morales Date: Mon, 16 Jun 2025 18:25:31 -0300 Subject: [PATCH 08/12] better position calculation --- ext/json/json_parser.y | 10 +++++----- ext/json/json_scanner.re | 23 +++++++++++------------ ext/json/tests/bug68546.phpt | 2 +- ext/json/tests/json_validate_002.phpt | 8 ++++++++ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y index f483841873fe2..7bb0a82f78a6a 100644 --- a/ext/json/json_parser.y +++ b/ext/json/json_parser.y @@ -35,7 +35,7 @@ int json_yydebug = 1; #define PHP_JSON_DEPTH_INC \ if (parser->max_depth && parser->depth >= parser->max_depth) { \ parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \ - parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ + parser->scanner.errpos = (size_t)((parser->scanner.str_start - parser->scanner.input_start) - parser->scanner.str_esc - parser->scanner.utf8_invalid_count); \ YYERROR; \ } \ ++parser->depth @@ -109,7 +109,7 @@ object_end: | ']' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; - parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ + parser->scanner.errpos = (size_t)((parser->scanner.str_start - parser->scanner.input_start) - parser->scanner.str_esc - parser->scanner.utf8_invalid_count); \ YYERROR; } ; @@ -166,7 +166,7 @@ array_end: | '}' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; - parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ + parser->scanner.errpos = (size_t)((parser->scanner.str_start - parser->scanner.input_start) - parser->scanner.str_esc - parser->scanner.utf8_invalid_count); \ YYERROR; } ; @@ -245,7 +245,7 @@ static int php_json_parser_object_update(php_json_parser *parser, zval *object, } else { if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') { parser->scanner.errcode = PHP_JSON_ERROR_INVALID_PROPERTY_NAME; - parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); \ + parser->scanner.errpos = (size_t)((parser->scanner.str_start - parser->scanner.input_start) - parser->scanner.str_esc - parser->scanner.utf8_invalid_count); \ zend_string_release_ex(key, 0); zval_ptr_dtor_nogc(zvalue); zval_ptr_dtor_nogc(object); @@ -304,7 +304,7 @@ static void php_json_yyerror(php_json_parser *parser, char const *msg) { if (!parser->scanner.errcode) { parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; - parser->scanner.errpos = (size_t)(parser->scanner.str_start - parser->scanner.input_start); + parser->scanner.errpos = (size_t)((parser->scanner.str_start - parser->scanner.input_start) - parser->scanner.str_esc - parser->scanner.utf8_invalid_count); } } diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re index fa06444ea33e8..6625506826d43 100644 --- a/ext/json/json_scanner.re +++ b/ext/json/json_scanner.re @@ -216,7 +216,7 @@ std: return PHP_JSON_T_EOI; } else { s->errcode = PHP_JSON_ERROR_CTRL_CHAR; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } } @@ -229,24 +229,23 @@ std: } CTRL { s->errcode = PHP_JSON_ERROR_CTRL_CHAR; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } UTF8 { s->errcode = PHP_JSON_ERROR_SYNTAX; - s->errpos = (size_t)(s->str_start - s->input_start); - + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } ANY { s->errcode = PHP_JSON_ERROR_UTF8; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } CTRL { s->errcode = PHP_JSON_ERROR_CTRL_CHAR; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } UTF16_1 { @@ -267,7 +266,7 @@ std: } UCS2 { s->errcode = PHP_JSON_ERROR_UTF16; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } ESC { @@ -276,7 +275,7 @@ std: } ESCPREF { s->errcode = PHP_JSON_ERROR_SYNTAX; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } @@ -307,7 +306,7 @@ std: if (s->options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) { if (s->utf8_invalid_count > INT_MAX - 2) { s->errcode = PHP_JSON_ERROR_UTF8; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } s->utf8_invalid_count += 2; @@ -318,7 +317,7 @@ std: PHP_JSON_CONDITION_GOTO(STR_P1); } s->errcode = PHP_JSON_ERROR_UTF8; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } @@ -384,7 +383,7 @@ std: break; default: s->errcode = PHP_JSON_ERROR_SYNTAX; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } @@ -414,7 +413,7 @@ std: <*>ANY { s->errcode = PHP_JSON_ERROR_SYNTAX; - s->errpos = (size_t)(s->str_start - s->input_start); + s->errpos = (size_t)(s->str_start - s->input_start - s->str_esc - s->utf8_invalid_count); return PHP_JSON_T_ERROR; } diff --git a/ext/json/tests/bug68546.phpt b/ext/json/tests/bug68546.phpt index 1ba57ba523056..4c4aff7e5dda5 100644 --- a/ext/json/tests/bug68546.phpt +++ b/ext/json/tests/bug68546.phpt @@ -16,5 +16,5 @@ NULL bool(true) NULL bool(true) -string(54) "The decoded property name is invalid near character 20" +string(54) "The decoded property name is invalid near character 15" Done diff --git a/ext/json/tests/json_validate_002.phpt b/ext/json/tests/json_validate_002.phpt index 9d514070a4ec0..e7e4b78693e39 100644 --- a/ext/json/tests/json_validate_002.phpt +++ b/ext/json/tests/json_validate_002.phpt @@ -9,6 +9,8 @@ json_validate_trycatchdump(""); json_validate_trycatchdump("-"); json_validate_trycatchdump("", -1); json_validate_trycatchdump('{"key1":"value1", "value2"}', 2); +json_validate_trycatchdump('{"text":"Hello \u20AC World", "key1":"Hello \xE2\x28 World"}', 2); +json_validate_trycatchdump('{"text":"Hello \u20AC World"}', 2); json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 1); json_validate_trycatchdump('{"key1":"value1", "key2":"value2"}', 2); json_validate_trycatchdump("-", 0); @@ -32,6 +34,12 @@ bool(false) int(4) string(30) "Syntax error near character 19" bool(false) +int(4) +string(30) "Syntax error near character 38" +bool(true) +int(0) +string(8) "No error" +bool(false) int(1) string(28) "Maximum stack depth exceeded" bool(true) From 765d57490b4b3fdd4f6223f1878144e17c4dbc31 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Tue, 17 Jun 2025 06:59:54 -0300 Subject: [PATCH 09/12] fix test json_encode_exceptions.phpt --- ext/json/tests/json_encode_exceptions.phpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/json/tests/json_encode_exceptions.phpt b/ext/json/tests/json_encode_exceptions.phpt index a0dd6c52680ac..5d6515cddc49b 100644 --- a/ext/json/tests/json_encode_exceptions.phpt +++ b/ext/json/tests/json_encode_exceptions.phpt @@ -26,17 +26,17 @@ object(JsonException)#1 (7) { ["code":protected]=> int(5) ["file":protected]=> - string(67) "/home/usuario/dev/php-src/ext/json/tests/json_encode_exceptions.php" + string(%d) "%s" ["line":protected]=> - int(4) + int(%d) ["trace":"Exception":private]=> array(1) { [0]=> array(4) { ["file"]=> - string(67) "/home/usuario/dev/php-src/ext/json/tests/json_encode_exceptions.php" + string(%d) "%s" ["line"]=> - int(4) + int(%d) ["function"]=> string(11) "json_encode" ["args"]=> From eb6400cc568e73fbef144e9962493fac52190948 Mon Sep 17 00:00:00 2001 From: Juan Morales Date: Fri, 20 Jun 2025 08:32:25 -0300 Subject: [PATCH 10/12] Update ext/json/json.c - style - missing space Co-authored-by: DanielEScherzer --- ext/json/json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/json/json.c b/ext/json/json.c index e57f1b193e5a1..9da7a3918a043 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -192,7 +192,7 @@ char *php_json_get_error_msg_wrapper(php_json_error_code error_code) /* {{{ */ case PHP_JSON_ERROR_UNSUPPORTED_TYPE: case PHP_JSON_ERROR_INVALID_PROPERTY_NAME: case PHP_JSON_ERROR_UTF16: - spprintf(&final_message, 0, "%s near character %zu",error_message, JSON_G(error_pos)); + spprintf(&final_message, 0, "%s near character %zu", error_message, JSON_G(error_pos)); break; default: spprintf(&final_message, 0, "%s", error_message); From 7255a81f5004703e6517b374b8cd98994118dc80 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Fri, 20 Jun 2025 08:36:14 -0300 Subject: [PATCH 11/12] code style fixes --- ext/json/json_parser.y | 3 +-- ext/json/php_json_scanner.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y index 7bb0a82f78a6a..87a0f6d5455d8 100644 --- a/ext/json/json_parser.y +++ b/ext/json/json_parser.y @@ -349,8 +349,7 @@ PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser, int options, int max_depth, const php_json_parser_methods *parser_methods) -{ - +{ memset(parser, 0, sizeof(php_json_parser)); php_json_scanner_init(&parser->scanner, str, str_len, options); parser->depth = 1; diff --git a/ext/json/php_json_scanner.h b/ext/json/php_json_scanner.h index 7acd8f5b66ce6..2ef2864359233 100644 --- a/ext/json/php_json_scanner.h +++ b/ext/json/php_json_scanner.h @@ -28,8 +28,8 @@ typedef struct _php_json_scanner { php_json_ctype *limit; /* the last read character + 1 position */ php_json_ctype *marker; /* marker position for backtracking */ php_json_ctype *ctxmarker; /* marker position for context backtracking */ - php_json_ctype *str_start; /* start position of the string */ - php_json_ctype *input_start; /* start position of the string */ + php_json_ctype *str_start; /* dynamic position of the string under analysis */ + php_json_ctype *input_start; /* fixed start position of the original string provided to the scanner */ php_json_ctype *pstr; /* string pointer for escapes conversion */ zval value; /* value */ int str_esc; /* number of extra characters for escaping */ From 0f3a191d2fc492273fab4a734adf48918991fbc2 Mon Sep 17 00:00:00 2001 From: juan-morales Date: Fri, 20 Jun 2025 08:37:40 -0300 Subject: [PATCH 12/12] style fix --- ext/json/php_json_encoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/json/php_json_encoder.h b/ext/json/php_json_encoder.h index ffae7434c44bd..9f4f0696d825d 100644 --- a/ext/json/php_json_encoder.h +++ b/ext/json/php_json_encoder.h @@ -26,7 +26,7 @@ struct _php_json_encoder { int depth; int max_depth; php_json_error_code error_code; - size_t error_pos; + size_t error_pos; }; static inline void php_json_encode_init(php_json_encoder *encoder)