1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Sascha Schumann <sascha@schumann.cx> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: var_unserializer.re 277374 2009-03-17 23:07:40Z felipe $ */
20 :
21 : #include "php.h"
22 : #include "ext/standard/php_var.h"
23 : #include "php_incomplete_class.h"
24 :
25 : /* {{{ reference-handling for unserializer: var_* */
26 : #define VAR_ENTRIES_MAX 1024
27 :
28 : typedef struct {
29 : zval *data[VAR_ENTRIES_MAX];
30 : long used_slots;
31 : void *next;
32 : } var_entries;
33 :
34 : static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
35 1284 : {
36 1284 : var_entries *var_hash = var_hashx->first, *prev = NULL;
37 :
38 2568 : while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
39 0 : prev = var_hash;
40 0 : var_hash = var_hash->next;
41 : }
42 :
43 1284 : if (!var_hash) {
44 471 : var_hash = emalloc(sizeof(var_entries));
45 471 : var_hash->used_slots = 0;
46 471 : var_hash->next = 0;
47 :
48 471 : if (!var_hashx->first)
49 471 : var_hashx->first = var_hash;
50 : else
51 0 : prev->next = var_hash;
52 : }
53 :
54 1284 : var_hash->data[var_hash->used_slots++] = *rval;
55 1284 : }
56 :
57 : static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
58 169 : {
59 169 : var_entries *var_hash = var_hashx->first_dtor, *prev = NULL;
60 :
61 338 : while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
62 0 : prev = var_hash;
63 0 : var_hash = var_hash->next;
64 : }
65 :
66 169 : if (!var_hash) {
67 41 : var_hash = emalloc(sizeof(var_entries));
68 41 : var_hash->used_slots = 0;
69 41 : var_hash->next = 0;
70 :
71 41 : if (!var_hashx->first_dtor)
72 41 : var_hashx->first_dtor = var_hash;
73 : else
74 0 : prev->next = var_hash;
75 : }
76 :
77 169 : Z_ADDREF_PP(rval);
78 169 : var_hash->data[var_hash->used_slots++] = *rval;
79 169 : }
80 :
81 : PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval)
82 9 : {
83 : long i;
84 9 : var_entries *var_hash = var_hashx->first;
85 :
86 27 : while (var_hash) {
87 52 : for (i = 0; i < var_hash->used_slots; i++) {
88 43 : if (var_hash->data[i] == ozval) {
89 9 : var_hash->data[i] = *nzval;
90 : /* do not break here */
91 : }
92 : }
93 9 : var_hash = var_hash->next;
94 : }
95 9 : }
96 :
97 : static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store)
98 110 : {
99 110 : var_entries *var_hash = var_hashx->first;
100 :
101 220 : while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
102 0 : var_hash = var_hash->next;
103 0 : id -= VAR_ENTRIES_MAX;
104 : }
105 :
106 110 : if (!var_hash) return !SUCCESS;
107 :
108 110 : if (id < 0 || id >= var_hash->used_slots) return !SUCCESS;
109 :
110 110 : *store = &var_hash->data[id];
111 :
112 110 : return SUCCESS;
113 : }
114 :
115 : PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
116 777 : {
117 : void *next;
118 : long i;
119 777 : var_entries *var_hash = var_hashx->first;
120 :
121 2025 : while (var_hash) {
122 471 : next = var_hash->next;
123 471 : efree(var_hash);
124 471 : var_hash = next;
125 : }
126 :
127 777 : var_hash = var_hashx->first_dtor;
128 :
129 1595 : while (var_hash) {
130 210 : for (i = 0; i < var_hash->used_slots; i++) {
131 169 : zval_ptr_dtor(&var_hash->data[i]);
132 : }
133 41 : next = var_hash->next;
134 41 : efree(var_hash);
135 41 : var_hash = next;
136 : }
137 777 : }
138 :
139 : /* }}} */
140 :
141 : static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen)
142 1 : {
143 : size_t i, j;
144 1 : char *str = safe_emalloc(*len, 1, 1);
145 1 : unsigned char *end = *(unsigned char **)p+maxlen;
146 :
147 1 : if (end < *p) {
148 0 : efree(str);
149 0 : return NULL;
150 : }
151 :
152 102 : for (i = 0; i < *len; i++) {
153 102 : if (*p >= end) {
154 1 : efree(str);
155 1 : return NULL;
156 : }
157 101 : if (**p != '\\') {
158 1 : str[i] = (char)**p;
159 : } else {
160 100 : unsigned char ch = 0;
161 :
162 300 : for (j = 0; j < 2; j++) {
163 200 : (*p)++;
164 400 : if (**p >= '0' && **p <= '9') {
165 200 : ch = (ch << 4) + (**p -'0');
166 0 : } else if (**p >= 'a' && **p <= 'f') {
167 0 : ch = (ch << 4) + (**p -'a'+10);
168 0 : } else if (**p >= 'A' && **p <= 'F') {
169 0 : ch = (ch << 4) + (**p -'A'+10);
170 : } else {
171 0 : efree(str);
172 0 : return NULL;
173 : }
174 : }
175 100 : str[i] = (char)ch;
176 : }
177 101 : (*p)++;
178 : }
179 0 : str[i] = 0;
180 0 : *len = i;
181 0 : return str;
182 : }
183 :
184 : #define YYFILL(n) do { } while (0)
185 : #define YYCTYPE unsigned char
186 : #define YYCURSOR cursor
187 : #define YYLIMIT limit
188 : #define YYMARKER marker
189 :
190 :
191 : /*!re2c
192 : uiv = [+]? [0-9]+;
193 : iv = [+-]? [0-9]+;
194 : nv = [+-]? ([0-9]* "." [0-9]+|[0-9]+ "." [0-9]*);
195 : nvexp = (iv | nv) [eE] [+-]? iv;
196 : any = [\000-\377];
197 : object = [OC];
198 : */
199 :
200 :
201 :
202 : static inline long parse_iv2(const unsigned char *p, const unsigned char **q)
203 1260 : {
204 : char cursor;
205 1260 : long result = 0;
206 1260 : int neg = 0;
207 :
208 1260 : switch (*p) {
209 : case '-':
210 10 : neg++;
211 : /* fall-through */
212 : case '+':
213 10 : p++;
214 : }
215 :
216 : while (1) {
217 2715 : cursor = (char)*p;
218 2715 : if (cursor >= '0' && cursor <= '9') {
219 1455 : result = result * 10 + cursor - '0';
220 : } else {
221 : break;
222 : }
223 1455 : p++;
224 1455 : }
225 1260 : if (q) *q = p;
226 1260 : if (neg) return -result;
227 1250 : return result;
228 : }
229 :
230 : static inline long parse_iv(const unsigned char *p)
231 1086 : {
232 1086 : return parse_iv2(p, NULL);
233 : }
234 :
235 : /* no need to check for length - re2c already did */
236 : static inline size_t parse_uiv(const unsigned char *p)
237 859 : {
238 : unsigned char cursor;
239 859 : size_t result = 0;
240 :
241 859 : if (*p == '+') {
242 0 : p++;
243 : }
244 :
245 : while (1) {
246 1824 : cursor = *p;
247 1824 : if (cursor >= '0' && cursor <= '9') {
248 965 : result = result * 10 + (size_t)(cursor - (unsigned char)'0');
249 : } else {
250 : break;
251 : }
252 965 : p++;
253 965 : }
254 859 : return result;
255 : }
256 :
257 : #define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC
258 : #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC
259 :
260 : static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements)
261 363 : {
262 1473 : while (elements-- > 0) {
263 : zval *key, *data, **old_data;
264 :
265 775 : ALLOC_INIT_ZVAL(key);
266 :
267 775 : if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
268 13 : zval_dtor(key);
269 13 : FREE_ZVAL(key);
270 13 : return 0;
271 : }
272 :
273 762 : if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
274 0 : zval_dtor(key);
275 0 : FREE_ZVAL(key);
276 0 : return 0;
277 : }
278 :
279 762 : ALLOC_INIT_ZVAL(data);
280 :
281 762 : if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
282 13 : zval_dtor(key);
283 13 : FREE_ZVAL(key);
284 13 : zval_dtor(data);
285 13 : FREE_ZVAL(data);
286 13 : return 0;
287 : }
288 :
289 749 : switch (Z_TYPE_P(key)) {
290 : case IS_LONG:
291 358 : if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) {
292 0 : var_push_dtor(var_hash, old_data);
293 : }
294 358 : zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL);
295 358 : break;
296 : case IS_STRING:
297 391 : if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
298 169 : var_push_dtor(var_hash, old_data);
299 : }
300 391 : zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
301 : break;
302 : }
303 :
304 749 : zval_dtor(key);
305 749 : FREE_ZVAL(key);
306 :
307 749 : if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
308 2 : (*p)--;
309 2 : return 0;
310 : }
311 : }
312 :
313 335 : return 1;
314 : }
315 :
316 : static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
317 360 : {
318 360 : if (*((*p)++) == '}')
319 358 : return 1;
320 :
321 : #if SOMETHING_NEW_MIGHT_LEAD_TO_CRASH_ENABLE_IF_YOU_ARE_BRAVE
322 : zval_ptr_dtor(rval);
323 : #endif
324 2 : return 0;
325 : }
326 :
327 : static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
328 25 : {
329 : long datalen;
330 :
331 25 : datalen = parse_iv2((*p) + 2, p);
332 :
333 25 : (*p) += 2;
334 :
335 25 : if (datalen < 0 || (*p) + datalen >= max) {
336 0 : zend_error(E_WARNING, "Insufficient data for unserializing - %ld required, %ld present", datalen, (long)(max - (*p)));
337 0 : return 0;
338 : }
339 :
340 25 : if (ce->unserialize == NULL) {
341 3 : zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
342 3 : object_init_ex(*rval, ce);
343 22 : } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
344 0 : return 0;
345 : }
346 :
347 25 : (*p) += datalen;
348 :
349 25 : return finish_nested_data(UNSERIALIZE_PASSTHRU);
350 : }
351 :
352 : static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
353 149 : {
354 : long elements;
355 :
356 149 : elements = parse_iv2((*p) + 2, p);
357 :
358 149 : (*p) += 2;
359 :
360 149 : object_init_ex(*rval, ce);
361 149 : return elements;
362 : }
363 :
364 : static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
365 149 : {
366 149 : zval *retval_ptr = NULL;
367 : zval fname;
368 :
369 149 : if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements)) {
370 0 : return 0;
371 : }
372 :
373 149 : if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY &&
374 : zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) {
375 8 : INIT_PZVAL(&fname);
376 8 : ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0);
377 8 : call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
378 : }
379 :
380 149 : if (retval_ptr)
381 8 : zval_ptr_dtor(&retval_ptr);
382 :
383 149 : return finish_nested_data(UNSERIALIZE_PASSTHRU);
384 :
385 : }
386 :
387 : PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
388 2161 : {
389 : const unsigned char *cursor, *limit, *marker, *start;
390 : zval **rval_ref;
391 :
392 2161 : limit = cursor = *p;
393 :
394 2161 : if (var_hash && cursor[0] != 'R') {
395 1284 : var_push(var_hash, rval);
396 : }
397 :
398 2161 : start = cursor;
399 :
400 :
401 :
402 : /*!re2c
403 :
404 : "R:" iv ";" {
405 : long id;
406 :
407 86 : *p = YYCURSOR;
408 86 : if (!var_hash) return 0;
409 :
410 86 : id = parse_iv(start + 2) - 1;
411 86 : if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
412 0 : return 0;
413 : }
414 :
415 86 : if (*rval != NULL) {
416 86 : zval_ptr_dtor(rval);
417 : }
418 86 : *rval = *rval_ref;
419 86 : Z_ADDREF_PP(rval);
420 86 : Z_SET_ISREF_PP(rval);
421 :
422 86 : return 1;
423 : }
424 :
425 : "r:" iv ";" {
426 : long id;
427 :
428 24 : *p = YYCURSOR;
429 24 : if (!var_hash) return 0;
430 :
431 24 : id = parse_iv(start + 2) - 1;
432 24 : if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
433 0 : return 0;
434 : }
435 :
436 24 : if (*rval == *rval_ref) return 0;
437 :
438 24 : if (*rval != NULL) {
439 24 : zval_ptr_dtor(rval);
440 : }
441 24 : *rval = *rval_ref;
442 24 : Z_ADDREF_PP(rval);
443 24 : Z_UNSET_ISREF_PP(rval);
444 :
445 24 : return 1;
446 : }
447 :
448 : "N;" {
449 61 : *p = YYCURSOR;
450 61 : INIT_PZVAL(*rval);
451 61 : ZVAL_NULL(*rval);
452 61 : return 1;
453 : }
454 :
455 : "b:" [01] ";" {
456 33 : *p = YYCURSOR;
457 33 : INIT_PZVAL(*rval);
458 33 : ZVAL_BOOL(*rval, parse_iv(start + 2));
459 33 : return 1;
460 : }
461 :
462 : "i:" iv ";" {
463 : #if SIZEOF_LONG == 4
464 730 : int digits = YYCURSOR - start - 3;
465 :
466 730 : if (start[2] == '-' || start[2] == '+') {
467 10 : digits--;
468 : }
469 :
470 : /* Use double for large long values that were serialized on a 64-bit system */
471 730 : if (digits >= MAX_LENGTH_OF_LONG - 1) {
472 9 : if (digits == MAX_LENGTH_OF_LONG - 1) {
473 9 : int cmp = strncmp(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
474 :
475 9 : if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
476 : goto use_double;
477 : }
478 : } else {
479 0 : goto use_double;
480 : }
481 : }
482 : #endif
483 729 : *p = YYCURSOR;
484 729 : INIT_PZVAL(*rval);
485 729 : ZVAL_LONG(*rval, parse_iv(start + 2));
486 729 : return 1;
487 : }
488 :
489 : "d:" ("NAN" | "-"? "INF") ";" {
490 3 : *p = YYCURSOR;
491 3 : INIT_PZVAL(*rval);
492 :
493 3 : if (!strncmp(start + 2, "NAN", 3)) {
494 1 : ZVAL_DOUBLE(*rval, php_get_nan());
495 2 : } else if (!strncmp(start + 2, "INF", 3)) {
496 1 : ZVAL_DOUBLE(*rval, php_get_inf());
497 1 : } else if (!strncmp(start + 2, "-INF", 4)) {
498 1 : ZVAL_DOUBLE(*rval, -php_get_inf());
499 : }
500 :
501 3 : return 1;
502 : }
503 :
504 : "d:" (iv | nv | nvexp) ";" {
505 : #if SIZEOF_LONG == 4
506 49 : use_double:
507 : #endif
508 49 : *p = YYCURSOR;
509 49 : INIT_PZVAL(*rval);
510 49 : ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
511 49 : return 1;
512 : }
513 :
514 : "s:" uiv ":" ["] {
515 : size_t len, maxlen;
516 : char *str;
517 :
518 681 : len = parse_uiv(start + 2);
519 681 : maxlen = max - YYCURSOR;
520 681 : if (maxlen < len) {
521 3 : *p = start + 2;
522 3 : return 0;
523 : }
524 :
525 678 : str = (char*)YYCURSOR;
526 :
527 678 : YYCURSOR += len;
528 :
529 678 : if (*(YYCURSOR) != '"') {
530 2 : *p = YYCURSOR;
531 2 : return 0;
532 : }
533 :
534 676 : YYCURSOR += 2;
535 676 : *p = YYCURSOR;
536 :
537 676 : INIT_PZVAL(*rval);
538 676 : ZVAL_STRINGL(*rval, str, len, 1);
539 676 : return 1;
540 : }
541 :
542 : "S:" uiv ":" ["] {
543 : size_t len, maxlen;
544 : char *str;
545 :
546 1 : len = parse_uiv(start + 2);
547 1 : maxlen = max - YYCURSOR;
548 1 : if (maxlen < len) {
549 0 : *p = start + 2;
550 0 : return 0;
551 : }
552 :
553 1 : if ((str = unserialize_str(&YYCURSOR, &len, maxlen)) == NULL) {
554 1 : return 0;
555 : }
556 :
557 0 : if (*(YYCURSOR) != '"') {
558 0 : efree(str);
559 0 : *p = YYCURSOR;
560 0 : return 0;
561 : }
562 :
563 0 : YYCURSOR += 2;
564 0 : *p = YYCURSOR;
565 :
566 0 : INIT_PZVAL(*rval);
567 0 : ZVAL_STRINGL(*rval, str, len, 0);
568 0 : return 1;
569 : }
570 :
571 : "a:" uiv ":" "{" {
572 214 : long elements = parse_iv(start + 2);
573 : /* use iv() not uiv() in order to check data range */
574 214 : *p = YYCURSOR;
575 :
576 214 : if (elements < 0) {
577 0 : return 0;
578 : }
579 :
580 214 : INIT_PZVAL(*rval);
581 :
582 214 : array_init_size(*rval, elements);
583 :
584 214 : if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements)) {
585 28 : return 0;
586 : }
587 :
588 186 : return finish_nested_data(UNSERIALIZE_PASSTHRU);
589 : }
590 :
591 : "o:" iv ":" ["] {
592 :
593 0 : INIT_PZVAL(*rval);
594 :
595 0 : return object_common2(UNSERIALIZE_PASSTHRU,
596 : object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
597 : }
598 :
599 : object ":" uiv ":" ["] {
600 : size_t len, len2, len3, maxlen;
601 : long elements;
602 : char *class_name;
603 : zend_class_entry *ce;
604 : zend_class_entry **pce;
605 177 : int incomplete_class = 0;
606 :
607 177 : int custom_object = 0;
608 :
609 : zval *user_func;
610 : zval *retval_ptr;
611 : zval **args[1];
612 : zval *arg_func_name;
613 :
614 177 : if (*start == 'C') {
615 25 : custom_object = 1;
616 : }
617 :
618 177 : INIT_PZVAL(*rval);
619 177 : len2 = len = parse_uiv(start + 2);
620 177 : maxlen = max - YYCURSOR;
621 177 : if (maxlen < len || len == 0) {
622 1 : *p = start + 2;
623 1 : return 0;
624 : }
625 :
626 176 : class_name = (char*)YYCURSOR;
627 :
628 176 : YYCURSOR += len;
629 :
630 176 : if (*(YYCURSOR) != '"') {
631 1 : *p = YYCURSOR;
632 1 : return 0;
633 : }
634 175 : if (*(YYCURSOR+1) != ':') {
635 1 : *p = YYCURSOR+1;
636 1 : return 0;
637 : }
638 :
639 174 : 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\\");
640 174 : if (len3 != len)
641 : {
642 0 : *p = YYCURSOR + len3 - len;
643 0 : return 0;
644 : }
645 :
646 174 : class_name = estrndup(class_name, len);
647 :
648 : do {
649 : /* Try to find class directly */
650 174 : if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
651 156 : ce = *pce;
652 156 : break;
653 : }
654 :
655 : /* Check for unserialize callback */
656 18 : if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
657 10 : incomplete_class = 1;
658 10 : ce = PHP_IC_ENTRY;
659 10 : break;
660 : }
661 :
662 : /* Call unserialize callback */
663 8 : MAKE_STD_ZVAL(user_func);
664 8 : ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
665 8 : args[0] = &arg_func_name;
666 8 : MAKE_STD_ZVAL(arg_func_name);
667 8 : ZVAL_STRING(arg_func_name, class_name, 1);
668 8 : if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
669 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
670 1 : incomplete_class = 1;
671 1 : ce = PHP_IC_ENTRY;
672 1 : zval_ptr_dtor(&user_func);
673 1 : zval_ptr_dtor(&arg_func_name);
674 1 : break;
675 : }
676 7 : if (retval_ptr) {
677 6 : zval_ptr_dtor(&retval_ptr);
678 : }
679 :
680 : /* The callback function may have defined the class */
681 7 : if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
682 4 : ce = *pce;
683 : } else {
684 3 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", user_func->value.str.val);
685 3 : incomplete_class = 1;
686 3 : ce = PHP_IC_ENTRY;
687 : }
688 :
689 7 : zval_ptr_dtor(&user_func);
690 7 : zval_ptr_dtor(&arg_func_name);
691 7 : break;
692 : } while (1);
693 :
694 174 : *p = YYCURSOR;
695 :
696 174 : if (custom_object) {
697 25 : int ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
698 :
699 25 : if (ret && incomplete_class) {
700 2 : php_store_class_name(*rval, class_name, len2);
701 : }
702 25 : efree(class_name);
703 25 : return ret;
704 : }
705 :
706 149 : elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
707 :
708 149 : if (incomplete_class) {
709 12 : php_store_class_name(*rval, class_name, len2);
710 : }
711 149 : efree(class_name);
712 :
713 149 : return object_common2(UNSERIALIZE_PASSTHRU, elements);
714 : }
715 :
716 : "}" {
717 : /* this is the case where we have less data than planned */
718 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
719 0 : return 0; /* not sure if it should be 0 or 1 here? */
720 : }
721 :
722 103 : any { return 0; }
723 :
724 : */
725 :
726 : return 0;
727 : }
|