Skip to content

json_last_error_msg - better message - error position near by #18866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Next Next commit
first setup
  • Loading branch information
juan-morales committed Jun 8, 2025
commit 70024b7f1bcb781d5633f2fee4c5dc3aef906625
15 changes: 14 additions & 1 deletion ext/json/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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:
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions ext/json/json_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions ext/json/php_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions ext/json/php_json_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions ext/json/php_json_scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions ext/json/tests/json_validate_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down