PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - lcov_data/ext/standard - var_unserializer.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 267 392 68.1 %
Date: 2022-01-23 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Generated by re2c 1.0.1 */
       2             : #line 1 "ext/standard/var_unserializer.re"
       3             : /*
       4             :   +----------------------------------------------------------------------+
       5             :   | PHP Version 7                                                        |
       6             :   +----------------------------------------------------------------------+
       7             :   | Copyright (c) 1997-2018 The PHP Group                                |
       8             :   +----------------------------------------------------------------------+
       9             :   | This source file is subject to version 3.01 of the PHP license,      |
      10             :   | that is bundled with this package in the file LICENSE, and is        |
      11             :   | available through the world-wide-web at the following url:           |
      12             :   | http://www.php.net/license/3_01.txt                                  |
      13             :   | If you did not receive a copy of the PHP license and are unable to   |
      14             :   | obtain it through the world-wide-web, please send a note to          |
      15             :   | license@php.net so we can mail you a copy immediately.               |
      16             :   +----------------------------------------------------------------------+
      17             :   | Author: Sascha Schumann <sascha@schumann.cx>                         |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #include "php.h"
      24             : #include "ext/standard/php_var.h"
      25             : #include "php_incomplete_class.h"
      26             : 
      27             : struct php_unserialize_data {
      28             :         void *first;
      29             :         void *last;
      30             :         void *first_dtor;
      31             :         void *last_dtor;
      32             :         HashTable *allowed_classes;
      33             : };
      34             : 
      35             : PHPAPI php_unserialize_data_t php_var_unserialize_init() {
      36             :         php_unserialize_data_t d;
      37             :         /* fprintf(stderr, "UNSERIALIZE_INIT    == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
      38             :         if (BG(serialize_lock) || !BG(unserialize).level) {
      39             :                 d = ecalloc(1, sizeof(struct php_unserialize_data));
      40             :                 if (!BG(serialize_lock)) {
      41             :                         BG(unserialize).data = d;
      42             :                         BG(unserialize).level = 1;
      43             :                 }
      44             :         } else {
      45             :                 d = BG(unserialize).data;
      46             :                 ++BG(unserialize).level;
      47             :         }
      48             :         return d;
      49             : }
      50             : 
      51             : PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
      52             :         /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
      53             :         if (BG(serialize_lock) || BG(unserialize).level == 1) {
      54             :                 var_destroy(&d);
      55             :                 efree(d);
      56             :         }
      57             :         if (!BG(serialize_lock) && !--BG(unserialize).level) {
      58             :                 BG(unserialize).data = NULL;
      59             :         }
      60             : }
      61             : 
      62             : PHPAPI HashTable *php_var_unserialize_get_allowed_classes(php_unserialize_data_t d) {
      63             :         return d->allowed_classes;
      64             : }
      65             : PHPAPI void php_var_unserialize_set_allowed_classes(php_unserialize_data_t d, HashTable *classes) {
      66             :         d->allowed_classes = classes;
      67             : }
      68             : 
      69             : 
      70             : /* {{{ reference-handling for unserializer: var_* */
      71             : #define VAR_ENTRIES_MAX 1024
      72             : #define VAR_ENTRIES_DBG 0
      73             : 
      74             : /* VAR_FLAG used in var_dtor entries to signify an entry on which __wakeup should be called */
      75             : #define VAR_WAKEUP_FLAG 1
      76             : 
      77             : typedef struct {
      78             :         zval *data[VAR_ENTRIES_MAX];
      79             :         zend_long used_slots;
      80             :         void *next;
      81             : } var_entries;
      82             : 
      83             : typedef struct {
      84             :         zval data[VAR_ENTRIES_MAX];
      85             :         zend_long used_slots;
      86             :         void *next;
      87             : } var_dtor_entries;
      88             : 
      89             : static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
      90             : {
      91             :         var_entries *var_hash = (*var_hashx)->last;
      92             : #if VAR_ENTRIES_DBG
      93             :         fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval));
      94             : #endif
      95             : 
      96             :         if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
      97             :                 var_hash = emalloc(sizeof(var_entries));
      98             :                 var_hash->used_slots = 0;
      99             :                 var_hash->next = 0;
     100             : 
     101             :                 if (!(*var_hashx)->first) {
     102             :                         (*var_hashx)->first = var_hash;
     103             :                 } else {
     104             :                         ((var_entries *) (*var_hashx)->last)->next = var_hash;
     105             :                 }
     106             : 
     107             :                 (*var_hashx)->last = var_hash;
     108             :         }
     109             : 
     110             :         var_hash->data[var_hash->used_slots++] = rval;
     111             : }
     112             : 
     113             : PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
     114             : {
     115             :         zval *tmp_var = var_tmp_var(var_hashx);
     116             :     if (!tmp_var) {
     117             :         return;
     118             :     }
     119             :         ZVAL_COPY(tmp_var, rval);
     120             : }
     121             : 
     122             : PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
     123             : {
     124             :     var_dtor_entries *var_hash;
     125             : 
     126             :     if (!var_hashx || !*var_hashx) {
     127             :         return NULL;
     128             :     }
     129             : 
     130             :     var_hash = (*var_hashx)->last_dtor;
     131             :     if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
     132             :         var_hash = emalloc(sizeof(var_dtor_entries));
     133             :         var_hash->used_slots = 0;
     134             :         var_hash->next = 0;
     135             : 
     136             :         if (!(*var_hashx)->first_dtor) {
     137             :             (*var_hashx)->first_dtor = var_hash;
     138             :         } else {
     139             :             ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
     140             :         }
     141             : 
     142             :         (*var_hashx)->last_dtor = var_hash;
     143             :     }
     144             :     ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]);
     145             :         Z_EXTRA(var_hash->data[var_hash->used_slots]) = 0;
     146             :     return &var_hash->data[var_hash->used_slots++];
     147             : }
     148             : 
     149             : PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
     150             : {
     151             :         zend_long i;
     152             :         var_entries *var_hash = (*var_hashx)->first;
     153             : #if VAR_ENTRIES_DBG
     154             :         fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(nzval));
     155             : #endif
     156             : 
     157             :         while (var_hash) {
     158             :                 for (i = 0; i < var_hash->used_slots; i++) {
     159             :                         if (var_hash->data[i] == ozval) {
     160             :                                 var_hash->data[i] = nzval;
     161             :                                 /* do not break here */
     162             :                         }
     163             :                 }
     164             :                 var_hash = var_hash->next;
     165             :         }
     166             : }
     167             : 
     168             : static zval *var_access(php_unserialize_data_t *var_hashx, zend_long id)
     169             : {
     170             :         var_entries *var_hash = (*var_hashx)->first;
     171             : #if VAR_ENTRIES_DBG
     172             :         fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
     173             : #endif
     174             : 
     175             :         while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
     176             :                 var_hash = var_hash->next;
     177             :                 id -= VAR_ENTRIES_MAX;
     178             :         }
     179             : 
     180             :         if (!var_hash) return NULL;
     181             : 
     182             :         if (id < 0 || id >= var_hash->used_slots) return NULL;
     183             : 
     184             :         return var_hash->data[id];
     185             : }
     186             : 
     187             : PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
     188             : {
     189             :         void *next;
     190             :         zend_long i;
     191             :         var_entries *var_hash = (*var_hashx)->first;
     192             :         var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
     193             :         zend_bool wakeup_failed = 0;
     194             :         zval wakeup_name;
     195             :         ZVAL_UNDEF(&wakeup_name);
     196             : 
     197             : #if VAR_ENTRIES_DBG
     198             :         fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
     199             : #endif
     200             : 
     201             :         while (var_hash) {
     202             :                 next = var_hash->next;
     203             :                 efree_size(var_hash, sizeof(var_entries));
     204             :                 var_hash = next;
     205             :         }
     206             : 
     207             :         while (var_dtor_hash) {
     208             :                 for (i = 0; i < var_dtor_hash->used_slots; i++) {
     209             :                         zval *zv = &var_dtor_hash->data[i];
     210             : #if VAR_ENTRIES_DBG
     211             :                         fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
     212             : #endif
     213             : 
     214             :                         /* Perform delayed __wakeup calls */
     215             :                         if (Z_EXTRA_P(zv) == VAR_WAKEUP_FLAG) {
     216             :                                 if (!wakeup_failed) {
     217             :                                         zval retval;
     218             :                                         if (Z_ISUNDEF(wakeup_name)) {
     219             :                                                 ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1);
     220             :                                         }
     221             : 
     222             :                                         BG(serialize_lock)++;
     223             :                                         if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
     224             :                                                 wakeup_failed = 1;
     225             :                                                 GC_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED;
     226             :                                         }
     227             :                                         BG(serialize_lock)--;
     228             : 
     229             :                                         zval_ptr_dtor(&retval);
     230             :                                 } else {
     231             :                                         GC_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED;
     232             :                                 }
     233             :                         }
     234             : 
     235             :                         zval_ptr_dtor(zv);
     236             :                 }
     237             :                 next = var_dtor_hash->next;
     238             :                 efree_size(var_dtor_hash, sizeof(var_dtor_entries));
     239             :                 var_dtor_hash = next;
     240             :         }
     241             : 
     242             :         zval_ptr_dtor(&wakeup_name);
     243             : }
     244             : 
     245             : /* }}} */
     246             : 
     247             : static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen)
     248             : {
     249             :         size_t i, j;
     250             :         zend_string *str = zend_string_safe_alloc(1, len, 0, 0);
     251             :         unsigned char *end = *(unsigned char **)p+maxlen;
     252             : 
     253             :         if (end < *p) {
     254             :                 zend_string_free(str);
     255             :                 return NULL;
     256             :         }
     257             : 
     258             :         for (i = 0; i < len; i++) {
     259             :                 if (*p >= end) {
     260             :                         zend_string_free(str);
     261             :                         return NULL;
     262             :                 }
     263             :                 if (**p != '\\') {
     264             :                         ZSTR_VAL(str)[i] = (char)**p;
     265             :                 } else {
     266             :                         unsigned char ch = 0;
     267             : 
     268             :                         for (j = 0; j < 2; j++) {
     269             :                                 (*p)++;
     270             :                                 if (**p >= '0' && **p <= '9') {
     271             :                                         ch = (ch << 4) + (**p -'0');
     272             :                                 } else if (**p >= 'a' && **p <= 'f') {
     273             :                                         ch = (ch << 4) + (**p -'a'+10);
     274             :                                 } else if (**p >= 'A' && **p <= 'F') {
     275             :                                         ch = (ch << 4) + (**p -'A'+10);
     276             :                                 } else {
     277             :                                         zend_string_free(str);
     278             :                                         return NULL;
     279             :                                 }
     280             :                         }
     281             :                         ZSTR_VAL(str)[i] = (char)ch;
     282             :                 }
     283             :                 (*p)++;
     284             :         }
     285             :         ZSTR_VAL(str)[i] = 0;
     286             :         ZSTR_LEN(str) = i;
     287             :         return str;
     288             : }
     289             : 
     290             : static inline int unserialize_allowed_class(
     291             :                 zend_string *class_name, php_unserialize_data_t *var_hashx)
     292             : {
     293             :         HashTable *classes = (*var_hashx)->allowed_classes;
     294             :         zend_string *lcname;
     295             :         int res;
     296             :         ALLOCA_FLAG(use_heap)
     297             : 
     298             :         if(classes == NULL) {
     299             :                 return 1;
     300             :         }
     301             :         if(!zend_hash_num_elements(classes)) {
     302             :                 return 0;
     303             :         }
     304             : 
     305             :         ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap);
     306             :         zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
     307             :         res = zend_hash_exists(classes, lcname);
     308             :         ZSTR_ALLOCA_FREE(lcname, use_heap);
     309             :         return res;
     310             : }
     311             : 
     312             : #define YYFILL(n) do { } while (0)
     313             : #define YYCTYPE unsigned char
     314             : #define YYCURSOR cursor
     315             : #define YYLIMIT limit
     316             : #define YYMARKER marker
     317             : 
     318             : 
     319             : #line 324 "ext/standard/var_unserializer.re"
     320             : 
     321             : 
     322             : 
     323             : 
     324             : static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **q)
     325             : {
     326             :         zend_long result = 0;
     327             :         char *end;
     328             : 
     329             :         errno = 0;
     330             :         result = ZEND_STRTOL((const char*)p, &end, 0);
     331             : 
     332             :         if (q) {
     333             :                 *q = (const unsigned char *)end;
     334             :         }
     335             : 
     336             :         if (errno) {
     337             :                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
     338             :                 return result;
     339             :         }
     340             : 
     341             :         return result;
     342             : }
     343             : 
     344             : static inline zend_long parse_iv(const unsigned char *p)
     345             : {
     346             :         return parse_iv2(p, NULL);
     347             : }
     348             : 
     349             : /* no need to check for length - re2c already did */
     350             : static inline size_t parse_uiv(const unsigned char *p)
     351             : {
     352             :         unsigned char cursor;
     353             :         size_t result = 0;
     354             : 
     355             :         if (*p == '+') {
     356             :                 p++;
     357             :         }
     358             : 
     359             :         while (1) {
     360             :                 cursor = *p;
     361             :                 if (cursor >= '0' && cursor <= '9') {
     362             :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     363             :                 } else {
     364             :                         break;
     365             :                 }
     366             :                 p++;
     367             :         }
     368             :         return result;
     369             : }
     370             : 
     371             : #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash
     372             : #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash
     373             : 
     374             : static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
     375             : 
     376             : static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
     377             : {
     378             :         while (elements-- > 0) {
     379             :                 zval key, *data, d, *old_data;
     380             :                 zend_ulong idx;
     381             : 
     382             :                 ZVAL_UNDEF(&key);
     383             : 
     384             :                 if (!php_var_unserialize_internal(&key, p, max, NULL)) {
     385             :                         zval_dtor(&key);
     386             :                         return 0;
     387             :                 }
     388             : 
     389             :                 data = NULL;
     390             :                 ZVAL_UNDEF(&d);
     391             : 
     392             :                 if (!objprops) {
     393             :                         if (Z_TYPE(key) == IS_LONG) {
     394             :                                 idx = Z_LVAL(key);
     395             : numeric_key:
     396             :                                 if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
     397             :                                         //??? update hash
     398             :                                         var_push_dtor(var_hash, old_data);
     399             :                                         data = zend_hash_index_update(ht, idx, &d);
     400             :                                 } else {
     401             :                                         data = zend_hash_index_add_new(ht, idx, &d);
     402             :                                 }
     403             :                         } else if (Z_TYPE(key) == IS_STRING) {
     404             :                                 if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
     405             :                                         goto numeric_key;
     406             :                                 }
     407             :                                 if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
     408             :                                         //??? update hash
     409             :                                         var_push_dtor(var_hash, old_data);
     410             :                                         data = zend_hash_update(ht, Z_STR(key), &d);
     411             :                                 } else {
     412             :                                         data = zend_hash_add_new(ht, Z_STR(key), &d);
     413             :                                 }
     414             :                         } else {
     415             :                                 zval_dtor(&key);
     416             :                                 return 0;
     417             :                         }
     418             :                 } else {
     419             :                         if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
     420             : string_key:
     421             :                                 if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
     422             :                                         if (Z_TYPE_P(old_data) == IS_INDIRECT) {
     423             :                                                 old_data = Z_INDIRECT_P(old_data);
     424             :                                         }
     425             :                                         var_push_dtor(var_hash, old_data);
     426             :                                         data = zend_hash_update_ind(ht, Z_STR(key), &d);
     427             :                                 } else {
     428             :                                         data = zend_hash_add_new(ht, Z_STR(key), &d);
     429             :                                 }
     430             :                         } else if (Z_TYPE(key) == IS_LONG) {
     431             :                                 /* object properties should include no integers */
     432             :                                 convert_to_string(&key);
     433             :                                 goto string_key;
     434             :                         } else {
     435             :                                 zval_dtor(&key);
     436             :                                 return 0;
     437             :                         }
     438             :                 }
     439             : 
     440             :                 if (!php_var_unserialize_internal(data, p, max, var_hash)) {
     441             :                         zval_dtor(&key);
     442             :                         return 0;
     443             :                 }
     444             : 
     445             :                 var_push_dtor(var_hash, data);
     446             :                 zval_dtor(&key);
     447             : 
     448             :                 if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
     449             :                         (*p)--;
     450             :                         return 0;
     451             :                 }
     452             :         }
     453             : 
     454             :         return 1;
     455             : }
     456             : 
     457             : static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
     458             : {
     459             :         if (*p >= max || **p != '}') {
     460             :                 return 0;
     461             :         }
     462             : 
     463             :         (*p)++;
     464             :         return 1;
     465             : }
     466             : 
     467             : static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     468             : {
     469             :         zend_long datalen;
     470             : 
     471             :         datalen = parse_iv2((*p) + 2, p);
     472             : 
     473             :         (*p) += 2;
     474             : 
     475             :         if (datalen < 0 || (max - (*p)) <= datalen) {
     476             :                 zend_error(E_WARNING, "Insufficient data for unserializing - " ZEND_LONG_FMT " required, " ZEND_LONG_FMT " present", datalen, (zend_long)(max - (*p)));
     477             :                 return 0;
     478             :         }
     479             : 
     480             :         /* Check that '}' is present before calling ce->unserialize() to mitigate issues
     481             :          * with unserialize reading past the end of the passed buffer if the string is not
     482             :          * appropriately terminated (usually NUL terminated, but '}' is also sufficient.) */
     483             :         if ((*p)[datalen] != '}') {
     484             :                 return 0;
     485             :         }
     486             : 
     487             :         if (ce->unserialize == NULL) {
     488             :                 zend_error(E_WARNING, "Class %s has no unserializer", ZSTR_VAL(ce->name));
     489             :                 object_init_ex(rval, ce);
     490             :         } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
     491             :                 return 0;
     492             :         }
     493             : 
     494             :         (*p) += datalen + 1; /* +1 for '}' */
     495             :         return 1;
     496             : }
     497             : 
     498             : static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     499             : {
     500             :         zend_long elements;
     501             : 
     502             :         if( *p >= max - 2) {
     503             :                 zend_error(E_WARNING, "Bad unserialize data");
     504             :                 return -1;
     505             :         }
     506             : 
     507             :         elements = parse_iv2((*p) + 2, p);
     508             : 
     509             :         (*p) += 2;
     510             : 
     511             :         if (ce->serialize == NULL) {
     512             :                 object_init_ex(rval, ce);
     513             :         } else {
     514             :                 /* If this class implements Serializable, it should not land here but in object_custom(). The passed string
     515             :                 obviously doesn't descend from the regular serializer. */
     516             :                 zend_error(E_WARNING, "Erroneous data format for unserializing '%s'", ZSTR_VAL(ce->name));
     517             :                 return -1;
     518             :         }
     519             : 
     520             :         return elements;
     521             : }
     522             : 
     523             : #ifdef PHP_WIN32
     524             : # pragma optimize("", off)
     525             : #endif
     526             : static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
     527             : {
     528             :         HashTable *ht;
     529             :         zend_bool has_wakeup;
     530             : 
     531             :         if (Z_TYPE_P(rval) != IS_OBJECT) {
     532             :                 return 0;
     533             :         }
     534             : 
     535             :         has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
     536             :                 && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
     537             : 
     538             :         ht = Z_OBJPROP_P(rval);
     539             :         if (elements >= HT_MAX_SIZE - zend_hash_num_elements(ht)) {
     540             :                 return 0;
     541             :         }
     542             : 
     543             :         zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
     544             :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
     545             :                 if (has_wakeup) {
     546             :                         ZVAL_DEREF(rval);
     547             :                         GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
     548             :                 }
     549             :                 return 0;
     550             :         }
     551             : 
     552             :         ZVAL_DEREF(rval);
     553             :         if (has_wakeup) {
     554             :                 /* Delay __wakeup call until end of serialization */
     555             :                 zval *wakeup_var = var_tmp_var(var_hash);
     556             :                 ZVAL_COPY(wakeup_var, rval);
     557             :                 Z_EXTRA_P(wakeup_var) = VAR_WAKEUP_FLAG;
     558             :         }
     559             : 
     560             :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     561             : }
     562             : #ifdef PHP_WIN32
     563             : # pragma optimize("", on)
     564             : #endif
     565             : 
     566             : PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
     567             : {
     568             :         var_entries *orig_var_entries = (*var_hash)->last;
     569             :         zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
     570             :         int result;
     571             : 
     572             :         result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
     573             : 
     574             :         if (!result) {
     575             :                 /* If the unserialization failed, mark all elements that have been added to var_hash
     576             :                  * as NULL. This will forbid their use by other unserialize() calls in the same
     577             :                  * unserialization context. */
     578             :                 var_entries *e = orig_var_entries;
     579             :                 zend_long s = orig_used_slots;
     580             :                 while (e) {
     581             :                         for (; s < e->used_slots; s++) {
     582             :                                 e->data[s] = NULL;
     583             :                         }
     584             : 
     585             :                         e = e->next;
     586             :                         s = 0;
     587             :                 }
     588             :         }
     589             : 
     590             :         return result;
     591             : }
     592             : 
     593             : static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
     594             : {
     595             :         const unsigned char *cursor, *limit, *marker, *start;
     596             :         zval *rval_ref;
     597             : 
     598             :         limit = max;
     599             :         cursor = *p;
     600             : 
     601             :         if (YYCURSOR >= YYLIMIT) {
     602             :                 return 0;
     603             :         }
     604             : 
     605             :         if (var_hash && (*p)[0] != 'R') {
     606             :                 var_push(var_hash, rval);
     607             :         }
     608             : 
     609             :         start = cursor;
     610             : 
     611             : 
     612             : #line 613 "ext/standard/var_unserializer.c"
     613             : {
     614             :         YYCTYPE yych;
     615             :         static const unsigned char yybm[] = {
     616             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     617             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     618             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     619             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     620             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     621             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     622             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     623             :                 128, 128,   0,   0,   0,   0,   0,   0, 
     624             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     625             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     626             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     627             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     628             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     629             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     630             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     631             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     632             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     633             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     634             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     635             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     636             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     637             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     638             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     639             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     640             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     641             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     642             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     643             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     644             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     645             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     646             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     647             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     648             :         };
     649      378773 :         if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
     650      378773 :         yych = *YYCURSOR;
     651      378773 :         switch (yych) {
     652      142720 :         case 'C':
     653      142720 :         case 'O':       goto yy4;
     654       10085 :         case 'N':       goto yy5;
     655         321 :         case 'R':       goto yy6;
     656           1 :         case 'S':       goto yy7;
     657       66916 :         case 'a':       goto yy8;
     658          98 :         case 'b':       goto yy9;
     659          79 :         case 'd':       goto yy10;
     660      145719 :         case 'i':       goto yy11;
     661           2 :         case 'o':       goto yy12;
     662       10087 :         case 'r':       goto yy13;
     663        2708 :         case 's':       goto yy14;
     664           5 :         case '}':       goto yy15;
     665          32 :         default:        goto yy2;
     666             :         }
     667          32 : yy2:
     668          32 :         ++YYCURSOR;
     669         101 : yy3:
     670             : #line 988 "ext/standard/var_unserializer.re"
     671             :         { return 0; }
     672             : #line 673 "ext/standard/var_unserializer.c"
     673      142720 : yy4:
     674      142720 :         yych = *(YYMARKER = ++YYCURSOR);
     675      142720 :         if (yych == ':') goto yy17;
     676           0 :         goto yy3;
     677       10085 : yy5:
     678       10085 :         yych = *++YYCURSOR;
     679       10085 :         if (yych == ';') goto yy19;
     680           0 :         goto yy3;
     681         321 : yy6:
     682         321 :         yych = *(YYMARKER = ++YYCURSOR);
     683         321 :         if (yych == ':') goto yy21;
     684           2 :         goto yy3;
     685           1 : yy7:
     686           1 :         yych = *(YYMARKER = ++YYCURSOR);
     687           1 :         if (yych == ':') goto yy22;
     688           0 :         goto yy3;
     689       66916 : yy8:
     690       66916 :         yych = *(YYMARKER = ++YYCURSOR);
     691       66916 :         if (yych == ':') goto yy23;
     692          23 :         goto yy3;
     693          98 : yy9:
     694          98 :         yych = *(YYMARKER = ++YYCURSOR);
     695          98 :         if (yych == ':') goto yy24;
     696           0 :         goto yy3;
     697          79 : yy10:
     698          79 :         yych = *(YYMARKER = ++YYCURSOR);
     699          79 :         if (yych == ':') goto yy25;
     700           2 :         goto yy3;
     701      145719 : yy11:
     702      145719 :         yych = *(YYMARKER = ++YYCURSOR);
     703      145719 :         if (yych == ':') goto yy26;
     704          15 :         goto yy3;
     705           2 : yy12:
     706           2 :         yych = *(YYMARKER = ++YYCURSOR);
     707           2 :         if (yych == ':') goto yy27;
     708           2 :         goto yy3;
     709       10087 : yy13:
     710       10087 :         yych = *(YYMARKER = ++YYCURSOR);
     711       10087 :         if (yych == ':') goto yy28;
     712           3 :         goto yy3;
     713        2708 : yy14:
     714        2708 :         yych = *(YYMARKER = ++YYCURSOR);
     715        2708 :         if (yych == ':') goto yy29;
     716           1 :         goto yy3;
     717           5 : yy15:
     718           5 :         ++YYCURSOR;
     719             : #line 982 "ext/standard/var_unserializer.re"
     720             :         {
     721             :         /* this is the case where we have less data than planned */
     722             :         php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
     723             :         return 0; /* not sure if it should be 0 or 1 here? */
     724             : }
     725             : #line 726 "ext/standard/var_unserializer.c"
     726      142720 : yy17:
     727      142720 :         yych = *++YYCURSOR;
     728      142720 :         if (yybm[0+yych] & 128) {
     729      142720 :                 goto yy31;
     730             :         }
     731           0 :         if (yych == '+') goto yy30;
     732           0 : yy18:
     733          21 :         YYCURSOR = YYMARKER;
     734          21 :         goto yy3;
     735       10085 : yy19:
     736       10085 :         ++YYCURSOR;
     737             : #line 666 "ext/standard/var_unserializer.re"
     738             :         {
     739             :         *p = YYCURSOR;
     740             :         ZVAL_NULL(rval);
     741             :         return 1;
     742             : }
     743             : #line 744 "ext/standard/var_unserializer.c"
     744         319 : yy21:
     745         319 :         yych = *++YYCURSOR;
     746         319 :         if (yych <= ',') {
     747           2 :                 if (yych == '+') goto yy33;
     748           2 :                 goto yy18;
     749             :         } else {
     750         317 :                 if (yych <= '-') goto yy33;
     751         317 :                 if (yych <= '/') goto yy18;
     752         317 :                 if (yych <= '9') goto yy34;
     753           0 :                 goto yy18;
     754             :         }
     755           1 : yy22:
     756           1 :         yych = *++YYCURSOR;
     757           1 :         if (yych == '+') goto yy36;
     758           1 :         if (yych <= '/') goto yy18;
     759           1 :         if (yych <= '9') goto yy37;
     760           0 :         goto yy18;
     761       66893 : yy23:
     762       66893 :         yych = *++YYCURSOR;
     763       66893 :         if (yych == '+') goto yy39;
     764       66893 :         if (yych <= '/') goto yy18;
     765       66892 :         if (yych <= '9') goto yy40;
     766           0 :         goto yy18;
     767          98 : yy24:
     768          98 :         yych = *++YYCURSOR;
     769          98 :         if (yych <= '/') goto yy18;
     770          98 :         if (yych <= '1') goto yy42;
     771           0 :         goto yy18;
     772          77 : yy25:
     773          77 :         yych = *++YYCURSOR;
     774          77 :         if (yych <= '/') {
     775          14 :                 if (yych <= ',') {
     776           0 :                         if (yych == '+') goto yy43;
     777           0 :                         goto yy18;
     778             :                 } else {
     779          14 :                         if (yych <= '-') goto yy44;
     780           0 :                         if (yych <= '.') goto yy45;
     781           0 :                         goto yy18;
     782             :                 }
     783             :         } else {
     784          63 :                 if (yych <= 'I') {
     785          62 :                         if (yych <= '9') goto yy46;
     786           1 :                         if (yych <= 'H') goto yy18;
     787           1 :                         goto yy48;
     788             :                 } else {
     789           1 :                         if (yych == 'N') goto yy49;
     790           0 :                         goto yy18;
     791             :                 }
     792             :         }
     793      145704 : yy26:
     794      145704 :         yych = *++YYCURSOR;
     795      145704 :         if (yych <= ',') {
     796           6 :                 if (yych == '+') goto yy50;
     797           6 :                 goto yy18;
     798             :         } else {
     799      145698 :                 if (yych <= '-') goto yy50;
     800      145690 :                 if (yych <= '/') goto yy18;
     801      145690 :                 if (yych <= '9') goto yy51;
     802           0 :                 goto yy18;
     803             :         }
     804           0 : yy27:
     805           0 :         yych = *++YYCURSOR;
     806           0 :         if (yych <= ',') {
     807           0 :                 if (yych == '+') goto yy53;
     808           0 :                 goto yy18;
     809             :         } else {
     810           0 :                 if (yych <= '-') goto yy53;
     811           0 :                 if (yych <= '/') goto yy18;
     812           0 :                 if (yych <= '9') goto yy54;
     813           0 :                 goto yy18;
     814             :         }
     815       10084 : yy28:
     816       10084 :         yych = *++YYCURSOR;
     817       10084 :         if (yych <= ',') {
     818           0 :                 if (yych == '+') goto yy56;
     819           0 :                 goto yy18;
     820             :         } else {
     821       10084 :                 if (yych <= '-') goto yy56;
     822       10084 :                 if (yych <= '/') goto yy18;
     823       10084 :                 if (yych <= '9') goto yy57;
     824           0 :                 goto yy18;
     825             :         }
     826        2707 : yy29:
     827        2707 :         yych = *++YYCURSOR;
     828        2707 :         if (yych == '+') goto yy59;
     829        2707 :         if (yych <= '/') goto yy18;
     830        2706 :         if (yych <= '9') goto yy60;
     831           0 :         goto yy18;
     832           0 : yy30:
     833           0 :         yych = *++YYCURSOR;
     834           0 :         if (yybm[0+yych] & 128) {
     835           0 :                 goto yy31;
     836             :         }
     837           0 :         goto yy18;
     838      142720 : yy31:
     839      142810 :         ++YYCURSOR;
     840      142810 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     841      142810 :         yych = *YYCURSOR;
     842      142810 :         if (yybm[0+yych] & 128) {
     843          90 :                 goto yy31;
     844             :         }
     845      142720 :         if (yych <= '/') goto yy18;
     846      142720 :         if (yych <= ':') goto yy62;
     847           0 :         goto yy18;
     848           0 : yy33:
     849           0 :         yych = *++YYCURSOR;
     850           0 :         if (yych <= '/') goto yy18;
     851           0 :         if (yych >= ':') goto yy18;
     852           0 : yy34:
     853         317 :         ++YYCURSOR;
     854         317 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     855         317 :         yych = *YYCURSOR;
     856         317 :         if (yych <= '/') goto yy18;
     857         315 :         if (yych <= '9') goto yy34;
     858         315 :         if (yych == ';') goto yy63;
     859           0 :         goto yy18;
     860           0 : yy36:
     861           0 :         yych = *++YYCURSOR;
     862           0 :         if (yych <= '/') goto yy18;
     863           0 :         if (yych >= ':') goto yy18;
     864           0 : yy37:
     865           3 :         ++YYCURSOR;
     866           3 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     867           3 :         yych = *YYCURSOR;
     868           3 :         if (yych <= '/') goto yy18;
     869           3 :         if (yych <= '9') goto yy37;
     870           1 :         if (yych <= ':') goto yy65;
     871           0 :         goto yy18;
     872           0 : yy39:
     873           0 :         yych = *++YYCURSOR;
     874           0 :         if (yych <= '/') goto yy18;
     875           0 :         if (yych >= ':') goto yy18;
     876           0 : yy40:
     877       66936 :         ++YYCURSOR;
     878       66936 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     879       66936 :         yych = *YYCURSOR;
     880       66936 :         if (yych <= '/') goto yy18;
     881       66935 :         if (yych <= '9') goto yy40;
     882       66891 :         if (yych <= ':') goto yy66;
     883           0 :         goto yy18;
     884          98 : yy42:
     885          98 :         yych = *++YYCURSOR;
     886          98 :         if (yych == ';') goto yy67;
     887           0 :         goto yy18;
     888           0 : yy43:
     889           0 :         yych = *++YYCURSOR;
     890           0 :         if (yych == '.') goto yy45;
     891           0 :         if (yych <= '/') goto yy18;
     892           0 :         if (yych <= '9') goto yy46;
     893           0 :         goto yy18;
     894          14 : yy44:
     895          14 :         yych = *++YYCURSOR;
     896          14 :         if (yych <= '/') {
     897           0 :                 if (yych != '.') goto yy18;
     898             :         } else {
     899          14 :                 if (yych <= '9') goto yy46;
     900           1 :                 if (yych == 'I') goto yy48;
     901           0 :                 goto yy18;
     902             :         }
     903           0 : yy45:
     904           0 :         yych = *++YYCURSOR;
     905           0 :         if (yych <= '/') goto yy18;
     906           0 :         if (yych <= '9') goto yy69;
     907           0 :         goto yy18;
     908          74 : yy46:
     909         216 :         ++YYCURSOR;
     910         216 :         if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
     911         216 :         yych = *YYCURSOR;
     912         216 :         if (yych <= ':') {
     913         199 :                 if (yych <= '.') {
     914          57 :                         if (yych <= '-') goto yy18;
     915          57 :                         goto yy69;
     916             :                 } else {
     917         142 :                         if (yych <= '/') goto yy18;
     918         142 :                         if (yych <= '9') goto yy46;
     919           0 :                         goto yy18;
     920             :                 }
     921             :         } else {
     922          17 :                 if (yych <= 'E') {
     923          17 :                         if (yych <= ';') goto yy71;
     924           0 :                         if (yych <= 'D') goto yy18;
     925           0 :                         goto yy73;
     926             :                 } else {
     927           0 :                         if (yych == 'e') goto yy73;
     928           0 :                         goto yy18;
     929             :                 }
     930             :         }
     931           2 : yy48:
     932           2 :         yych = *++YYCURSOR;
     933           2 :         if (yych == 'N') goto yy74;
     934           0 :         goto yy18;
     935           1 : yy49:
     936           1 :         yych = *++YYCURSOR;
     937           1 :         if (yych == 'A') goto yy75;
     938           0 :         goto yy18;
     939           8 : yy50:
     940           8 :         yych = *++YYCURSOR;
     941           8 :         if (yych <= '/') goto yy18;
     942           8 :         if (yych >= ':') goto yy18;
     943           8 : yy51:
     944      175317 :         ++YYCURSOR;
     945      175317 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     946      175317 :         yych = *YYCURSOR;
     947      175317 :         if (yych <= '/') goto yy18;
     948      175310 :         if (yych <= '9') goto yy51;
     949      145691 :         if (yych == ';') goto yy76;
     950           0 :         goto yy18;
     951           0 : yy53:
     952           0 :         yych = *++YYCURSOR;
     953           0 :         if (yych <= '/') goto yy18;
     954           0 :         if (yych >= ':') goto yy18;
     955           0 : yy54:
     956           0 :         ++YYCURSOR;
     957           0 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     958           0 :         yych = *YYCURSOR;
     959           0 :         if (yych <= '/') goto yy18;
     960           0 :         if (yych <= '9') goto yy54;
     961           0 :         if (yych <= ':') goto yy78;
     962           0 :         goto yy18;
     963           0 : yy56:
     964           0 :         yych = *++YYCURSOR;
     965           0 :         if (yych <= '/') goto yy18;
     966           0 :         if (yych >= ':') goto yy18;
     967           0 : yy57:
     968       38988 :         ++YYCURSOR;
     969       38988 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     970       38988 :         yych = *YYCURSOR;
     971       38988 :         if (yych <= '/') goto yy18;
     972       38988 :         if (yych <= '9') goto yy57;
     973       10084 :         if (yych == ';') goto yy79;
     974           0 :         goto yy18;
     975           0 : yy59:
     976           0 :         yych = *++YYCURSOR;
     977           0 :         if (yych <= '/') goto yy18;
     978           0 :         if (yych >= ':') goto yy18;
     979           0 : yy60:
     980        3380 :         ++YYCURSOR;
     981        3380 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     982        3380 :         yych = *YYCURSOR;
     983        3380 :         if (yych <= '/') goto yy18;
     984        3380 :         if (yych <= '9') goto yy60;
     985        2706 :         if (yych <= ':') goto yy81;
     986           0 :         goto yy18;
     987      142720 : yy62:
     988      142720 :         yych = *++YYCURSOR;
     989      142720 :         if (yych == '"') goto yy82;
     990           0 :         goto yy18;
     991         315 : yy63:
     992         315 :         ++YYCURSOR;
     993             : #line 617 "ext/standard/var_unserializer.re"
     994             :         {
     995             :         zend_long id;
     996             : 
     997             :         *p = YYCURSOR;
     998             :         if (!var_hash) return 0;
     999             : 
    1000             :         id = parse_iv(start + 2) - 1;
    1001             :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
    1002             :                 return 0;
    1003             :         }
    1004             : 
    1005             :         if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
    1006             :                 return 0;
    1007             :         }
    1008             : 
    1009             :         if (Z_ISREF_P(rval_ref)) {
    1010             :                 ZVAL_COPY(rval, rval_ref);
    1011             :         } else {
    1012             :                 ZVAL_NEW_REF(rval_ref, rval_ref);
    1013             :                 ZVAL_COPY(rval, rval_ref);
    1014             :         }
    1015             : 
    1016             :         return 1;
    1017             : }
    1018             : #line 1019 "ext/standard/var_unserializer.c"
    1019           1 : yy65:
    1020           1 :         yych = *++YYCURSOR;
    1021           1 :         if (yych == '"') goto yy84;
    1022           0 :         goto yy18;
    1023       66891 : yy66:
    1024       66891 :         yych = *++YYCURSOR;
    1025       66891 :         if (yych == '{') goto yy86;
    1026           1 :         goto yy18;
    1027          98 : yy67:
    1028          98 :         ++YYCURSOR;
    1029             : #line 672 "ext/standard/var_unserializer.re"
    1030             :         {
    1031             :         *p = YYCURSOR;
    1032             :         ZVAL_BOOL(rval, parse_iv(start + 2));
    1033             :         return 1;
    1034             : }
    1035             : #line 1036 "ext/standard/var_unserializer.c"
    1036          57 : yy69:
    1037        1759 :         ++YYCURSOR;
    1038        1759 :         if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
    1039        1759 :         yych = *YYCURSOR;
    1040        1759 :         if (yych <= ';') {
    1041        1739 :                 if (yych <= '/') goto yy18;
    1042        1739 :                 if (yych <= '9') goto yy69;
    1043          37 :                 if (yych <= ':') goto yy18;
    1044             :         } else {
    1045          20 :                 if (yych <= 'E') {
    1046          20 :                         if (yych <= 'D') goto yy18;
    1047          20 :                         goto yy73;
    1048             :                 } else {
    1049           0 :                         if (yych == 'e') goto yy73;
    1050           0 :                         goto yy18;
    1051             :                 }
    1052             :         }
    1053          74 : yy71:
    1054          74 :         ++YYCURSOR;
    1055             : #line 720 "ext/standard/var_unserializer.re"
    1056             :         {
    1057             : #if SIZEOF_ZEND_LONG == 4
    1058             : use_double:
    1059             : #endif
    1060             :         *p = YYCURSOR;
    1061             :         ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
    1062             :         return 1;
    1063             : }
    1064             : #line 1065 "ext/standard/var_unserializer.c"
    1065          20 : yy73:
    1066          20 :         yych = *++YYCURSOR;
    1067          20 :         if (yych <= ',') {
    1068           4 :                 if (yych == '+') goto yy88;
    1069           0 :                 goto yy18;
    1070             :         } else {
    1071          16 :                 if (yych <= '-') goto yy88;
    1072           0 :                 if (yych <= '/') goto yy18;
    1073           0 :                 if (yych <= '9') goto yy89;
    1074           0 :                 goto yy18;
    1075             :         }
    1076           2 : yy74:
    1077           2 :         yych = *++YYCURSOR;
    1078           2 :         if (yych == 'F') goto yy91;
    1079           0 :         goto yy18;
    1080           1 : yy75:
    1081           1 :         yych = *++YYCURSOR;
    1082           1 :         if (yych == 'N') goto yy91;
    1083           0 :         goto yy18;
    1084      145691 : yy76:
    1085      145691 :         ++YYCURSOR;
    1086             : #line 678 "ext/standard/var_unserializer.re"
    1087             :         {
    1088             : #if SIZEOF_ZEND_LONG == 4
    1089             :         int digits = YYCURSOR - start - 3;
    1090             : 
    1091             :         if (start[2] == '-' || start[2] == '+') {
    1092             :                 digits--;
    1093             :         }
    1094             : 
    1095             :         /* Use double for large zend_long values that were serialized on a 64-bit system */
    1096             :         if (digits >= MAX_LENGTH_OF_LONG - 1) {
    1097             :                 if (digits == MAX_LENGTH_OF_LONG - 1) {
    1098             :                         int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
    1099             : 
    1100             :                         if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
    1101             :                                 goto use_double;
    1102             :                         }
    1103             :                 } else {
    1104             :                         goto use_double;
    1105             :                 }
    1106             :         }
    1107             : #endif
    1108             :         *p = YYCURSOR;
    1109             :         ZVAL_LONG(rval, parse_iv(start + 2));
    1110             :         return 1;
    1111             : }
    1112             : #line 1113 "ext/standard/var_unserializer.c"
    1113           0 : yy78:
    1114           0 :         yych = *++YYCURSOR;
    1115           0 :         if (yych == '"') goto yy92;
    1116           0 :         goto yy18;
    1117       10084 : yy79:
    1118       10084 :         ++YYCURSOR;
    1119             : #line 642 "ext/standard/var_unserializer.re"
    1120             :         {
    1121             :         zend_long id;
    1122             : 
    1123             :         *p = YYCURSOR;
    1124             :         if (!var_hash) return 0;
    1125             : 
    1126             :         id = parse_iv(start + 2) - 1;
    1127             :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
    1128             :                 return 0;
    1129             :         }
    1130             : 
    1131             :         if (rval_ref == rval) {
    1132             :                 return 0;
    1133             :         }
    1134             : 
    1135             :         if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
    1136             :                 return 0;
    1137             :         }
    1138             : 
    1139             :         ZVAL_COPY(rval, rval_ref);
    1140             : 
    1141             :         return 1;
    1142             : }
    1143             : #line 1144 "ext/standard/var_unserializer.c"
    1144        2706 : yy81:
    1145        2706 :         yych = *++YYCURSOR;
    1146        2706 :         if (yych == '"') goto yy94;
    1147           0 :         goto yy18;
    1148      142720 : yy82:
    1149      142720 :         ++YYCURSOR;
    1150             : #line 830 "ext/standard/var_unserializer.re"
    1151             :         {
    1152             :         size_t len, len2, len3, maxlen;
    1153             :         zend_long elements;
    1154             :         char *str;
    1155             :         zend_string *class_name;
    1156             :         zend_class_entry *ce;
    1157             :         int incomplete_class = 0;
    1158             : 
    1159             :         int custom_object = 0;
    1160             : 
    1161             :         zval user_func;
    1162             :         zval retval;
    1163             :         zval args[1];
    1164             : 
    1165             :     if (!var_hash) return 0;
    1166             :         if (*start == 'C') {
    1167             :                 custom_object = 1;
    1168             :         }
    1169             : 
    1170             :         len2 = len = parse_uiv(start + 2);
    1171             :         maxlen = max - YYCURSOR;
    1172             :         if (maxlen < len || len == 0) {
    1173             :                 *p = start + 2;
    1174             :                 return 0;
    1175             :         }
    1176             : 
    1177             :         str = (char*)YYCURSOR;
    1178             : 
    1179             :         YYCURSOR += len;
    1180             : 
    1181             :         if (*(YYCURSOR) != '"') {
    1182             :                 *p = YYCURSOR;
    1183             :                 return 0;
    1184             :         }
    1185             :         if (*(YYCURSOR+1) != ':') {
    1186             :                 *p = YYCURSOR+1;
    1187             :                 return 0;
    1188             :         }
    1189             : 
    1190             :         len3 = strspn(str, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
    1191             :         if (len3 != len)
    1192             :         {
    1193             :                 *p = YYCURSOR + len3 - len;
    1194             :                 return 0;
    1195             :         }
    1196             : 
    1197             :         class_name = zend_string_init(str, len, 0);
    1198             : 
    1199             :         do {
    1200             :                 if(!unserialize_allowed_class(class_name, var_hash)) {
    1201             :                         incomplete_class = 1;
    1202             :                         ce = PHP_IC_ENTRY;
    1203             :                         break;
    1204             :                 }
    1205             : 
    1206             :                 /* Try to find class directly */
    1207             :                 BG(serialize_lock)++;
    1208             :                 ce = zend_lookup_class(class_name);
    1209             :                 if (ce) {
    1210             :                         BG(serialize_lock)--;
    1211             :                         if (EG(exception)) {
    1212             :                                 zend_string_release(class_name);
    1213             :                                 return 0;
    1214             :                         }
    1215             :                         break;
    1216             :                 }
    1217             :                 BG(serialize_lock)--;
    1218             : 
    1219             :                 if (EG(exception)) {
    1220             :                         zend_string_release(class_name);
    1221             :                         return 0;
    1222             :                 }
    1223             : 
    1224             :                 /* Check for unserialize callback */
    1225             :                 if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
    1226             :                         incomplete_class = 1;
    1227             :                         ce = PHP_IC_ENTRY;
    1228             :                         break;
    1229             :                 }
    1230             : 
    1231             :                 /* Call unserialize callback */
    1232             :                 ZVAL_STRING(&user_func, PG(unserialize_callback_func));
    1233             : 
    1234             :                 ZVAL_STR_COPY(&args[0], class_name);
    1235             :                 BG(serialize_lock)++;
    1236             :                 if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
    1237             :                         BG(serialize_lock)--;
    1238             :                         if (EG(exception)) {
    1239             :                                 zend_string_release(class_name);
    1240             :                                 zval_ptr_dtor(&user_func);
    1241             :                                 zval_ptr_dtor(&args[0]);
    1242             :                                 return 0;
    1243             :                         }
    1244             :                         php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
    1245             :                         incomplete_class = 1;
    1246             :                         ce = PHP_IC_ENTRY;
    1247             :                         zval_ptr_dtor(&user_func);
    1248             :                         zval_ptr_dtor(&args[0]);
    1249             :                         break;
    1250             :                 }
    1251             :                 BG(serialize_lock)--;
    1252             :                 zval_ptr_dtor(&retval);
    1253             :                 if (EG(exception)) {
    1254             :                         zend_string_release(class_name);
    1255             :                         zval_ptr_dtor(&user_func);
    1256             :                         zval_ptr_dtor(&args[0]);
    1257             :                         return 0;
    1258             :                 }
    1259             : 
    1260             :                 /* The callback function may have defined the class */
    1261             :                 BG(serialize_lock)++;
    1262             :                 if ((ce = zend_lookup_class(class_name)) == NULL) {
    1263             :                         php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
    1264             :                         incomplete_class = 1;
    1265             :                         ce = PHP_IC_ENTRY;
    1266             :                 }
    1267             :                 BG(serialize_lock)--;
    1268             : 
    1269             :                 zval_ptr_dtor(&user_func);
    1270             :                 zval_ptr_dtor(&args[0]);
    1271             :                 break;
    1272             :         } while (1);
    1273             : 
    1274             :         *p = YYCURSOR;
    1275             : 
    1276             :         if (custom_object) {
    1277             :                 int ret;
    1278             : 
    1279             :                 ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
    1280             : 
    1281             :                 if (ret && incomplete_class) {
    1282             :                         php_store_class_name(rval, ZSTR_VAL(class_name), len2);
    1283             :                 }
    1284             :                 zend_string_release(class_name);
    1285             :                 return ret;
    1286             :         }
    1287             : 
    1288             :         elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
    1289             : 
    1290             :         if (elements < 0) {
    1291             :            zend_string_release(class_name);
    1292             :            return 0;
    1293             :         }
    1294             : 
    1295             :         if (incomplete_class) {
    1296             :                 php_store_class_name(rval, ZSTR_VAL(class_name), len2);
    1297             :         }
    1298             :         zend_string_release(class_name);
    1299             : 
    1300             :         return object_common2(UNSERIALIZE_PASSTHRU, elements);
    1301             : }
    1302             : #line 1303 "ext/standard/var_unserializer.c"
    1303           1 : yy84:
    1304           1 :         ++YYCURSOR;
    1305             : #line 761 "ext/standard/var_unserializer.re"
    1306             :         {
    1307             :         size_t len, maxlen;
    1308             :         zend_string *str;
    1309             : 
    1310             :         len = parse_uiv(start + 2);
    1311             :         maxlen = max - YYCURSOR;
    1312             :         if (maxlen < len) {
    1313             :                 *p = start + 2;
    1314             :                 return 0;
    1315             :         }
    1316             : 
    1317             :         if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
    1318             :                 return 0;
    1319             :         }
    1320             : 
    1321             :         if (*(YYCURSOR) != '"') {
    1322             :                 zend_string_free(str);
    1323             :                 *p = YYCURSOR;
    1324             :                 return 0;
    1325             :         }
    1326             : 
    1327             :         if (*(YYCURSOR + 1) != ';') {
    1328             :                 efree(str);
    1329             :                 *p = YYCURSOR + 1;
    1330             :                 return 0;
    1331             :         }
    1332             : 
    1333             :         YYCURSOR += 2;
    1334             :         *p = YYCURSOR;
    1335             : 
    1336             :         ZVAL_STR(rval, str);
    1337             :         return 1;
    1338             : }
    1339             : #line 1340 "ext/standard/var_unserializer.c"
    1340       66890 : yy86:
    1341       66890 :         ++YYCURSOR;
    1342             : #line 795 "ext/standard/var_unserializer.re"
    1343             :         {
    1344             :         zend_long elements = parse_iv(start + 2);
    1345             :         /* use iv() not uiv() in order to check data range */
    1346             :         *p = YYCURSOR;
    1347             :     if (!var_hash) return 0;
    1348             : 
    1349             :         if (elements < 0 || elements >= HT_MAX_SIZE) {
    1350             :                 return 0;
    1351             :         }
    1352             : 
    1353             :         array_init_size(rval, elements);
    1354             :         if (elements) {
    1355             :                 /* we can't convert from packed to hash during unserialization, because
    1356             :                    reference to some zvals might be keept in var_hash (to support references) */
    1357             :                 zend_hash_real_init(Z_ARRVAL_P(rval), 0);
    1358             :         }
    1359             : 
    1360             :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
    1361             :                 return 0;
    1362             :         }
    1363             : 
    1364             :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
    1365             : }
    1366             : #line 1367 "ext/standard/var_unserializer.c"
    1367          20 : yy88:
    1368          20 :         yych = *++YYCURSOR;
    1369          20 :         if (yych <= ',') {
    1370           0 :                 if (yych == '+') goto yy96;
    1371           0 :                 goto yy18;
    1372             :         } else {
    1373          20 :                 if (yych <= '-') goto yy96;
    1374          20 :                 if (yych <= '/') goto yy18;
    1375          20 :                 if (yych >= ':') goto yy18;
    1376             :         }
    1377          20 : yy89:
    1378          42 :         ++YYCURSOR;
    1379          42 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
    1380          42 :         yych = *YYCURSOR;
    1381          42 :         if (yych <= '/') goto yy18;
    1382          42 :         if (yych <= '9') goto yy89;
    1383          20 :         if (yych == ';') goto yy71;
    1384           0 :         goto yy18;
    1385           3 : yy91:
    1386           3 :         yych = *++YYCURSOR;
    1387           3 :         if (yych == ';') goto yy97;
    1388           0 :         goto yy18;
    1389           0 : yy92:
    1390           0 :         ++YYCURSOR;
    1391             : #line 819 "ext/standard/var_unserializer.re"
    1392             :         {
    1393             :         zend_long elements;
    1394             :     if (!var_hash) return 0;
    1395             : 
    1396             :         elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
    1397             :         if (elements < 0 || elements >= HT_MAX_SIZE) {
    1398             :                 return 0;
    1399             :         }
    1400             :         return object_common2(UNSERIALIZE_PASSTHRU, elements);
    1401             : }
    1402             : #line 1403 "ext/standard/var_unserializer.c"
    1403        2706 : yy94:
    1404        2706 :         ++YYCURSOR;
    1405             : #line 729 "ext/standard/var_unserializer.re"
    1406             :         {
    1407             :         size_t len, maxlen;
    1408             :         char *str;
    1409             : 
    1410             :         len = parse_uiv(start + 2);
    1411             :         maxlen = max - YYCURSOR;
    1412             :         if (maxlen < len) {
    1413             :                 *p = start + 2;
    1414             :                 return 0;
    1415             :         }
    1416             : 
    1417             :         str = (char*)YYCURSOR;
    1418             : 
    1419             :         YYCURSOR += len;
    1420             : 
    1421             :         if (*(YYCURSOR) != '"') {
    1422             :                 *p = YYCURSOR;
    1423             :                 return 0;
    1424             :         }
    1425             : 
    1426             :         if (*(YYCURSOR + 1) != ';') {
    1427             :                 *p = YYCURSOR + 1;
    1428             :                 return 0;
    1429             :         }
    1430             : 
    1431             :         YYCURSOR += 2;
    1432             :         *p = YYCURSOR;
    1433             : 
    1434             :         ZVAL_STRINGL(rval, str, len);
    1435             :         return 1;
    1436             : }
    1437             : #line 1438 "ext/standard/var_unserializer.c"
    1438           0 : yy96:
    1439           0 :         yych = *++YYCURSOR;
    1440           0 :         if (yych <= '/') goto yy18;
    1441           0 :         if (yych <= '9') goto yy89;
    1442           0 :         goto yy18;
    1443           3 : yy97:
    1444           3 :         ++YYCURSOR;
    1445             : #line 704 "ext/standard/var_unserializer.re"
    1446             :         {
    1447             :         *p = YYCURSOR;
    1448             : 
    1449             :         if (!strncmp((char*)start + 2, "NAN", 3)) {
    1450             :                 ZVAL_DOUBLE(rval, php_get_nan());
    1451             :         } else if (!strncmp((char*)start + 2, "INF", 3)) {
    1452             :                 ZVAL_DOUBLE(rval, php_get_inf());
    1453             :         } else if (!strncmp((char*)start + 2, "-INF", 4)) {
    1454             :                 ZVAL_DOUBLE(rval, -php_get_inf());
    1455             :         } else {
    1456             :                 ZVAL_NULL(rval);
    1457             :         }
    1458             : 
    1459             :         return 1;
    1460             : }
    1461             : #line 1462 "ext/standard/var_unserializer.c"
    1462             : }
    1463             : #line 990 "ext/standard/var_unserializer.re"
    1464             : 
    1465             : 
    1466             :         return 0;
    1467             : }

Generated by: LCOV version 1.10

Generated at Mon, 24 Jan 2022 01:16:36 +0000 (5 days ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.