This source file includes following definitions.
- var_push
- var_push_dtor
- var_tmp_var
- var_replace
- var_access
- var_destroy
- unserialize_str
- unserialize_allowed_class
- parse_iv2
- parse_iv
- parse_uiv
- process_nested_data
- finish_nested_data
- object_custom
- object_common1
- object_common2
- php_var_unserialize
- php_var_unserialize_ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "php.h"
23 #include "ext/standard/php_var.h"
24 #include "php_incomplete_class.h"
25
26
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
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
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
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
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
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
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
440
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
619 php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
620 return 0;
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
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
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
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
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
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
857
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
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 }