Patch max_input_vars.patch for *General Issues Bug #60655
Patch version 2012-01-05 05:04 UTC
Return to Bug #60655
| Download this patch
Patch Revisions:
2012-01-05 05:04 UTC | 2012-01-05 05:03 UTC | 2012-01-05 05:02 UTC | 2012-01-05 04:17 UTC | 2012-01-05 04:08 UTCDeveloper: laruence@php.net
-Warning: unserialize() expects exactly 1 parameter, 2 given in %s on line 21
+Notice: unserialize(): Error at offset 0 of 1 bytes in %sserialization_error_001.php on line %d
bool(false)
Done
Index: trunk/ext/standard/tests/serialize/unserialize_max_vars.phpt
===================================================================
--- trunk/ext/standard/tests/serialize/unserialize_max_vars.phpt (revision 0)
+++ trunk/ext/standard/tests/serialize/unserialize_max_vars.phpt (revision 0)
@@ -0,0 +1,57 @@
+--TEST--
+Test unserialize() functions with max_input_vars
+--FILE--
+<?php
+$str = serialize(array(1,2,3)); // there will be 4 items, array, and 1, 2, 3
+
+print_r(unserialize($str, 3));
+print_r(unserialize($str, 4));
+
+$str = serialize(array(array(),array(2,3))); // there will be 5 items, array, and array, array, 2, 3
+print_r(unserialize($str, 3));
+print_r(unserialize($str, 5));
+
+$obj = (object)(array(array(),array(2,3)));
+$str = serialize($obj);
+
+print_r(unserialize($str, 3));
+print_r(unserialize($str, 5));
+?>
+--EXPECTF--
+Warning: unserialize(): Unserialized variables exceeded 3 in %sunserialize_max_vars.php on line %d
+Array
+(
+ [0] => 1
+ [1] => 2
+ [2] => 3
+)
+
+Warning: unserialize(): Unserialized variables exceeded 3 in %sunserialize_max_vars.php on line %d
+Array
+(
+ [0] => Array
+ (
+ )
+
+ [1] => Array
+ (
+ [0] => 2
+ [1] => 3
+ )
+
+)
+
+Warning: unserialize(): Unserialized variables exceeded 3 in %sunserialize_max_vars.php on line %d
+stdClass Object
+(
+ [0] => Array
+ (
+ )
+
+ [1] => Array
+ (
+ [0] => 2
+ [1] => 3
+ )
+
+)
Index: trunk/ext/standard/var_unserializer.c
===================================================================
--- trunk/ext/standard/var_unserializer.c (revision 321767)
+++ trunk/ext/standard/var_unserializer.c (working copy)
FREE_ZVAL(key);
return 0;
}
+ --(BG(unserialize).num_vars);
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
zval_dtor(key);
@@ -297,12 +298,14 @@
switch (Z_TYPE_P(key)) {
+ }
if (var_hash && cursor[0] != 'R') {
var_push(var_hash, rval);
}
}
start = cursor;
-
-
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 616 "ext/standard/var_unserializer.re"
+#line 632 "ext/standard/var_unserializer.re"
{
INIT_PZVAL(*rval);
+ ++(BG(unserialize).num_vars);
{
INIT_PZVAL(*rval);
+ ++(BG(unserialize).num_vars);
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 716 "ext/standard/var_unserializer.c"
Index: trunk/ext/standard/php_var.h
===================================================================
--- trunk/ext/standard/php_var.h (revision 321767)
+++ trunk/ext/standard/php_var.h (working copy)
@@ -95,9 +95,12 @@
@@ -95,9 +95,13 @@
} else { \
(var_hash_ptr) = (php_serialize_data_t)BG(unserialize).var_hash; \
++BG(unserialize).level; \
- } \
+ } \
+ BG(unserialize).num_vars = 0; \
+ BG(unserialize).max_vars = 0; \
} while (0)
+#define PHP_VAR_UNSERIALIZE_MAX_VARS(max_vars) BG(unserialize).max_vars = max_vars;
+
return 1;
}
@@ -533,6 +545,7 @@
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -561,6 +574,7 @@
INIT_PZVAL(*rval);
ZVAL_STRINGL(*rval, str, len, 1);
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -590,6 +604,7 @@
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -561,6 +574,7 @@
INIT_PZVAL(*rval);
ZVAL_STRINGL(*rval, str, len, 1);
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -590,6 +604,7 @@
INIT_PZVAL(*rval);
ZVAL_STRINGL(*rval, str, len, 0);
+ ++(BG(unserialize).num_vars);
{
int utf16_len;
zval *z;
@@ -627,7 +628,7 @@
}
}
ALLOC_INIT_ZVAL(z);
- jp = new_JSON_parser(depth);
+ jp = new_JSON_parser(depth, max_vars);
if (parse_JSON_ex(jp, z, utf16, utf16_len, options TSRMLS_CC)) {
+$x = json_decode($json, false, 512, 1000, JSON_BIGINT_AS_STRING);
var_dump($x->largenum);
echo "Done\n";
?>
Index: trunk/ext/json/tests/max_input_vars.phpt
===================================================================
--- trunk/ext/json/tests/max_input_vars.phpt (revision 0)
+++ trunk/ext/json/tests/max_input_vars.phpt (revision 0)
@@ -0,0 +1,40 @@
+--TEST--
+json_decode() with max_input_vars
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+$a = array(1,2,3,4); //an array, and 1,2,3,4 total 5 elements
+$str = json_encode($a);
+
+print_r(json_decode($str, false, 512, 4));
+var_dump(json_last_error() == JSON_ERROR_MAX_VARS);
+print_r(json_decode($str, false, 512, 5));
+
+$a = array(1,array(1),3); //an array, 1, an array, 1, 3 total 5 elements
+$str = json_encode($a);
+print_r(json_decode($str, true, 512, 4));
+var_dump(json_last_error() == JSON_ERROR_MAX_VARS);
+print_r(json_decode($str, true, 512, 5));
+?>
+--EXPECT--
+bool(true)
+Array
+(
+ [0] => 1
+ [1] => 2
+ [2] => 3
+ [3] => 4
+)
+bool(true)
+Array
+(
+ [0] => 1
+ [1] => Array
+ (
+ [0] => 1
+ )
+
+ [2] => 3
+)
Index: trunk/ext/json/tests/json_decode_error.phpt
===================================================================
--- trunk/ext/json/tests/json_decode_error.phpt (revision 321767)
+++ trunk/ext/json/tests/json_decode_error.phpt (working copy)
echo "\n-- Testing json_decode() function with more than expected no. of arguments --\n";
$extra_arg = 10;
-var_dump( json_decode('"abc"', TRUE, 512, 0, $extra_arg) );
+var_dump( json_decode('"abc"', TRUE, 512, 0, 1000, $extra_arg) );
?>
===Done===
@@ -34,6 +34,6 @@
?>
===Done===
@@ -34,6 +34,6 @@
-- Testing json_decode() function with more than expected no. of arguments --
-Warning: json_decode() expects at most 4 parameters, 5 given in %s on line %d
+Warning: json_decode() expects at most 5 parameters, 6 given in %s on line %d
if (jp->top > 1) {
attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
+ ++num_vars;
}
}
JSON_RESET_TYPE();
@@ -643,6 +658,7 @@
static inline void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC)
{
- php_json_decode_ex(return_value, str, str_len, assoc ? PHP_JSON_OBJECT_AS_ARRAY : 0, depth TSRMLS_CC);
+ php_json_decode_ex(return_value, str, str_len, assoc ? PHP_JSON_OBJECT_AS_ARRAY : 0, depth, 0 TSRMLS_CC);
}
}
Index: trunk/ext/json/JSON_parser.h
===================================================================
--- trunk/ext/json/JSON_parser.h (revision 321767)
+++ trunk/ext/json/JSON_parser.h (working copy)
@@ -15,20 +15,22 @@
int top;
int error_code;
int* stack;
+ long max_vars;
zval **the_zstack;
zval *the_static_zstack[JSON_PARSER_DEFAULT_DEPTH];
} * JSON_parser;
int top;
int error_code;
int* stack;
+ long max_vars;
zval **the_zstack;
zval *the_static_zstack[JSON_PARSER_DEFAULT_DEPTH];
} * JSON_parser;
enum error_codes {
PHP_JSON_ERROR_NONE = 0,
- PHP_JSON_ERROR_DEPTH,
+ PHP_JSON_ERROR_DEPTH,
PHP_JSON_ERROR_SYNTAX,
- PHP_JSON_ERROR_UTF8
+ PHP_JSON_ERROR_UTF8,
+ PHP_JSON_ERROR_MAX_VARS,
};
-extern JSON_parser new_JSON_parser(int depth);
+extern JSON_parser new_JSON_parser(int depth, long max_vars);
};
-extern JSON_parser new_JSON_parser(int depth);
+extern JSON_parser new_JSON_parser(int depth, long max_vars);
extern int parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int options TSRMLS_DC);
extern int free_JSON_parser(JSON_parser jp);
Index: trunk/main/rfc1867.c
continue;
}
Index: trunk/main/php_variables.c
===================================================================
===================================================================
--- trunk/main/php_variables.c (revision 321767)
+++ trunk/main/php_variables.c (working copy)
@@ -178,15 +178,10 @@
} else {
- }
- MAKE_STD_ZVAL(gpc_element);
- array_init(gpc_element);
- zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
- }
- }
+ || Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
+ MAKE_STD_ZVAL(gpc_element);
+ array_init(gpc_element);
+ zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
{
char *var, *val, *e, *s, *p;
zval *array_ptr = (zval *) arg;
+ long num_vars = 0;
if (SG(request_info).post_data == NULL) {
return;
return;
@@ -270,6 +259,11 @@
}
efree(val);
}
}
+ ++num_vars;
+ if (PG(max_input_vars) && num_vars >= PG(max_input_vars)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Post variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
+ return;
+ }
+ }
s = p + 1;
}
}
if (s < e) {
Index: branches/PHP_5_3/ext/standard/basic_functions.h
===================================================================
--- branches/PHP_5_3/ext/standard/basic_functions.h (revision 321767)
+++ branches/PHP_5_3/ext/standard/basic_functions.h (working copy)
@@ -208,6 +208,10 @@
/* var.c */
zend_class_entry *incomplete_class;
+ struct {
+ long max_vars;
+ long num_vars;
+ } unserialize;
/* url_scanner_ex.re */
url_adapt_state_ex_t url_adapt_state_ex;
Index: branches/PHP_5_3/ext/standard/var.c
===================================================================
--- branches/PHP_5_3/ext/standard/var.c (revision 321767)
+++ branches/PHP_5_3/ext/standard/var.c (working copy)
@@ -923,8 +923,9 @@
int buf_len;
const unsigned char *p;
php_unserialize_data_t var_hash;
+ long max_vars = PG(max_input_vars);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &buf, &buf_len, &max_vars) == FAILURE) {
RETURN_FALSE;
}
@@ -934,10 +935,13 @@
p = (const unsigned char*) buf;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ PHP_VAR_UNSERIALIZE_MAX_VARS(max_vars);
if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) {
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
zval_dtor(return_value);
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
+ if (!BG(unserialize).max_vars || BG(unserialize).num_vars < BG(unserialize).max_vars) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
+ }
RETURN_FALSE;
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
Index: branches/PHP_5_3/ext/standard/php_var.h
===================================================================
--- branches/PHP_5_3/ext/standard/php_var.h (revision 321767)
+++ branches/PHP_5_3/ext/standard/php_var.h (working copy)
@@ -21,6 +21,7 @@
#ifndef PHP_VAR_H
#define PHP_VAR_H
+#include "ext/standard/basic_functions.h"
#include "ext/standard/php_smart_str_public.h"
PHP_FUNCTION(var_dump);
@@ -57,10 +58,15 @@
#define PHP_VAR_UNSERIALIZE_INIT(var_hash) \
(var_hash).first = 0; \
- (var_hash).first_dtor = 0
+ (var_hash).first_dtor = 0; \
+ BG(unserialize).num_vars = 0; \
+ BG(unserialize).max_vars = 0
+
#define PHP_VAR_UNSERIALIZE_DESTROY(var_hash) \
var_destroy(&(var_hash))
+#define PHP_VAR_UNSERIALIZE_MAX_VARS(max_vars) BG(unserialize).max_vars = max_vars
+
PHPAPI void var_replace(php_unserialize_data_t *var_hash, zval *ozval, zval **nzval);
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hash, zval **val);
PHPAPI void var_destroy(php_unserialize_data_t *var_hash);
Index: branches/PHP_5_3/ext/standard/var_unserializer.re
===================================================================
--- branches/PHP_5_3/ext/standard/var_unserializer.re (revision 321767)
+++ branches/PHP_5_3/ext/standard/var_unserializer.re (working copy)
@@ -269,6 +269,7 @@
FREE_ZVAL(key);
return 0;
}
+ --(BG(unserialize).num_vars);
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
zval_dtor(key);
@@ -398,6 +399,11 @@
limit = cursor = *p;
+ if (BG(unserialize).max_vars && BG(unserialize).num_vars >= BG(unserialize).max_vars) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unserialized variables exceeded %ld", BG(unserialize).max_vars);
+ return 0;
+ }
+
if (var_hash && cursor[0] != 'R') {
var_push(var_hash, rval);
}
@@ -425,7 +431,7 @@
*rval = *rval_ref;
Z_ADDREF_PP(rval);
Z_SET_ISREF_PP(rval);
-
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -449,6 +455,7 @@
Z_ADDREF_PP(rval);
Z_UNSET_ISREF_PP(rval);
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -456,6 +463,7 @@
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_NULL(*rval);
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -463,6 +471,7 @@
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_BOOL(*rval, parse_iv(start + 2));
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -490,6 +499,7 @@
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_LONG(*rval, parse_iv(start + 2));
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -505,6 +515,7 @@
ZVAL_DOUBLE(*rval, -php_get_inf());
}
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -515,6 +526,7 @@
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -543,6 +555,7 @@
INIT_PZVAL(*rval);
ZVAL_STRINGL(*rval, str, len, 1);
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -572,6 +585,7 @@
INIT_PZVAL(*rval);
ZVAL_STRINGL(*rval, str, len, 0);
+ ++(BG(unserialize).num_vars);
return 1;
}
@@ -588,6 +602,7 @@
array_init_size(*rval, elements);
+ ++(BG(unserialize).num_vars);
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements, 0)) {
return 0;
}
@@ -599,6 +614,7 @@
INIT_PZVAL(*rval);
+ ++(BG(unserialize).num_vars);
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
@@ -701,6 +717,7 @@
*p = YYCURSOR;
if (custom_object) {
+ ++(BG(unserialize).num_vars);
int ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
if (ret && incomplete_class) {
@@ -717,6 +734,7 @@
}
efree(class_name);
+ ++(BG(unserialize).num_vars);
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
Index: branches/PHP_5_3/ext/json/json.c
===================================================================
--- branches/PHP_5_3/ext/json/json.c (revision 321767)
+++ branches/PHP_5_3/ext/json/json.c (working copy)
@@ -76,6 +76,7 @@
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_MAX_VARS", PHP_JSON_ERROR_MAX_VARS, 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);
@@ -485,7 +486,7 @@
}
/* }}} */
-PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC) /* {{{ */
+PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, zend_bool assoc, long depth, long max_vars TSRMLS_DC) /* {{{ */
{
int utf16_len;
zval *z;
@@ -510,7 +511,7 @@
}
ALLOC_INIT_ZVAL(z);
- jp = new_JSON_parser(depth);
+ jp = new_JSON_parser(depth, max_vars);
if (parse_JSON(jp, z, utf16, utf16_len, assoc TSRMLS_CC)) {
*return_value = *z;
}
@@ -584,8 +585,9 @@
int str_len;
zend_bool assoc = 0; /* return JS objects as PHP objects by default */
long depth = JSON_PARSER_DEFAULT_DEPTH;
+ long max_vars = PG(max_input_vars);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &str, &str_len, &assoc, &depth) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bll", &str, &str_len, &assoc, &depth, &max_vars) == FAILURE) {
return;
}
@@ -595,7 +597,7 @@
RETURN_NULL();
}
- php_json_decode(return_value, str, str_len, assoc, depth TSRMLS_CC);
+ php_json_decode_ex(return_value, str, str_len, assoc, depth, max_vars TSRMLS_CC);
}
/* }}} */
Index: branches/PHP_5_3/ext/json/tests/json_decode_error.phpt
===================================================================
--- branches/PHP_5_3/ext/json/tests/json_decode_error.phpt (revision 321767)
+++ branches/PHP_5_3/ext/json/tests/json_decode_error.phpt (working copy)
@@ -20,7 +20,7 @@
echo "\n-- Testing json_decode() function with more than expected no. of arguments --\n";
$extra_arg = 10;
-var_dump( json_decode('"abc"', TRUE, 512, $extra_arg) );
+var_dump( json_decode('"abc"', TRUE, 512, 1000, $extra_arg) );
?>
===Done===
@@ -34,6 +34,6 @@
-- Testing json_decode() function with more than expected no. of arguments --
-Warning: json_decode() expects at most 3 parameters, 4 given in %s on line %d
+Warning: json_decode() expects at most 4 parameters, 5 given in %s on line %d
NULL
===Done===
Index: branches/PHP_5_3/ext/json/JSON_parser.c
===================================================================
--- branches/PHP_5_3/ext/json/JSON_parser.c (revision 321767)
+++ branches/PHP_5_3/ext/json/JSON_parser.c (working copy)
@@ -239,11 +239,12 @@
JSON_checker_char will delete the JSON_checker object if it sees an error.
*/
JSON_parser
-new_JSON_parser(int depth)
+new_JSON_parser(int depth, long max_vars)
{
JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct));
jp->state = GO;
jp->depth = depth;
+ jp->max_vars = max_vars;
jp->top = -1;
jp->error_code = PHP_JSON_ERROR_NONE;
jp->stack = (int*)ecalloc(depth, sizeof(int));
@@ -426,6 +427,7 @@
int next_class; /* the next character class */
int next_state; /* the next state */
int the_index;
+ long num_vars = 1; /* the container is also counted in */
smart_str buf = {0};
smart_str key = {0};
@@ -436,6 +438,11 @@
JSON_RESET_TYPE();
for (the_index = 0; the_index < length; the_index += 1) {
+ if (jp->max_vars && num_vars >= jp->max_vars) {
+ jp->error_code = PHP_JSON_ERROR_MAX_VARS;
+ FREE_BUFFERS();
+ return false;
+ }
next_char = utf16_json[the_index];
if (next_char >= 128) {
next_class = C_ETC;
@@ -540,6 +547,7 @@
}
key.len = 0;
buf.len = 0;
+ ++num_vars;
JSON_RESET_TYPE();
}
@@ -561,6 +569,7 @@
json_create_zval(&mval, &buf, type);
add_next_index_zval(jp->the_zstack[jp->top], mval);
buf.len = 0;
+ ++num_vars;
JSON_RESET_TYPE();
}
@@ -585,6 +594,7 @@
if (jp->top == 1) {
obj = z;
} else {
+ ++num_vars;
ALLOC_INIT_ZVAL(obj);
}
@@ -626,6 +636,7 @@
if (jp->top > 1) {
attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC);
+ ++num_vars;
}
JSON_RESET_TYPE();
@@ -683,6 +694,7 @@
} else {
add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval);
}
+ ++num_vars;
key.len = 0;
}
jp->state = KE;
@@ -691,6 +703,7 @@
case MODE_ARRAY:
if (type != -1) {
add_next_index_zval(jp->the_zstack[jp->top], mval);
+ ++num_vars;
}
jp->state = VA;
break;
Index: branches/PHP_5_3/ext/json/php_json.h
===================================================================
--- branches/PHP_5_3/ext/json/php_json.h (revision 321767)
+++ branches/PHP_5_3/ext/json/php_json.h (working copy)
@@ -48,7 +48,11 @@
#endif
PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC);
-PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC);
+PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, zend_bool assoc, long depth, long max_vars TSRMLS_DC);
+static inline void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC)
+{
+ php_json_decode_ex(return_value, str, str_len, assoc, depth, 0 TSRMLS_CC);
+}
#define PHP_JSON_HEX_TAG (1<<0)
#define PHP_JSON_HEX_AMP (1<<1)
Index: branches/PHP_5_3/ext/json/JSON_parser.h
===================================================================
--- branches/PHP_5_3/ext/json/JSON_parser.h (revision 321767)
+++ branches/PHP_5_3/ext/json/JSON_parser.h (working copy)
@@ -14,6 +14,7 @@
int top;
int error_code;
int* stack;
+ long max_vars;
zval **the_zstack;
zval *the_static_zstack[JSON_PARSER_DEFAULT_DEPTH];
} * JSON_parser;
@@ -24,10 +25,11 @@
PHP_JSON_ERROR_STATE_MISMATCH,
PHP_JSON_ERROR_CTRL_CHAR,
PHP_JSON_ERROR_SYNTAX,
- PHP_JSON_ERROR_UTF8
+ PHP_JSON_ERROR_UTF8,
+ PHP_JSON_ERROR_MAX_VARS
};
-extern JSON_parser new_JSON_parser(int depth);
+extern JSON_parser new_JSON_parser(int depth, long max_vars);
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);
#endif
Index: branches/PHP_5_3/main/rfc1867.c
===================================================================
--- branches/PHP_5_3/main/rfc1867.c (revision 321767)
+++ branches/PHP_5_3/main/rfc1867.c (working copy)
-Warning: unserialize() expects exactly 1 parameter, 2 given in %s on line 21
+Notice: unserialize(): Error at offset 0 of 1 bytes in %sserialization_error_001.php on line %d
bool(false)
Done
Index: branches/PHP_5_4/ext/standard/tests/serialize/unserialize_max_vars.phpt
===================================================================
--- branches/PHP_5_4/ext/standard/tests/serialize/unserialize_max_vars.phpt (revision 0)
+++ branches/PHP_5_4/ext/standard/tests/serialize/unserialize_max_vars.phpt (revision 0)
@@ -0,0 +1,57 @@
+--TEST--
+Test unserialize() functions with max_input_vars
+--FILE--
+<?php
+$str = serialize(array(1,2,3)); // there will be 4 items, array, and 1, 2, 3
+
+print_r(unserialize($str, 3));
+print_r(unserialize($str, 4));
+
+$str = serialize(array(array(),array(2,3))); // there will be 5 items, array, and array, array, 2, 3
+print_r(unserialize($str, 3));
+print_r(unserialize($str, 5));
+
+$obj = (object)(array(array(),array(2,3)));
+$str = serialize($obj);
+
+print_r(unserialize($str, 3));
+print_r(unserialize($str, 5));
+?>
+--EXPECTF--
+Warning: unserialize(): Unserialized variables exceeded 3 in %sunserialize_max_vars.php on line %d
+Array
+(
+ [0] => 1
+ [1] => 2
+ [2] => 3
+)
+
+Warning: unserialize(): Unserialized variables exceeded 3 in %sunserialize_max_vars.php on line %d
+Array
+(
+ [0] => Array
+ (
+ )
+
+ [1] => Array
+ (
+ [0] => 2
+ [1] => 3
+ )
+
+)
+
+Warning: unserialize(): Unserialized variables exceeded 3 in %sunserialize_max_vars.php on line %d
+stdClass Object
+(
+ [0] => Array
+ (
+ )
+
+ [1] => Array
+ (
+ [0] => 2
+ [1] => 3
+ )
+
+)
Index: branches/PHP_5_4/ext/standard/var_unserializer.c
===================================================================
--- branches/PHP_5_4/ext/standard/var_unserializer.c (revision 321767)
+++ branches/PHP_5_4/ext/standard/var_unserializer.c (working copy)
Index: branches/PHP_5_4/ext/standard/php_var.h
===================================================================
--- branches/PHP_5_4/ext/standard/php_var.h (revision 321767)
+++ branches/PHP_5_4/ext/standard/php_var.h (working copy)
@@ -95,9 +95,12 @@
@@ -95,9 +95,13 @@
} else { \
(var_hash_ptr) = (php_serialize_data_t)BG(unserialize).var_hash; \
++BG(unserialize).level; \
- } \
+ } \
+ BG(unserialize).num_vars = 0; \
+ BG(unserialize).max_vars = 0; \
} while (0)
+#define PHP_VAR_UNSERIALIZE_MAX_VARS(max_vars) BG(unserialize).max_vars = max_vars;
+
|