-
Notifications
You must be signed in to change notification settings - Fork 8k
RFC - json_validate() #9399
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
RFC - json_validate() #9399
Changes from 16 commits
0405a86
8f86a67
344687f
cfbee85
85dcc6a
6688e20
47756e9
ae041be
8e97349
52ab14e
1b1b4f3
baf8ec6
d038d1f
722303b
f02c89c
70467bc
8b528bd
7331b47
2e92c03
d71b16f
9223115
a08d066
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -178,6 +178,25 @@ PHP_JSON_API zend_result php_json_decode_ex(zval *return_value, const char *str, | |||||
} | ||||||
/* }}} */ | ||||||
|
||||||
/* {{{ */ | ||||||
PHP_JSON_API zend_result php_json_validate_ex(zval *return_value, const char *str, size_t str_len, zend_long options, zend_long depth) | ||||||
{ | ||||||
php_json_parser parser; | ||||||
|
||||||
const php_json_parser_methods parser_validate_methods = get_validate_methods(); | ||||||
php_json_parser_init_ex(&parser, return_value, str, str_len, (int)options, (int)depth, &parser_validate_methods); | ||||||
|
||||||
if (php_json_yyparse(&parser)) { | ||||||
php_json_error_code error_code = php_json_parser_error_code(&parser); | ||||||
JSON_G(error_code) = error_code; | ||||||
RETVAL_FALSE; | ||||||
return FAILURE; | ||||||
} | ||||||
|
||||||
return SUCCESS; | ||||||
} | ||||||
juan-morales marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
/* }}} */ | ||||||
|
||||||
/* {{{ Returns the JSON representation of a value */ | ||||||
PHP_FUNCTION(json_encode) | ||||||
{ | ||||||
|
@@ -270,6 +289,52 @@ PHP_FUNCTION(json_decode) | |||||
} | ||||||
/* }}} */ | ||||||
|
||||||
/* {{{ Validates if a string contains a valid json */ | ||||||
PHP_FUNCTION(json_validate) | ||||||
{ | ||||||
char *str; | ||||||
size_t str_len; | ||||||
zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH; | ||||||
zend_long options = 0; | ||||||
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 3) | ||||||
Z_PARAM_STRING(str, str_len) | ||||||
Z_PARAM_OPTIONAL | ||||||
Z_PARAM_LONG(depth) | ||||||
Z_PARAM_LONG(options) | ||||||
ZEND_PARSE_PARAMETERS_END(); | ||||||
|
||||||
|
||||||
if ((options != 0) && (options != PHP_JSON_INVALID_UTF8_IGNORE)) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
this works, but checking for any bits found in bitwise not in allowed flags is shorter and conventional - it also works and is used for combinations of multiple flags |
||||||
zend_argument_value_error(3, "must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE)"); | ||||||
RETURN_THROWS(); | ||||||
} | ||||||
|
||||||
if (!str_len) { | ||||||
JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX; | ||||||
RETURN_FALSE; | ||||||
} | ||||||
|
||||||
JSON_G(error_code) = PHP_JSON_ERROR_NONE; | ||||||
|
||||||
if (depth <= 0) { | ||||||
zend_argument_value_error(2, "must be greater than 0"); | ||||||
RETURN_THROWS(); | ||||||
} | ||||||
|
||||||
if (depth > INT_MAX) { | ||||||
zend_argument_value_error(2, "must be less than %d", INT_MAX); | ||||||
RETURN_THROWS(); | ||||||
} | ||||||
|
||||||
if (php_json_validate_ex(return_value, str, str_len, options, depth) == SUCCESS) { | ||||||
RETURN_TRUE; | ||||||
} | ||||||
|
||||||
RETURN_FALSE; | ||||||
} | ||||||
/* }}} */ | ||||||
|
||||||
/* {{{ Returns the error code of the last json_encode() or json_decode() call. */ | ||||||
PHP_FUNCTION(json_last_error) | ||||||
{ | ||||||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
--TEST-- | ||
json_validate() - General usage | ||
--FILE-- | ||
<?php | ||
|
||
var_dump( | ||
json_validate(""), | ||
json_validate("."), | ||
json_validate("<?>"), | ||
json_validate(";"), | ||
json_validate("руссиш"), | ||
json_validate("blah"), | ||
json_validate('{ "": "": "" } }'), | ||
json_validate('{ "": { "": "" }'), | ||
json_validate('{ "test": {} "foo": "bar" }, "test2": {"foo" : "bar" }, "test2": {"foo" : "bar" } }'), | ||
|
||
json_validate('{ "test": { "foo": "bar" } }'), | ||
juan-morales marked this conversation as resolved.
Show resolved
Hide resolved
|
||
json_validate('{ "test": { "foo": "" } }'), | ||
json_validate('{ "": { "foo": "" } }'), | ||
json_validate('{ "": { "": "" } }'), | ||
json_validate('{ "test": {"foo": "bar"}, "test2": {"foo" : "bar" }, "test2": {"foo" : "bar" } }'), | ||
json_validate('{ "test": {"foo": "bar"}, "test2": {"foo" : "bar" }, "test3": {"foo" : "bar" } }'), | ||
); | ||
|
||
?> | ||
--EXPECT-- | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(true) | ||
bool(true) | ||
bool(true) | ||
bool(true) | ||
bool(true) | ||
bool(true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--TEST-- | ||
json_validate() - Error handling | ||
--FILE-- | ||
<?php | ||
|
||
require_once("json_validate_requires.inc"); | ||
|
||
json_validate_trycatchdump(null); | ||
json_validate_trycatchdump(""); | ||
json_validate_trycatchdump("-"); | ||
json_validate_trycatchdump("", -1); | ||
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-- | ||
Deprecated: json_validate(): Passing null to parameter #1 ($json) of type string is deprecated in %s on line %d | ||
bool(false) | ||
int(4) | ||
string(12) "Syntax error" | ||
bool(false) | ||
int(4) | ||
string(12) "Syntax error" | ||
bool(false) | ||
int(4) | ||
string(12) "Syntax error" | ||
bool(false) | ||
int(4) | ||
string(12) "Syntax error" | ||
bool(false) | ||
int(1) | ||
string(28) "Maximum stack depth exceeded" | ||
bool(true) | ||
int(0) | ||
string(8) "No error" | ||
Error: 0 json_validate(): Argument #2 ($depth) must be greater than 0 | ||
int(0) | ||
string(8) "No error" | ||
Error: 0 json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE) | ||
int(0) | ||
string(8) "No error" | ||
Error: 0 json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE) | ||
int(0) | ||
string(8) "No error" | ||
bool(false) | ||
int(4) | ||
string(12) "Syntax error" | ||
bool(true) | ||
int(0) | ||
string(8) "No error" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--TEST-- | ||
json_validate() - Error handling for max depth | ||
--SKIPIF-- | ||
<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only"); ?> | ||
--FILE-- | ||
<?php | ||
|
||
try { | ||
var_dump(json_validate("-", PHP_INT_MAX)); | ||
} catch (ValueError $error) { | ||
echo $error->getMessage() . PHP_EOL; | ||
var_dump(json_last_error(), json_last_error_msg()); | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
json_validate(): Argument #2 ($depth) must be less than %d | ||
int(0) | ||
string(8) "No error" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--TEST-- | ||
json_validate() - Invalid UTF-8's | ||
--FILE-- | ||
<?php | ||
|
||
require_once("json_validate_requires.inc"); | ||
|
||
echo "Testing Invalid UTF-8" . PHP_EOL; | ||
|
||
|
||
json_validate_trycatchdump("\"a\xb0b\""); | ||
json_validate_trycatchdump("\"a\xd0\xf2b\""); | ||
json_validate_trycatchdump("\"\x61\xf0\x80\x80\x41\""); | ||
json_validate_trycatchdump("[\"\xc1\xc1\",\"a\"]"); | ||
|
||
json_validate_trycatchdump("\"a\xb0b\"", 512, JSON_INVALID_UTF8_IGNORE); | ||
json_validate_trycatchdump("\"a\xd0\xf2b\"", 512, JSON_INVALID_UTF8_IGNORE); | ||
json_validate_trycatchdump("\"\x61\xf0\x80\x80\x41\"", 512, JSON_INVALID_UTF8_IGNORE); | ||
json_validate_trycatchdump("[\"\xc1\xc1\",\"a\"]", 512, JSON_INVALID_UTF8_IGNORE); | ||
|
||
?> | ||
--EXPECT-- | ||
Testing Invalid UTF-8 | ||
bool(false) | ||
int(5) | ||
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" | ||
bool(false) | ||
int(5) | ||
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" | ||
bool(false) | ||
int(5) | ||
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" | ||
bool(false) | ||
int(5) | ||
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded" | ||
bool(true) | ||
int(0) | ||
string(8) "No error" | ||
bool(true) | ||
int(0) | ||
string(8) "No error" | ||
bool(true) | ||
int(0) | ||
string(8) "No error" | ||
bool(true) | ||
int(0) | ||
string(8) "No error" |
Uh oh!
There was an error while loading. Please reload this page.