Created
August 10, 2015 08:55
-
-
Save laruence/3aad977c46c3eee715f4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c | |
index eb5081d..94532c7 100644 | |
--- a/Zend/zend_hash.c | |
+++ b/Zend/zend_hash.c | |
@@ -807,6 +807,24 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht) | |
} | |
} | |
+ZEND_API int ZEND_FASTCALL zend_hash_resize(HashTable *ht, uint32_t size) { | |
+ if (ht->nTableSize < HT_MAX_SIZE) { | |
+ void *old_data = HT_GET_DATA_ADDR(ht); | |
+ Bucket *old_buckets = ht->arData; | |
+ | |
+ HANDLE_BLOCK_INTERRUPTIONS(); | |
+ ht->nTableSize = zend_hash_check_size(size); | |
+ ht->nTableMask = -ht->nTableSize; | |
+ HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT)); | |
+ memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed); | |
+ pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT); | |
+ zend_hash_rehash(ht); | |
+ HANDLE_UNBLOCK_INTERRUPTIONS(); | |
+ } else { | |
+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket)); | |
+ } | |
+} | |
+ | |
ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) | |
{ | |
Bucket *p; | |
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h | |
index 4a33b95..b323096 100644 | |
--- a/Zend/zend_hash.h | |
+++ b/Zend/zend_hash.h | |
@@ -212,6 +212,7 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_ | |
#define zend_hash_next_free_element(ht) \ | |
(ht)->nNextFreeElement | |
+ZEND_API int ZEND_FASTCALL zend_hash_resize(HashTable *ht, uint32_t size); | |
ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht); | |
ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source); | |
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c | |
index ea1c971..6bc37a8 100644 | |
--- a/ext/standard/var_unserializer.c | |
+++ b/ext/standard/var_unserializer.c | |
@@ -470,13 +470,14 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) | |
{ | |
zval retval; | |
zval fname; | |
+ HashTable *ht = Z_OBJPROP_P(rval); | |
if (Z_TYPE_P(rval) != IS_OBJECT) { | |
return 0; | |
} | |
- //??? TODO: resize before | |
- if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_P(rval), elements, 1)) { | |
+ zend_hash_resize(ht, zend_hash_num_elements(ht) + elements); | |
+ if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { | |
return 0; | |
} | |
@@ -528,7 +529,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) | |
start = cursor; | |
-#line 532 "ext/standard/var_unserializer.c" | |
+#line 533 "ext/standard/var_unserializer.c" | |
{ | |
YYCTYPE yych; | |
static const unsigned char yybm[] = { | |
@@ -588,9 +589,9 @@ yy2: | |
yych = *(YYMARKER = ++YYCURSOR); | |
if (yych == ':') goto yy95; | |
yy3: | |
-#line 879 "ext/standard/var_unserializer.re" | |
+#line 880 "ext/standard/var_unserializer.re" | |
{ return 0; } | |
-#line 594 "ext/standard/var_unserializer.c" | |
+#line 595 "ext/standard/var_unserializer.c" | |
yy4: | |
yych = *(YYMARKER = ++YYCURSOR); | |
if (yych == ':') goto yy89; | |
@@ -633,13 +634,13 @@ yy13: | |
goto yy3; | |
yy14: | |
++YYCURSOR; | |
-#line 873 "ext/standard/var_unserializer.re" | |
+#line 874 "ext/standard/var_unserializer.re" | |
{ | |
/* this is the case where we have less data than planned */ | |
php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data"); | |
return 0; /* not sure if it should be 0 or 1 here? */ | |
} | |
-#line 643 "ext/standard/var_unserializer.c" | |
+#line 644 "ext/standard/var_unserializer.c" | |
yy16: | |
yych = *++YYCURSOR; | |
goto yy3; | |
@@ -669,7 +670,7 @@ yy20: | |
yych = *++YYCURSOR; | |
if (yych != '"') goto yy18; | |
++YYCURSOR; | |
-#line 728 "ext/standard/var_unserializer.re" | |
+#line 729 "ext/standard/var_unserializer.re" | |
{ | |
size_t len, len2, len3, maxlen; | |
zend_long elements; | |
@@ -814,7 +815,7 @@ yy20: | |
return object_common2(UNSERIALIZE_PASSTHRU, elements); | |
} | |
-#line 818 "ext/standard/var_unserializer.c" | |
+#line 819 "ext/standard/var_unserializer.c" | |
yy25: | |
yych = *++YYCURSOR; | |
if (yych <= ',') { | |
@@ -839,7 +840,7 @@ yy27: | |
yych = *++YYCURSOR; | |
if (yych != '"') goto yy18; | |
++YYCURSOR; | |
-#line 720 "ext/standard/var_unserializer.re" | |
+#line 721 "ext/standard/var_unserializer.re" | |
{ | |
//??? INIT_PZVAL(rval); | |
@@ -847,7 +848,7 @@ yy27: | |
return object_common2(UNSERIALIZE_PASSTHRU, | |
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); | |
} | |
-#line 851 "ext/standard/var_unserializer.c" | |
+#line 852 "ext/standard/var_unserializer.c" | |
yy32: | |
yych = *++YYCURSOR; | |
if (yych == '+') goto yy33; | |
@@ -868,7 +869,7 @@ yy34: | |
yych = *++YYCURSOR; | |
if (yych != '{') goto yy18; | |
++YYCURSOR; | |
-#line 699 "ext/standard/var_unserializer.re" | |
+#line 700 "ext/standard/var_unserializer.re" | |
{ | |
zend_long elements = parse_iv(start + 2); | |
/* use iv() not uiv() in order to check data range */ | |
@@ -889,7 +890,7 @@ yy34: | |
return finish_nested_data(UNSERIALIZE_PASSTHRU); | |
} | |
-#line 893 "ext/standard/var_unserializer.c" | |
+#line 894 "ext/standard/var_unserializer.c" | |
yy39: | |
yych = *++YYCURSOR; | |
if (yych == '+') goto yy40; | |
@@ -910,7 +911,7 @@ yy41: | |
yych = *++YYCURSOR; | |
if (yych != '"') goto yy18; | |
++YYCURSOR; | |
-#line 671 "ext/standard/var_unserializer.re" | |
+#line 672 "ext/standard/var_unserializer.re" | |
{ | |
size_t len, maxlen; | |
zend_string *str; | |
@@ -938,7 +939,7 @@ yy41: | |
ZVAL_STR(rval, str); | |
return 1; | |
} | |
-#line 942 "ext/standard/var_unserializer.c" | |
+#line 943 "ext/standard/var_unserializer.c" | |
yy46: | |
yych = *++YYCURSOR; | |
if (yych == '+') goto yy47; | |
@@ -959,7 +960,7 @@ yy48: | |
yych = *++YYCURSOR; | |
if (yych != '"') goto yy18; | |
++YYCURSOR; | |
-#line 644 "ext/standard/var_unserializer.re" | |
+#line 645 "ext/standard/var_unserializer.re" | |
{ | |
size_t len, maxlen; | |
char *str; | |
@@ -986,7 +987,7 @@ yy48: | |
ZVAL_STRINGL(rval, str, len); | |
return 1; | |
} | |
-#line 990 "ext/standard/var_unserializer.c" | |
+#line 991 "ext/standard/var_unserializer.c" | |
yy53: | |
yych = *++YYCURSOR; | |
if (yych <= '/') { | |
@@ -1074,7 +1075,7 @@ yy61: | |
} | |
yy63: | |
++YYCURSOR; | |
-#line 635 "ext/standard/var_unserializer.re" | |
+#line 636 "ext/standard/var_unserializer.re" | |
{ | |
#if SIZEOF_ZEND_LONG == 4 | |
use_double: | |
@@ -1083,7 +1084,7 @@ use_double: | |
ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); | |
return 1; | |
} | |
-#line 1087 "ext/standard/var_unserializer.c" | |
+#line 1088 "ext/standard/var_unserializer.c" | |
yy65: | |
yych = *++YYCURSOR; | |
if (yych <= ',') { | |
@@ -1142,7 +1143,7 @@ yy73: | |
yych = *++YYCURSOR; | |
if (yych != ';') goto yy18; | |
++YYCURSOR; | |
-#line 619 "ext/standard/var_unserializer.re" | |
+#line 620 "ext/standard/var_unserializer.re" | |
{ | |
*p = YYCURSOR; | |
@@ -1158,7 +1159,7 @@ yy73: | |
return 1; | |
} | |
-#line 1162 "ext/standard/var_unserializer.c" | |
+#line 1163 "ext/standard/var_unserializer.c" | |
yy76: | |
yych = *++YYCURSOR; | |
if (yych == 'N') goto yy73; | |
@@ -1185,7 +1186,7 @@ yy79: | |
if (yych <= '9') goto yy79; | |
if (yych != ';') goto yy18; | |
++YYCURSOR; | |
-#line 593 "ext/standard/var_unserializer.re" | |
+#line 594 "ext/standard/var_unserializer.re" | |
{ | |
#if SIZEOF_ZEND_LONG == 4 | |
int digits = YYCURSOR - start - 3; | |
@@ -1211,7 +1212,7 @@ yy79: | |
ZVAL_LONG(rval, parse_iv(start + 2)); | |
return 1; | |
} | |
-#line 1215 "ext/standard/var_unserializer.c" | |
+#line 1216 "ext/standard/var_unserializer.c" | |
yy83: | |
yych = *++YYCURSOR; | |
if (yych <= '/') goto yy18; | |
@@ -1219,22 +1220,22 @@ yy83: | |
yych = *++YYCURSOR; | |
if (yych != ';') goto yy18; | |
++YYCURSOR; | |
-#line 587 "ext/standard/var_unserializer.re" | |
+#line 588 "ext/standard/var_unserializer.re" | |
{ | |
*p = YYCURSOR; | |
ZVAL_BOOL(rval, parse_iv(start + 2)); | |
return 1; | |
} | |
-#line 1229 "ext/standard/var_unserializer.c" | |
+#line 1230 "ext/standard/var_unserializer.c" | |
yy87: | |
++YYCURSOR; | |
-#line 581 "ext/standard/var_unserializer.re" | |
+#line 582 "ext/standard/var_unserializer.re" | |
{ | |
*p = YYCURSOR; | |
ZVAL_NULL(rval); | |
return 1; | |
} | |
-#line 1238 "ext/standard/var_unserializer.c" | |
+#line 1239 "ext/standard/var_unserializer.c" | |
yy89: | |
yych = *++YYCURSOR; | |
if (yych <= ',') { | |
@@ -1257,7 +1258,7 @@ yy91: | |
if (yych <= '9') goto yy91; | |
if (yych != ';') goto yy18; | |
++YYCURSOR; | |
-#line 558 "ext/standard/var_unserializer.re" | |
+#line 559 "ext/standard/var_unserializer.re" | |
{ | |
zend_long id; | |
@@ -1280,7 +1281,7 @@ yy91: | |
return 1; | |
} | |
-#line 1284 "ext/standard/var_unserializer.c" | |
+#line 1285 "ext/standard/var_unserializer.c" | |
yy95: | |
yych = *++YYCURSOR; | |
if (yych <= ',') { | |
@@ -1303,7 +1304,7 @@ yy97: | |
if (yych <= '9') goto yy97; | |
if (yych != ';') goto yy18; | |
++YYCURSOR; | |
-#line 536 "ext/standard/var_unserializer.re" | |
+#line 537 "ext/standard/var_unserializer.re" | |
{ | |
zend_long id; | |
@@ -1325,9 +1326,9 @@ yy97: | |
return 1; | |
} | |
-#line 1329 "ext/standard/var_unserializer.c" | |
+#line 1330 "ext/standard/var_unserializer.c" | |
} | |
-#line 881 "ext/standard/var_unserializer.re" | |
+#line 882 "ext/standard/var_unserializer.re" | |
return 0; | |
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re | |
index 7d4ca2c..dc2f84a 100644 | |
--- a/ext/standard/var_unserializer.re | |
+++ b/ext/standard/var_unserializer.re | |
@@ -474,13 +474,14 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) | |
{ | |
zval retval; | |
zval fname; | |
+ HashTable *ht = Z_OBJPROP_P(rval); | |
if (Z_TYPE_P(rval) != IS_OBJECT) { | |
return 0; | |
} | |
- //??? TODO: resize before | |
- if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_P(rval), elements, 1)) { | |
+ zend_hash_resize(ht, zend_hash_num_elements(ht) + elements); | |
+ if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment