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: 359 393 91.3 %
Date: 2016-07-26 Functions: 17 17 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             : /* {{{ reference-handling for unserializer: var_* */
      26             : #define VAR_ENTRIES_MAX 1024
      27             : #define VAR_ENTRIES_DBG 0
      28             : 
      29             : typedef struct {
      30             :         zval *data[VAR_ENTRIES_MAX];
      31             :         zend_long used_slots;
      32             :         void *next;
      33             : } var_entries;
      34             : 
      35             : typedef struct {
      36             :         zval data[VAR_ENTRIES_MAX];
      37             :         zend_long used_slots;
      38             :         void *next;
      39             : } var_dtor_entries;
      40             : 
      41      232482 : static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
      42             : {
      43      232482 :         var_entries *var_hash = (*var_hashx)->last;
      44             : #if VAR_ENTRIES_DBG
      45             :         fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval));
      46             : #endif
      47             : 
      48      232482 :         if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
      49       66922 :                 var_hash = emalloc(sizeof(var_entries));
      50       66922 :                 var_hash->used_slots = 0;
      51       66922 :                 var_hash->next = 0;
      52             : 
      53       66922 :                 if (!(*var_hashx)->first) {
      54       66893 :                         (*var_hashx)->first = var_hash;
      55             :                 } else {
      56          29 :                         ((var_entries *) (*var_hashx)->last)->next = var_hash;
      57             :                 }
      58             : 
      59       66922 :                 (*var_hashx)->last = var_hash;
      60             :         }
      61             : 
      62      232482 :         var_hash->data[var_hash->used_slots++] = rval;
      63      232482 : }
      64             : 
      65      212589 : PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
      66             : {
      67      212589 :         zval *tmp_var = var_tmp_var(var_hashx);
      68      212589 :     if (!tmp_var) {
      69           0 :         return;
      70             :     }
      71      212589 :         ZVAL_COPY(tmp_var, rval);
      72             : }
      73             : 
      74      212937 : PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
      75             : {
      76             :     var_dtor_entries *var_hash;
      77             : 
      78      212937 :     if (!var_hashx || !*var_hashx) {
      79           0 :         return NULL;
      80             :     }
      81             : 
      82      212937 :     var_hash = (*var_hashx)->last_dtor;
      83      212937 :     if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
      84       66768 :         var_hash = emalloc(sizeof(var_dtor_entries));
      85       66768 :         var_hash->used_slots = 0;
      86       66768 :         var_hash->next = 0;
      87             : 
      88       66768 :         if (!(*var_hashx)->first_dtor) {
      89       66759 :             (*var_hashx)->first_dtor = var_hash;
      90             :         } else {
      91           9 :             ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
      92             :         }
      93             : 
      94       66768 :         (*var_hashx)->last_dtor = var_hash;
      95             :     }
      96      212937 :     ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]);
      97      212937 :     return &var_hash->data[var_hash->used_slots++];
      98             : }
      99             : 
     100       20070 : PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
     101             : {
     102             :         zend_long i;
     103       20070 :         var_entries *var_hash = (*var_hashx)->first;
     104             : #if VAR_ENTRIES_DBG
     105             :         fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(nzval));
     106             : #endif
     107             : 
     108      440930 :         while (var_hash) {
     109   400501330 :                 for (i = 0; i < var_hash->used_slots; i++) {
     110   400100540 :                         if (var_hash->data[i] == ozval) {
     111       20069 :                                 var_hash->data[i] = nzval;
     112             :                                 /* do not break here */
     113             :                         }
     114             :                 }
     115      400790 :                 var_hash = var_hash->next;
     116             :         }
     117       20070 : }
     118             : 
     119       10374 : static zval *var_access(php_unserialize_data_t *var_hashx, zend_long id)
     120             : {
     121       10374 :         var_entries *var_hash = (*var_hashx)->first;
     122             : #if VAR_ENTRIES_DBG
     123             :         fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
     124             : #endif
     125             : 
     126       64686 :         while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
     127       43938 :                 var_hash = var_hash->next;
     128       43938 :                 id -= VAR_ENTRIES_MAX;
     129             :         }
     130             : 
     131       10374 :         if (!var_hash) return NULL;
     132             : 
     133       10373 :         if (id < 0 || id >= var_hash->used_slots) return NULL;
     134             : 
     135       10373 :         return var_hash->data[id];
     136             : }
     137             : 
     138       67241 : PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
     139             : {
     140             :         void *next;
     141             :         zend_long i;
     142       67241 :         var_entries *var_hash = (*var_hashx)->first;
     143       67241 :         var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
     144             : #if VAR_ENTRIES_DBG
     145             :         fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
     146             : #endif
     147             : 
     148      201404 :         while (var_hash) {
     149       66922 :                 next = var_hash->next;
     150       66922 :                 efree_size(var_hash, sizeof(var_entries));
     151       66922 :                 var_hash = next;
     152             :         }
     153             : 
     154      201250 :         while (var_dtor_hash) {
     155      279705 :                 for (i = 0; i < var_dtor_hash->used_slots; i++) {
     156             : #if VAR_ENTRIES_DBG
     157             :                         fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
     158             : #endif
     159      212937 :                         zval_ptr_dtor(&var_dtor_hash->data[i]);
     160             :                 }
     161       66768 :                 next = var_dtor_hash->next;
     162       66768 :                 efree_size(var_dtor_hash, sizeof(var_dtor_entries));
     163       66768 :                 var_dtor_hash = next;
     164             :         }
     165       67241 : }
     166             : 
     167             : /* }}} */
     168             : 
     169           2 : static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen)
     170             : {
     171             :         size_t i, j;
     172           2 :         zend_string *str = zend_string_safe_alloc(1, len, 0, 0);
     173           2 :         unsigned char *end = *(unsigned char **)p+maxlen;
     174             : 
     175           2 :         if (end < *p) {
     176             :                 zend_string_free(str);
     177           0 :                 return NULL;
     178             :         }
     179             : 
     180         134 :         for (i = 0; i < len; i++) {
     181         133 :                 if (*p >= end) {
     182             :                         zend_string_free(str);
     183           1 :                         return NULL;
     184             :                 }
     185         132 :                 if (**p != '\\') {
     186          17 :                         ZSTR_VAL(str)[i] = (char)**p;
     187             :                 } else {
     188         115 :                         unsigned char ch = 0;
     189             : 
     190         345 :                         for (j = 0; j < 2; j++) {
     191         230 :                                 (*p)++;
     192         460 :                                 if (**p >= '0' && **p <= '9') {
     193         230 :                                         ch = (ch << 4) + (**p -'0');
     194           0 :                                 } else if (**p >= 'a' && **p <= 'f') {
     195           0 :                                         ch = (ch << 4) + (**p -'a'+10);
     196           0 :                                 } else if (**p >= 'A' && **p <= 'F') {
     197           0 :                                         ch = (ch << 4) + (**p -'A'+10);
     198             :                                 } else {
     199             :                                         zend_string_free(str);
     200           0 :                                         return NULL;
     201             :                                 }
     202             :                         }
     203         115 :                         ZSTR_VAL(str)[i] = (char)ch;
     204             :                 }
     205         132 :                 (*p)++;
     206             :         }
     207           1 :         ZSTR_VAL(str)[i] = 0;
     208           1 :         ZSTR_LEN(str) = i;
     209           1 :         return str;
     210             : }
     211             : 
     212      142660 : static inline int unserialize_allowed_class(zend_string *class_name, HashTable *classes)
     213             : {
     214             :         zend_string *lcname;
     215             :         int res;
     216             :         ALLOCA_FLAG(use_heap)
     217             : 
     218      142660 :         if(classes == NULL) {
     219      142650 :                 return 1;
     220             :         }
     221          10 :         if(!zend_hash_num_elements(classes)) {
     222           3 :                 return 0;
     223             :         }
     224             : 
     225          14 :         ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap);
     226           7 :         zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
     227           7 :         res = zend_hash_exists(classes, lcname);
     228           7 :         ZSTR_ALLOCA_FREE(lcname, use_heap);
     229           7 :         return res;
     230             : }
     231             : 
     232             : #define YYFILL(n) do { } while (0)
     233             : #define YYCTYPE unsigned char
     234             : #define YYCURSOR cursor
     235             : #define YYLIMIT limit
     236             : #define YYMARKER marker
     237             : 
     238             : 
     239             : /*!re2c
     240             : uiv = [+]? [0-9]+;
     241             : iv = [+-]? [0-9]+;
     242             : nv = [+-]? ([0-9]* "." [0-9]+|[0-9]+ "." [0-9]*);
     243             : nvexp = (iv | nv) [eE] [+-]? iv;
     244             : any = [\000-\377];
     245             : object = [OC];
     246             : */
     247             : 
     248             : 
     249             : 
     250      365584 : static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **q)
     251             : {
     252             :         char cursor;
     253      365584 :         zend_long result = 0;
     254      365584 :         int neg = 0;
     255             : 
     256      365584 :         switch (*p) {
     257             :                 case '-':
     258           8 :                         neg++;
     259             :                         /* fall-through */
     260             :                 case '+':
     261           8 :                         p++;
     262             :         }
     263             : 
     264             :         while (1) {
     265      789751 :                 cursor = (char)*p;
     266      789751 :                 if (cursor >= '0' && cursor <= '9') {
     267      424167 :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     268             :                 } else {
     269             :                         break;
     270             :                 }
     271      424167 :                 p++;
     272      424167 :         }
     273      365584 :         if (q) *q = p;
     274      365584 :         if (neg) return -result;
     275      365576 :         return result;
     276             : }
     277             : 
     278      222927 : static inline zend_long parse_iv(const unsigned char *p)
     279             : {
     280      222927 :         return parse_iv2(p, NULL);
     281             : }
     282             : 
     283             : /* no need to check for length - re2c already did */
     284      145223 : static inline size_t parse_uiv(const unsigned char *p)
     285             : {
     286             :         unsigned char cursor;
     287      145223 :         size_t result = 0;
     288             : 
     289      145223 :         if (*p == '+') {
     290           0 :                 p++;
     291             :         }
     292             : 
     293             :         while (1) {
     294      291136 :                 cursor = *p;
     295      291136 :                 if (cursor >= '0' && cursor <= '9') {
     296      145913 :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     297             :                 } else {
     298             :                         break;
     299             :                 }
     300      145913 :                 p++;
     301      145913 :         }
     302      145223 :         return result;
     303             : }
     304             : 
     305             : #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes
     306             : #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
     307             : 
     308             : static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
     309             : {
     310      355020 :         while (elements-- > 0) {
     311             :                 zval key, *data, d, *old_data;
     312             :                 zend_ulong idx;
     313             : 
     314      145626 :                 ZVAL_UNDEF(&key);
     315             : 
     316      145626 :                 if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
     317             :                         zval_dtor(&key);
     318          16 :                         return 0;
     319             :                 }
     320             : 
     321      145610 :                 data = NULL;
     322      145610 :                 ZVAL_UNDEF(&d);
     323             : 
     324      145610 :                 if (!objprops) {
     325      144299 :                         if (Z_TYPE(key) == IS_LONG) {
     326      143808 :                                 idx = Z_LVAL(key);
     327             : numeric_key:
     328      143809 :                                 if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
     329             :                                         //??? update hash
     330           4 :                                         var_push_dtor(var_hash, old_data);
     331           4 :                                         data = zend_hash_index_update(ht, idx, &d);
     332             :                                 } else {
     333      143805 :                                         data = zend_hash_index_add_new(ht, idx, &d);
     334             :                                 }
     335         491 :                         } else if (Z_TYPE(key) == IS_STRING) {
     336         982 :                                 if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
     337             :                                         goto numeric_key;
     338             :                                 }
     339         490 :                                 if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
     340             :                                         //??? update hash
     341           0 :                                         var_push_dtor(var_hash, old_data);
     342           0 :                                         data = zend_hash_update(ht, Z_STR(key), &d);
     343             :                                 } else {
     344         490 :                                         data = zend_hash_add_new(ht, Z_STR(key), &d);
     345             :                                 }
     346             :                         } else {
     347             :                                 zval_dtor(&key);
     348           0 :                                 return 0;
     349             :                         }
     350             :                 } else {
     351        1311 :                         if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
     352             : string_key:
     353        1311 :                                 if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
     354         429 :                                         if (Z_TYPE_P(old_data) == IS_INDIRECT) {
     355         231 :                                                 old_data = Z_INDIRECT_P(old_data);
     356             :                                         }
     357         429 :                                         var_push_dtor(var_hash, old_data);
     358         429 :                                         data = zend_hash_update_ind(ht, Z_STR(key), &d);
     359             :                                 } else {
     360         882 :                                         data = zend_hash_add_new(ht, Z_STR(key), &d);
     361             :                                 }
     362          12 :                         } else if (Z_TYPE(key) == IS_LONG) {
     363             :                                 /* object properties should include no integers */
     364          12 :                                 convert_to_string(&key);
     365             :                                 goto string_key;
     366             :                         } else {
     367             :                                 zval_dtor(&key);
     368           0 :                                 return 0;
     369             :                         }
     370             :                 }
     371             : 
     372      145610 :                 if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
     373             :                         zval_dtor(&key);
     374          24 :                         return 0;
     375             :                 }
     376             : 
     377      145586 :                 if (UNEXPECTED(Z_ISUNDEF_P(data))) {
     378           2 :                         if (Z_TYPE(key) == IS_LONG) {
     379           2 :                                 zend_hash_index_del(ht, Z_LVAL(key));
     380             :                         } else {
     381           0 :                                 zend_hash_del_ind(ht, Z_STR(key));
     382             :                         }
     383             :                 } else {
     384      145584 :                         var_push_dtor(var_hash, data);
     385             :                 }
     386             : 
     387             :                 zval_dtor(&key);
     388             : 
     389      145586 :                 if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
     390           0 :                         (*p)--;
     391           0 :                         return 0;
     392             :                 }
     393             :         }
     394             : 
     395      209394 :         return 1;
     396             : }
     397             : 
     398      209446 : static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
     399             : {
     400      209446 :         if (*((*p)++) == '}')
     401      209444 :                 return 1;
     402             : 
     403             : #if SOMETHING_NEW_MIGHT_LEAD_TO_CRASH_ENABLE_IF_YOU_ARE_BRAVE
     404             :         zval_ptr_dtor(rval);
     405             : #endif
     406           2 :         return 0;
     407             : }
     408             : 
     409          68 : static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     410             : {
     411             :         zend_long datalen;
     412             : 
     413          68 :         datalen = parse_iv2((*p) + 2, p);
     414             : 
     415          68 :         (*p) += 2;
     416             : 
     417          68 :         if (datalen < 0 || (max - (*p)) <= datalen) {
     418           1 :                 zend_error(E_WARNING, "Insufficient data for unserializing - " ZEND_LONG_FMT " required, " ZEND_LONG_FMT " present", datalen, (zend_long)(max - (*p)));
     419           1 :                 return 0;
     420             :         }
     421             : 
     422          67 :         if (ce->unserialize == NULL) {
     423           3 :                 zend_error(E_WARNING, "Class %s has no unserializer", ZSTR_VAL(ce->name));
     424           3 :                 object_init_ex(rval, ce);
     425          64 :         } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
     426           5 :                 return 0;
     427             :         }
     428             : 
     429          62 :         (*p) += datalen;
     430             : 
     431          62 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     432             : }
     433             : 
     434      142589 : static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     435             : {
     436             :         zend_long elements;
     437             : 
     438      142589 :         elements = parse_iv2((*p) + 2, p);
     439             : 
     440      142589 :         (*p) += 2;
     441             : 
     442      142589 :         if (ce->serialize == NULL) {
     443      142586 :                 object_init_ex(rval, ce);
     444             :         } else {
     445             :                 /* If this class implements Serializable, it should not land here but in object_custom(). The passed string
     446             :                 obviously doesn't descend from the regular serializer. */
     447           3 :                 zend_error(E_WARNING, "Erroneous data format for unserializing '%s'", ZSTR_VAL(ce->name));
     448           3 :                 return 0;
     449             :         }
     450             : 
     451      142586 :         return elements;
     452             : }
     453             : 
     454             : #ifdef PHP_WIN32
     455             : # pragma optimize("", off)
     456             : #endif
     457      142589 : static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
     458             : {
     459             :         zval retval;
     460             :         zval fname;
     461             :         HashTable *ht;
     462             : 
     463      142589 :         if (Z_TYPE_P(rval) != IS_OBJECT) {
     464           3 :                 return 0;
     465             :         }
     466             : 
     467      142586 :         ht = Z_OBJPROP_P(rval);
     468      142586 :         zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
     469      142586 :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
     470           2 :                 return 0;
     471             :         }
     472             : 
     473      142584 :         ZVAL_DEREF(rval);
     474      285152 :         if (Z_OBJCE_P(rval) != PHP_IC_ENTRY &&
     475      142568 :                 zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
     476          92 :                 ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
     477          46 :                 BG(serialize_lock)++;
     478          46 :                 call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL);
     479          46 :                 BG(serialize_lock)--;
     480             :                 zval_dtor(&fname);
     481             :                 zval_dtor(&retval);
     482             :         }
     483             : 
     484      142584 :         if (EG(exception)) {
     485          10 :                 return 0;
     486             :         }
     487             : 
     488      142574 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     489             : 
     490             : }
     491             : #ifdef PHP_WIN32
     492             : # pragma optimize("", on)
     493             : #endif
     494             : 
     495       20594 : PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash)
     496             : {
     497       20594 :         HashTable *classes = NULL;
     498       20594 :         return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
     499             : }
     500             : 
     501             : 
     502      378419 : PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
     503             : {
     504             :         const unsigned char *cursor, *limit, *marker, *start;
     505             :         zval *rval_ref;
     506             : 
     507      378419 :         limit = max;
     508      378419 :         cursor = *p;
     509             : 
     510      378419 :         if (YYCURSOR >= YYLIMIT) {
     511          16 :                 return 0;
     512             :         }
     513             : 
     514      378403 :         if (var_hash && (*p)[0] != 'R') {
     515      232482 :                 var_push(var_hash, rval);
     516             :         }
     517             : 
     518      378403 :         start = cursor;
     519             : 
     520             : /*!re2c
     521             : 
     522             : "R:" iv ";"         {
     523             :         zend_long id;
     524             : 
     525         293 :         *p = YYCURSOR;
     526         293 :         if (!var_hash) return 0;
     527             : 
     528         293 :         id = parse_iv(start + 2) - 1;
     529         293 :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
     530           1 :                 return 0;
     531             :         }
     532             : 
     533         292 :         zval_ptr_dtor(rval);
     534         606 :         if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
     535           1 :                 ZVAL_UNDEF(rval);
     536           1 :                 return 1;
     537             :         }
     538         291 :         if (Z_ISREF_P(rval_ref)) {
     539          23 :                 ZVAL_COPY(rval, rval_ref);
     540             :         } else {
     541         268 :                 ZVAL_NEW_REF(rval_ref, rval_ref);
     542         268 :                 ZVAL_COPY(rval, rval_ref);
     543             :         }
     544             : 
     545         291 :         return 1;
     546             : }
     547             : 
     548             : "r:" iv ";"         {
     549             :         zend_long id;
     550             : 
     551       10081 :         *p = YYCURSOR;
     552       10081 :         if (!var_hash) return 0;
     553             : 
     554       10081 :         id = parse_iv(start + 2) - 1;
     555       10081 :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
     556           0 :                 return 0;
     557             :         }
     558             : 
     559       10081 :         if (rval_ref == rval) {
     560           2 :                 return 0;
     561             :         }
     562             : 
     563       20157 :         if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
     564           1 :                 ZVAL_UNDEF(rval);
     565           1 :                 return 1;
     566             :         }
     567             : 
     568       10078 :         ZVAL_COPY(rval, rval_ref);
     569             : 
     570       10078 :         return 1;
     571             : }
     572             : 
     573             : "N;"  {
     574       10081 :         *p = YYCURSOR;
     575       10081 :         ZVAL_NULL(rval);
     576       10081 :         return 1;
     577             : }
     578             : 
     579             : "b:" [01] ";"       {
     580          87 :         *p = YYCURSOR;
     581          87 :         ZVAL_BOOL(rval, parse_iv(start + 2));
     582          87 :         return 1;
     583             : }
     584             : 
     585             : "i:" iv ";" {
     586             : #if SIZEOF_ZEND_LONG == 4
     587             :         int digits = YYCURSOR - start - 3;
     588             : 
     589             :         if (start[2] == '-' || start[2] == '+') {
     590             :                 digits--;
     591             :         }
     592             : 
     593             :         /* Use double for large zend_long values that were serialized on a 64-bit system */
     594             :         if (digits >= MAX_LENGTH_OF_LONG - 1) {
     595             :                 if (digits == MAX_LENGTH_OF_LONG - 1) {
     596             :                         int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
     597             : 
     598             :                         if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
     599             :                                 goto use_double;
     600             :                         }
     601             :                 } else {
     602             :                         goto use_double;
     603             :                 }
     604             :         }
     605             : #endif
     606      145617 :         *p = YYCURSOR;
     607      145617 :         ZVAL_LONG(rval, parse_iv(start + 2));
     608      145617 :         return 1;
     609             : }
     610             : 
     611             : "d:" ("NAN" | "-"? "INF") ";" {
     612           3 :         *p = YYCURSOR;
     613             : 
     614           3 :         if (!strncmp((char*)start + 2, "NAN", 3)) {
     615           1 :                 ZVAL_DOUBLE(rval, php_get_nan());
     616           2 :         } else if (!strncmp((char*)start + 2, "INF", 3)) {
     617           1 :                 ZVAL_DOUBLE(rval, php_get_inf());
     618           1 :         } else if (!strncmp((char*)start + 2, "-INF", 4)) {
     619           1 :                 ZVAL_DOUBLE(rval, -php_get_inf());
     620             :         } else {
     621           0 :                 ZVAL_NULL(rval);
     622             :         }
     623             : 
     624           3 :         return 1;
     625             : }
     626             : 
     627             : "d:" (iv | nv | nvexp) ";"  {
     628             : #if SIZEOF_ZEND_LONG == 4
     629             : use_double:
     630             : #endif
     631          70 :         *p = YYCURSOR;
     632          70 :         ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
     633          70 :         return 1;
     634             : }
     635             : 
     636             : "s:" uiv ":" ["]       {
     637             :         size_t len, maxlen;
     638             :         char *str;
     639             : 
     640        2557 :         len = parse_uiv(start + 2);
     641        2557 :         maxlen = max - YYCURSOR;
     642        2557 :         if (maxlen < len) {
     643           3 :                 *p = start + 2;
     644           3 :                 return 0;
     645             :         }
     646             : 
     647        2554 :         str = (char*)YYCURSOR;
     648             : 
     649        2554 :         YYCURSOR += len;
     650             : 
     651        2554 :         if (*(YYCURSOR) != '"') {
     652           2 :                 *p = YYCURSOR;
     653           2 :                 return 0;
     654             :         }
     655             : 
     656        2552 :         if (*(YYCURSOR + 1) != ';') {
     657           4 :                 *p = YYCURSOR + 1;
     658           4 :                 return 0;
     659             :         }
     660             : 
     661        2548 :         YYCURSOR += 2;
     662        2548 :         *p = YYCURSOR;
     663             : 
     664        5096 :         ZVAL_STRINGL(rval, str, len);
     665        2548 :         return 1;
     666             : }
     667             : 
     668             : "S:" uiv ":" ["]       {
     669             :         size_t len, maxlen;
     670             :         zend_string *str;
     671             : 
     672           2 :         len = parse_uiv(start + 2);
     673           2 :         maxlen = max - YYCURSOR;
     674           2 :         if (maxlen < len) {
     675           0 :                 *p = start + 2;
     676           0 :                 return 0;
     677             :         }
     678             : 
     679           2 :         if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
     680           1 :                 return 0;
     681             :         }
     682             : 
     683           1 :         if (*(YYCURSOR) != '"') {
     684             :                 zend_string_free(str);
     685           0 :                 *p = YYCURSOR;
     686           0 :                 return 0;
     687             :         }
     688             : 
     689           1 :         if (*(YYCURSOR + 1) != ';') {
     690           0 :                 efree(str);
     691           0 :                 *p = YYCURSOR + 1;
     692           0 :                 return 0;
     693             :         }
     694             : 
     695           1 :         YYCURSOR += 2;
     696           1 :         *p = YYCURSOR;
     697             : 
     698           1 :         ZVAL_STR(rval, str);
     699           1 :         return 1;
     700             : }
     701             : 
     702             : "a:" uiv ":" "{" {
     703       66849 :         zend_long elements = parse_iv(start + 2);
     704             :         /* use iv() not uiv() in order to check data range */
     705       66849 :         *p = YYCURSOR;
     706       66849 :     if (!var_hash) return 0;
     707             : 
     708       66848 :         if (elements < 0) {
     709           0 :                 return 0;
     710             :         }
     711             : 
     712       66848 :         array_init_size(rval, elements);
     713       66848 :         if (elements) {
     714             :                 /* we can't convert from packed to hash during unserialization, because
     715             :                    reference to some zvals might be keept in var_hash (to support references) */
     716       66803 :                 zend_hash_real_init(Z_ARRVAL_P(rval), 0);
     717             :         }
     718             : 
     719      133696 :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
     720          38 :                 return 0;
     721             :         }
     722             : 
     723       66810 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     724             : }
     725             : 
     726             : "o:" iv ":" ["] {
     727           0 :     if (!var_hash) return 0;
     728             : 
     729           0 :         return object_common2(UNSERIALIZE_PASSTHRU,
     730             :                         object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
     731             : }
     732             : 
     733             : object ":" uiv ":" ["] {
     734             :         size_t len, len2, len3, maxlen;
     735             :         zend_long elements;
     736             :         char *str;
     737             :         zend_string *class_name;
     738             :         zend_class_entry *ce;
     739      142664 :         int incomplete_class = 0;
     740             : 
     741      142664 :         int custom_object = 0;
     742             : 
     743             :         zval user_func;
     744             :         zval retval;
     745             :         zval args[1];
     746             : 
     747      142664 :     if (!var_hash) return 0;
     748      142664 :         if (*start == 'C') {
     749          68 :                 custom_object = 1;
     750             :         }
     751             : 
     752      142664 :         len2 = len = parse_uiv(start + 2);
     753      142664 :         maxlen = max - YYCURSOR;
     754      142664 :         if (maxlen < len || len == 0) {
     755           1 :                 *p = start + 2;
     756           1 :                 return 0;
     757             :         }
     758             : 
     759      142663 :         str = (char*)YYCURSOR;
     760             : 
     761      142663 :         YYCURSOR += len;
     762             : 
     763      142663 :         if (*(YYCURSOR) != '"') {
     764           1 :                 *p = YYCURSOR;
     765           1 :                 return 0;
     766             :         }
     767      142662 :         if (*(YYCURSOR+1) != ':') {
     768           1 :                 *p = YYCURSOR+1;
     769           1 :                 return 0;
     770             :         }
     771             : 
     772      142661 :         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\\");
     773      142661 :         if (len3 != len)
     774             :         {
     775           1 :                 *p = YYCURSOR + len3 - len;
     776           1 :                 return 0;
     777             :         }
     778             : 
     779      142660 :         class_name = zend_string_init(str, len, 0);
     780             : 
     781             :         do {
     782      142660 :                 if(!unserialize_allowed_class(class_name, classes)) {
     783           6 :                         incomplete_class = 1;
     784           6 :                         ce = PHP_IC_ENTRY;
     785           6 :                         break;
     786             :                 }
     787             : 
     788             :                 /* Try to find class directly */
     789      142654 :                 BG(serialize_lock)++;
     790      142654 :                 ce = zend_lookup_class(class_name);
     791      142654 :                 if (ce) {
     792      142631 :                         BG(serialize_lock)--;
     793      142631 :                         if (EG(exception)) {
     794             :                                 zend_string_release(class_name);
     795           0 :                                 return 0;
     796             :                         }
     797      142631 :                         break;
     798             :                 }
     799          23 :                 BG(serialize_lock)--;
     800             : 
     801          23 :                 if (EG(exception)) {
     802             :                         zend_string_release(class_name);
     803           2 :                         return 0;
     804             :                 }
     805             : 
     806             :                 /* Check for unserialize callback */
     807          21 :                 if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
     808          11 :                         incomplete_class = 1;
     809          11 :                         ce = PHP_IC_ENTRY;
     810          11 :                         break;
     811             :                 }
     812             : 
     813             :                 /* Call unserialize callback */
     814          20 :                 ZVAL_STRING(&user_func, PG(unserialize_callback_func));
     815             : 
     816          10 :                 ZVAL_STR_COPY(&args[0], class_name);
     817          10 :                 BG(serialize_lock)++;
     818          10 :                 if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
     819           1 :                         BG(serialize_lock)--;
     820           1 :                         if (EG(exception)) {
     821             :                                 zend_string_release(class_name);
     822           0 :                                 zval_ptr_dtor(&user_func);
     823           0 :                                 zval_ptr_dtor(&args[0]);
     824           0 :                                 return 0;
     825             :                         }
     826           1 :                         php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
     827           1 :                         incomplete_class = 1;
     828           1 :                         ce = PHP_IC_ENTRY;
     829           1 :                         zval_ptr_dtor(&user_func);
     830           1 :                         zval_ptr_dtor(&args[0]);
     831           1 :                         break;
     832             :                 }
     833           9 :                 BG(serialize_lock)--;
     834           9 :                 zval_ptr_dtor(&retval);
     835           9 :                 if (EG(exception)) {
     836             :                         zend_string_release(class_name);
     837           1 :                         zval_ptr_dtor(&user_func);
     838           1 :                         zval_ptr_dtor(&args[0]);
     839           1 :                         return 0;
     840             :                 }
     841             : 
     842             :                 /* The callback function may have defined the class */
     843           8 :                 if ((ce = zend_lookup_class(class_name)) == NULL) {
     844           2 :                         php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
     845           2 :                         incomplete_class = 1;
     846           2 :                         ce = PHP_IC_ENTRY;
     847             :                 }
     848             : 
     849           8 :                 zval_ptr_dtor(&user_func);
     850           8 :                 zval_ptr_dtor(&args[0]);
     851           8 :                 break;
     852             :         } while (1);
     853             : 
     854      142657 :         *p = YYCURSOR;
     855             : 
     856      142657 :         if (custom_object) {
     857             :                 int ret;
     858             : 
     859          68 :                 ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
     860             : 
     861          68 :                 if (ret && incomplete_class) {
     862           2 :                         php_store_class_name(rval, ZSTR_VAL(class_name), len2);
     863             :                 }
     864             :                 zend_string_release(class_name);
     865          68 :                 return ret;
     866             :         }
     867             : 
     868      142589 :         elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
     869             : 
     870      142589 :         if (incomplete_class) {
     871          17 :                 php_store_class_name(rval, ZSTR_VAL(class_name), len2);
     872             :         }
     873             :         zend_string_release(class_name);
     874             : 
     875      142589 :         return object_common2(UNSERIALIZE_PASSTHRU, elements);
     876             : }
     877             : 
     878             : "}" {
     879             :         /* this is the case where we have less data than planned */
     880           0 :         php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
     881           0 :         return 0; /* not sure if it should be 0 or 1 here? */
     882             : }
     883             : 
     884          99 : any     { return 0; }
     885             : 
     886             : */
     887             : 
     888             :         return 0;
     889             : }

Generated by: LCOV version 1.10

Generated at Tue, 26 Jul 2016 17:07:49 +0000 (2 hours ago)

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