scottmac Fri Dec 19 02:01:00 2008 UTC Modified files: /php-src/ext/json JSON_parser.c JSON_parser.h json.c php_json.h /php-src/ext/json/tests 007.phpt Log: Add json_last_error() for getting a bit of information about what failed during a decode, also fixes a segfault when we have [1} [DOC]
http://cvs.php.net/viewvc.cgi/php-src/ext/json/JSON_parser.c?r1=1.21&r2=1.22&diff_format=u Index: php-src/ext/json/JSON_parser.c diff -u php-src/ext/json/JSON_parser.c:1.21 php-src/ext/json/JSON_parser.c:1.22 --- php-src/ext/json/JSON_parser.c:1.21 Wed Dec 17 15:46:00 2008 +++ php-src/ext/json/JSON_parser.c Fri Dec 19 02:00:59 2008 @@ -194,13 +194,6 @@ MODE_OBJECT, }; -enum error_codes { - ERROR_DEPTH, - ERROR_MISMATCH, - ERROR_CTRL_CHAR, - ERROR_SYNTAX, -}; - /* Push a mode onto the stack. Return false if there is overflow. @@ -210,7 +203,7 @@ { jp->top += 1; if (jp->top >= jp->depth) { - jp->error = ERROR_DEPTH; + jp->error_code = PHP_JSON_ERROR_DEPTH; return false; } jp->stack[jp->top] = mode; @@ -226,7 +219,7 @@ pop(JSON_parser jp, int mode) { if (jp->top < 0 || jp->stack[jp->top] != mode) { - jp->error = ERROR_MISMATCH; + jp->error_code = PHP_JSON_ERROR_STATE_MISMATCH; return false; } jp->top -= 1; @@ -252,6 +245,7 @@ jp->state = GO; jp->depth = depth; jp->top = -1; + jp->error_code = PHP_JSON_ERROR_NONE; jp->stack = (int*)ecalloc(depth, sizeof(int)); push(jp, MODE_DONE); return jp; @@ -428,7 +422,7 @@ } else { next_class = ascii_class[next_char]; if (next_class <= __) { - jp->error = ERROR_CTRL_CHAR; + jp->error_code = PHP_JSON_ERROR_CTRL_CHAR; FREE_BUFFERS(); return false; } @@ -511,9 +505,7 @@ break; /* } */ case -8: - if (type != -1 && - (jp->stack[jp->top] == MODE_OBJECT || - jp->stack[jp->top] == MODE_ARRAY)) + if (type != -1 && jp->stack[jp->top] == MODE_OBJECT) { zval *mval; smart_str_0(&buf); @@ -541,9 +533,7 @@ /* ] */ case -7: { - if (type != -1 && - (jp->stack[jp->top] == MODE_OBJECT || - jp->stack[jp->top] == MODE_ARRAY)) + if (type != -1 && jp->stack[jp->top] == MODE_ARRAY) { zval *mval; smart_str_0(&buf); @@ -702,7 +692,7 @@ */ default: { - jp->error = ERROR_SYNTAX; + jp->error_code = PHP_JSON_ERROR_SYNTAX; FREE_BUFFERS(); return false; } @@ -711,11 +701,14 @@ } FREE_BUFFERS(); + if (jp->state == OK && pop(jp, MODE_DONE)) { + return true; + } - return jp->state == OK && pop(jp, MODE_DONE); + jp->error_code = PHP_JSON_ERROR_SYNTAX; + return false; } - /* * Local variables: * tab-width: 4 http://cvs.php.net/viewvc.cgi/php-src/ext/json/JSON_parser.h?r1=1.3&r2=1.4&diff_format=u Index: php-src/ext/json/JSON_parser.h diff -u php-src/ext/json/JSON_parser.h:1.3 php-src/ext/json/JSON_parser.h:1.4 --- php-src/ext/json/JSON_parser.h:1.3 Wed Dec 17 14:39:56 2008 +++ php-src/ext/json/JSON_parser.h Fri Dec 19 02:00:59 2008 @@ -12,12 +12,20 @@ int state; int depth; int top; - int error; + int error_code; int* stack; zval *the_zstack[JSON_PARSER_MAX_DEPTH]; } * JSON_parser; +enum error_codes { + PHP_JSON_ERROR_NONE = 0, + PHP_JSON_ERROR_DEPTH, + PHP_JSON_ERROR_STATE_MISMATCH, + PHP_JSON_ERROR_CTRL_CHAR, + PHP_JSON_ERROR_SYNTAX, +}; + extern JSON_parser new_JSON_parser(int depth); extern int parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC); extern int free_JSON_parser(JSON_parser jp); http://cvs.php.net/viewvc.cgi/php-src/ext/json/json.c?r1=1.44&r2=1.45&diff_format=u Index: php-src/ext/json/json.c diff -u php-src/ext/json/json.c:1.44 php-src/ext/json/json.c:1.45 --- php-src/ext/json/json.c:1.44 Wed Dec 17 14:39:56 2008 +++ php-src/ext/json/json.c Fri Dec 19 02:00:59 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: json.c,v 1.44 2008/12/17 14:39:56 scottmac Exp $ */ +/* $Id: json.c,v 1.45 2008/12/19 02:00:59 scottmac Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -33,6 +33,7 @@ static PHP_MINFO_FUNCTION(json); static PHP_FUNCTION(json_encode); static PHP_FUNCTION(json_decode); +static PHP_FUNCTION(json_last_error); static const char digits[] = "0123456789abcdef"; @@ -41,24 +42,28 @@ #define PHP_JSON_HEX_APOS (1<<2) #define PHP_JSON_HEX_QUOT (1<<3) +ZEND_DECLARE_MODULE_GLOBALS(json) + /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1) ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1) ZEND_ARG_INFO(0, json) ZEND_ARG_INFO(0, assoc) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0) +ZEND_END_ARG_INFO() /* }}} */ -/* {{{ json_functions[] - * - * Every user visible function must have an entry in json_functions[]. - */ +/* {{{ json_functions[] */ static const function_entry json_functions[] = { PHP_FE(json_encode, arginfo_json_encode) PHP_FE(json_decode, arginfo_json_decode) + PHP_FE(json_last_error, arginfo_json_last_error) {NULL, NULL, NULL} }; /* }}} */ @@ -71,17 +76,29 @@ REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } /* }}} */ +/* {{{ PHP_GINIT_FUNCTION +*/ +static PHP_GINIT_FUNCTION(json) +{ + json_globals->error_code = 0; +} +/* }}} */ + /* {{{ json_module_entry */ zend_module_entry json_module_entry = { -#if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, -#endif "json", json_functions, PHP_MINIT(json), @@ -89,10 +106,12 @@ NULL, NULL, PHP_MINFO(json), -#if ZEND_MODULE_API_NO >= 20010901 PHP_JSON_VERSION, -#endif - STANDARD_MODULE_PROPERTIES + PHP_MODULE_GLOBALS(json), + PHP_GINIT(json), + NULL, + NULL, + STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ @@ -580,10 +599,23 @@ if (str_type == IS_STRING) { efree(utf16); } + JSON_G(error_code) = jp->error_code; free_JSON_parser(jp); } /* }}} */ +/* {{{ proto int json_last_error() U + Returns the error code of the last json_decode(). */ +static PHP_FUNCTION(json_last_error) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_LONG(JSON_G(error_code)); +} +/* }}} */ + /* * Local variables: * tab-width: 4 http://cvs.php.net/viewvc.cgi/php-src/ext/json/php_json.h?r1=1.13&r2=1.14&diff_format=u Index: php-src/ext/json/php_json.h diff -u php-src/ext/json/php_json.h:1.13 php-src/ext/json/php_json.h:1.14 --- php-src/ext/json/php_json.h:1.13 Tue Jul 22 15:31:00 2008 +++ php-src/ext/json/php_json.h Fri Dec 19 02:00:59 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_json.h,v 1.13 2008/07/22 15:31:00 jani Exp $ */ +/* $Id: php_json.h,v 1.14 2008/12/19 02:00:59 scottmac Exp $ */ #ifndef PHP_JSON_H #define PHP_JSON_H @@ -30,6 +30,16 @@ #include "TSRM.h" #endif +ZEND_BEGIN_MODULE_GLOBALS(json) + int error_code; +ZEND_END_MODULE_GLOBALS(json) + +#ifdef ZTS +# define JSON_G(v) TSRMG(json_globals_id, zend_json_globals *, v) +#else +# define JSON_G(v) (json_globals.v) +#endif + #endif /* PHP_JSON_H */ /* http://cvs.php.net/viewvc.cgi/php-src/ext/json/tests/007.phpt?r1=1.1&r2=1.2&diff_format=u Index: php-src/ext/json/tests/007.phpt diff -u /dev/null php-src/ext/json/tests/007.phpt:1.2 --- /dev/null Fri Dec 19 02:01:00 2008 +++ php-src/ext/json/tests/007.phpt Fri Dec 19 02:00:59 2008 @@ -0,0 +1,36 @@ +--TEST-- +json_last_error() tests +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php +var_dump(json_decode("[1]")); +var_dump(json_last_error()); +var_dump(json_decode("[[1]]", false, 2)); +var_dump(json_last_error()); +var_dump(json_decode("[1}")); +var_dump(json_last_error()); +var_dump(json_decode('["' . chr(0) . 'abcd"]')); +var_dump(json_last_error()); +var_dump(json_decode("[1")); +var_dump(json_last_error()); + + +echo "Done\n"; +?> +--EXPECT-- +array(1) { + [0]=> + int(1) +} +int(0) +NULL +int(1) +NULL +int(2) +NULL +int(3) +NULL +int(4) +Done +
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php