Skip to content

Instantly share code, notes, and snippets.

@laruence
Created August 10, 2015 08:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laruence/3aad977c46c3eee715f4 to your computer and use it in GitHub Desktop.
Save laruence/3aad977c46c3eee715f4 to your computer and use it in GitHub Desktop.
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