My Alpine packages repository.
https://dryabzhinsky.noip.me/packages/en/alpinelinux-support/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1474 lines
31 KiB
1474 lines
31 KiB
From: Markus Koschany <apo@debian.org> |
|
Date: Sun, 19 Mar 2017 20:45:23 +0100 |
|
Subject: CVE-2016-7479 |
|
|
|
var_unserializer.c was recreated with the re2c tool in Wheezy. |
|
|
|
Origin: https://git.php.net/?p=php-src.git;a=commit;h=0426b916df396a23e5c34514e4f2f0627efdcdf0 |
|
--- |
|
ext/standard/var_unserializer.c | 964 ++++++++++++++++++++++++++++----------- |
|
ext/standard/var_unserializer.re | 84 ++-- |
|
2 files changed, 745 insertions(+), 303 deletions(-) |
|
|
|
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c |
|
index bb0301c..22594ad 100644 |
|
--- a/ext/standard/var_unserializer.c |
|
+++ b/ext/standard/var_unserializer.c |
|
@@ -1,4 +1,5 @@ |
|
-/* Generated by re2c 0.13.7.5 on Mon Aug 31 23:15:46 2015 */ |
|
+/* Generated by re2c 0.13.5 on Sun Mar 19 22:57:00 2017 */ |
|
+#line 1 "ext/standard/var_unserializer.re" |
|
/* |
|
+----------------------------------------------------------------------+ |
|
| PHP Version 5 | |
|
@@ -28,6 +29,11 @@ |
|
#define VAR_ENTRIES_MAX 1024 |
|
#define VAR_ENTRIES_DBG 0 |
|
|
|
+#define VAR_WAKEUP_FLAG 1 |
|
+#define WITH_WAKEUP_FLAG(zv_ptr) ((zval *) ((zend_uintptr_t) zv_ptr | VAR_WAKEUP_FLAG)) |
|
+#define WITHOUT_WAKEUP_FLAG(zv_ptr) ((zval *) ((zend_uintptr_t) zv_ptr & ~VAR_WAKEUP_FLAG)) |
|
+#define HAS_WAKEUP_FLAG(zv_ptr) ((zend_uintptr_t) zv_ptr & VAR_WAKEUP_FLAG) |
|
+ |
|
typedef struct { |
|
zval *data[VAR_ENTRIES_MAX]; |
|
long used_slots; |
|
@@ -58,12 +64,12 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval) |
|
var_hash->data[var_hash->used_slots++] = *rval; |
|
} |
|
|
|
-PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) |
|
+static inline zval **get_var_push_dtor_slot(php_unserialize_data_t *var_hashx) |
|
{ |
|
var_entries *var_hash; |
|
|
|
if (!var_hashx || !*var_hashx) { |
|
- return; |
|
+ return NULL; |
|
} |
|
|
|
var_hash = (*var_hashx)->last_dtor; |
|
@@ -85,8 +91,14 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) |
|
(*var_hashx)->last_dtor = var_hash; |
|
} |
|
|
|
+ return &var_hash->data[var_hash->used_slots++]; |
|
+} |
|
+ |
|
+PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) |
|
+{ |
|
+ zval **slot = get_var_push_dtor_slot(var_hashx); |
|
Z_ADDREF_PP(rval); |
|
- var_hash->data[var_hash->used_slots++] = *rval; |
|
+ *slot = *rval; |
|
} |
|
|
|
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval) |
|
@@ -164,6 +176,9 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) |
|
void *next; |
|
long i; |
|
var_entries *var_hash = (*var_hashx)->first; |
|
+ zend_bool wakeup_failed = 0; |
|
+ TSRMLS_FETCH(); |
|
+ |
|
#if VAR_ENTRIES_DBG |
|
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L); |
|
#endif |
|
@@ -178,10 +193,35 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) |
|
|
|
while (var_hash) { |
|
for (i = 0; i < var_hash->used_slots; i++) { |
|
+ zval *zv = var_hash->data[i]; |
|
#if VAR_ENTRIES_DBG |
|
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_hash->data[i], Z_REFCOUNT_P(var_hash->data[i])); |
|
#endif |
|
- zval_ptr_dtor(&var_hash->data[i]); |
|
+ |
|
+ if (HAS_WAKEUP_FLAG(zv)) { |
|
+ zv = WITHOUT_WAKEUP_FLAG(zv); |
|
+ if (!wakeup_failed) { |
|
+ zval *retval_ptr = NULL; |
|
+ zval wakeup_name; |
|
+ INIT_PZVAL(&wakeup_name); |
|
+ ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1, 0); |
|
+ |
|
+ BG(serialize_lock)++; |
|
+ if (call_user_function_ex(CG(function_table), &zv, &wakeup_name, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC) == FAILURE || retval_ptr == NULL) { |
|
+ wakeup_failed = 1; |
|
+ zend_object_store_ctor_failed(zv TSRMLS_CC); |
|
+ } |
|
+ BG(serialize_lock)--; |
|
+ |
|
+ if (retval_ptr) { |
|
+ zval_ptr_dtor(&retval_ptr); |
|
+ } |
|
+ } else { |
|
+ zend_object_store_ctor_failed(zv TSRMLS_CC); |
|
+ } |
|
+ } |
|
+ |
|
+ zval_ptr_dtor(&zv); |
|
} |
|
next = var_hash->next; |
|
efree(var_hash); |
|
@@ -241,6 +281,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen |
|
#define YYMARKER marker |
|
|
|
|
|
+#line 289 "ext/standard/var_unserializer.re" |
|
|
|
|
|
|
|
@@ -434,19 +475,16 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) |
|
#endif |
|
static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) |
|
{ |
|
- zval *retval_ptr = NULL; |
|
- zval fname; |
|
- |
|
if (Z_TYPE_PP(rval) != IS_OBJECT) { |
|
return 0; |
|
} |
|
|
|
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { |
|
- /* We've got partially constructed object on our hands here. Wipe it. */ |
|
- if(Z_TYPE_PP(rval) == IS_OBJECT) { |
|
- zend_hash_clean(Z_OBJPROP_PP(rval)); |
|
- zend_object_store_ctor_failed(*rval TSRMLS_CC); |
|
- } |
|
+ /* We've got partially constructed object on our hands here. Wipe it. */ |
|
+ if (Z_TYPE_PP(rval) == IS_OBJECT) { |
|
+ zend_hash_clean(Z_OBJPROP_PP(rval)); |
|
+ zend_object_store_ctor_failed(*rval TSRMLS_CC); |
|
+ } |
|
ZVAL_NULL(*rval); |
|
return 0; |
|
} |
|
@@ -456,20 +494,16 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) |
|
} |
|
|
|
if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && |
|
- zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { |
|
- INIT_PZVAL(&fname); |
|
- ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0); |
|
- BG(serialize_lock)++; |
|
- call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); |
|
- BG(serialize_lock)--; |
|
- } |
|
- |
|
- if (retval_ptr) { |
|
- zval_ptr_dtor(&retval_ptr); |
|
- } |
|
- |
|
- if (EG(exception)) { |
|
- return 0; |
|
+ zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup")) |
|
+ ) { |
|
+ /* Store object for delayed __wakeup call. Remove references. */ |
|
+ zval **slot = get_var_push_dtor_slot(var_hash); |
|
+ zval *zv = *rval; |
|
+ Z_ADDREF_P(zv); |
|
+ if (PZVAL_IS_REF(zv)) { |
|
+ SEPARATE_ZVAL(&zv); |
|
+ } |
|
+ *slot = WITH_WAKEUP_FLAG(zv); |
|
} |
|
|
|
return finish_nested_data(UNSERIALIZE_PASSTHRU); |
|
@@ -500,42 +534,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) |
|
|
|
|
|
|
|
+#line 538 "<stdout>" |
|
{ |
|
YYCTYPE yych; |
|
- static const unsigned char yybm[] = { |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 128, 128, 128, 128, 128, 128, 128, 128, |
|
- 128, 128, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- 0, 0, 0, 0, 0, 0, 0, 0, |
|
- }; |
|
|
|
if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); |
|
yych = *YYCURSOR; |
|
@@ -557,86 +558,147 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) |
|
} |
|
yy2: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy95; |
|
+ switch (yych) { |
|
+ case ':': goto yy95; |
|
+ default: goto yy3; |
|
+ } |
|
yy3: |
|
+#line 901 "ext/standard/var_unserializer.re" |
|
{ return 0; } |
|
+#line 569 "<stdout>" |
|
yy4: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy89; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy89; |
|
+ default: goto yy3; |
|
+ } |
|
yy5: |
|
yych = *++YYCURSOR; |
|
- if (yych == ';') goto yy87; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ';': goto yy87; |
|
+ default: goto yy3; |
|
+ } |
|
yy6: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy83; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy83; |
|
+ default: goto yy3; |
|
+ } |
|
yy7: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy77; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy77; |
|
+ default: goto yy3; |
|
+ } |
|
yy8: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy53; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy53; |
|
+ default: goto yy3; |
|
+ } |
|
yy9: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy46; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy46; |
|
+ default: goto yy3; |
|
+ } |
|
yy10: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy39; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy39; |
|
+ default: goto yy3; |
|
+ } |
|
yy11: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy32; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy32; |
|
+ default: goto yy3; |
|
+ } |
|
yy12: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy25; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy25; |
|
+ default: goto yy3; |
|
+ } |
|
yy13: |
|
yych = *(YYMARKER = ++YYCURSOR); |
|
- if (yych == ':') goto yy17; |
|
- goto yy3; |
|
+ switch (yych) { |
|
+ case ':': goto yy17; |
|
+ default: goto yy3; |
|
+ } |
|
yy14: |
|
++YYCURSOR; |
|
+#line 895 "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 638 "<stdout>" |
|
yy16: |
|
yych = *++YYCURSOR; |
|
goto yy3; |
|
yy17: |
|
yych = *++YYCURSOR; |
|
- if (yybm[0+yych] & 128) { |
|
- goto yy20; |
|
+ switch (yych) { |
|
+ case '+': goto yy19; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy20; |
|
+ default: goto yy18; |
|
} |
|
- if (yych == '+') goto yy19; |
|
yy18: |
|
YYCURSOR = YYMARKER; |
|
goto yy3; |
|
yy19: |
|
yych = *++YYCURSOR; |
|
- if (yybm[0+yych] & 128) { |
|
- goto yy20; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy20; |
|
+ default: goto yy18; |
|
} |
|
- goto yy18; |
|
yy20: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
|
yych = *YYCURSOR; |
|
- if (yybm[0+yych] & 128) { |
|
- goto yy20; |
|
- } |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy20; |
|
+ case ':': goto yy22; |
|
+ default: goto yy18; |
|
+ } |
|
+yy22: |
|
yych = *++YYCURSOR; |
|
- if (yych != '"') goto yy18; |
|
+ switch (yych) { |
|
+ case '"': goto yy23; |
|
+ default: goto yy18; |
|
+ } |
|
+yy23: |
|
++YYCURSOR; |
|
+#line 743 "ext/standard/var_unserializer.re" |
|
{ |
|
size_t len, len2, len3, maxlen; |
|
long elements; |
|
@@ -788,30 +850,66 @@ yy20: |
|
|
|
return object_common2(UNSERIALIZE_PASSTHRU, elements); |
|
} |
|
+#line 854 "<stdout>" |
|
yy25: |
|
yych = *++YYCURSOR; |
|
- if (yych <= ',') { |
|
- if (yych != '+') goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy26; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy27; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': |
|
+ case '-': goto yy26; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy27; |
|
+ default: goto yy18; |
|
} |
|
yy26: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy27; |
|
+ default: goto yy18; |
|
+ } |
|
yy27: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy27; |
|
- if (yych >= ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy27; |
|
+ case ':': goto yy29; |
|
+ default: goto yy18; |
|
+ } |
|
+yy29: |
|
yych = *++YYCURSOR; |
|
- if (yych != '"') goto yy18; |
|
+ switch (yych) { |
|
+ case '"': goto yy30; |
|
+ default: goto yy18; |
|
+ } |
|
+yy30: |
|
++YYCURSOR; |
|
+#line 730 "ext/standard/var_unserializer.re" |
|
{ |
|
long elements; |
|
if (!var_hash) return 0; |
|
@@ -824,26 +922,65 @@ yy27: |
|
} |
|
return object_common2(UNSERIALIZE_PASSTHRU, elements); |
|
} |
|
+#line 926 "<stdout>" |
|
yy32: |
|
yych = *++YYCURSOR; |
|
- if (yych == '+') goto yy33; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy34; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': goto yy33; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy34; |
|
+ default: goto yy18; |
|
+ } |
|
yy33: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy34; |
|
+ default: goto yy18; |
|
+ } |
|
yy34: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy34; |
|
- if (yych >= ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy34; |
|
+ case ':': goto yy36; |
|
+ default: goto yy18; |
|
+ } |
|
+yy36: |
|
yych = *++YYCURSOR; |
|
- if (yych != '{') goto yy18; |
|
+ switch (yych) { |
|
+ case '{': goto yy37; |
|
+ default: goto yy18; |
|
+ } |
|
+yy37: |
|
++YYCURSOR; |
|
+#line 709 "ext/standard/var_unserializer.re" |
|
{ |
|
long elements = parse_iv(start + 2); |
|
/* use iv() not uiv() in order to check data range */ |
|
@@ -864,26 +1001,65 @@ yy34: |
|
|
|
return finish_nested_data(UNSERIALIZE_PASSTHRU); |
|
} |
|
+#line 1005 "<stdout>" |
|
yy39: |
|
yych = *++YYCURSOR; |
|
- if (yych == '+') goto yy40; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy41; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': goto yy40; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy41; |
|
+ default: goto yy18; |
|
+ } |
|
yy40: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy41; |
|
+ default: goto yy18; |
|
+ } |
|
yy41: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy41; |
|
- if (yych >= ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy41; |
|
+ case ':': goto yy43; |
|
+ default: goto yy18; |
|
+ } |
|
+yy43: |
|
yych = *++YYCURSOR; |
|
- if (yych != '"') goto yy18; |
|
+ switch (yych) { |
|
+ case '"': goto yy44; |
|
+ default: goto yy18; |
|
+ } |
|
+yy44: |
|
++YYCURSOR; |
|
+#line 680 "ext/standard/var_unserializer.re" |
|
{ |
|
size_t len, maxlen; |
|
char *str; |
|
@@ -912,26 +1088,65 @@ yy41: |
|
ZVAL_STRINGL(*rval, str, len, 0); |
|
return 1; |
|
} |
|
+#line 1092 "<stdout>" |
|
yy46: |
|
yych = *++YYCURSOR; |
|
- if (yych == '+') goto yy47; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy48; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': goto yy47; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy48; |
|
+ default: goto yy18; |
|
+ } |
|
yy47: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy48; |
|
+ default: goto yy18; |
|
+ } |
|
yy48: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy48; |
|
- if (yych >= ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy48; |
|
+ case ':': goto yy50; |
|
+ default: goto yy18; |
|
+ } |
|
+yy50: |
|
yych = *++YYCURSOR; |
|
- if (yych != '"') goto yy18; |
|
+ switch (yych) { |
|
+ case '"': goto yy51; |
|
+ default: goto yy18; |
|
+ } |
|
+yy51: |
|
++YYCURSOR; |
|
+#line 652 "ext/standard/var_unserializer.re" |
|
{ |
|
size_t len, maxlen; |
|
char *str; |
|
@@ -959,93 +1174,131 @@ yy48: |
|
ZVAL_STRINGL(*rval, str, len, 1); |
|
return 1; |
|
} |
|
+#line 1178 "<stdout>" |
|
yy53: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') { |
|
- if (yych <= ',') { |
|
- if (yych == '+') goto yy57; |
|
- goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy55; |
|
- if (yych <= '.') goto yy60; |
|
- goto yy18; |
|
- } |
|
- } else { |
|
- if (yych <= 'I') { |
|
- if (yych <= '9') goto yy58; |
|
- if (yych <= 'H') goto yy18; |
|
- goto yy56; |
|
- } else { |
|
- if (yych != 'N') goto yy18; |
|
- } |
|
- } |
|
+ switch (yych) { |
|
+ case '+': goto yy57; |
|
+ case '-': goto yy55; |
|
+ case '.': goto yy60; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy58; |
|
+ case 'I': goto yy56; |
|
+ case 'N': goto yy54; |
|
+ default: goto yy18; |
|
+ } |
|
+yy54: |
|
yych = *++YYCURSOR; |
|
- if (yych == 'A') goto yy76; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case 'A': goto yy76; |
|
+ default: goto yy18; |
|
+ } |
|
yy55: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') { |
|
- if (yych == '.') goto yy60; |
|
- goto yy18; |
|
- } else { |
|
- if (yych <= '9') goto yy58; |
|
- if (yych != 'I') goto yy18; |
|
+ switch (yych) { |
|
+ case '.': goto yy60; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy58; |
|
+ case 'I': goto yy56; |
|
+ default: goto yy18; |
|
} |
|
yy56: |
|
yych = *++YYCURSOR; |
|
- if (yych == 'N') goto yy72; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case 'N': goto yy72; |
|
+ default: goto yy18; |
|
+ } |
|
yy57: |
|
yych = *++YYCURSOR; |
|
- if (yych == '.') goto yy60; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '.': goto yy60; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy58; |
|
+ default: goto yy18; |
|
+ } |
|
yy58: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4); |
|
yych = *YYCURSOR; |
|
- if (yych <= ':') { |
|
- if (yych <= '.') { |
|
- if (yych <= '-') goto yy18; |
|
- goto yy70; |
|
- } else { |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy58; |
|
- goto yy18; |
|
- } |
|
- } else { |
|
- if (yych <= 'E') { |
|
- if (yych <= ';') goto yy63; |
|
- if (yych <= 'D') goto yy18; |
|
- goto yy65; |
|
- } else { |
|
- if (yych == 'e') goto yy65; |
|
- goto yy18; |
|
- } |
|
+ switch (yych) { |
|
+ case '.': goto yy70; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy58; |
|
+ case ';': goto yy63; |
|
+ case 'E': |
|
+ case 'e': goto yy65; |
|
+ default: goto yy18; |
|
} |
|
yy60: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy61; |
|
+ default: goto yy18; |
|
+ } |
|
yy61: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4); |
|
yych = *YYCURSOR; |
|
- if (yych <= ';') { |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy61; |
|
- if (yych <= ':') goto yy18; |
|
- } else { |
|
- if (yych <= 'E') { |
|
- if (yych <= 'D') goto yy18; |
|
- goto yy65; |
|
- } else { |
|
- if (yych == 'e') goto yy65; |
|
- goto yy18; |
|
- } |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy61; |
|
+ case ';': goto yy63; |
|
+ case 'E': |
|
+ case 'e': goto yy65; |
|
+ default: goto yy18; |
|
} |
|
yy63: |
|
++YYCURSOR; |
|
+#line 642 "ext/standard/var_unserializer.re" |
|
{ |
|
#if SIZEOF_LONG == 4 |
|
use_double: |
|
@@ -1055,64 +1308,109 @@ use_double: |
|
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); |
|
return 1; |
|
} |
|
+#line 1312 "<stdout>" |
|
yy65: |
|
yych = *++YYCURSOR; |
|
- if (yych <= ',') { |
|
- if (yych != '+') goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy66; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy67; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': |
|
+ case '-': goto yy66; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy67; |
|
+ default: goto yy18; |
|
} |
|
yy66: |
|
yych = *++YYCURSOR; |
|
- if (yych <= ',') { |
|
- if (yych == '+') goto yy69; |
|
- goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy69; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '+': |
|
+ case '-': goto yy69; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy67; |
|
+ default: goto yy18; |
|
} |
|
yy67: |
|
++YYCURSOR; |
|
if (YYLIMIT <= YYCURSOR) YYFILL(1); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy67; |
|
- if (yych == ';') goto yy63; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy67; |
|
+ case ';': goto yy63; |
|
+ default: goto yy18; |
|
+ } |
|
yy69: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy67; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy67; |
|
+ default: goto yy18; |
|
+ } |
|
yy70: |
|
++YYCURSOR; |
|
if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4); |
|
yych = *YYCURSOR; |
|
- if (yych <= ';') { |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy70; |
|
- if (yych <= ':') goto yy18; |
|
- goto yy63; |
|
- } else { |
|
- if (yych <= 'E') { |
|
- if (yych <= 'D') goto yy18; |
|
- goto yy65; |
|
- } else { |
|
- if (yych == 'e') goto yy65; |
|
- goto yy18; |
|
- } |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy70; |
|
+ case ';': goto yy63; |
|
+ case 'E': |
|
+ case 'e': goto yy65; |
|
+ default: goto yy18; |
|
} |
|
yy72: |
|
yych = *++YYCURSOR; |
|
- if (yych != 'F') goto yy18; |
|
+ switch (yych) { |
|
+ case 'F': goto yy73; |
|
+ default: goto yy18; |
|
+ } |
|
yy73: |
|
yych = *++YYCURSOR; |
|
- if (yych != ';') goto yy18; |
|
+ switch (yych) { |
|
+ case ';': goto yy74; |
|
+ default: goto yy18; |
|
+ } |
|
+yy74: |
|
++YYCURSOR; |
|
+#line 627 "ext/standard/var_unserializer.re" |
|
{ |
|
*p = YYCURSOR; |
|
INIT_PZVAL(*rval); |
|
@@ -1127,32 +1425,66 @@ yy73: |
|
|
|
return 1; |
|
} |
|
+#line 1429 "<stdout>" |
|
yy76: |
|
yych = *++YYCURSOR; |
|
- if (yych == 'N') goto yy73; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case 'N': goto yy73; |
|
+ default: goto yy18; |
|
+ } |
|
yy77: |
|
yych = *++YYCURSOR; |
|
- if (yych <= ',') { |
|
- if (yych != '+') goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy78; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy79; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': |
|
+ case '-': goto yy78; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy79; |
|
+ default: goto yy18; |
|
} |
|
yy78: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy79; |
|
+ default: goto yy18; |
|
+ } |
|
yy79: |
|
++YYCURSOR; |
|
if (YYLIMIT <= YYCURSOR) YYFILL(1); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy79; |
|
- if (yych != ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy79; |
|
+ case ';': goto yy81; |
|
+ default: goto yy18; |
|
+ } |
|
+yy81: |
|
++YYCURSOR; |
|
+#line 600 "ext/standard/var_unserializer.re" |
|
{ |
|
#if SIZEOF_LONG == 4 |
|
int digits = YYCURSOR - start - 3; |
|
@@ -1179,49 +1511,93 @@ yy79: |
|
ZVAL_LONG(*rval, parse_iv(start + 2)); |
|
return 1; |
|
} |
|
+#line 1515 "<stdout>" |
|
yy83: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= '2') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': goto yy84; |
|
+ default: goto yy18; |
|
+ } |
|
+yy84: |
|
yych = *++YYCURSOR; |
|
- if (yych != ';') goto yy18; |
|
+ switch (yych) { |
|
+ case ';': goto yy85; |
|
+ default: goto yy18; |
|
+ } |
|
+yy85: |
|
++YYCURSOR; |
|
+#line 593 "ext/standard/var_unserializer.re" |
|
{ |
|
*p = YYCURSOR; |
|
INIT_PZVAL(*rval); |
|
ZVAL_BOOL(*rval, parse_iv(start + 2)); |
|
return 1; |
|
} |
|
+#line 1538 "<stdout>" |
|
yy87: |
|
++YYCURSOR; |
|
+#line 586 "ext/standard/var_unserializer.re" |
|
{ |
|
*p = YYCURSOR; |
|
INIT_PZVAL(*rval); |
|
ZVAL_NULL(*rval); |
|
return 1; |
|
} |
|
+#line 1548 "<stdout>" |
|
yy89: |
|
yych = *++YYCURSOR; |
|
- if (yych <= ',') { |
|
- if (yych != '+') goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy90; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy91; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': |
|
+ case '-': goto yy90; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy91; |
|
+ default: goto yy18; |
|
} |
|
yy90: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy91; |
|
+ default: goto yy18; |
|
+ } |
|
yy91: |
|
++YYCURSOR; |
|
if (YYLIMIT <= YYCURSOR) YYFILL(1); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy91; |
|
- if (yych != ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy91; |
|
+ case ';': goto yy93; |
|
+ default: goto yy18; |
|
+ } |
|
+yy93: |
|
++YYCURSOR; |
|
+#line 563 "ext/standard/var_unserializer.re" |
|
{ |
|
long id; |
|
|
|
@@ -1244,28 +1620,60 @@ yy91: |
|
|
|
return 1; |
|
} |
|
+#line 1624 "<stdout>" |
|
yy95: |
|
yych = *++YYCURSOR; |
|
- if (yych <= ',') { |
|
- if (yych != '+') goto yy18; |
|
- } else { |
|
- if (yych <= '-') goto yy96; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy97; |
|
- goto yy18; |
|
+ switch (yych) { |
|
+ case '+': |
|
+ case '-': goto yy96; |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy97; |
|
+ default: goto yy18; |
|
} |
|
yy96: |
|
yych = *++YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych >= ':') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy97; |
|
+ default: goto yy18; |
|
+ } |
|
yy97: |
|
++YYCURSOR; |
|
if (YYLIMIT <= YYCURSOR) YYFILL(1); |
|
yych = *YYCURSOR; |
|
- if (yych <= '/') goto yy18; |
|
- if (yych <= '9') goto yy97; |
|
- if (yych != ';') goto yy18; |
|
+ switch (yych) { |
|
+ case '0': |
|
+ case '1': |
|
+ case '2': |
|
+ case '3': |
|
+ case '4': |
|
+ case '5': |
|
+ case '6': |
|
+ case '7': |
|
+ case '8': |
|
+ case '9': goto yy97; |
|
+ case ';': goto yy99; |
|
+ default: goto yy18; |
|
+ } |
|
+yy99: |
|
++YYCURSOR; |
|
+#line 542 "ext/standard/var_unserializer.re" |
|
{ |
|
long id; |
|
|
|
@@ -1286,7 +1694,9 @@ yy97: |
|
|
|
return 1; |
|
} |
|
+#line 1698 "<stdout>" |
|
} |
|
+#line 903 "ext/standard/var_unserializer.re" |
|
|
|
|
|
return 0; |
|
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re |
|
index 0302723..d4d5622 100644 |
|
--- a/ext/standard/var_unserializer.re |
|
+++ b/ext/standard/var_unserializer.re |
|
@@ -27,6 +27,11 @@ |
|
#define VAR_ENTRIES_MAX 1024 |
|
#define VAR_ENTRIES_DBG 0 |
|
|
|
+#define VAR_WAKEUP_FLAG 1 |
|
+#define WITH_WAKEUP_FLAG(zv_ptr) ((zval *) ((zend_uintptr_t) zv_ptr | VAR_WAKEUP_FLAG)) |
|
+#define WITHOUT_WAKEUP_FLAG(zv_ptr) ((zval *) ((zend_uintptr_t) zv_ptr & ~VAR_WAKEUP_FLAG)) |
|
+#define HAS_WAKEUP_FLAG(zv_ptr) ((zend_uintptr_t) zv_ptr & VAR_WAKEUP_FLAG) |
|
+ |
|
typedef struct { |
|
zval *data[VAR_ENTRIES_MAX]; |
|
long used_slots; |
|
@@ -57,12 +62,12 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval) |
|
var_hash->data[var_hash->used_slots++] = *rval; |
|
} |
|
|
|
-PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) |
|
+static inline zval **get_var_push_dtor_slot(php_unserialize_data_t *var_hashx) |
|
{ |
|
var_entries *var_hash; |
|
|
|
if (!var_hashx || !*var_hashx) { |
|
- return; |
|
+ return NULL; |
|
} |
|
|
|
var_hash = (*var_hashx)->last_dtor; |
|
@@ -84,8 +89,14 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) |
|
(*var_hashx)->last_dtor = var_hash; |
|
} |
|
|
|
+ return &var_hash->data[var_hash->used_slots++]; |
|
+} |
|
+ |
|
+PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) |
|
+{ |
|
+ zval **slot = get_var_push_dtor_slot(var_hashx); |
|
Z_ADDREF_PP(rval); |
|
- var_hash->data[var_hash->used_slots++] = *rval; |
|
+ *slot = *rval; |
|
} |
|
|
|
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval) |
|
@@ -163,6 +174,9 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) |
|
void *next; |
|
long i; |
|
var_entries *var_hash = (*var_hashx)->first; |
|
+ zend_bool wakeup_failed = 0; |
|
+ TSRMLS_FETCH(); |
|
+ |
|
#if VAR_ENTRIES_DBG |
|
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L); |
|
#endif |
|
@@ -177,10 +191,35 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) |
|
|
|
while (var_hash) { |
|
for (i = 0; i < var_hash->used_slots; i++) { |
|
+ zval *zv = var_hash->data[i]; |
|
#if VAR_ENTRIES_DBG |
|
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_hash->data[i], Z_REFCOUNT_P(var_hash->data[i])); |
|
#endif |
|
- zval_ptr_dtor(&var_hash->data[i]); |
|
+ |
|
+ if (HAS_WAKEUP_FLAG(zv)) { |
|
+ zv = WITHOUT_WAKEUP_FLAG(zv); |
|
+ if (!wakeup_failed) { |
|
+ zval *retval_ptr = NULL; |
|
+ zval wakeup_name; |
|
+ INIT_PZVAL(&wakeup_name); |
|
+ ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1, 0); |
|
+ |
|
+ BG(serialize_lock)++; |
|
+ if (call_user_function_ex(CG(function_table), &zv, &wakeup_name, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC) == FAILURE || retval_ptr == NULL) { |
|
+ wakeup_failed = 1; |
|
+ zend_object_store_ctor_failed(zv TSRMLS_CC); |
|
+ } |
|
+ BG(serialize_lock)--; |
|
+ |
|
+ if (retval_ptr) { |
|
+ zval_ptr_dtor(&retval_ptr); |
|
+ } |
|
+ } else { |
|
+ zend_object_store_ctor_failed(zv TSRMLS_CC); |
|
+ } |
|
+ } |
|
+ |
|
+ zval_ptr_dtor(&zv); |
|
} |
|
next = var_hash->next; |
|
efree(var_hash); |
|
@@ -440,19 +479,16 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) |
|
#endif |
|
static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) |
|
{ |
|
- zval *retval_ptr = NULL; |
|
- zval fname; |
|
- |
|
if (Z_TYPE_PP(rval) != IS_OBJECT) { |
|
return 0; |
|
} |
|
|
|
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { |
|
- /* We've got partially constructed object on our hands here. Wipe it. */ |
|
- if(Z_TYPE_PP(rval) == IS_OBJECT) { |
|
- zend_hash_clean(Z_OBJPROP_PP(rval)); |
|
- zend_object_store_ctor_failed(*rval TSRMLS_CC); |
|
- } |
|
+ /* We've got partially constructed object on our hands here. Wipe it. */ |
|
+ if (Z_TYPE_PP(rval) == IS_OBJECT) { |
|
+ zend_hash_clean(Z_OBJPROP_PP(rval)); |
|
+ zend_object_store_ctor_failed(*rval TSRMLS_CC); |
|
+ } |
|
ZVAL_NULL(*rval); |
|
return 0; |
|
} |
|
@@ -462,20 +498,16 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) |
|
} |
|
|
|
if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && |
|
- zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { |
|
- INIT_PZVAL(&fname); |
|
- ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0); |
|
- BG(serialize_lock)++; |
|
- call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); |
|
- BG(serialize_lock)--; |
|
- } |
|
- |
|
- if (retval_ptr) { |
|
- zval_ptr_dtor(&retval_ptr); |
|
- } |
|
- |
|
- if (EG(exception)) { |
|
- return 0; |
|
+ zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup")) |
|
+ ) { |
|
+ /* Store object for delayed __wakeup call. Remove references. */ |
|
+ zval **slot = get_var_push_dtor_slot(var_hash); |
|
+ zval *zv = *rval; |
|
+ Z_ADDREF_P(zv); |
|
+ if (PZVAL_IS_REF(zv)) { |
|
+ SEPARATE_ZVAL(&zv); |
|
+ } |
|
+ *slot = WITH_WAKEUP_FLAG(zv); |
|
} |
|
|
|
return finish_nested_data(UNSERIALIZE_PASSTHRU);
|
|
|