1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Json last error msg/error message with location error (#20629)

This slightly extend error messages with locations taken from scanner / parser
This commit is contained in:
Juan Morales
2026-01-03 14:34:19 -03:00
committed by GitHub
parent 46a1534e64
commit b80ffc5b2e
22 changed files with 1453 additions and 32 deletions

View File

@@ -63,6 +63,8 @@ static PHP_GINIT_FUNCTION(json)
#endif
json_globals->encoder_depth = 0;
json_globals->error_code = 0;
json_globals->error_line = 0;
json_globals->error_column = 0;
json_globals->encode_max_depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
}
/* }}} */
@@ -70,6 +72,8 @@ static PHP_GINIT_FUNCTION(json)
static PHP_RINIT_FUNCTION(json)
{
JSON_G(error_code) = 0;
JSON_G(error_line) = 0;
JSON_G(error_column) = 0;
return SUCCESS;
}
@@ -177,6 +181,18 @@ static const char *php_json_get_error_msg(php_json_error_code error_code) /* {{{
}
/* }}} */
static zend_string *php_json_get_error_msg_with_location(php_json_error_code error_code, size_t line, size_t column) /* {{{ */
{
const char *base_msg = php_json_get_error_msg(error_code);
if (line > 0 && column > 0) {
return zend_strpprintf(0, "%s near location %zu:%zu", base_msg, line, column);
}
return zend_string_init(base_msg, strlen(base_msg), 0);
}
/* }}} */
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;
@@ -185,10 +201,17 @@ 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_line = php_json_parser_error_line(&parser);
size_t error_column = php_json_parser_error_column(&parser);
if (!(options & PHP_JSON_THROW_ON_ERROR)) {
JSON_G(error_code) = error_code;
JSON_G(error_line) = error_line;
JSON_G(error_column) = error_column;
} else {
zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(error_code), error_code);
zend_string *error_msg = php_json_get_error_msg_with_location(error_code, error_line, error_column);
zend_throw_exception(php_json_exception_ce, ZSTR_VAL(error_msg), error_code);
zend_string_release(error_msg);
}
RETVAL_NULL();
return FAILURE;
@@ -208,7 +231,12 @@ 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_line = php_json_parser_error_line(&parser);
size_t error_column = php_json_parser_error_column(&parser);
JSON_G(error_code) = error_code;
JSON_G(error_line) = error_line;
JSON_G(error_column) = error_column;
return false;
}
@@ -274,11 +302,15 @@ PHP_FUNCTION(json_decode)
if (!(options & PHP_JSON_THROW_ON_ERROR)) {
JSON_G(error_code) = PHP_JSON_ERROR_NONE;
JSON_G(error_line) = 0;
JSON_G(error_column) = 0;
}
if (!str_len) {
if (!(options & PHP_JSON_THROW_ON_ERROR)) {
JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX;
JSON_G(error_line) = 0;
JSON_G(error_column) = 0;
} else {
zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(PHP_JSON_ERROR_SYNTAX), PHP_JSON_ERROR_SYNTAX);
}
@@ -331,10 +363,14 @@ PHP_FUNCTION(json_validate)
if (!str_len) {
JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX;
JSON_G(error_line) = 0;
JSON_G(error_column) = 0;
RETURN_FALSE;
}
JSON_G(error_code) = PHP_JSON_ERROR_NONE;
JSON_G(error_line) = 0;
JSON_G(error_column) = 0;
if (depth <= 0) {
zend_argument_value_error(2, "must be greater than 0");
@@ -364,6 +400,10 @@ PHP_FUNCTION(json_last_error_msg)
{
ZEND_PARSE_PARAMETERS_NONE();
RETURN_STRING(php_json_get_error_msg(JSON_G(error_code)));
RETVAL_STR(php_json_get_error_msg_with_location(
JSON_G(error_code),
JSON_G(error_line),
JSON_G(error_column)
));
}
/* }}} */

View File

@@ -41,6 +41,7 @@ int json_yydebug = 1;
}
%locations
%define api.prefix {php_json_yy}
%define api.pure full
%param { php_json_parser *parser }
@@ -49,7 +50,6 @@ int json_yydebug = 1;
zval value;
}
%token <value> PHP_JSON_T_NUL
%token <value> PHP_JSON_T_TRUE
%token <value> PHP_JSON_T_FALSE
@@ -66,8 +66,8 @@ int json_yydebug = 1;
%destructor { zval_ptr_dtor_nogc(&$$); } <value>
%code {
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
static void php_json_yyerror(php_json_parser *parser, char const *msg);
static int php_json_yylex(union YYSTYPE *value, YYLTYPE *location, php_json_parser *parser);
static void php_json_yyerror(YYLTYPE *location, php_json_parser *parser, char const *msg);
static int php_json_parser_array_create(php_json_parser *parser, zval *array);
static int php_json_parser_object_create(php_json_parser *parser, zval *array);
@@ -277,7 +277,7 @@ static int php_json_parser_object_update_validate(php_json_parser *parser, zval
return SUCCESS;
}
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
static int php_json_yylex(union YYSTYPE *value, YYLTYPE *location, php_json_parser *parser)
{
int token = php_json_scan(&parser->scanner);
@@ -293,10 +293,15 @@ static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
value->value = parser->scanner.value;
}
location->first_column = PHP_JSON_SCANNER_LOCATION(parser->scanner, first_column);
location->first_line = PHP_JSON_SCANNER_LOCATION(parser->scanner, first_line);
location->last_column = PHP_JSON_SCANNER_LOCATION(parser->scanner, last_column);
location->last_line = PHP_JSON_SCANNER_LOCATION(parser->scanner, last_line);
return token;
}
static void php_json_yyerror(php_json_parser *parser, char const *msg)
static void php_json_yyerror(YYLTYPE *location, php_json_parser *parser, char const *msg)
{
if (!parser->scanner.errcode) {
parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
@@ -308,6 +313,16 @@ 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_line(const php_json_parser *parser)
{
return parser->scanner.errloc.first_line;
}
PHP_JSON_API size_t php_json_parser_error_column(const php_json_parser *parser)
{
return parser->scanner.errloc.first_column;
}
static const php_json_parser_methods default_parser_methods =
{
php_json_parser_array_create,

View File

@@ -52,6 +52,8 @@
#define PHP_JSON_INT_MAX_LENGTH (MAX_LENGTH_OF_LONG - 1)
#define PHP_JSON_TOKEN_LENGTH() ((size_t) (s->cursor - s->token))
#define PHP_JSON_TOKEN_LOCATION(location) (s)->errloc.location
static void php_json_scanner_copy_string(php_json_scanner *s, size_t esc_size)
{
@@ -96,6 +98,10 @@ void php_json_scanner_init(php_json_scanner *s, const char *str, size_t str_len,
s->cursor = (php_json_ctype *) str;
s->limit = (php_json_ctype *) str + str_len;
s->options = options;
PHP_JSON_TOKEN_LOCATION(first_column) = 1;
PHP_JSON_TOKEN_LOCATION(first_line) = 1;
PHP_JSON_TOKEN_LOCATION(last_column) = 1;
PHP_JSON_TOKEN_LOCATION(last_line) = 1;
PHP_JSON_CONDITION_SET(JS);
}
@@ -104,6 +110,8 @@ int php_json_scan(php_json_scanner *s)
ZVAL_NULL(&s->value);
std:
PHP_JSON_TOKEN_LOCATION(first_column) = s->errloc.last_column;
PHP_JSON_TOKEN_LOCATION(first_line) = s->errloc.last_line;
s->token = s->cursor;
/*!re2c
@@ -149,27 +157,50 @@ std:
UTF16_3 = UTFPREF ( ( ( HEXC | [efEF] ) HEX ) | ( [dD] HEX7 ) ) HEX{2} ;
UTF16_4 = UTFPREF [dD] [89abAB] HEX{2} UTFPREF [dD] [c-fC-F] HEX{2} ;
<JS>"{" { return '{'; }
<JS>"}" { return '}'; }
<JS>"[" { return '['; }
<JS>"]" { return ']'; }
<JS>":" { return ':'; }
<JS>"," { return ','; }
<JS>"{" {
PHP_JSON_TOKEN_LOCATION(last_column)++;
return '{';
}
<JS>"}" {
PHP_JSON_TOKEN_LOCATION(last_column)++;
return '}';
}
<JS>"[" {
PHP_JSON_TOKEN_LOCATION(last_column)++;
return '[';
}
<JS>"]" {
PHP_JSON_TOKEN_LOCATION(last_column)++;
return ']';
}
<JS>":" {
PHP_JSON_TOKEN_LOCATION(last_column)++;
return ':';
}
<JS>"," {
PHP_JSON_TOKEN_LOCATION(last_column)++;
return ',';
}
<JS>"null" {
PHP_JSON_TOKEN_LOCATION(last_column) += 4;
ZVAL_NULL(&s->value);
return PHP_JSON_T_NUL;
}
<JS>"true" {
PHP_JSON_TOKEN_LOCATION(last_column) += 4;
ZVAL_TRUE(&s->value);
return PHP_JSON_T_TRUE;
}
<JS>"false" {
PHP_JSON_TOKEN_LOCATION(last_column) += 5;
ZVAL_FALSE(&s->value);
return PHP_JSON_T_FALSE;
}
<JS>INT {
bool bigint = 0, negative = s->token[0] == '-';
size_t digits = (size_t) (s->cursor - s->token - negative);
size_t digits = PHP_JSON_TOKEN_LENGTH();
PHP_JSON_TOKEN_LOCATION(last_column) += digits;
digits -= negative;
if (digits >= PHP_JSON_INT_MAX_LENGTH) {
if (digits == PHP_JSON_INT_MAX_LENGTH) {
int cmp = strncmp((char *) (s->token + negative), LONG_MIN_DIGITS, PHP_JSON_INT_MAX_LENGTH);
@@ -192,10 +223,19 @@ std:
}
}
<JS>FLOAT|EXP {
PHP_JSON_TOKEN_LOCATION(last_column) += PHP_JSON_TOKEN_LENGTH();
ZVAL_DOUBLE(&s->value, zend_strtod((char *) s->token, NULL));
return PHP_JSON_T_DOUBLE;
}
<JS>NL|WS { goto std; }
<JS>NL {
PHP_JSON_TOKEN_LOCATION(last_line)++;
PHP_JSON_TOKEN_LOCATION(last_column) = 1;
goto std;
}
<JS>WS {
PHP_JSON_TOKEN_LOCATION(last_column) += PHP_JSON_TOKEN_LENGTH();
goto std;
}
<JS>EOI {
if (s->limit < s->cursor) {
return PHP_JSON_T_EOI;
@@ -205,6 +245,7 @@ std:
}
}
<JS>["] {
PHP_JSON_TOKEN_LOCATION(last_column)++;
s->str_start = s->cursor;
s->str_esc = 0;
s->utf8_invalid = 0;
@@ -229,18 +270,22 @@ std:
return PHP_JSON_T_ERROR;
}
<STR_P1>UTF16_1 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
s->str_esc += 5;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>UTF16_2 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
s->str_esc += 4;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>UTF16_3 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
s->str_esc += 3;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>UTF16_4 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
s->str_esc += 8;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
@@ -249,6 +294,7 @@ std:
return PHP_JSON_T_ERROR;
}
<STR_P1>ESC {
PHP_JSON_TOKEN_LOCATION(last_column) += 2;
s->str_esc++;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
@@ -257,6 +303,7 @@ std:
return PHP_JSON_T_ERROR;
}
<STR_P1>["] {
PHP_JSON_TOKEN_LOCATION(last_column)++;
zend_string *str;
size_t len = (size_t)(s->cursor - s->str_start - s->str_esc - 1 + s->utf8_invalid_count);
if (len == 0) {
@@ -277,7 +324,22 @@ std:
return PHP_JSON_T_STRING;
}
}
<STR_P1>UTF8 { PHP_JSON_CONDITION_GOTO(STR_P1); }
<STR_P1>UTF8_1 {
PHP_JSON_TOKEN_LOCATION(last_column)++;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>UTF8_2 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>UTF8_3 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>UTF8_4 {
PHP_JSON_TOKEN_LOCATION(last_column) += 1;
PHP_JSON_CONDITION_GOTO(STR_P1);
}
<STR_P1>ANY {
if (s->options & (PHP_JSON_INVALID_UTF8_IGNORE | PHP_JSON_INVALID_UTF8_SUBSTITUTE)) {
if (s->options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) {
@@ -295,7 +357,6 @@ std:
s->errcode = PHP_JSON_ERROR_UTF8;
return PHP_JSON_T_ERROR;
}
<STR_P2_UTF,STR_P2_BIN>UTF16_1 {
int utf16 = php_json_ucs2_to_int(s, 2);
PHP_JSON_SCANNER_COPY_UTF();

View File

@@ -86,6 +86,8 @@ ZEND_BEGIN_MODULE_GLOBALS(json)
int encoder_depth;
int encode_max_depth;
php_json_error_code error_code;
size_t error_line;
size_t error_column;
ZEND_END_MODULE_GLOBALS(json)
PHP_JSON_API ZEND_EXTERN_MODULE_GLOBALS(json)

View File

@@ -50,12 +50,20 @@ typedef struct _php_json_parser_methods {
php_json_parser_func_object_end_t object_end;
} php_json_parser_methods;
typedef struct _php_json_parser_location {
size_t first_line;
size_t first_column;
size_t last_line;
size_t last_column;
} php_json_parser_location;
struct _php_json_parser {
php_json_scanner scanner;
zval *return_value;
int depth;
int max_depth;
php_json_parser_methods methods;
php_json_parser_location *location;
};
PHP_JSON_API void php_json_parser_init_ex(
@@ -77,6 +85,10 @@ 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_line(const php_json_parser *parser);
PHP_JSON_API size_t php_json_parser_error_column(const php_json_parser *parser);
PHP_JSON_API int php_json_parse(php_json_parser *parser);
int php_json_yyparse(php_json_parser *parser);

View File

@@ -22,6 +22,17 @@
typedef unsigned char php_json_ctype;
typedef struct _php_json_error_location {
/** first column of the error */
size_t first_column;
/** first line of the error */
size_t first_line;
/** last column of the error */
size_t last_column;
/** last line of the error */
size_t last_line;
} php_json_error_location;
typedef struct _php_json_scanner {
php_json_ctype *cursor; /* cursor position */
php_json_ctype *token; /* token position */
@@ -35,10 +46,12 @@ typedef struct _php_json_scanner {
int state; /* condition state */
int options; /* options */
php_json_error_code errcode; /* error type if there is an error */
php_json_error_location errloc; /* error location */
int utf8_invalid; /* whether utf8 is invalid */
int utf8_invalid_count; /* number of extra character for invalid utf8 */
} php_json_scanner;
#define PHP_JSON_SCANNER_LOCATION(scanner, slocation) (scanner).errloc.slocation
void php_json_scanner_init(php_json_scanner *scanner, const char *str, size_t str_len, int options);
int php_json_scan(php_json_scanner *s);

View File

@@ -24,14 +24,14 @@ int(0)
string(8) "No error"
NULL
int(1)
string(28) "Maximum stack depth exceeded"
string(46) "Maximum stack depth exceeded near location 1:2"
NULL
int(2)
string(42) "State mismatch (invalid or malformed JSON)"
string(60) "State mismatch (invalid or malformed JSON) near location 1:3"
NULL
int(3)
string(53) "Control character error, possibly incorrectly encoded"
string(71) "Control character error, possibly incorrectly encoded near location 1:2"
NULL
int(4)
string(12) "Syntax error"
string(30) "Syntax error near location 1:3"
Done

View File

@@ -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(68) "Single unpaired UTF-16 surrogate in unicode escape near location 1:1"

View File

@@ -5,7 +5,7 @@ Bug #68546 (json_decode() Fatal error: Cannot access property started with '\0')
var_dump(json_decode('{"key": {"\u0000": "aa"}}'));
var_dump(json_last_error() === JSON_ERROR_INVALID_PROPERTY_NAME);
var_dump(json_decode('[{"key1": 0, "\u0000": 1}]'));
var_dump(json_decode('[{"key1": 0, "\u1234": 1, "\u0000": 1}]'));
var_dump(json_last_error() === JSON_ERROR_INVALID_PROPERTY_NAME);
var_dump(json_last_error_msg());
@@ -16,5 +16,5 @@ NULL
bool(true)
NULL
bool(true)
string(36) "The decoded property name is invalid"
string(55) "The decoded property name is invalid near location 1:27"
Done

View File

@@ -13,7 +13,7 @@ try {
--EXPECTF--
object(JsonException)#1 (7) {
["message":protected]=>
string(12) "Syntax error"
string(30) "Syntax error near location 1:2"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>

View File

@@ -0,0 +1,121 @@
--TEST--
json_last_error_msg() - Error location reporting with ASCII characters
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing errors at various locations with ASCII characters\n\n";
// Error at start
echo "Error at position 1:1:\n";
json_validate_trycatchdump("-");
// Error in middle of simple object
echo "\nError at position 1:10:\n";
json_validate_trycatchdump('{"name": "value}');
// Missing colon
echo "\nError at position 1:9:\n";
json_validate_trycatchdump('{"name" "value"}');
// Extra comma
echo "\nError at position 1:16:\n";
json_validate_trycatchdump('{"name": "val",}');
// Missing closing bracket in array
echo "\nError at position 1:15:\n";
json_validate_trycatchdump('[1, 2, 3, 4, 5');
// Invalid value
echo "\nError at position 1:10:\n";
json_validate_trycatchdump('{"test": undefined}');
// Trailing comma in array
echo "\nError at position 1:7:\n";
json_validate_trycatchdump('[1, 2,]');
// Single quote instead of double quote
echo "\nError at position 1:2:\n";
json_validate_trycatchdump("{'key': 'value'}");
// Missing closing brace
echo "\nError at position 1:16:\n";
json_validate_trycatchdump('{"key": "value"');
// Double comma
echo "\nError at position 1:4:\n";
json_validate_trycatchdump('[1,, 2]');
// Invalid escape sequence
echo "\nError at position 1:10:\n";
json_validate_trycatchdump('{"test": "\x"}');
// Unescaped control character
echo "\nError at position 1:10:\n";
json_validate_trycatchdump('{"test": "' . "\n" . '"}');
?>
--EXPECT--
Testing errors at various locations with ASCII characters
Error at position 1:1:
bool(false)
int(4)
string(30) "Syntax error near location 1:1"
Error at position 1:10:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error at position 1:9:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Error at position 1:16:
bool(false)
int(4)
string(31) "Syntax error near location 1:16"
Error at position 1:15:
bool(false)
int(4)
string(31) "Syntax error near location 1:15"
Error at position 1:10:
bool(false)
int(4)
string(31) "Syntax error near location 1:10"
Error at position 1:7:
bool(false)
int(4)
string(30) "Syntax error near location 1:7"
Error at position 1:2:
bool(false)
int(4)
string(30) "Syntax error near location 1:2"
Error at position 1:16:
bool(false)
int(4)
string(31) "Syntax error near location 1:16"
Error at position 1:4:
bool(false)
int(4)
string(30) "Syntax error near location 1:4"
Error at position 1:10:
bool(false)
int(4)
string(31) "Syntax error near location 1:10"
Error at position 1:10:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"

View File

@@ -0,0 +1,103 @@
--TEST--
json_last_error_msg() - Error location reporting with Unicode UTF-8 characters
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations with Unicode UTF-8 characters\n\n";
// Error after UTF-8 characters (Japanese)
echo "Error after Japanese characters:\n";
json_validate_trycatchdump('{"プレスキット": "value}');
// Error after UTF-8 characters (Russian)
echo "\nError after Russian characters:\n";
json_validate_trycatchdump('{"имя": "значение}');
// Error after UTF-8 characters (Chinese)
echo "\nError after Chinese characters:\n";
json_validate_trycatchdump('{"名字": "值}');
// Error after UTF-8 characters (Arabic)
echo "\nError after Arabic characters:\n";
json_validate_trycatchdump('{"اسم": "قيمة}');
// Error after UTF-8 characters (Emoji)
echo "\nError after Emoji:\n";
json_validate_trycatchdump('{"emoji": "😀🎉}');
// Mixed ASCII and UTF-8
echo "\nError in mixed ASCII and UTF-8:\n";
json_validate_trycatchdump('{"name": "John", "город": "Москва}');
// UTF-8 with escaped sequences
echo "\nError with UTF-8 escaped sequences:\n";
json_validate_trycatchdump('{"test": "\u30d7\u30ec\u30b9}');
// Multiple UTF-8 keys with error
echo "\nError in object with multiple UTF-8 keys:\n";
json_validate_trycatchdump('{"キー1": "値1", "キー2": "値2}');
// Array with UTF-8 and error
echo "\nError in array with UTF-8 strings:\n";
json_validate_trycatchdump('["文字列1", "文字列2", "文字列3}');
// Nested object with UTF-8 and error
echo "\nError in nested object with UTF-8:\n";
json_validate_trycatchdump('{"外部": {"内部": "値}');
?>
--EXPECT--
Testing error locations with Unicode UTF-8 characters
Error after Japanese characters:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:12"
Error after Russian characters:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error after Chinese characters:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:8"
Error after Arabic characters:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error after Emoji:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:11"
Error in mixed ASCII and UTF-8:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:27"
Error with UTF-8 escaped sequences:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error in object with multiple UTF-8 keys:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:22"
Error in array with UTF-8 strings:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:18"
Error in nested object with UTF-8:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:15"

View File

@@ -0,0 +1,72 @@
--TEST--
json_last_error_msg() - Error location reporting with multi-line JSON
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations in multi-line JSON\n\n";
// Error on line 2
echo "Error on line 2, column 13:\n";
$json = '{
"name": "value
}';
json_validate_trycatchdump($json);
// Error on line 3
echo "\nError on line 3, column 12:\n";
$json = '{
"key1": "value1",
"key2" "value2"
}';
json_validate_trycatchdump($json);
// Error on line 5 in nested structure
echo "\nError on line 5, column 26:\n";
$json = '{
"outer": {
"inner": {
"deep": {
"value": "unclosed
}
}
}
}';
json_validate_trycatchdump($json);
// Error on last line
echo "\nError on line 7, column 1:\n";
$json = '{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
"key5": "value5"
';
json_validate_trycatchdump($json);
?>
--EXPECT--
Testing error locations in multi-line JSON
Error on line 2, column 13:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 2:13"
Error on line 3, column 12:
bool(false)
int(4)
string(31) "Syntax error near location 3:12"
Error on line 5, column 26:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 5:26"
Error on line 7, column 1:
bool(false)
int(4)
string(30) "Syntax error near location 7:1"

View File

@@ -0,0 +1,93 @@
--TEST--
json_last_error_msg() - Error location reporting with deeply nested structures
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations in deeply nested structures\n\n";
// Error in deeply nested object
echo "Error in deeply nested object:\n";
$json = '{"a": {"b": {"c": {"d": {"e": "value}}}}}';
json_validate_trycatchdump($json);
// Error in deeply nested array
echo "\nError in deeply nested array:\n";
$json = '[[[[[1, 2, 3, 4, 5]]]]]';
json_validate_trycatchdump($json);
// Error in mixed nested structures
echo "\nError in mixed nested structures:\n";
$json = '{"arr": [{"obj": [{"key": "val"}]}]}';
json_validate_trycatchdump($json);
// Error at the end of deep nesting
echo "\nError at end of deep nesting:\n";
$json = '{"level1": {"level2": {"level3": {"level4": "value"}}}}';
json_validate_trycatchdump($json);
// Error in middle of deep nesting
echo "\nError in middle of deep nesting:\n";
$json = '{"l1": {"l2": {"l3" {"l4": "val"}}}}';
json_validate_trycatchdump($json);
// Complex structure with error
echo "\nError in complex structure:\n";
$json = '{"users": [{"name": "John", "age": 30}, {"name": "Jane", "age": 25}], "count": 2, "status": "active}';
json_validate_trycatchdump($json);
// Array of objects with error
echo "\nError in array of objects:\n";
$json = '[{"id": 1, "name": "A"}, {"id": 2, "name": "B"}, {"id": 3, "name": "C}]';
json_validate_trycatchdump($json);
// Object with array values error
echo "\nError in object with array values:\n";
$json = '{"numbers": [1, 2, 3], "strings": ["a", "b", "c"], "booleans": [true, false, true}';
json_validate_trycatchdump($json);
?>
--EXPECT--
Testing error locations in deeply nested structures
Error in deeply nested object:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:31"
Error in deeply nested array:
bool(true)
int(0)
string(8) "No error"
Error in mixed nested structures:
bool(true)
int(0)
string(8) "No error"
Error at end of deep nesting:
bool(true)
int(0)
string(8) "No error"
Error in middle of deep nesting:
bool(false)
int(4)
string(31) "Syntax error near location 1:21"
Error in complex structure:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:93"
Error in array of objects:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:68"
Error in object with array values:
bool(false)
int(2)
string(61) "State mismatch (invalid or malformed JSON) near location 1:82"

View File

@@ -0,0 +1,103 @@
--TEST--
json_last_error_msg() - Error location reporting with UTF-16 surrogate pairs
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations with UTF-16 surrogate pairs and escape sequences\n\n";
// Error after UTF-16 escaped characters
echo "Error after UTF-16 escaped emoji:\n";
json_validate_trycatchdump('{"emoji": "\uD83D\uDE00}');
// Error after multiple UTF-16 pairs
echo "\nError after multiple UTF-16 pairs:\n";
json_validate_trycatchdump('{"test": "\uD83D\uDE00\uD83C\uDF89}');
// Mixed UTF-8 and UTF-16 escapes
echo "\nError with mixed UTF-8 and UTF-16:\n";
json_validate_trycatchdump('{"mixed": "Hello \u4E16\u754C world}');
// UTF-16 in key and value
echo "\nError with UTF-16 in key:\n";
json_validate_trycatchdump('{"\u30D7\u30EC\u30B9": "value}');
// Multiple keys with UTF-16
echo "\nError with multiple UTF-16 keys:\n";
json_validate_trycatchdump('{"\u0041\u0042": "val1", "\u0043\u0044": "val2}');
// BMP characters (Basic Multilingual Plane)
echo "\nError with BMP characters:\n";
json_validate_trycatchdump('{"test": "\u0048\u0065\u006C\u006C\u006F}');
// Supplementary plane characters (beyond BMP)
echo "\nError with supplementary plane:\n";
json_validate_trycatchdump('{"music": "\uD834\uDD1E}');
// Array with UTF-16 escaped strings
echo "\nError in array with UTF-16:\n";
json_validate_trycatchdump('["\u0031", "\u0032", "\u0033}');
// Nested with UTF-16
echo "\nError in nested structure with UTF-16:\n";
json_validate_trycatchdump('{"outer": {"\u6D4B\u8BD5": "value}');
// UTF-16 with control characters
echo "\nError with UTF-16 and control chars:\n";
json_validate_trycatchdump('{"data": "\u0009\u000A\u000D}');
?>
--EXPECT--
Testing error locations with UTF-16 surrogate pairs and escape sequences
Error after UTF-16 escaped emoji:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:11"
Error after multiple UTF-16 pairs:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with mixed UTF-8 and UTF-16:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:11"
Error with UTF-16 in key:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error with multiple UTF-16 keys:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:22"
Error with BMP characters:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with supplementary plane:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:11"
Error in array with UTF-16:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:12"
Error in nested structure with UTF-16:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:18"
Error with UTF-16 and control chars:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"

View File

@@ -0,0 +1,152 @@
--TEST--
json_last_error_msg() - Error location reporting edge cases
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error location edge cases\n\n";
// Error at very start
echo "Error at position 1:1:\n";
json_validate_trycatchdump('');
// Error at position 1:1 with single character
echo "\nError at position 1:1 with invalid char:\n";
json_validate_trycatchdump('x');
// Error after whitespace
echo "\nError after leading whitespace:\n";
json_validate_trycatchdump(' {');
// Error with only whitespace
echo "\nError with tabs and spaces:\n";
json_validate_trycatchdump(" \t \n ");
// Error after newlines
echo "\nError after multiple newlines:\n";
json_validate_trycatchdump("\n\n\n{");
// Long string with error at end
echo "\nError at end of long string:\n";
$longString = '{"key": "' . str_repeat('a', 1000) . '"}';
// Remove closing brace to create error
$longString = substr($longString, 0, -1);
json_validate_trycatchdump($longString);
// Error with very long key name
echo "\nError with very long key:\n";
$longKey = '{"' . str_repeat('x', 500) . '": "value}';
json_validate_trycatchdump($longKey);
// Empty object followed by error
echo "\nError after empty object:\n";
json_validate_trycatchdump('{}x');
// Empty array followed by error
echo "\nError after empty array:\n";
json_validate_trycatchdump('[]x');
// Multiple values (invalid JSON)
echo "\nError with multiple root values:\n";
json_validate_trycatchdump('{}{}');
// Number followed by invalid content
echo "\nError after valid number:\n";
json_validate_trycatchdump('123x');
// Boolean followed by invalid content
echo "\nError after valid boolean:\n";
json_validate_trycatchdump('truex');
// Null followed by invalid content
echo "\nError after valid null:\n";
json_validate_trycatchdump('nullx');
// String followed by invalid content
echo "\nError after valid string:\n";
json_validate_trycatchdump('"test"x');
// Error with mixed whitespace
echo "\nError with mixed whitespace:\n";
json_validate_trycatchdump("{\n\t\"key\": \n\t\"value\n}");
?>
--EXPECT--
Testing error location edge cases
Error at position 1:1:
bool(false)
int(4)
string(12) "Syntax error"
Error at position 1:1 with invalid char:
bool(false)
int(4)
string(30) "Syntax error near location 1:1"
Error after leading whitespace:
bool(false)
int(4)
string(30) "Syntax error near location 1:5"
Error with tabs and spaces:
bool(false)
int(4)
string(30) "Syntax error near location 2:3"
Error after multiple newlines:
bool(false)
int(4)
string(30) "Syntax error near location 4:2"
Error at end of long string:
bool(false)
int(4)
string(33) "Syntax error near location 1:1011"
Error with very long key:
bool(false)
int(3)
string(73) "Control character error, possibly incorrectly encoded near location 1:506"
Error after empty object:
bool(false)
int(4)
string(30) "Syntax error near location 1:3"
Error after empty array:
bool(false)
int(4)
string(30) "Syntax error near location 1:3"
Error with multiple root values:
bool(false)
int(4)
string(30) "Syntax error near location 1:3"
Error after valid number:
bool(false)
int(4)
string(30) "Syntax error near location 1:4"
Error after valid boolean:
bool(false)
int(4)
string(30) "Syntax error near location 1:5"
Error after valid null:
bool(false)
int(4)
string(30) "Syntax error near location 1:5"
Error after valid string:
bool(false)
int(4)
string(30) "Syntax error near location 1:7"
Error with mixed whitespace:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 3:2"

View File

@@ -0,0 +1,178 @@
--TEST--
json_last_error_msg() - Error location with various error types
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations with different error types\n\n";
// State mismatch errors
echo "State mismatch - expected value:\n";
json_validate_trycatchdump('{"key": }');
echo "\nState mismatch - expected key:\n";
json_validate_trycatchdump('{: "value"}');
echo "\nState mismatch - trailing comma in object:\n";
json_validate_trycatchdump('{"a": 1, "b": 2,}');
echo "\nState mismatch - trailing comma in array:\n";
json_validate_trycatchdump('[1, 2, 3,]');
// Number format errors
echo "\nInvalid number format - leading zero:\n";
json_validate_trycatchdump('{"num": 01}');
echo "\nInvalid number format - multiple decimals:\n";
json_validate_trycatchdump('{"num": 1.2.3}');
echo "\nInvalid number format - incomplete exponent:\n";
json_validate_trycatchdump('{"num": 1e}');
echo "\nInvalid number format - double sign:\n";
json_validate_trycatchdump('{"num": --1}');
// String errors
echo "\nUnclosed string:\n";
json_validate_trycatchdump('{"key": "value');
echo "\nInvalid escape sequence:\n";
json_validate_trycatchdump('{"key": "\\q"}');
echo "\nIncomplete unicode escape:\n";
json_validate_trycatchdump('{"key": "\\u123"}');
echo "\nInvalid unicode escape:\n";
json_validate_trycatchdump('{"key": "\\uGGGG"}');
// Keyword errors
echo "\nInvalid true keyword:\n";
json_validate_trycatchdump('{"val": tru}');
echo "\nInvalid false keyword:\n";
json_validate_trycatchdump('{"val": fals}');
echo "\nInvalid null keyword:\n";
json_validate_trycatchdump('{"val": nul}');
// Structure errors
echo "\nMismatched brackets - ] instead of }:\n";
json_validate_trycatchdump('{"key": "val"]');
echo "\nMismatched brackets - } instead of ]:\n";
json_validate_trycatchdump('["val"}');
echo "\nExtra closing bracket:\n";
json_validate_trycatchdump('{"key": "val"}}');
echo "\nMissing comma between elements:\n";
json_validate_trycatchdump('[1 2 3]');
echo "\nMissing comma between object properties:\n";
json_validate_trycatchdump('{"a": 1 "b": 2}');
?>
--EXPECT--
Testing error locations with different error types
State mismatch - expected value:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
State mismatch - expected key:
bool(false)
int(4)
string(30) "Syntax error near location 1:2"
State mismatch - trailing comma in object:
bool(false)
int(4)
string(31) "Syntax error near location 1:17"
State mismatch - trailing comma in array:
bool(false)
int(4)
string(31) "Syntax error near location 1:10"
Invalid number format - leading zero:
bool(false)
int(4)
string(31) "Syntax error near location 1:10"
Invalid number format - multiple decimals:
bool(false)
int(4)
string(31) "Syntax error near location 1:12"
Invalid number format - incomplete exponent:
bool(false)
int(4)
string(31) "Syntax error near location 1:10"
Invalid number format - double sign:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Unclosed string:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Invalid escape sequence:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Incomplete unicode escape:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Invalid unicode escape:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Invalid true keyword:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Invalid false keyword:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Invalid null keyword:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
Mismatched brackets - ] instead of }:
bool(false)
int(2)
string(61) "State mismatch (invalid or malformed JSON) near location 1:14"
Mismatched brackets - } instead of ]:
bool(false)
int(2)
string(60) "State mismatch (invalid or malformed JSON) near location 1:7"
Extra closing bracket:
bool(false)
int(4)
string(31) "Syntax error near location 1:15"
Missing comma between elements:
bool(false)
int(4)
string(30) "Syntax error near location 1:4"
Missing comma between object properties:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"

View File

@@ -0,0 +1,182 @@
--TEST--
json_last_error_msg() - Error location with mixed UTF-8 multi-byte characters
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations with various UTF-8 multi-byte character widths\n\n";
// 2-byte UTF-8 characters (Latin Extended)
echo "Error with 2-byte UTF-8 (Latin Extended):\n";
json_validate_trycatchdump('{"café": "value}');
echo "\nError with 2-byte UTF-8 (Greek):\n";
json_validate_trycatchdump('{"Ελληνικά": "value}');
echo "\nError with 2-byte UTF-8 (Cyrillic):\n";
json_validate_trycatchdump('{"Привет": "мир}');
// 3-byte UTF-8 characters (CJK)
echo "\nError with 3-byte UTF-8 (Chinese):\n";
json_validate_trycatchdump('{"中文": "测试}');
echo "\nError with 3-byte UTF-8 (Japanese Hiragana):\n";
json_validate_trycatchdump('{"ひらがな": "テスト}');
echo "\nError with 3-byte UTF-8 (Japanese Katakana):\n";
json_validate_trycatchdump('{"カタカナ": "テスト}');
echo "\nError with 3-byte UTF-8 (Korean):\n";
json_validate_trycatchdump('{"한글": "테스트}');
// 4-byte UTF-8 characters (Emoji and special symbols)
echo "\nError with 4-byte UTF-8 (Emoji faces):\n";
json_validate_trycatchdump('{"emoji": "😀😃😄😁}');
echo "\nError with 4-byte UTF-8 (Emoji objects):\n";
json_validate_trycatchdump('{"objects": "🎉🎊🎁🎈}');
echo "\nError with 4-byte UTF-8 (Mathematical symbols):\n";
json_validate_trycatchdump('{"math": "𝕒𝕓𝕔𝕕}');
// Mixed byte-width characters
echo "\nError with mixed 1-2-3 byte UTF-8:\n";
json_validate_trycatchdump('{"mix": "Aéø中文}');
echo "\nError with mixed 2-3-4 byte UTF-8:\n";
json_validate_trycatchdump('{"mix": "Привет中文😀}');
echo "\nError with all byte widths:\n";
json_validate_trycatchdump('{"all": "Aéø中文😀}');
// UTF-8 in keys at different positions
echo "\nError with UTF-8 key at start:\n";
json_validate_trycatchdump('{"🔑": "value}');
echo "\nError with multiple UTF-8 keys:\n";
json_validate_trycatchdump('{"キー1": "値1", "キー2": "値2", "キー3": "値3}');
// Array with mixed UTF-8
echo "\nError in array with mixed UTF-8:\n";
json_validate_trycatchdump('["ASCII", "café", "中文", "😀}');
// Complex nested structure with UTF-8
echo "\nError in nested structure with various UTF-8:\n";
json_validate_trycatchdump('{"外层": {"中层": {"内层": "值}}}');
// UTF-8 with special combining characters
echo "\nError with combining diacritical marks:\n";
json_validate_trycatchdump('{"tëst": "vâlue}');
// Right-to-left languages
echo "\nError with Hebrew:\n";
json_validate_trycatchdump('{"שלום": "עולם}');
echo "\nError with Arabic with diacritics:\n";
json_validate_trycatchdump('{"مرحبا": "عالم}');
?>
--EXPECT--
Testing error locations with various UTF-8 multi-byte character widths
Error with 2-byte UTF-8 (Latin Extended):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with 2-byte UTF-8 (Greek):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:14"
Error with 2-byte UTF-8 (Cyrillic):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:12"
Error with 3-byte UTF-8 (Chinese):
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:8"
Error with 3-byte UTF-8 (Japanese Hiragana):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with 3-byte UTF-8 (Japanese Katakana):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with 3-byte UTF-8 (Korean):
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:8"
Error with 4-byte UTF-8 (Emoji faces):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:11"
Error with 4-byte UTF-8 (Emoji objects):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:13"
Error with 4-byte UTF-8 (Mathematical symbols):
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with mixed 1-2-3 byte UTF-8:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error with mixed 2-3-4 byte UTF-8:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error with all byte widths:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error with UTF-8 key at start:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:7"
Error with multiple UTF-8 keys:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:35"
Error in array with mixed UTF-8:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:25"
Error in nested structure with various UTF-8:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:22"
Error with combining diacritical marks:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with Hebrew:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
Error with Arabic with diacritics:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:11"

View File

@@ -0,0 +1,110 @@
--TEST--
json_last_error_msg() - Error location with depth errors and complex nesting
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations with depth-related issues\n\n";
// Test max depth error with location
echo "Max depth error at specific location:\n";
$json = '{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":{"j":"val"}}}}}}}}}}';
json_validate_trycatchdump($json, 5);
echo "\nMax depth error in array:\n";
$json = '[[[[[[[[[[10]]]]]]]]]]';
json_validate_trycatchdump($json, 5);
echo "\nMax depth error with mixed structures:\n";
$json = '[{"a":[{"b":[{"c":"val"}]}]}]';
json_validate_trycatchdump($json, 3);
// Syntax error at deep level
echo "\nSyntax error at deep nesting level:\n";
$json = '{"l1":{"l2":{"l3":{"l4":{"l5":"unclosed}}}}}';
json_validate_trycatchdump($json);
echo "\nSyntax error in deep array:\n";
$json = '[[[[["value]]]]]';
json_validate_trycatchdump($json);
// Valid deep structure followed by error
echo "\nError after valid deep structure:\n";
$json = '{"valid":{"nested":{"structure":"ok"}},"error":"unclosed}';
json_validate_trycatchdump($json);
// Multiple nested objects with error in middle
echo "\nError in middle of nested structure:\n";
$json = '{"outer":{"middle":{"inner" "value"}}}';
json_validate_trycatchdump($json);
// Array with nested objects and error
echo "\nError in array with nested objects:\n";
$json = '[{"a":{"b":"val"}},{"c":{"d":"val}}}]';
json_validate_trycatchdump($json);
// Deep structure with UTF-8 and error
echo "\nError in deep UTF-8 structure:\n";
$json = '{"外":{"中":{"内":"値}}}';
json_validate_trycatchdump($json);
// Very deep valid structure (should pass)
echo "\nValid deep structure within limit:\n";
$json = '{"a":{"b":{"c":{"d":"val"}}}}';
json_validate_trycatchdump($json, 10);
?>
--EXPECT--
Testing error locations with depth-related issues
Max depth error at specific location:
bool(false)
int(1)
string(47) "Maximum stack depth exceeded near location 1:21"
Max depth error in array:
bool(false)
int(1)
string(46) "Maximum stack depth exceeded near location 1:5"
Max depth error with mixed structures:
bool(false)
int(1)
string(46) "Maximum stack depth exceeded near location 1:7"
Syntax error at deep nesting level:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:31"
Syntax error in deep array:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:6"
Error after valid deep structure:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:48"
Error in middle of nested structure:
bool(false)
int(4)
string(31) "Syntax error near location 1:29"
Error in array with nested objects:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:30"
Error in deep UTF-8 structure:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:16"
Valid deep structure within limit:
bool(true)
int(0)
string(8) "No error"

View File

@@ -0,0 +1,164 @@
--TEST--
json_last_error_msg() - Error location with whitespace variations
--FILE--
<?php
require_once("json_validate_requires.inc");
echo "Testing error locations with various whitespace patterns\n\n";
// Error after spaces
echo "Error after multiple spaces:\n";
json_validate_trycatchdump(' {');
// Error after tabs
echo "\nError after tabs:\n";
json_validate_trycatchdump("\t\t\t{");
// Error after mixed whitespace
echo "\nError after mixed whitespace:\n";
json_validate_trycatchdump(" \t {");
// Error on new line
echo "\nError on second line:\n";
json_validate_trycatchdump("{\n}x");
// Error with CRLF line endings
echo "\nError with CRLF line endings:\n";
json_validate_trycatchdump("{\r\n\"key\": \"value\r\n}");
// Error with multiple blank lines
echo "\nError after blank lines:\n";
json_validate_trycatchdump("\n\n\n{");
// Whitespace inside strings (should not affect location)
echo "\nError in string with spaces:\n";
json_validate_trycatchdump('{"key": "value with spaces}');
// Whitespace before and after colons
echo "\nError with whitespace around colon:\n";
json_validate_trycatchdump('{"key" : "value}');
// Whitespace before and after commas
echo "\nError with whitespace around comma:\n";
json_validate_trycatchdump('{"a": 1 , "b": 2 , "c": 3}');
// Pretty printed JSON with error
echo "\nError in pretty printed JSON:\n";
$json = '{
"name": "John",
"age": 30,
"city": "New York
}';
json_validate_trycatchdump($json);
// Heavily indented JSON with error
echo "\nError in heavily indented JSON:\n";
$json = '{
"level1": {
"level2": {
"level3": {
"value": "test
}
}
}
}';
json_validate_trycatchdump($json);
// Mixed tabs and spaces with error
echo "\nError with mixed tabs and spaces:\n";
$json = "{\n\t \"key1\": \"val1\",\n \t\"key2\": \"val2\n}";
json_validate_trycatchdump($json);
// Whitespace-only line before error
echo "\nError after whitespace-only line:\n";
$json = "{\n \n \"key\": \"value\n}";
json_validate_trycatchdump($json);
// No whitespace (compact JSON) with error
echo "\nError in compact JSON:\n";
json_validate_trycatchdump('{"a":"b","c":"d","e":"f}');
// Unicode whitespace characters (if supported)
echo "\nError with regular spaces:\n";
json_validate_trycatchdump('{ "key": "value}');
?>
--EXPECT--
Testing error locations with various whitespace patterns
Error after multiple spaces:
bool(false)
int(4)
string(30) "Syntax error near location 1:7"
Error after tabs:
bool(false)
int(4)
string(30) "Syntax error near location 1:5"
Error after mixed whitespace:
bool(false)
int(4)
string(30) "Syntax error near location 1:7"
Error on second line:
bool(false)
int(4)
string(30) "Syntax error near location 2:2"
Error with CRLF line endings:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 2:8"
Error after blank lines:
bool(false)
int(4)
string(30) "Syntax error near location 4:2"
Error in string with spaces:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 1:9"
Error with whitespace around colon:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:12"
Error with whitespace around comma:
bool(true)
int(0)
string(8) "No error"
Error in pretty printed JSON:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 4:11"
Error in heavily indented JSON:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 5:26"
Error with mixed tabs and spaces:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 3:12"
Error after whitespace-only line:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 3:12"
Error in compact JSON:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:22"
Error with regular spaces:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"

View File

@@ -23,13 +23,13 @@ int(4)
string(12) "Syntax error"
bool(false)
int(4)
string(12) "Syntax error"
string(30) "Syntax error near location 1:1"
bool(false)
int(4)
string(12) "Syntax error"
bool(false)
int(1)
string(28) "Maximum stack depth exceeded"
string(46) "Maximum stack depth exceeded near location 1:1"
bool(true)
int(0)
string(8) "No error"
@@ -44,7 +44,7 @@ int(0)
string(8) "No error"
bool(false)
int(4)
string(12) "Syntax error"
string(30) "Syntax error near location 1:1"
bool(true)
int(0)
string(8) "No error"

View File

@@ -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(74) "Malformed UTF-8 characters, possibly incorrectly encoded near location 1:1"
bool(false)
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
string(74) "Malformed UTF-8 characters, possibly incorrectly encoded near location 1:1"
bool(false)
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
string(74) "Malformed UTF-8 characters, possibly incorrectly encoded near location 1:1"
bool(false)
int(5)
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
string(74) "Malformed UTF-8 characters, possibly incorrectly encoded near location 1:2"
bool(true)
int(0)
string(8) "No error"