diff options
Diffstat (limited to 'ext/standard/var_unserializer.c')
-rw-r--r-- | ext/standard/var_unserializer.c | 135 |
1 files changed, 71 insertions, 64 deletions
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index ac17529c20..575070b5b7 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -68,7 +68,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) var_hash = (*var_hashx)->last_dtor; #if VAR_ENTRIES_DBG - fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval)); + fprintf(stderr, "var_push_dtor(%p, %ld): %d\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval)); #endif if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) { @@ -91,9 +91,15 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval) { - var_entries *var_hash = (*var_hashx)->last_dtor; + var_entries *var_hash; + + if (!var_hashx || !*var_hashx) { + return; + } + + var_hash = (*var_hashx)->last_dtor; #if VAR_ENTRIES_DBG - fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval)); + fprintf(stderr, "var_push_dtor_no_addref(%p, %ld): %d (%d)\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval)); #endif if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) { @@ -120,7 +126,7 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n #if VAR_ENTRIES_DBG fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval)); #endif - + while (var_hash) { for (i = 0; i < var_hash->used_slots; i++) { if (var_hash->data[i] == ozval) { @@ -138,7 +144,7 @@ static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store) #if VAR_ENTRIES_DBG fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id); #endif - + while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) { var_hash = var_hash->next; id -= VAR_ENTRIES_MAX; @@ -161,7 +167,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) #if VAR_ENTRIES_DBG fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L); #endif - + while (var_hash) { next = var_hash->next; efree(var_hash); @@ -169,9 +175,12 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) } var_hash = (*var_hashx)->first_dtor; - + while (var_hash) { for (i = 0; i < var_hash->used_slots; 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]); } next = var_hash->next; @@ -232,7 +241,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen #define YYMARKER marker -#line 240 "ext/standard/var_unserializer.re" +#line 249 "ext/standard/var_unserializer.re" @@ -250,7 +259,7 @@ static inline long parse_iv2(const unsigned char *p, const unsigned char **q) case '+': p++; } - + while (1) { cursor = (char)*p; if (cursor >= '0' && cursor <= '9') { @@ -279,7 +288,7 @@ static inline size_t parse_uiv(const unsigned char *p) if (*p == '+') { p++; } - + while (1) { cursor = *p; if (cursor >= '0' && cursor <= '9') { @@ -303,23 +312,20 @@ 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)) { - zval_dtor(key); - FREE_ZVAL(key); + var_push_dtor_no_addref(var_hash, &key); return 0; } if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) { - zval_dtor(key); - FREE_ZVAL(key); + var_push_dtor_no_addref(var_hash, &key); return 0; } ALLOC_INIT_ZVAL(data); if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) { - zval_dtor(key); - FREE_ZVAL(key); - zval_ptr_dtor(&data); + var_push_dtor_no_addref(var_hash, &key); + var_push_dtor_no_addref(var_hash, &data); return 0; } @@ -348,9 +354,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long sizeof data, NULL); } var_push_dtor(var_hash, &data); - - zval_dtor(key); - FREE_ZVAL(key); + var_push_dtor_no_addref(var_hash, &key); if (elements && *(*p-1) != ';' && *(*p-1) != '}') { (*p)--; @@ -400,7 +404,7 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce) static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) { long elements; - + elements = parse_iv2((*p) + 2, p); (*p) += 2; @@ -464,21 +468,21 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) limit = max; cursor = *p; - + if (YYCURSOR >= YYLIMIT) { return 0; } - + if (var_hash && cursor[0] != 'R') { var_push(var_hash, rval); } start = cursor; - - -#line 482 "ext/standard/var_unserializer.c" + + +#line 486 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -538,9 +542,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 833 "ext/standard/var_unserializer.re" +#line 840 "ext/standard/var_unserializer.re" { return 0; } -#line 544 "ext/standard/var_unserializer.c" +#line 548 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -583,13 +587,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 827 "ext/standard/var_unserializer.re" +#line 834 "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 593 "ext/standard/var_unserializer.c" +#line 597 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -620,7 +624,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 681 "ext/standard/var_unserializer.re" +#line 687 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -636,10 +640,11 @@ yy20: zval **args[1]; zval *arg_func_name; + if (!var_hash) return 0; if (*start == 'C') { custom_object = 1; } - + INIT_PZVAL(*rval); len2 = len = parse_uiv(start + 2); maxlen = max - YYCURSOR; @@ -688,14 +693,14 @@ yy20: efree(class_name); return 0; } - + /* Check for unserialize callback */ if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) { incomplete_class = 1; ce = PHP_IC_ENTRY; break; } - + /* Call unserialize callback */ MAKE_STD_ZVAL(user_func); ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); @@ -728,7 +733,7 @@ yy20: zval_ptr_dtor(&arg_func_name); return 0; } - + /* The callback function may have defined the class */ if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) { ce = *pce; @@ -756,7 +761,7 @@ yy20: efree(class_name); return ret; } - + elements = object_common1(UNSERIALIZE_PASSTHRU, ce); if (incomplete_class) { @@ -766,7 +771,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 770 "ext/standard/var_unserializer.c" +#line 775 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -791,15 +796,16 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 673 "ext/standard/var_unserializer.re" +#line 678 "ext/standard/var_unserializer.re" { + if (!var_hash) return 0; INIT_PZVAL(*rval); - + return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 803 "ext/standard/var_unserializer.c" +#line 809 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -820,11 +826,12 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 653 "ext/standard/var_unserializer.re" +#line 657 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ *p = YYCURSOR; + if (!var_hash) return 0; if (elements < 0) { return 0; @@ -840,7 +847,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 844 "ext/standard/var_unserializer.c" +#line 851 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -861,7 +868,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 624 "ext/standard/var_unserializer.re" +#line 628 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -890,7 +897,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 894 "ext/standard/var_unserializer.c" +#line 901 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -911,7 +918,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 596 "ext/standard/var_unserializer.re" +#line 600 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -939,7 +946,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 943 "ext/standard/var_unserializer.c" +#line 950 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1027,7 +1034,7 @@ yy61: } yy63: ++YYCURSOR; -#line 586 "ext/standard/var_unserializer.re" +#line 590 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1037,7 +1044,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1041 "ext/standard/var_unserializer.c" +#line 1048 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1096,7 +1103,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 571 "ext/standard/var_unserializer.re" +#line 575 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1111,7 +1118,7 @@ yy73: return 1; } -#line 1115 "ext/standard/var_unserializer.c" +#line 1122 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1138,7 +1145,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 544 "ext/standard/var_unserializer.re" +#line 548 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1165,7 +1172,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1169 "ext/standard/var_unserializer.c" +#line 1176 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1173,24 +1180,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 537 "ext/standard/var_unserializer.re" +#line 541 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1184 "ext/standard/var_unserializer.c" +#line 1191 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 530 "ext/standard/var_unserializer.re" +#line 534 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1194 "ext/standard/var_unserializer.c" +#line 1201 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1213,7 +1220,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 507 "ext/standard/var_unserializer.re" +#line 511 "ext/standard/var_unserializer.re" { long id; @@ -1233,10 +1240,10 @@ yy91: *rval = *rval_ref; Z_ADDREF_PP(rval); Z_UNSET_ISREF_PP(rval); - + return 1; } -#line 1240 "ext/standard/var_unserializer.c" +#line 1247 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1259,7 +1266,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 486 "ext/standard/var_unserializer.re" +#line 490 "ext/standard/var_unserializer.re" { long id; @@ -1272,17 +1279,17 @@ yy97: } if (*rval != NULL) { - zval_ptr_dtor(rval); + var_push_dtor_no_addref(var_hash, rval); } *rval = *rval_ref; Z_ADDREF_PP(rval); Z_SET_ISREF_PP(rval); - + return 1; } -#line 1284 "ext/standard/var_unserializer.c" +#line 1291 "ext/standard/var_unserializer.c" } -#line 835 "ext/standard/var_unserializer.re" +#line 842 "ext/standard/var_unserializer.re" return 0; |