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.re (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 389 430 90.5 %
Date: 2016-09-27 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2016 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Sascha Schumann <sascha@schumann.cx>                         |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #include "php.h"
      22             : #include "ext/standard/php_var.h"
      23             : #include "php_incomplete_class.h"
      24             : 
      25             : struct php_unserialize_data {
      26             :         void *first;
      27             :         void *last;
      28             :         void *first_dtor;
      29             :         void *last_dtor;
      30             :         HashTable *allowed_classes;
      31             : };
      32             : 
      33       67336 : PHPAPI php_unserialize_data_t php_var_unserialize_init() {
      34             :         php_unserialize_data_t d;
      35             :         /* fprintf(stderr, "UNSERIALIZE_INIT    == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
      36      134611 :         if (BG(serialize_lock) || !BG(unserialize).level) {
      37       67275 :                 d = ecalloc(1, sizeof(struct php_unserialize_data));
      38       67275 :                 if (!BG(serialize_lock)) {
      39       67269 :                         BG(unserialize).data = d;
      40       67269 :                         BG(unserialize).level = 1;
      41             :                 }
      42             :         } else {
      43          61 :                 d = BG(unserialize).data;
      44          61 :                 ++BG(unserialize).level;
      45             :         }
      46       67336 :         return d;
      47             : }
      48             : 
      49       67336 : PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
      50             :         /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
      51       67336 :         if (BG(serialize_lock) || BG(unserialize).level == 1) {
      52       67275 :                 var_destroy(&d);
      53       67275 :                 efree(d);
      54             :         }
      55       67336 :         if (!BG(serialize_lock) && !--BG(unserialize).level) {
      56       67269 :                 BG(unserialize).data = NULL;
      57             :         }
      58       67336 : }
      59             : 
      60       66611 : PHPAPI HashTable *php_var_unserialize_get_allowed_classes(php_unserialize_data_t d) {
      61       66611 :         return d->allowed_classes;
      62             : }
      63       66618 : PHPAPI void php_var_unserialize_set_allowed_classes(php_unserialize_data_t d, HashTable *classes) {
      64       66618 :         d->allowed_classes = classes;
      65       66618 : }
      66             : 
      67             : 
      68             : /* {{{ reference-handling for unserializer: var_* */
      69             : #define VAR_ENTRIES_MAX 1024
      70             : #define VAR_ENTRIES_DBG 0
      71             : 
      72             : typedef struct {
      73             :         zval *data[VAR_ENTRIES_MAX];
      74             :         zend_long used_slots;
      75             :         void *next;
      76             : } var_entries;
      77             : 
      78             : typedef struct {
      79             :         zval data[VAR_ENTRIES_MAX];
      80             :         zend_long used_slots;
      81             :         void *next;
      82             : } var_dtor_entries;
      83             : 
      84      232490 : static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
      85             : {
      86      232490 :         var_entries *var_hash = (*var_hashx)->last;
      87             : #if VAR_ENTRIES_DBG
      88             :         fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval));
      89             : #endif
      90             : 
      91      232490 :         if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
      92       66939 :                 var_hash = emalloc(sizeof(var_entries));
      93       66939 :                 var_hash->used_slots = 0;
      94       66939 :                 var_hash->next = 0;
      95             : 
      96       66939 :                 if (!(*var_hashx)->first) {
      97       66910 :                         (*var_hashx)->first = var_hash;
      98             :                 } else {
      99          29 :                         ((var_entries *) (*var_hashx)->last)->next = var_hash;
     100             :                 }
     101             : 
     102       66939 :                 (*var_hashx)->last = var_hash;
     103             :         }
     104             : 
     105      232490 :         var_hash->data[var_hash->used_slots++] = rval;
     106      232490 : }
     107             : 
     108      212580 : PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
     109             : {
     110      212580 :         zval *tmp_var = var_tmp_var(var_hashx);
     111      212580 :     if (!tmp_var) {
     112           0 :         return;
     113             :     }
     114      212580 :         ZVAL_COPY(tmp_var, rval);
     115             : }
     116             : 
     117      212932 : PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
     118             : {
     119             :     var_dtor_entries *var_hash;
     120             : 
     121      212932 :     if (!var_hashx || !*var_hashx) {
     122           0 :         return NULL;
     123             :     }
     124             : 
     125      212932 :     var_hash = (*var_hashx)->last_dtor;
     126      212932 :     if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
     127       66782 :         var_hash = emalloc(sizeof(var_dtor_entries));
     128       66782 :         var_hash->used_slots = 0;
     129       66782 :         var_hash->next = 0;
     130             : 
     131       66782 :         if (!(*var_hashx)->first_dtor) {
     132       66773 :             (*var_hashx)->first_dtor = var_hash;
     133             :         } else {
     134           9 :             ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
     135             :         }
     136             : 
     137       66782 :         (*var_hashx)->last_dtor = var_hash;
     138             :     }
     139      212932 :     ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]);
     140      212932 :     return &var_hash->data[var_hash->used_slots++];
     141             : }
     142             : 
     143       20070 : PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
     144             : {
     145             :         zend_long i;
     146       20070 :         var_entries *var_hash = (*var_hashx)->first;
     147             : #if VAR_ENTRIES_DBG
     148             :         fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(nzval));
     149             : #endif
     150             : 
     151      440930 :         while (var_hash) {
     152   400501330 :                 for (i = 0; i < var_hash->used_slots; i++) {
     153   400100540 :                         if (var_hash->data[i] == ozval) {
     154       20069 :                                 var_hash->data[i] = nzval;
     155             :                                 /* do not break here */
     156             :                         }
     157             :                 }
     158      400790 :                 var_hash = var_hash->next;
     159             :         }
     160       20070 : }
     161             : 
     162       10386 : static zval *var_access(php_unserialize_data_t *var_hashx, zend_long id)
     163             : {
     164       10386 :         var_entries *var_hash = (*var_hashx)->first;
     165             : #if VAR_ENTRIES_DBG
     166             :         fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
     167             : #endif
     168             : 
     169       64710 :         while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
     170       43938 :                 var_hash = var_hash->next;
     171       43938 :                 id -= VAR_ENTRIES_MAX;
     172             :         }
     173             : 
     174       10386 :         if (!var_hash) return NULL;
     175             : 
     176       10385 :         if (id < 0 || id >= var_hash->used_slots) return NULL;
     177             : 
     178       10385 :         return var_hash->data[id];
     179             : }
     180             : 
     181       67275 : PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
     182             : {
     183             :         void *next;
     184             :         zend_long i;
     185       67275 :         var_entries *var_hash = (*var_hashx)->first;
     186       67275 :         var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
     187             : #if VAR_ENTRIES_DBG
     188             :         fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
     189             : #endif
     190             : 
     191      201489 :         while (var_hash) {
     192       66939 :                 next = var_hash->next;
     193       66939 :                 efree_size(var_hash, sizeof(var_entries));
     194       66939 :                 var_hash = next;
     195             :         }
     196             : 
     197      201332 :         while (var_dtor_hash) {
     198      279714 :                 for (i = 0; i < var_dtor_hash->used_slots; i++) {
     199             : #if VAR_ENTRIES_DBG
     200             :                         fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
     201             : #endif
     202      212932 :                         zval_ptr_dtor(&var_dtor_hash->data[i]);
     203             :                 }
     204       66782 :                 next = var_dtor_hash->next;
     205       66782 :                 efree_size(var_dtor_hash, sizeof(var_dtor_entries));
     206       66782 :                 var_dtor_hash = next;
     207             :         }
     208       67275 : }
     209             : 
     210             : /* }}} */
     211             : 
     212           1 : static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen)
     213             : {
     214             :         size_t i, j;
     215           1 :         zend_string *str = zend_string_safe_alloc(1, len, 0, 0);
     216           1 :         unsigned char *end = *(unsigned char **)p+maxlen;
     217             : 
     218           1 :         if (end < *p) {
     219             :                 zend_string_free(str);
     220           0 :                 return NULL;
     221             :         }
     222             : 
     223         102 :         for (i = 0; i < len; i++) {
     224         102 :                 if (*p >= end) {
     225             :                         zend_string_free(str);
     226           1 :                         return NULL;
     227             :                 }
     228         101 :                 if (**p != '\\') {
     229           1 :                         ZSTR_VAL(str)[i] = (char)**p;
     230             :                 } else {
     231         100 :                         unsigned char ch = 0;
     232             : 
     233         300 :                         for (j = 0; j < 2; j++) {
     234         200 :                                 (*p)++;
     235         400 :                                 if (**p >= '0' && **p <= '9') {
     236         200 :                                         ch = (ch << 4) + (**p -'0');
     237           0 :                                 } else if (**p >= 'a' && **p <= 'f') {
     238           0 :                                         ch = (ch << 4) + (**p -'a'+10);
     239           0 :                                 } else if (**p >= 'A' && **p <= 'F') {
     240           0 :                                         ch = (ch << 4) + (**p -'A'+10);
     241             :                                 } else {
     242             :                                         zend_string_free(str);
     243           0 :                                         return NULL;
     244             :                                 }
     245             :                         }
     246         100 :                         ZSTR_VAL(str)[i] = (char)ch;
     247             :                 }
     248         101 :                 (*p)++;
     249             :         }
     250           0 :         ZSTR_VAL(str)[i] = 0;
     251           0 :         ZSTR_LEN(str) = i;
     252           0 :         return str;
     253             : }
     254             : 
     255      142676 : static inline int unserialize_allowed_class(
     256             :                 zend_string *class_name, php_unserialize_data_t *var_hashx)
     257             : {
     258      142676 :         HashTable *classes = (*var_hashx)->allowed_classes;
     259             :         zend_string *lcname;
     260             :         int res;
     261             :         ALLOCA_FLAG(use_heap)
     262             : 
     263      142676 :         if(classes == NULL) {
     264      142666 :                 return 1;
     265             :         }
     266          10 :         if(!zend_hash_num_elements(classes)) {
     267           1 :                 return 0;
     268             :         }
     269             : 
     270          18 :         ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap);
     271           9 :         zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
     272           9 :         res = zend_hash_exists(classes, lcname);
     273           9 :         ZSTR_ALLOCA_FREE(lcname, use_heap);
     274           9 :         return res;
     275             : }
     276             : 
     277             : #define YYFILL(n) do { } while (0)
     278             : #define YYCTYPE unsigned char
     279             : #define YYCURSOR cursor
     280             : #define YYLIMIT limit
     281             : #define YYMARKER marker
     282             : 
     283             : 
     284             : /*!re2c
     285             : uiv = [+]? [0-9]+;
     286             : iv = [+-]? [0-9]+;
     287             : nv = [+-]? ([0-9]* "." [0-9]+|[0-9]+ "." [0-9]*);
     288             : nvexp = (iv | nv) [eE] [+-]? iv;
     289             : any = [\000-\377];
     290             : object = [OC];
     291             : */
     292             : 
     293             : 
     294             : 
     295      365650 : static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **q)
     296             : {
     297             :         char cursor;
     298      365650 :         zend_long result = 0;
     299      365650 :         int neg = 0;
     300             : 
     301      365650 :         switch (*p) {
     302             :                 case '-':
     303           8 :                         neg++;
     304             :                         /* fall-through */
     305             :                 case '+':
     306           8 :                         p++;
     307             :         }
     308             : 
     309             :         while (1) {
     310      789902 :                 cursor = (char)*p;
     311      789902 :                 if (cursor >= '0' && cursor <= '9') {
     312      424252 :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     313             :                 } else {
     314             :                         break;
     315             :                 }
     316      424252 :                 p++;
     317      424252 :         }
     318      365650 :         if (q) *q = p;
     319      365650 :         if (neg) return -result;
     320      365642 :         return result;
     321             : }
     322             : 
     323      222977 : static inline zend_long parse_iv(const unsigned char *p)
     324             : {
     325      222977 :         return parse_iv2(p, NULL);
     326             : }
     327             : 
     328             : /* no need to check for length - re2c already did */
     329      145186 : static inline size_t parse_uiv(const unsigned char *p)
     330             : {
     331             :         unsigned char cursor;
     332      145186 :         size_t result = 0;
     333             : 
     334      145186 :         if (*p == '+') {
     335           0 :                 p++;
     336             :         }
     337             : 
     338             :         while (1) {
     339      291051 :                 cursor = *p;
     340      291051 :                 if (cursor >= '0' && cursor <= '9') {
     341      145865 :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     342             :                 } else {
     343             :                         break;
     344             :                 }
     345      145865 :                 p++;
     346      145865 :         }
     347      145186 :         return result;
     348             : }
     349             : 
     350             : #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash
     351             : #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash
     352             : 
     353             : static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
     354             : 
     355             : static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
     356             : {
     357      355023 :         while (elements-- > 0) {
     358             :                 zval key, *data, d, *old_data;
     359             :                 zend_ulong idx;
     360             : 
     361      145625 :                 ZVAL_UNDEF(&key);
     362             : 
     363      145625 :                 if (!php_var_unserialize_internal(&key, p, max, NULL)) {
     364             :                         zval_dtor(&key);
     365          23 :                         return 0;
     366             :                 }
     367             : 
     368      145602 :                 data = NULL;
     369      145602 :                 ZVAL_UNDEF(&d);
     370             : 
     371      145602 :                 if (!objprops) {
     372      144286 :                         if (Z_TYPE(key) == IS_LONG) {
     373      143821 :                                 idx = Z_LVAL(key);
     374             : numeric_key:
     375      143822 :                                 if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
     376             :                                         //??? update hash
     377           4 :                                         var_push_dtor(var_hash, old_data);
     378           4 :                                         data = zend_hash_index_update(ht, idx, &d);
     379             :                                 } else {
     380      143818 :                                         data = zend_hash_index_add_new(ht, idx, &d);
     381             :                                 }
     382         465 :                         } else if (Z_TYPE(key) == IS_STRING) {
     383         930 :                                 if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
     384             :                                         goto numeric_key;
     385             :                                 }
     386         464 :                                 if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
     387             :                                         //??? update hash
     388           0 :                                         var_push_dtor(var_hash, old_data);
     389           0 :                                         data = zend_hash_update(ht, Z_STR(key), &d);
     390             :                                 } else {
     391         464 :                                         data = zend_hash_add_new(ht, Z_STR(key), &d);
     392             :                                 }
     393             :                         } else {
     394             :                                 zval_dtor(&key);
     395           0 :                                 return 0;
     396             :                         }
     397             :                 } else {
     398        1316 :                         if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
     399             : string_key:
     400        1316 :                                 if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
     401         433 :                                         if (Z_TYPE_P(old_data) == IS_INDIRECT) {
     402         235 :                                                 old_data = Z_INDIRECT_P(old_data);
     403             :                                         }
     404         433 :                                         var_push_dtor(var_hash, old_data);
     405         433 :                                         data = zend_hash_update_ind(ht, Z_STR(key), &d);
     406             :                                 } else {
     407         883 :                                         data = zend_hash_add_new(ht, Z_STR(key), &d);
     408             :                                 }
     409          15 :                         } else if (Z_TYPE(key) == IS_LONG) {
     410             :                                 /* object properties should include no integers */
     411          15 :                                 convert_to_string(&key);
     412             :                                 goto string_key;
     413             :                         } else {
     414             :                                 zval_dtor(&key);
     415           0 :                                 return 0;
     416             :                         }
     417             :                 }
     418             : 
     419      145602 :                 if (!php_var_unserialize_internal(data, p, max, var_hash)) {
     420             :                         zval_dtor(&key);
     421          32 :                         return 0;
     422             :                 }
     423             : 
     424      145570 :                 if (UNEXPECTED(Z_ISUNDEF_P(data))) {
     425           2 :                         if (Z_TYPE(key) == IS_LONG) {
     426           2 :                                 zend_hash_index_del(ht, Z_LVAL(key));
     427             :                         } else {
     428           0 :                                 zend_hash_del_ind(ht, Z_STR(key));
     429             :                         }
     430             :                 } else {
     431      145568 :                         var_push_dtor(var_hash, data);
     432             :                 }
     433             : 
     434             :                 zval_dtor(&key);
     435             : 
     436      145570 :                 if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
     437           0 :                         (*p)--;
     438           0 :                         return 0;
     439             :                 }
     440             :         }
     441             : 
     442      209398 :         return 1;
     443             : }
     444             : 
     445      209453 : static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
     446             : {
     447      209453 :         if (*((*p)++) == '}')
     448      209449 :                 return 1;
     449             : 
     450             : #if SOMETHING_NEW_MIGHT_LEAD_TO_CRASH_ENABLE_IF_YOU_ARE_BRAVE
     451             :         zval_ptr_dtor(rval);
     452             : #endif
     453           4 :         return 0;
     454             : }
     455             : 
     456          75 : static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     457             : {
     458             :         zend_long datalen;
     459             : 
     460          75 :         datalen = parse_iv2((*p) + 2, p);
     461             : 
     462          75 :         (*p) += 2;
     463             : 
     464          75 :         if (datalen < 0 || (max - (*p)) <= datalen) {
     465           1 :                 zend_error(E_WARNING, "Insufficient data for unserializing - " ZEND_LONG_FMT " required, " ZEND_LONG_FMT " present", datalen, (zend_long)(max - (*p)));
     466           1 :                 return 0;
     467             :         }
     468             : 
     469          74 :         if (ce->unserialize == NULL) {
     470           3 :                 zend_error(E_WARNING, "Class %s has no unserializer", ZSTR_VAL(ce->name));
     471           3 :                 object_init_ex(rval, ce);
     472          71 :         } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
     473           7 :                 return 0;
     474             :         }
     475             : 
     476          67 :         (*p) += datalen;
     477             : 
     478          67 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     479             : }
     480             : 
     481      142598 : static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     482             : {
     483             :         zend_long elements;
     484             : 
     485      142598 :         elements = parse_iv2((*p) + 2, p);
     486             : 
     487      142598 :         (*p) += 2;
     488             : 
     489      142598 :         if (ce->serialize == NULL) {
     490      142595 :                 object_init_ex(rval, ce);
     491             :         } else {
     492             :                 /* If this class implements Serializable, it should not land here but in object_custom(). The passed string
     493             :                 obviously doesn't descend from the regular serializer. */
     494           3 :                 zend_error(E_WARNING, "Erroneous data format for unserializing '%s'", ZSTR_VAL(ce->name));
     495           3 :                 return 0;
     496             :         }
     497             : 
     498      142595 :         return elements;
     499             : }
     500             : 
     501             : #ifdef PHP_WIN32
     502             : # pragma optimize("", off)
     503             : #endif
     504      142598 : static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
     505             : {
     506             :         zval retval;
     507             :         zval fname;
     508             :         HashTable *ht;
     509             :         zend_bool has_wakeup;
     510             : 
     511      142598 :         if (Z_TYPE_P(rval) != IS_OBJECT) {
     512           3 :                 return 0;
     513             :         }
     514             : 
     515      285173 :         has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
     516      142578 :                 && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
     517             : 
     518      142595 :         ht = Z_OBJPROP_P(rval);
     519      142595 :         zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
     520      142595 :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
     521          10 :                 if (has_wakeup) {
     522           6 :                         ZVAL_DEREF(rval);
     523           6 :                         GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
     524             :                 }
     525          10 :                 return 0;
     526             :         }
     527             : 
     528      142585 :         ZVAL_DEREF(rval);
     529      142585 :         if (has_wakeup) {
     530          98 :                 ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
     531          49 :                 BG(serialize_lock)++;
     532          98 :                 if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
     533          12 :                         GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
     534             :                 }
     535          49 :                 BG(serialize_lock)--;
     536             :                 zval_dtor(&fname);
     537             :                 zval_dtor(&retval);
     538             :         }
     539             : 
     540      142585 :         if (EG(exception)) {
     541          12 :                 return 0;
     542             :         }
     543             : 
     544      142573 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     545             : }
     546             : #ifdef PHP_WIN32
     547             : # pragma optimize("", on)
     548             : #endif
     549             : 
     550       87212 : PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
     551             : {
     552       87212 :         var_entries *orig_var_entries = (*var_hash)->last;
     553       87212 :         zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
     554             :         int result;
     555             :         
     556       87212 :         result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
     557             : 
     558       87212 :         if (!result) {
     559             :                 /* If the unserialization failed, mark all elements that have been added to var_hash
     560             :                  * as NULL. This will forbid their use by other unserialize() calls in the same
     561             :                  * unserialization context. */
     562         177 :                 var_entries *e = orig_var_entries;
     563         177 :                 zend_long s = orig_used_slots;
     564         372 :                 while (e) {
     565          30 :                         for (; s < e->used_slots; s++) {
     566          12 :                                 e->data[s] = NULL;
     567             :                         }
     568             : 
     569          18 :                         e = e->next;
     570          18 :                         s = 0;
     571             :                 }
     572             :         }
     573             : 
     574       87212 :         return result;
     575             : }
     576             : 
     577      378439 : static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
     578             : {
     579             :         const unsigned char *cursor, *limit, *marker, *start;
     580             :         zval *rval_ref;
     581             : 
     582      378439 :         limit = max;
     583      378439 :         cursor = *p;
     584             : 
     585      378439 :         if (YYCURSOR >= YYLIMIT) {
     586          19 :                 return 0;
     587             :         }
     588             : 
     589      378420 :         if (var_hash && (*p)[0] != 'R') {
     590      232490 :                 var_push(var_hash, rval);
     591             :         }
     592             : 
     593      378420 :         start = cursor;
     594             : 
     595             : /*!re2c
     596             : 
     597             : "R:" iv ";"         {
     598             :         zend_long id;
     599             : 
     600         304 :         *p = YYCURSOR;
     601         304 :         if (!var_hash) return 0;
     602             : 
     603         304 :         id = parse_iv(start + 2) - 1;
     604         304 :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
     605           5 :                 return 0;
     606             :         }
     607             : 
     608         299 :         zval_ptr_dtor(rval);
     609         620 :         if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
     610           1 :                 ZVAL_UNDEF(rval);
     611           1 :                 return 1;
     612             :         }
     613         298 :         if (Z_ISREF_P(rval_ref)) {
     614          23 :                 ZVAL_COPY(rval, rval_ref);
     615             :         } else {
     616         275 :                 ZVAL_NEW_REF(rval_ref, rval_ref);
     617         275 :                 ZVAL_COPY(rval, rval_ref);
     618             :         }
     619             : 
     620         298 :         return 1;
     621             : }
     622             : 
     623             : "r:" iv ";"         {
     624             :         zend_long id;
     625             : 
     626       10082 :         *p = YYCURSOR;
     627       10082 :         if (!var_hash) return 0;
     628             : 
     629       10082 :         id = parse_iv(start + 2) - 1;
     630       10082 :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
     631           0 :                 return 0;
     632             :         }
     633             : 
     634       10082 :         if (rval_ref == rval) {
     635           2 :                 return 0;
     636             :         }
     637             : 
     638       20159 :         if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
     639           1 :                 ZVAL_UNDEF(rval);
     640           1 :                 return 1;
     641             :         }
     642             : 
     643       10079 :         ZVAL_COPY(rval, rval_ref);
     644             : 
     645       10079 :         return 1;
     646             : }
     647             : 
     648             : "N;"  {
     649       10081 :         *p = YYCURSOR;
     650       10081 :         ZVAL_NULL(rval);
     651       10081 :         return 1;
     652             : }
     653             : 
     654             : "b:" [01] ";"       {
     655          99 :         *p = YYCURSOR;
     656          99 :         ZVAL_BOOL(rval, parse_iv(start + 2));
     657          99 :         return 1;
     658             : }
     659             : 
     660             : "i:" iv ";" {
     661             : #if SIZEOF_ZEND_LONG == 4
     662             :         int digits = YYCURSOR - start - 3;
     663             : 
     664             :         if (start[2] == '-' || start[2] == '+') {
     665             :                 digits--;
     666             :         }
     667             : 
     668             :         /* Use double for large zend_long values that were serialized on a 64-bit system */
     669             :         if (digits >= MAX_LENGTH_OF_LONG - 1) {
     670             :                 if (digits == MAX_LENGTH_OF_LONG - 1) {
     671             :                         int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
     672             : 
     673             :                         if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
     674             :                                 goto use_double;
     675             :                         }
     676             :                 } else {
     677             :                         goto use_double;
     678             :                 }
     679             :         }
     680             : #endif
     681      145633 :         *p = YYCURSOR;
     682      145633 :         ZVAL_LONG(rval, parse_iv(start + 2));
     683      145633 :         return 1;
     684             : }
     685             : 
     686             : "d:" ("NAN" | "-"? "INF") ";" {
     687           3 :         *p = YYCURSOR;
     688             : 
     689           3 :         if (!strncmp((char*)start + 2, "NAN", 3)) {
     690           1 :                 ZVAL_DOUBLE(rval, php_get_nan());
     691           2 :         } else if (!strncmp((char*)start + 2, "INF", 3)) {
     692           1 :                 ZVAL_DOUBLE(rval, php_get_inf());
     693           1 :         } else if (!strncmp((char*)start + 2, "-INF", 4)) {
     694           1 :                 ZVAL_DOUBLE(rval, -php_get_inf());
     695             :         } else {
     696           0 :                 ZVAL_NULL(rval);
     697             :         }
     698             : 
     699           3 :         return 1;
     700             : }
     701             : 
     702             : "d:" (iv | nv | nvexp) ";"  {
     703             : #if SIZEOF_ZEND_LONG == 4
     704             : use_double:
     705             : #endif
     706          69 :         *p = YYCURSOR;
     707          69 :         ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
     708          69 :         return 1;
     709             : }
     710             : 
     711             : "s:" uiv ":" ["]       {
     712             :         size_t len, maxlen;
     713             :         char *str;
     714             : 
     715        2505 :         len = parse_uiv(start + 2);
     716        2505 :         maxlen = max - YYCURSOR;
     717        2505 :         if (maxlen < len) {
     718           5 :                 *p = start + 2;
     719           5 :                 return 0;
     720             :         }
     721             : 
     722        2500 :         str = (char*)YYCURSOR;
     723             : 
     724        2500 :         YYCURSOR += len;
     725             : 
     726        2500 :         if (*(YYCURSOR) != '"') {
     727           2 :                 *p = YYCURSOR;
     728           2 :                 return 0;
     729             :         }
     730             : 
     731        2498 :         if (*(YYCURSOR + 1) != ';') {
     732           4 :                 *p = YYCURSOR + 1;
     733           4 :                 return 0;
     734             :         }
     735             : 
     736        2494 :         YYCURSOR += 2;
     737        2494 :         *p = YYCURSOR;
     738             : 
     739        4988 :         ZVAL_STRINGL(rval, str, len);
     740        2494 :         return 1;
     741             : }
     742             : 
     743             : "S:" uiv ":" ["]       {
     744             :         size_t len, maxlen;
     745             :         zend_string *str;
     746             : 
     747           1 :         len = parse_uiv(start + 2);
     748           1 :         maxlen = max - YYCURSOR;
     749           1 :         if (maxlen < len) {
     750           0 :                 *p = start + 2;
     751           0 :                 return 0;
     752             :         }
     753             : 
     754           1 :         if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
     755           1 :                 return 0;
     756             :         }
     757             : 
     758           0 :         if (*(YYCURSOR) != '"') {
     759             :                 zend_string_free(str);
     760           0 :                 *p = YYCURSOR;
     761           0 :                 return 0;
     762             :         }
     763             : 
     764           0 :         if (*(YYCURSOR + 1) != ';') {
     765           0 :                 efree(str);
     766           0 :                 *p = YYCURSOR + 1;
     767           0 :                 return 0;
     768             :         }
     769             : 
     770           0 :         YYCURSOR += 2;
     771           0 :         *p = YYCURSOR;
     772             : 
     773           0 :         ZVAL_STR(rval, str);
     774           0 :         return 1;
     775             : }
     776             : 
     777             : "a:" uiv ":" "{" {
     778       66859 :         zend_long elements = parse_iv(start + 2);
     779             :         /* use iv() not uiv() in order to check data range */
     780       66859 :         *p = YYCURSOR;
     781       66859 :     if (!var_hash) return 0;
     782             : 
     783       66858 :         if (elements < 0) {
     784           0 :                 return 0;
     785             :         }
     786             : 
     787       66858 :         array_init_size(rval, elements);
     788       66858 :         if (elements) {
     789             :                 /* we can't convert from packed to hash during unserialization, because
     790             :                    reference to some zvals might be keept in var_hash (to support references) */
     791       66813 :                 zend_hash_real_init(Z_ARRVAL_P(rval), 0);
     792             :         }
     793             : 
     794      133716 :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
     795          45 :                 return 0;
     796             :         }
     797             : 
     798       66813 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     799             : }
     800             : 
     801             : "o:" iv ":" ["] {
     802           0 :     if (!var_hash) return 0;
     803             : 
     804           0 :         return object_common2(UNSERIALIZE_PASSTHRU,
     805             :                         object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
     806             : }
     807             : 
     808             : object ":" uiv ":" ["] {
     809             :         size_t len, len2, len3, maxlen;
     810             :         zend_long elements;
     811             :         char *str;
     812             :         zend_string *class_name;
     813             :         zend_class_entry *ce;
     814      142680 :         int incomplete_class = 0;
     815             : 
     816      142680 :         int custom_object = 0;
     817             : 
     818             :         zval user_func;
     819             :         zval retval;
     820             :         zval args[1];
     821             : 
     822      142680 :     if (!var_hash) return 0;
     823      142680 :         if (*start == 'C') {
     824          75 :                 custom_object = 1;
     825             :         }
     826             : 
     827      142680 :         len2 = len = parse_uiv(start + 2);
     828      142680 :         maxlen = max - YYCURSOR;
     829      142680 :         if (maxlen < len || len == 0) {
     830           1 :                 *p = start + 2;
     831           1 :                 return 0;
     832             :         }
     833             : 
     834      142679 :         str = (char*)YYCURSOR;
     835             : 
     836      142679 :         YYCURSOR += len;
     837             : 
     838      142679 :         if (*(YYCURSOR) != '"') {
     839           1 :                 *p = YYCURSOR;
     840           1 :                 return 0;
     841             :         }
     842      142678 :         if (*(YYCURSOR+1) != ':') {
     843           1 :                 *p = YYCURSOR+1;
     844           1 :                 return 0;
     845             :         }
     846             : 
     847      142677 :         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\\");
     848      142677 :         if (len3 != len)
     849             :         {
     850           1 :                 *p = YYCURSOR + len3 - len;
     851           1 :                 return 0;
     852             :         }
     853             : 
     854      142676 :         class_name = zend_string_init(str, len, 0);
     855             : 
     856             :         do {
     857      142676 :                 if(!unserialize_allowed_class(class_name, var_hash)) {
     858           5 :                         incomplete_class = 1;
     859           5 :                         ce = PHP_IC_ENTRY;
     860           5 :                         break;
     861             :                 }
     862             : 
     863             :                 /* Try to find class directly */
     864      142671 :                 BG(serialize_lock)++;
     865      142671 :                 ce = zend_lookup_class(class_name);
     866      142671 :                 if (ce) {
     867      142648 :                         BG(serialize_lock)--;
     868      142648 :                         if (EG(exception)) {
     869             :                                 zend_string_release(class_name);
     870           0 :                                 return 0;
     871             :                         }
     872      142648 :                         break;
     873             :                 }
     874          23 :                 BG(serialize_lock)--;
     875             : 
     876          23 :                 if (EG(exception)) {
     877             :                         zend_string_release(class_name);
     878           2 :                         return 0;
     879             :                 }
     880             : 
     881             :                 /* Check for unserialize callback */
     882          21 :                 if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
     883          11 :                         incomplete_class = 1;
     884          11 :                         ce = PHP_IC_ENTRY;
     885          11 :                         break;
     886             :                 }
     887             : 
     888             :                 /* Call unserialize callback */
     889          20 :                 ZVAL_STRING(&user_func, PG(unserialize_callback_func));
     890             : 
     891          10 :                 ZVAL_STR_COPY(&args[0], class_name);
     892          10 :                 BG(serialize_lock)++;
     893          10 :                 if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
     894           1 :                         BG(serialize_lock)--;
     895           1 :                         if (EG(exception)) {
     896             :                                 zend_string_release(class_name);
     897           0 :                                 zval_ptr_dtor(&user_func);
     898           0 :                                 zval_ptr_dtor(&args[0]);
     899           0 :                                 return 0;
     900             :                         }
     901           1 :                         php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
     902           1 :                         incomplete_class = 1;
     903           1 :                         ce = PHP_IC_ENTRY;
     904           1 :                         zval_ptr_dtor(&user_func);
     905           1 :                         zval_ptr_dtor(&args[0]);
     906           1 :                         break;
     907             :                 }
     908           9 :                 BG(serialize_lock)--;
     909           9 :                 zval_ptr_dtor(&retval);
     910           9 :                 if (EG(exception)) {
     911             :                         zend_string_release(class_name);
     912           1 :                         zval_ptr_dtor(&user_func);
     913           1 :                         zval_ptr_dtor(&args[0]);
     914           1 :                         return 0;
     915             :                 }
     916             : 
     917             :                 /* The callback function may have defined the class */
     918           8 :                 if ((ce = zend_lookup_class(class_name)) == NULL) {
     919           2 :                         php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
     920           2 :                         incomplete_class = 1;
     921           2 :                         ce = PHP_IC_ENTRY;
     922             :                 }
     923             : 
     924           8 :                 zval_ptr_dtor(&user_func);
     925           8 :                 zval_ptr_dtor(&args[0]);
     926           8 :                 break;
     927             :         } while (1);
     928             : 
     929      142673 :         *p = YYCURSOR;
     930             : 
     931      142673 :         if (custom_object) {
     932             :                 int ret;
     933             : 
     934          75 :                 ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
     935             : 
     936          75 :                 if (ret && incomplete_class) {
     937           2 :                         php_store_class_name(rval, ZSTR_VAL(class_name), len2);
     938             :                 }
     939             :                 zend_string_release(class_name);
     940          75 :                 return ret;
     941             :         }
     942             : 
     943      142598 :         elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
     944             : 
     945      142598 :         if (incomplete_class) {
     946          16 :                 php_store_class_name(rval, ZSTR_VAL(class_name), len2);
     947             :         }
     948             :         zend_string_release(class_name);
     949             : 
     950      142598 :         return object_common2(UNSERIALIZE_PASSTHRU, elements);
     951             : }
     952             : 
     953             : "}" {
     954             :         /* this is the case where we have less data than planned */
     955           4 :         php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
     956           4 :         return 0; /* not sure if it should be 0 or 1 here? */
     957             : }
     958             : 
     959         100 : any     { return 0; }
     960             : 
     961             : */
     962             : 
     963             :         return 0;
     964             : }

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:11 +0000 (2 days ago)

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