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