Skip to content

Commit 09f7bb2

Browse files
committed
Followup for bug #72785
Fix incorrect handling of nesting ... need to reset to the old value afterwards.
1 parent 5d394b3 commit 09f7bb2

File tree

4 files changed

+594
-563
lines changed

4 files changed

+594
-563
lines changed

ext/standard/php_var.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ PHPAPI php_serialize_data_t php_var_serialize_init(void);
5050
PHPAPI void php_var_serialize_destroy(php_serialize_data_t d);
5151
PHPAPI php_unserialize_data_t php_var_unserialize_init(void);
5252
PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d);
53+
PHPAPI HashTable *php_var_unserialize_get_allowed_classes(php_unserialize_data_t d);
5354
PHPAPI void php_var_unserialize_set_allowed_classes(php_unserialize_data_t d, HashTable *classes);
5455

5556
#define PHP_VAR_SERIALIZE_INIT(d) \

ext/standard/var.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,7 @@ PHP_FUNCTION(unserialize)
10651065
const unsigned char *p;
10661066
php_unserialize_data_t var_hash;
10671067
zval *options = NULL, *classes = NULL;
1068-
HashTable *class_hash = NULL;
1068+
HashTable *class_hash = NULL, *prev_class_hash;
10691069

10701070
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &options) == FAILURE) {
10711071
RETURN_FALSE;
@@ -1077,7 +1077,9 @@ PHP_FUNCTION(unserialize)
10771077

10781078
p = (const unsigned char*) buf;
10791079
PHP_VAR_UNSERIALIZE_INIT(var_hash);
1080-
if(options != NULL) {
1080+
1081+
prev_class_hash = php_var_unserialize_get_allowed_classes(var_hash);
1082+
if (options != NULL) {
10811083
classes = zend_hash_str_find(Z_ARRVAL_P(options), "allowed_classes", sizeof("allowed_classes")-1);
10821084
if (classes && Z_TYPE_P(classes) != IS_ARRAY && Z_TYPE_P(classes) != IS_TRUE && Z_TYPE_P(classes) != IS_FALSE) {
10831085
php_error_docref(NULL, E_WARNING, "allowed_classes option should be array or boolean");
@@ -1104,32 +1106,31 @@ PHP_FUNCTION(unserialize)
11041106
}
11051107

11061108
if (!php_var_unserialize(return_value, &p, p + buf_len, &var_hash)) {
1107-
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1108-
if (class_hash) {
1109-
zend_hash_destroy(class_hash);
1110-
FREE_HASHTABLE(class_hash);
1111-
}
11121109
zval_ptr_dtor(return_value);
11131110
if (!EG(exception)) {
11141111
php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes",
11151112
(zend_long)((char*)p - buf), buf_len);
11161113
}
1117-
RETURN_FALSE;
1118-
}
1119-
/* We should keep an reference to return_value to prevent it from being dtor
1120-
in case nesting calls to unserialize */
1121-
var_push_dtor(&var_hash, return_value);
1114+
RETVAL_FALSE;
1115+
} else {
1116+
/* We should keep an reference to return_value to prevent it from being dtor
1117+
in case nesting calls to unserialize */
1118+
var_push_dtor(&var_hash, return_value);
11221119

1123-
/* Ensure return value is a value */
1124-
if (Z_ISREF_P(return_value)) {
1125-
zend_unwrap_reference(return_value);
1120+
/* Ensure return value is a value */
1121+
if (Z_ISREF_P(return_value)) {
1122+
zend_unwrap_reference(return_value);
1123+
}
11261124
}
11271125

1128-
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
11291126
if (class_hash) {
11301127
zend_hash_destroy(class_hash);
11311128
FREE_HASHTABLE(class_hash);
11321129
}
1130+
1131+
/* Reset to previous allowed_classes in case this is a nested call */
1132+
php_var_unserialize_set_allowed_classes(var_hash, prev_class_hash);
1133+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
11331134
}
11341135
/* }}} */
11351136

0 commit comments

Comments
 (0)