Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Secured unserialize #315

Closed
wants to merge 3 commits into from

3 participants

@smalyshev
Owner

Implementation of secured unserialize() RFC here: https://wiki.php.net/rfc/secure_unserialize

@hakre

What is the current status quo of memory bombs and array key attacks?

@weltling

Core tests pass on windows and linux. Looks like like there is a green light at least in 5.4 the patch is made upon )

@smalyshev smalyshev added the RFC label
@smalyshev
Owner

Closing, will move to master.

@smalyshev smalyshev closed this
@smalyshev
Owner

See #908

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 30, 2013
  1. @smalyshev
  2. @smalyshev
  3. @smalyshev

    add tests

    smalyshev authored
This page is out of date. Refresh to see the latest.
View
1  ext/standard/php_var.h
@@ -51,6 +51,7 @@ typedef struct php_unserialize_data* php_unserialize_data_t;
PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC);
PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC);
+PHPAPI int php_var_unserialize_ex(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes TSRMLS_DC);
#define PHP_VAR_SERIALIZE_INIT(var_hash_ptr) \
do { \
View
6 ext/standard/tests/serialize/serialization_error_001.phpt
@@ -21,7 +21,7 @@ var_dump( unserialize() );
//Test serialize with one more than the expected number of arguments
var_dump( serialize(1,2) );
-var_dump( unserialize(1,2) );
+var_dump( unserialize(1,2,3) );
echo "Done";
?>
@@ -31,12 +31,12 @@ echo "Done";
Warning: serialize() expects exactly 1 parameter, 0 given in %s on line 16
NULL
-Warning: unserialize() expects exactly 1 parameter, 0 given in %s on line 17
+Warning: unserialize() expects at least 1 parameter, 0 given in %s on line 17
bool(false)
Warning: serialize() expects exactly 1 parameter, 2 given in %s on line 20
NULL
-Warning: unserialize() expects exactly 1 parameter, 2 given in %s on line 21
+Warning: unserialize() expects at most 2 parameters, 3 given in %s on line 21
bool(false)
Done
View
88 ext/standard/tests/serialize/unserialize_classes.phpt
@@ -0,0 +1,88 @@
+--TEST--
+Test unserialize() with second parameter
+--FILE--
+<?php
+class foo {
+ public $x = "bar";
+}
+$z = array(new foo(), 2, "3");
+$s = serialize($z);
+
+var_dump(unserialize($s));
+var_dump(unserialize($s, false));
+var_dump(unserialize($s, true));
+var_dump(unserialize($s, array("bar")));
+var_dump(unserialize($s, array("FOO")));
+var_dump(unserialize($s, array("bar", "fOo")));
+
+--EXPECTF--
+array(3) {
+ [0]=>
+ object(foo)#%d (1) {
+ ["x"]=>
+ string(3) "bar"
+ }
+ [1]=>
+ int(2)
+ [2]=>
+ string(1) "3"
+}
+array(3) {
+ [0]=>
+ object(__PHP_Incomplete_Class)#%d (2) {
+ ["__PHP_Incomplete_Class_Name"]=>
+ string(3) "foo"
+ ["x"]=>
+ string(3) "bar"
+ }
+ [1]=>
+ int(2)
+ [2]=>
+ string(1) "3"
+}
+array(3) {
+ [0]=>
+ object(foo)#%d (1) {
+ ["x"]=>
+ string(3) "bar"
+ }
+ [1]=>
+ int(2)
+ [2]=>
+ string(1) "3"
+}
+array(3) {
+ [0]=>
+ object(__PHP_Incomplete_Class)#%d (2) {
+ ["__PHP_Incomplete_Class_Name"]=>
+ string(3) "foo"
+ ["x"]=>
+ string(3) "bar"
+ }
+ [1]=>
+ int(2)
+ [2]=>
+ string(1) "3"
+}
+array(3) {
+ [0]=>
+ object(foo)#%d (1) {
+ ["x"]=>
+ string(3) "bar"
+ }
+ [1]=>
+ int(2)
+ [2]=>
+ string(1) "3"
+}
+array(3) {
+ [0]=>
+ object(foo)#%d (1) {
+ ["x"]=>
+ string(3) "bar"
+ }
+ [1]=>
+ int(2)
+ [2]=>
+ string(1) "3"
+}
View
38 ext/standard/var.c
@@ -945,7 +945,7 @@ PHP_FUNCTION(serialize)
}
/* }}} */
-/* {{{ proto mixed unserialize(string variable_representation)
+/* {{{ proto mixed unserialize(string variable_representation[, bool|array allowed_classes])
Takes a string representation of variable and recreates it */
PHP_FUNCTION(unserialize)
{
@@ -953,8 +953,10 @@ PHP_FUNCTION(unserialize)
int buf_len;
const unsigned char *p;
php_unserialize_data_t var_hash;
+ zval *classes = NULL;
+ HashTable *class_hash = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &buf, &buf_len, &classes) == FAILURE) {
RETURN_FALSE;
}
@@ -964,8 +966,35 @@ PHP_FUNCTION(unserialize)
p = (const unsigned char*) buf;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
- if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) {
+ if(classes != NULL) {
+ if(Z_TYPE_P(classes) == IS_ARRAY || !zend_is_true(classes)) {
+ ALLOC_HASHTABLE(class_hash);
+ zend_hash_init(class_hash, (Z_TYPE_P(classes) == IS_ARRAY)?zend_hash_num_elements(Z_ARRVAL_P(classes)):0, NULL, NULL, 0);
+ }
+ if(class_hash && Z_TYPE_P(classes) == IS_ARRAY) {
+ HashPosition pos;
+ HashTable *ht = Z_ARRVAL_P(classes);
+ zval **data;
+ ALLOCA_FLAG(use_heap)
+
+ zend_hash_internal_pointer_reset_ex(ht, &pos);
+ while(zend_hash_get_current_data_ex(ht, (void **)&data, &pos) == SUCCESS) {
+ char *lc_name;
+ convert_to_string_ex(data);
+ lc_name = do_alloca(Z_STRLEN_PP(data) + 1, use_heap);
+ zend_str_tolower_copy(lc_name, Z_STRVAL_PP(data), Z_STRLEN_PP(data));
+ zend_hash_add_empty_element(class_hash, lc_name, Z_STRLEN_PP(data));
+ free_alloca(lc_name, use_heap);
+ zend_hash_move_forward_ex(ht, &pos);
+ }
+ }
+ }
+
+ if (!php_var_unserialize_ex(&return_value, &p, p + buf_len, &var_hash, class_hash TSRMLS_CC)) {
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ if(class_hash) {
+ zend_hash_destroy(class_hash);
+ }
zval_dtor(return_value);
if (!EG(exception)) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
@@ -973,6 +1002,9 @@ PHP_FUNCTION(unserialize)
RETURN_FALSE;
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ if(class_hash) {
+ zend_hash_destroy(class_hash);
+ }
}
/* }}} */
View
106 ext/standard/var_unserializer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Sat Mar 9 22:33:09 2013 */
+/* Generated by re2c 0.13.5 on Sat Mar 30 12:24:34 2013 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
@@ -194,6 +194,25 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
return str;
}
+static inline int unserialize_allowed_class(const char *class_name, int len, HashTable *classes)
+{
+ char *lc_name;
+ int res;
+ ALLOCA_FLAG(use_heap)
+
+ if(classes == NULL) {
+ return 1;
+ }
+ if(!zend_hash_num_elements(classes)) {
+ return 0;
+ }
+ lc_name = do_alloca(len + 1, use_heap);
+ zend_str_tolower_copy(lc_name, class_name, len);
+ res = zend_hash_exists(classes, lc_name, len);
+ free_alloca(lc_name, use_heap);
+ return res;
+}
+
#define YYFILL(n) do { } while (0)
#define YYCTYPE unsigned char
#define YYCURSOR cursor
@@ -201,7 +220,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
#define YYMARKER marker
-#line 209 "ext/standard/var_unserializer.re"
+#line 228 "ext/standard/var_unserializer.re"
@@ -261,8 +280,8 @@ static inline size_t parse_uiv(const unsigned char *p)
return result;
}
-#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC
-#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC
+#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes TSRMLS_DC
+#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes TSRMLS_CC
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops)
{
@@ -271,7 +290,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
ALLOC_INIT_ZVAL(key);
- if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
+ if (!php_var_unserialize_ex(&key, p, max, NULL, classes TSRMLS_CC)) {
zval_dtor(key);
FREE_ZVAL(key);
return 0;
@@ -285,7 +304,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
ALLOC_INIT_ZVAL(data);
- if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
+ if (!php_var_unserialize_ex(&data, p, max, var_hash, classes TSRMLS_CC)) {
zval_dtor(key);
FREE_ZVAL(key);
zval_dtor(data);
@@ -411,7 +430,14 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
# pragma optimize("", on)
#endif
-PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
+PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC)
+{
+ HashTable *classes = NULL;
+ return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
+}
+
+
+PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
zval **rval_ref;
@@ -432,7 +458,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
-#line 436 "ext/standard/var_unserializer.c"
+#line 462 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
@@ -492,9 +518,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy95;
yy3:
-#line 785 "ext/standard/var_unserializer.re"
+#line 817 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 498 "ext/standard/var_unserializer.c"
+#line 524 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy89;
@@ -537,13 +563,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
goto yy3;
yy14:
++YYCURSOR;
-#line 779 "ext/standard/var_unserializer.re"
+#line 811 "ext/standard/var_unserializer.re"
{
/* this is the case where we have less data than planned */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
return 0; /* not sure if it should be 0 or 1 here? */
}
-#line 547 "ext/standard/var_unserializer.c"
+#line 573 "ext/standard/var_unserializer.c"
yy16:
yych = *++YYCURSOR;
goto yy3;
@@ -573,7 +599,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 635 "ext/standard/var_unserializer.re"
+#line 661 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
long elements;
@@ -624,6 +650,12 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
class_name = estrndup(class_name, len);
do {
+ if(!unserialize_allowed_class(class_name, len, classes)) {
+ incomplete_class = 1;
+ ce = PHP_IC_ENTRY;
+ break;
+ }
+
/* Try to find class directly */
BG(serialize_lock) = 1;
if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
@@ -717,7 +749,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 721 "ext/standard/var_unserializer.c"
+#line 753 "ext/standard/var_unserializer.c"
yy25:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -742,7 +774,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 627 "ext/standard/var_unserializer.re"
+#line 653 "ext/standard/var_unserializer.re"
{
INIT_PZVAL(*rval);
@@ -750,7 +782,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 754 "ext/standard/var_unserializer.c"
+#line 786 "ext/standard/var_unserializer.c"
yy32:
yych = *++YYCURSOR;
if (yych == '+') goto yy33;
@@ -771,7 +803,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '{') goto yy18;
++YYCURSOR;
-#line 607 "ext/standard/var_unserializer.re"
+#line 633 "ext/standard/var_unserializer.re"
{
long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
@@ -791,7 +823,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 795 "ext/standard/var_unserializer.c"
+#line 827 "ext/standard/var_unserializer.c"
yy39:
yych = *++YYCURSOR;
if (yych == '+') goto yy40;
@@ -812,7 +844,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 578 "ext/standard/var_unserializer.re"
+#line 604 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -841,7 +873,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_STRINGL(*rval, str, len, 0);
return 1;
}
-#line 845 "ext/standard/var_unserializer.c"
+#line 877 "ext/standard/var_unserializer.c"
yy46:
yych = *++YYCURSOR;
if (yych == '+') goto yy47;
@@ -862,7 +894,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 550 "ext/standard/var_unserializer.re"
+#line 576 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -890,7 +922,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_STRINGL(*rval, str, len, 1);
return 1;
}
-#line 894 "ext/standard/var_unserializer.c"
+#line 926 "ext/standard/var_unserializer.c"
yy53:
yych = *++YYCURSOR;
if (yych <= '/') {
@@ -978,7 +1010,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
}
yy63:
++YYCURSOR;
-#line 540 "ext/standard/var_unserializer.re"
+#line 566 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
use_double:
@@ -988,7 +1020,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
return 1;
}
-#line 992 "ext/standard/var_unserializer.c"
+#line 1024 "ext/standard/var_unserializer.c"
yy65:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1047,7 +1079,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 525 "ext/standard/var_unserializer.re"
+#line 551 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
@@ -1062,7 +1094,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return 1;
}
-#line 1066 "ext/standard/var_unserializer.c"
+#line 1098 "ext/standard/var_unserializer.c"
yy76:
yych = *++YYCURSOR;
if (yych == 'N') goto yy73;
@@ -1089,7 +1121,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
if (yych <= '9') goto yy79;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 498 "ext/standard/var_unserializer.re"
+#line 524 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
int digits = YYCURSOR - start - 3;
@@ -1116,7 +1148,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_LONG(*rval, parse_iv(start + 2));
return 1;
}
-#line 1120 "ext/standard/var_unserializer.c"
+#line 1152 "ext/standard/var_unserializer.c"
yy83:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
@@ -1124,24 +1156,24 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 491 "ext/standard/var_unserializer.re"
+#line 517 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_BOOL(*rval, parse_iv(start + 2));
return 1;
}
-#line 1135 "ext/standard/var_unserializer.c"
+#line 1167 "ext/standard/var_unserializer.c"
yy87:
++YYCURSOR;
-#line 484 "ext/standard/var_unserializer.re"
+#line 510 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_NULL(*rval);
return 1;
}
-#line 1145 "ext/standard/var_unserializer.c"
+#line 1177 "ext/standard/var_unserializer.c"
yy89:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1164,7 +1196,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
if (yych <= '9') goto yy91;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 461 "ext/standard/var_unserializer.re"
+#line 487 "ext/standard/var_unserializer.re"
{
long id;
@@ -1187,7 +1219,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return 1;
}
-#line 1191 "ext/standard/var_unserializer.c"
+#line 1223 "ext/standard/var_unserializer.c"
yy95:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1210,7 +1242,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
if (yych <= '9') goto yy97;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 440 "ext/standard/var_unserializer.re"
+#line 466 "ext/standard/var_unserializer.re"
{
long id;
@@ -1231,9 +1263,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return 1;
}
-#line 1235 "ext/standard/var_unserializer.c"
+#line 1267 "ext/standard/var_unserializer.c"
}
-#line 787 "ext/standard/var_unserializer.re"
+#line 819 "ext/standard/var_unserializer.re"
return 0;
View
42 ext/standard/var_unserializer.re
@@ -192,6 +192,25 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
return str;
}
+static inline int unserialize_allowed_class(const char *class_name, int len, HashTable *classes)
+{
+ char *lc_name;
+ int res;
+ ALLOCA_FLAG(use_heap)
+
+ if(classes == NULL) {
+ return 1;
+ }
+ if(!zend_hash_num_elements(classes)) {
+ return 0;
+ }
+ lc_name = do_alloca(len + 1, use_heap);
+ zend_str_tolower_copy(lc_name, class_name, len);
+ res = zend_hash_exists(classes, lc_name, len);
+ free_alloca(lc_name, use_heap);
+ return res;
+}
+
#define YYFILL(n) do { } while (0)
#define YYCTYPE unsigned char
#define YYCURSOR cursor
@@ -265,8 +284,8 @@ static inline size_t parse_uiv(const unsigned char *p)
return result;
}
-#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC
-#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC
+#define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes TSRMLS_DC
+#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes TSRMLS_CC
static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops)
{
@@ -275,7 +294,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
ALLOC_INIT_ZVAL(key);
- if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
+ if (!php_var_unserialize_ex(&key, p, max, NULL, classes TSRMLS_CC)) {
zval_dtor(key);
FREE_ZVAL(key);
return 0;
@@ -289,7 +308,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
ALLOC_INIT_ZVAL(data);
- if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
+ if (!php_var_unserialize_ex(&data, p, max, var_hash, classes TSRMLS_CC)) {
zval_dtor(key);
FREE_ZVAL(key);
zval_dtor(data);
@@ -415,7 +434,14 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
# pragma optimize("", on)
#endif
-PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
+PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC)
+{
+ HashTable *classes = NULL;
+ return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
+}
+
+
+PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
zval **rval_ref;
@@ -682,6 +708,12 @@ object ":" uiv ":" ["] {
class_name = estrndup(class_name, len);
do {
+ if(!unserialize_allowed_class(class_name, len, classes)) {
+ incomplete_class = 1;
+ ce = PHP_IC_ENTRY;
+ break;
+ }
+
/* Try to find class directly */
BG(serialize_lock) = 1;
if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
Something went wrong with that request. Please try again.