root/ext/standard/var_unserializer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. var_push
  2. var_push_dtor
  3. var_tmp_var
  4. var_replace
  5. var_access
  6. var_destroy
  7. unserialize_str
  8. unserialize_allowed_class
  9. parse_iv2
  10. parse_iv
  11. parse_uiv
  12. process_nested_data
  13. finish_nested_data
  14. object_custom
  15. object_common1
  16. object_common2
  17. php_var_unserialize
  18. php_var_unserialize_ex

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

/* [<][>][^][v][top][bottom][index][help] */