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: 296 334 88.6 %
Date: 2014-10-30 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 30 Oct 2014 07:41:45 +0000 (28 hours ago)

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