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: 356 386 92.2 %
Date: 2016-06-25 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      232329 : static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
      42             : {
      43      232329 :         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_PP(rval));
      46             : #endif
      47             : 
      48      232329 :         if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
      49       66906 :                 var_hash = emalloc(sizeof(var_entries));
      50       66906 :                 var_hash->used_slots = 0;
      51       66906 :                 var_hash->next = 0;
      52             : 
      53       66906 :                 if (!(*var_hashx)->first) {
      54       66877 :                         (*var_hashx)->first = var_hash;
      55             :                 } else {
      56          29 :                         ((var_entries *) (*var_hashx)->last)->next = var_hash;
      57             :                 }
      58             : 
      59       66906 :                 (*var_hashx)->last = var_hash;
      60             :         }
      61             : 
      62      232329 :         var_hash->data[var_hash->used_slots++] = rval;
      63      232329 : }
      64             : 
      65      145920 : PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
      66             : {
      67      145920 :         zval *tmp_var = var_tmp_var(var_hashx);
      68      145920 :     if (!tmp_var) {
      69           0 :         return;
      70             :     }
      71      145920 :         ZVAL_COPY(tmp_var, rval);
      72             : }
      73             : 
      74      146010 : PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
      75             : {
      76             :     var_dtor_entries *var_hash;
      77             : 
      78      146010 :     if (!var_hashx || !*var_hashx) {
      79           0 :         return NULL;
      80             :     }
      81             : 
      82      146010 :     var_hash = (*var_hashx)->last_dtor;
      83      146010 :     if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
      84       66599 :         var_hash = emalloc(sizeof(var_dtor_entries));
      85       66599 :         var_hash->used_slots = 0;
      86       66599 :         var_hash->next = 0;
      87             : 
      88       66599 :         if (!(*var_hashx)->first_dtor) {
      89       66590 :             (*var_hashx)->first_dtor = var_hash;
      90             :         } else {
      91           9 :             ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
      92             :         }
      93             : 
      94       66599 :         (*var_hashx)->last_dtor = var_hash;
      95             :     }
      96      146010 :     ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]);
      97      146010 :     return &var_hash->data[var_hash->used_slots++];
      98             : }
      99             : 
     100       20261 : PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
     101             : {
     102             :         zend_long i;
     103       20261 :         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_PP(nzval));
     106             : #endif
     107             : 
     108      441503 :         while (var_hash) {
     109   400502286 :                 for (i = 0; i < var_hash->used_slots; i++) {
     110   400101305 :                         if (var_hash->data[i] == ozval) {
     111       20238 :                                 var_hash->data[i] = nzval;
     112             :                                 /* do not break here */
     113             :                         }
     114             :                 }
     115      400981 :                 var_hash = var_hash->next;
     116             :         }
     117       20261 : }
     118             : 
     119       10347 : static zval *var_access(php_unserialize_data_t *var_hashx, zend_long id)
     120             : {
     121       10347 :         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       64632 :         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       10347 :         if (!var_hash) return NULL;
     132             : 
     133       10347 :         if (id < 0 || id >= var_hash->used_slots) return NULL;
     134             : 
     135       10347 :         return var_hash->data[id];
     136             : }
     137             : 
     138       67212 : PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
     139             : {
     140             :         void *next;
     141             :         zend_long i;
     142       67212 :         var_entries *var_hash = (*var_hashx)->first;
     143       67212 :         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      201322 :         while (var_hash) {
     149       66898 :                 next = var_hash->next;
     150       66898 :                 efree_size(var_hash, sizeof(var_entries));
     151       66898 :                 var_hash = next;
     152             :         }
     153             : 
     154      201017 :         while (var_dtor_hash) {
     155      212582 :                 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      145989 :                         zval_ptr_dtor(&var_dtor_hash->data[i]);
     160             :                 }
     161       66593 :                 next = var_dtor_hash->next;
     162       66593 :                 efree_size(var_dtor_hash, sizeof(var_dtor_entries));
     163       66593 :                 var_dtor_hash = next;
     164             :         }
     165       67212 : }
     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_alloc(len, 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      142608 : 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      142608 :         if(classes == NULL) {
     219      142598 :                 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      365423 : static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **q)
     251             : {
     252             :         char cursor;
     253      365423 :         zend_long result = 0;
     254      365423 :         int neg = 0;
     255             : 
     256      365423 :         switch (*p) {
     257             :                 case '-':
     258           8 :                         neg++;
     259             :                         /* fall-through */
     260             :                 case '+':
     261           8 :                         p++;
     262             :         }
     263             : 
     264             :         while (1) {
     265      789391 :                 cursor = (char)*p;
     266      789391 :                 if (cursor >= '0' && cursor <= '9') {
     267      423968 :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     268             :                 } else {
     269             :                         break;
     270             :                 }
     271      423968 :                 p++;
     272      423968 :         }
     273      365423 :         if (q) *q = p;
     274      365423 :         if (neg) return -result;
     275      365415 :         return result;
     276             : }
     277             : 
     278      222818 : static inline zend_long parse_iv(const unsigned char *p)
     279             : {
     280      222818 :         return parse_iv2(p, NULL);
     281             : }
     282             : 
     283             : /* no need to check for length - re2c already did */
     284      145071 : static inline size_t parse_uiv(const unsigned char *p)
     285             : {
     286             :         unsigned char cursor;
     287      145071 :         size_t result = 0;
     288             : 
     289      145071 :         if (*p == '+') {
     290           0 :                 p++;
     291             :         }
     292             : 
     293             :         while (1) {
     294      290806 :                 cursor = *p;
     295      290806 :                 if (cursor >= '0' && cursor <= '9') {
     296      145735 :                         result = result * 10 + (size_t)(cursor - (unsigned char)'0');
     297             :                 } else {
     298             :                         break;
     299             :                 }
     300      145735 :                 p++;
     301      145735 :         }
     302      145071 :         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      354840 :         while (elements-- > 0) {
     311             :                 zval key, *data, d, *old_data;
     312             :                 zend_ulong idx;
     313             : 
     314      145515 :                 ZVAL_UNDEF(&key);
     315             : 
     316      145515 :                 if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
     317             :                         zval_dtor(&key);
     318          15 :                         return 0;
     319             :                 }
     320             : 
     321      145500 :                 data = NULL;
     322      145500 :                 ZVAL_UNDEF(&d);
     323             : 
     324      145500 :                 if (!objprops) {
     325      144241 :                         if (Z_TYPE(key) == IS_LONG) {
     326      143777 :                                 idx = Z_LVAL(key);
     327             : numeric_key:
     328      143778 :                                 if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
     329             :                                         //??? update hash
     330           2 :                                         var_push_dtor(var_hash, old_data);
     331           2 :                                         data = zend_hash_index_update(ht, idx, &d);
     332             :                                 } else {
     333      143776 :                                         data = zend_hash_index_add_new(ht, idx, &d);
     334             :                                 }
     335         464 :                         } else if (Z_TYPE(key) == IS_STRING) {
     336         928 :                                 if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
     337             :                                         goto numeric_key;
     338             :                                 }
     339         463 :                                 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         463 :                                         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        1259 :                         if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
     352             : string_key:
     353        1259 :                                 if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
     354         416 :                                         if (Z_TYPE_P(old_data) == IS_INDIRECT) {
     355         220 :                                                 old_data = Z_INDIRECT_P(old_data);
     356             :                                         }
     357         416 :                                         var_push_dtor(var_hash, old_data);
     358         416 :                                         data = zend_hash_update_ind(ht, Z_STR(key), &d);
     359             :                                 } else {
     360         843 :                                         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      145500 :                 if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
     373             :                         zval_dtor(&key);
     374          20 :                         return 0;
     375             :                 }
     376             : 
     377      145478 :                 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      145476 :                         var_push_dtor(var_hash, data);
     385             :                 }
     386             : 
     387             :                 zval_dtor(&key);
     388             : 
     389      145478 :                 if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
     390           2 :                         (*p)--;
     391           2 :                         return 0;
     392             :                 }
     393             :         }
     394             : 
     395      209325 :         return 1;
     396             : }
     397             : 
     398      209372 : static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
     399             : {
     400      209372 :         if (*((*p)++) == '}')
     401      209370 :                 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          63 : static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     410             : {
     411             :         zend_long datalen;
     412             : 
     413          63 :         datalen = parse_iv2((*p) + 2, p);
     414             : 
     415          63 :         (*p) += 2;
     416             : 
     417          63 :         if (datalen < 0 || (max - (*p)) <= datalen) {
     418           1 :                 zend_error(E_WARNING, "Insufficient data for unserializing - %pd required, %pd present", datalen, (zend_long)(max - (*p)));
     419           1 :                 return 0;
     420             :         }
     421             : 
     422          62 :         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          59 :         } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
     426           5 :                 return 0;
     427             :         }
     428             : 
     429          57 :         (*p) += datalen;
     430             : 
     431          57 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     432             : }
     433             : 
     434      142542 : static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
     435             : {
     436             :         zend_long elements;
     437             : 
     438      142542 :         elements = parse_iv2((*p) + 2, p);
     439             : 
     440      142542 :         (*p) += 2;
     441             : 
     442      142542 :         if (ce->serialize == NULL) {
     443      142539 :                 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      142539 :         return elements;
     452             : }
     453             : 
     454             : #ifdef PHP_WIN32
     455             : # pragma optimize("", off)
     456             : #endif
     457      142542 : static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
     458             : {
     459             :         zval retval;
     460             :         zval fname;
     461             :         HashTable *ht;
     462             : 
     463      142542 :         if (Z_TYPE_P(rval) != IS_OBJECT) {
     464           3 :                 return 0;
     465             :         }
     466             : 
     467      142539 :         ht = Z_OBJPROP_P(rval);
     468      142539 :         zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
     469      142539 :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
     470           2 :                 return 0;
     471             :         }
     472             : 
     473      142537 :         ZVAL_DEREF(rval);
     474      285059 :         if (Z_OBJCE_P(rval) != PHP_IC_ENTRY &&
     475      142522 :                 zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
     476          90 :                 ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
     477          45 :                 BG(serialize_lock)++;
     478          45 :                 call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL);
     479          37 :                 BG(serialize_lock)--;
     480             :                 zval_dtor(&fname);
     481             :                 zval_dtor(&retval);
     482             :         }
     483             : 
     484      142529 :         if (EG(exception)) {
     485           2 :                 return 0;
     486             :         }
     487             : 
     488      142527 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     489             : 
     490             : }
     491             : #ifdef PHP_WIN32
     492             : # pragma optimize("", on)
     493             : #endif
     494             : 
     495       20564 : PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash)
     496             : {
     497       20564 :         HashTable *classes = NULL;
     498       20564 :         return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
     499             : }
     500             : 
     501             : 
     502      378152 : PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
     503             : {
     504             :         const unsigned char *cursor, *limit, *marker, *start;
     505             :         zval *rval_ref;
     506             : 
     507      378152 :         limit = max;
     508      378152 :         cursor = *p;
     509             : 
     510      378152 :         if (YYCURSOR >= YYLIMIT) {
     511          16 :                 return 0;
     512             :         }
     513             : 
     514      378136 :         if (var_hash && (*p)[0] != 'R') {
     515      232329 :                 var_push(var_hash, rval);
     516             :         }
     517             : 
     518      378136 :         start = cursor;
     519             : 
     520             : /*!re2c
     521             : 
     522             : "R:" iv ";"         {
     523             :         zend_long id;
     524             : 
     525         290 :         *p = YYCURSOR;
     526         290 :         if (!var_hash) return 0;
     527             : 
     528         290 :         id = parse_iv(start + 2) - 1;
     529         290 :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
     530           0 :                 return 0;
     531             :         }
     532             : 
     533         290 :         zval_ptr_dtor(rval);
     534         602 :         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         289 :         if (Z_ISREF_P(rval_ref)) {
     539          23 :                 ZVAL_COPY(rval, rval_ref);
     540             :         } else {
     541         266 :                 ZVAL_NEW_REF(rval_ref, rval_ref);
     542         266 :                 ZVAL_COPY(rval, rval_ref);
     543             :         }
     544             : 
     545         289 :         return 1;
     546             : }
     547             : 
     548             : "r:" iv ";"         {
     549             :         zend_long id;
     550             : 
     551       10057 :         *p = YYCURSOR;
     552       10057 :         if (!var_hash) return 0;
     553             : 
     554       10057 :         id = parse_iv(start + 2) - 1;
     555       10057 :         if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
     556           0 :                 return 0;
     557             :         }
     558             : 
     559       10057 :         if (rval_ref == rval) {
     560           2 :                 return 0;
     561             :         }
     562             : 
     563       20109 :         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       10054 :         ZVAL_COPY(rval, rval_ref);
     569             : 
     570       10054 :         return 1;
     571             : }
     572             : 
     573             : "N;"  {
     574       10076 :         *p = YYCURSOR;
     575       10076 :         ZVAL_NULL(rval);
     576       10076 :         return 1;
     577             : }
     578             : 
     579             : "b:" [01] ";"       {
     580          84 :         *p = YYCURSOR;
     581          84 :         ZVAL_BOOL(rval, parse_iv(start + 2));
     582          84 :         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      145561 :         *p = YYCURSOR;
     607      145561 :         ZVAL_LONG(rval, parse_iv(start + 2));
     608      145561 :         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        2457 :         len = parse_uiv(start + 2);
     641        2457 :         maxlen = max - YYCURSOR;
     642        2457 :         if (maxlen < len) {
     643           3 :                 *p = start + 2;
     644           3 :                 return 0;
     645             :         }
     646             : 
     647        2454 :         str = (char*)YYCURSOR;
     648             : 
     649        2454 :         YYCURSOR += len;
     650             : 
     651        2454 :         if (*(YYCURSOR) != '"') {
     652           2 :                 *p = YYCURSOR;
     653           2 :                 return 0;
     654             :         }
     655             : 
     656        2452 :         YYCURSOR += 2;
     657        2452 :         *p = YYCURSOR;
     658             : 
     659        4904 :         ZVAL_STRINGL(rval, str, len);
     660        2452 :         return 1;
     661             : }
     662             : 
     663             : "S:" uiv ":" ["]       {
     664             :         size_t len, maxlen;
     665             :         zend_string *str;
     666             : 
     667           2 :         len = parse_uiv(start + 2);
     668           2 :         maxlen = max - YYCURSOR;
     669           2 :         if (maxlen < len) {
     670           0 :                 *p = start + 2;
     671           0 :                 return 0;
     672             :         }
     673             : 
     674           2 :         if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
     675           1 :                 return 0;
     676             :         }
     677             : 
     678           1 :         if (*(YYCURSOR) != '"') {
     679             :                 zend_string_free(str);
     680           0 :                 *p = YYCURSOR;
     681           0 :                 return 0;
     682             :         }
     683             : 
     684           1 :         YYCURSOR += 2;
     685           1 :         *p = YYCURSOR;
     686             : 
     687           1 :         ZVAL_STR(rval, str);
     688           1 :         return 1;
     689             : }
     690             : 
     691             : "a:" uiv ":" "{" {
     692       66826 :         zend_long elements = parse_iv(start + 2);
     693             :         /* use iv() not uiv() in order to check data range */
     694       66826 :         *p = YYCURSOR;
     695       66826 :     if (!var_hash) return 0;
     696             : 
     697       66825 :         if (elements < 0) {
     698           0 :                 return 0;
     699             :         }
     700             : 
     701       66825 :         array_init_size(rval, elements);
     702             : //??? we can't convert from packed to hash during unserialization, because
     703             : //??? reference to some zvals might be keept in var_hash (to support references)
     704       66825 :         if (elements) {
     705       66782 :                 zend_hash_real_init(Z_ARRVAL_P(rval), 0);
     706             :         }
     707             : 
     708      133648 :         if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
     709          35 :                 return 0;
     710             :         }
     711             : 
     712       66788 :         return finish_nested_data(UNSERIALIZE_PASSTHRU);
     713             : }
     714             : 
     715             : "o:" iv ":" ["] {
     716           0 :     if (!var_hash) return 0;
     717             : 
     718           0 :         return object_common2(UNSERIALIZE_PASSTHRU,
     719             :                         object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
     720             : }
     721             : 
     722             : object ":" uiv ":" ["] {
     723             :         size_t len, len2, len3, maxlen;
     724             :         zend_long elements;
     725             :         char *str;
     726             :         zend_string *class_name;
     727             :         zend_class_entry *ce;
     728      142612 :         int incomplete_class = 0;
     729             : 
     730      142612 :         int custom_object = 0;
     731             : 
     732             :         zval user_func;
     733             :         zval retval;
     734             :         zval args[1];
     735             : 
     736      142612 :     if (!var_hash) return 0;
     737      142612 :         if (*start == 'C') {
     738          63 :                 custom_object = 1;
     739             :         }
     740             : 
     741      142612 :         len2 = len = parse_uiv(start + 2);
     742      142612 :         maxlen = max - YYCURSOR;
     743      142612 :         if (maxlen < len || len == 0) {
     744           1 :                 *p = start + 2;
     745           1 :                 return 0;
     746             :         }
     747             : 
     748      142611 :         str = (char*)YYCURSOR;
     749             : 
     750      142611 :         YYCURSOR += len;
     751             : 
     752      142611 :         if (*(YYCURSOR) != '"') {
     753           1 :                 *p = YYCURSOR;
     754           1 :                 return 0;
     755             :         }
     756      142610 :         if (*(YYCURSOR+1) != ':') {
     757           1 :                 *p = YYCURSOR+1;
     758           1 :                 return 0;
     759             :         }
     760             : 
     761      142609 :         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\\");
     762      142609 :         if (len3 != len)
     763             :         {
     764           1 :                 *p = YYCURSOR + len3 - len;
     765           1 :                 return 0;
     766             :         }
     767             : 
     768      142608 :         class_name = zend_string_init(str, len, 0);
     769             : 
     770             :         do {
     771      142608 :                 if(!unserialize_allowed_class(class_name, classes)) {
     772           6 :                         incomplete_class = 1;
     773           6 :                         ce = PHP_IC_ENTRY;
     774           6 :                         break;
     775             :                 }
     776             : 
     777             :                 /* Try to find class directly */
     778      142602 :                 BG(serialize_lock)++;
     779      142602 :                 ce = zend_lookup_class(class_name);
     780      142602 :                 if (ce) {
     781      142580 :                         BG(serialize_lock)--;
     782      142580 :                         if (EG(exception)) {
     783             :                                 zend_string_release(class_name);
     784           0 :                                 return 0;
     785             :                         }
     786      142580 :                         break;
     787             :                 }
     788          22 :                 BG(serialize_lock)--;
     789             : 
     790          22 :                 if (EG(exception)) {
     791             :                         zend_string_release(class_name);
     792           2 :                         return 0;
     793             :                 }
     794             : 
     795             :                 /* Check for unserialize callback */
     796          20 :                 if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
     797          10 :                         incomplete_class = 1;
     798          10 :                         ce = PHP_IC_ENTRY;
     799          10 :                         break;
     800             :                 }
     801             : 
     802             :                 /* Call unserialize callback */
     803          20 :                 ZVAL_STRING(&user_func, PG(unserialize_callback_func));
     804             : 
     805          10 :                 ZVAL_STR_COPY(&args[0], class_name);
     806          10 :                 BG(serialize_lock)++;
     807          10 :                 if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
     808           1 :                         BG(serialize_lock)--;
     809           1 :                         if (EG(exception)) {
     810             :                                 zend_string_release(class_name);
     811           0 :                                 zval_ptr_dtor(&user_func);
     812           0 :                                 zval_ptr_dtor(&args[0]);
     813           0 :                                 return 0;
     814             :                         }
     815           1 :                         php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
     816           1 :                         incomplete_class = 1;
     817           1 :                         ce = PHP_IC_ENTRY;
     818           1 :                         zval_ptr_dtor(&user_func);
     819           1 :                         zval_ptr_dtor(&args[0]);
     820           1 :                         break;
     821             :                 }
     822           9 :                 BG(serialize_lock)--;
     823           9 :                 zval_ptr_dtor(&retval);
     824           9 :                 if (EG(exception)) {
     825             :                         zend_string_release(class_name);
     826           1 :                         zval_ptr_dtor(&user_func);
     827           1 :                         zval_ptr_dtor(&args[0]);
     828           1 :                         return 0;
     829             :                 }
     830             : 
     831             :                 /* The callback function may have defined the class */
     832           8 :                 if ((ce = zend_lookup_class(class_name)) == NULL) {
     833           2 :                         php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
     834           2 :                         incomplete_class = 1;
     835           2 :                         ce = PHP_IC_ENTRY;
     836             :                 }
     837             : 
     838           8 :                 zval_ptr_dtor(&user_func);
     839           8 :                 zval_ptr_dtor(&args[0]);
     840           8 :                 break;
     841             :         } while (1);
     842             : 
     843      142605 :         *p = YYCURSOR;
     844             : 
     845      142605 :         if (custom_object) {
     846             :                 int ret;
     847             : 
     848          63 :                 ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
     849             : 
     850          63 :                 if (ret && incomplete_class) {
     851           2 :                         php_store_class_name(rval, ZSTR_VAL(class_name), len2);
     852             :                 }
     853             :                 zend_string_release(class_name);
     854          63 :                 return ret;
     855             :         }
     856             : 
     857      142542 :         elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
     858             : 
     859      142542 :         if (incomplete_class) {
     860          16 :                 php_store_class_name(rval, ZSTR_VAL(class_name), len2);
     861             :         }
     862             :         zend_string_release(class_name);
     863             : 
     864      142542 :         return object_common2(UNSERIALIZE_PASSTHRU, elements);
     865             : }
     866             : 
     867             : "}" {
     868             :         /* this is the case where we have less data than planned */
     869           0 :         php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
     870           0 :         return 0; /* not sure if it should be 0 or 1 here? */
     871             : }
     872             : 
     873          98 : any     { return 0; }
     874             : 
     875             : */
     876             : 
     877             :         return 0;
     878             : }

Generated by: LCOV version 1.10

Generated at Sat, 25 Jun 2016 07:09:09 +0000 (8 hours ago)

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