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 277375 2009-03-17 23:10:13Z 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 971 : {
36 971 : var_entries *var_hash = var_hashx->first, *prev = NULL;
37 :
38 1942 : 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 971 : if (!var_hash) {
44 335 : var_hash = emalloc(sizeof(var_entries));
45 335 : var_hash->used_slots = 0;
46 335 : var_hash->next = 0;
47 :
48 335 : if (!var_hashx->first)
49 335 : var_hashx->first = var_hash;
50 : else
51 0 : prev->next = var_hash;
52 : }
53 :
54 971 : var_hash->data[var_hash->used_slots++] = *rval;
55 971 : }
56 :
57 : static inline void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
58 152 : {
59 152 : var_entries *var_hash = var_hashx->first_dtor, *prev = NULL;
60 :
61 304 : 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 152 : if (!var_hash) {
67 37 : var_hash = emalloc(sizeof(var_entries));
68 37 : var_hash->used_slots = 0;
69 37 : var_hash->next = 0;
70 :
71 37 : if (!var_hashx->first_dtor)
72 37 : var_hashx->first_dtor = var_hash;
73 : else
74 0 : prev->next = var_hash;
75 : }
76 :
77 152 : (*rval)->refcount++;
78 152 : var_hash->data[var_hash->used_slots++] = *rval;
79 152 : }
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 95 : {
99 95 : var_entries *var_hash = var_hashx->first;
100 :
101 190 : 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 95 : if (!var_hash) return !SUCCESS;
107 :
108 95 : if (id < 0 || id >= var_hash->used_slots) return !SUCCESS;
109 :
110 95 : *store = &var_hash->data[id];
111 :
112 95 : return SUCCESS;
113 : }
114 :
115 : PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
116 636 : {
117 : void *next;
118 : long i;
119 636 : var_entries *var_hash = var_hashx->first;
120 :
121 1607 : while (var_hash) {
122 335 : next = var_hash->next;
123 335 : efree(var_hash);
124 335 : var_hash = next;
125 : }
126 :
127 636 : var_hash = var_hashx->first_dtor;
128 :
129 1309 : while (var_hash) {
130 189 : for (i = 0; i < var_hash->used_slots; i++) {
131 152 : zval_ptr_dtor(&var_hash->data[i]);
132 : }
133 37 : next = var_hash->next;
134 37 : efree(var_hash);
135 37 : var_hash = next;
136 : }
137 636 : }
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 1053 : {
204 : char cursor;
205 1053 : long result = 0;
206 1053 : int neg = 0;
207 :
208 1053 : switch (*p) {
209 : case '-':
210 10 : neg++;
211 : /* fall-through */
212 : case '+':
213 10 : p++;
214 : }
215 :
216 : while (1) {
217 2262 : cursor = (char)*p;
218 2262 : if (cursor >= '0' && cursor <= '9') {
219 1209 : result = result * 10 + cursor - '0';
220 : } else {
221 : break;
222 : }
223 1209 : p++;
224 1209 : }
225 1053 : if (q) *q = p;
226 1053 : if (neg) return -result;
227 1043 : return result;
228 : }
229 :
230 : static inline long parse_iv(const unsigned char *p)
231 927 : {
232 927 : 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 664 : {
238 : unsigned char cursor;
239 664 : size_t result = 0;
240 :
241 664 : if (*p == '+') {
242 0 : p++;
243 : }
244 :
245 : while (1) {
246 1418 : cursor = *p;
247 1418 : if (cursor >= '0' && cursor <= '9') {
248 754 : result = result * 10 + (size_t)(cursor - (unsigned char)'0');
249 : } else {
250 : break;
251 : }
252 754 : p++;
253 754 : }
254 664 : 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 286 : {
262 1216 : while (elements-- > 0) {
263 : zval *key, *data, **old_data;
264 :
265 672 : ALLOC_INIT_ZVAL(key);
266 :
267 672 : 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 659 : 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 659 : ALLOC_INIT_ZVAL(data);
280 :
281 659 : 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 646 : switch (Z_TYPE_P(key)) {
290 : case IS_LONG:
291 318 : 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 318 : zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL);
295 318 : break;
296 : case IS_STRING:
297 328 : if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
298 152 : var_push_dtor(var_hash, old_data);
299 : }
300 328 : zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
301 : break;
302 : }
303 :
304 646 : zval_dtor(key);
305 646 : FREE_ZVAL(key);
306 :
307 646 : if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
308 2 : (*p)--;
309 2 : return 0;
310 : }
311 : }
312 :
313 258 : return 1;
314 : }
315 :
316 : static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
317 264 : {
318 264 : if (*((*p)++) == '}')
319 262 : 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 8 : {
329 : long datalen;
330 :
331 8 : if (ce->unserialize == NULL) {
332 2 : zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
333 2 : return 0;
334 : }
335 :
336 6 : datalen = parse_iv2((*p) + 2, p);
337 :
338 6 : (*p) += 2;
339 :
340 6 : if (datalen < 0 || (*p) + datalen >= max) {
341 0 : zend_error(E_WARNING, "Insufficient data for unserializing - %ld required, %ld present", datalen, (long)(max - (*p)));
342 0 : return 0;
343 : }
344 :
345 6 : if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
346 0 : return 0;
347 : }
348 :
349 6 : (*p) += datalen;
350 :
351 6 : return finish_nested_data(UNSERIALIZE_PASSTHRU);
352 : }
353 :
354 : static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
355 120 : {
356 : long elements;
357 :
358 120 : elements = parse_iv2((*p) + 2, p);
359 :
360 120 : (*p) += 2;
361 :
362 120 : object_init_ex(*rval, ce);
363 120 : return elements;
364 : }
365 :
366 : static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
367 120 : {
368 120 : zval *retval_ptr = NULL;
369 : zval fname;
370 :
371 120 : if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements)) {
372 0 : return 0;
373 : }
374 :
375 120 : if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY &&
376 : zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) {
377 6 : INIT_PZVAL(&fname);
378 6 : ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0);
379 6 : call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
380 : }
381 :
382 120 : if (retval_ptr)
383 6 : zval_ptr_dtor(&retval_ptr);
384 :
385 120 : return finish_nested_data(UNSERIALIZE_PASSTHRU);
386 :
387 : }
388 :
389 : PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
390 1737 : {
391 : const unsigned char *cursor, *limit, *marker, *start;
392 : zval **rval_ref;
393 :
394 1737 : limit = cursor = *p;
395 :
396 1737 : if (var_hash && cursor[0] != 'R') {
397 971 : var_push(var_hash, rval);
398 : }
399 :
400 1737 : start = cursor;
401 :
402 :
403 :
404 : /*!re2c
405 :
406 : "R:" iv ";" {
407 : long id;
408 :
409 85 : *p = YYCURSOR;
410 85 : if (!var_hash) return 0;
411 :
412 85 : id = parse_iv(start + 2) - 1;
413 85 : if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
414 0 : return 0;
415 : }
416 :
417 85 : if (*rval != NULL) {
418 85 : zval_ptr_dtor(rval);
419 : }
420 85 : *rval = *rval_ref;
421 85 : (*rval)->refcount++;
422 85 : (*rval)->is_ref = 1;
423 :
424 85 : return 1;
425 : }
426 :
427 : "r:" iv ";" {
428 : long id;
429 :
430 10 : *p = YYCURSOR;
431 10 : if (!var_hash) return 0;
432 :
433 10 : id = parse_iv(start + 2) - 1;
434 10 : if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
435 0 : return 0;
436 : }
437 :
438 10 : if (*rval == *rval_ref) return 0;
439 :
440 10 : if (*rval != NULL) {
441 10 : zval_ptr_dtor(rval);
442 : }
443 10 : *rval = *rval_ref;
444 10 : (*rval)->refcount++;
445 10 : (*rval)->is_ref = 0;
446 :
447 10 : return 1;
448 : }
449 :
450 : "N;" {
451 53 : *p = YYCURSOR;
452 53 : INIT_PZVAL(*rval);
453 53 : ZVAL_NULL(*rval);
454 53 : return 1;
455 : }
456 :
457 : "b:" [01] ";" {
458 32 : *p = YYCURSOR;
459 32 : INIT_PZVAL(*rval);
460 32 : ZVAL_BOOL(*rval, parse_iv(start + 2));
461 32 : return 1;
462 : }
463 :
464 : "i:" iv ";" {
465 : #if SIZEOF_LONG == 4
466 635 : int digits = YYCURSOR - start - 3;
467 :
468 635 : if (start[2] == '-' || start[2] == '+') {
469 10 : digits--;
470 : }
471 :
472 : /* Use double for large long values that were serialized on a 64-bit system */
473 635 : if (digits >= MAX_LENGTH_OF_LONG - 1) {
474 8 : if (digits == MAX_LENGTH_OF_LONG - 1) {
475 8 : int cmp = strncmp(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
476 :
477 8 : if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
478 : goto use_double;
479 : }
480 : } else {
481 0 : goto use_double;
482 : }
483 : }
484 : #endif
485 634 : *p = YYCURSOR;
486 634 : INIT_PZVAL(*rval);
487 634 : ZVAL_LONG(*rval, parse_iv(start + 2));
488 634 : return 1;
489 : }
490 :
491 : "d:" ("NAN" | "-"? "INF") ";" {
492 3 : *p = YYCURSOR;
493 3 : INIT_PZVAL(*rval);
494 :
495 3 : if (!strncmp(start + 2, "NAN", 3)) {
496 1 : ZVAL_DOUBLE(*rval, php_get_nan());
497 2 : } else if (!strncmp(start + 2, "INF", 3)) {
498 1 : ZVAL_DOUBLE(*rval, php_get_inf());
499 1 : } else if (!strncmp(start + 2, "-INF", 4)) {
500 1 : ZVAL_DOUBLE(*rval, -php_get_inf());
501 : }
502 :
503 3 : return 1;
504 : }
505 :
506 : "d:" (iv | nv | nvexp) ";" {
507 : #if SIZEOF_LONG == 4
508 49 : use_double:
509 : #endif
510 49 : *p = YYCURSOR;
511 49 : INIT_PZVAL(*rval);
512 49 : ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
513 49 : return 1;
514 : }
515 :
516 : "s:" uiv ":" ["] {
517 : size_t len, maxlen;
518 : char *str;
519 :
520 532 : len = parse_uiv(start + 2);
521 532 : maxlen = max - YYCURSOR;
522 532 : if (maxlen < len) {
523 3 : *p = start + 2;
524 3 : return 0;
525 : }
526 :
527 529 : str = (char*)YYCURSOR;
528 :
529 529 : YYCURSOR += len;
530 :
531 529 : if (*(YYCURSOR) != '"') {
532 2 : *p = YYCURSOR;
533 2 : return 0;
534 : }
535 :
536 527 : YYCURSOR += 2;
537 527 : *p = YYCURSOR;
538 :
539 527 : INIT_PZVAL(*rval);
540 527 : ZVAL_STRINGL(*rval, str, len, 1);
541 527 : return 1;
542 : }
543 :
544 : "S:" uiv ":" ["] {
545 : size_t len, maxlen;
546 : char *str;
547 :
548 1 : len = parse_uiv(start + 2);
549 1 : maxlen = max - YYCURSOR;
550 1 : if (maxlen < len) {
551 0 : *p = start + 2;
552 0 : return 0;
553 : }
554 :
555 1 : if ((str = unserialize_str(&YYCURSOR, &len, maxlen)) == NULL) {
556 1 : return 0;
557 : }
558 :
559 0 : if (*(YYCURSOR) != '"') {
560 0 : efree(str);
561 0 : *p = YYCURSOR;
562 0 : return 0;
563 : }
564 :
565 0 : YYCURSOR += 2;
566 0 : *p = YYCURSOR;
567 :
568 0 : INIT_PZVAL(*rval);
569 0 : ZVAL_STRINGL(*rval, str, len, 0);
570 0 : return 1;
571 : }
572 :
573 : "a:" uiv ":" "{" {
574 166 : long elements = parse_iv(start + 2);
575 : /* use iv() not uiv() in order to check data range */
576 166 : *p = YYCURSOR;
577 :
578 166 : if (elements < 0) {
579 0 : return 0;
580 : }
581 :
582 166 : INIT_PZVAL(*rval);
583 166 : Z_TYPE_PP(rval) = IS_ARRAY;
584 166 : ALLOC_HASHTABLE(Z_ARRVAL_PP(rval));
585 :
586 166 : zend_hash_init(Z_ARRVAL_PP(rval), elements + 1, NULL, ZVAL_PTR_DTOR, 0);
587 :
588 166 : if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements)) {
589 28 : return 0;
590 : }
591 :
592 138 : return finish_nested_data(UNSERIALIZE_PASSTHRU);
593 : }
594 :
595 : "o:" iv ":" ["] {
596 :
597 0 : INIT_PZVAL(*rval);
598 :
599 0 : return object_common2(UNSERIALIZE_PASSTHRU,
600 : object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
601 : }
602 :
603 : object ":" uiv ":" ["] {
604 : size_t len, len2, len3, maxlen;
605 : long elements;
606 : char *class_name;
607 : zend_class_entry *ce;
608 : zend_class_entry **pce;
609 131 : int incomplete_class = 0;
610 :
611 131 : int custom_object = 0;
612 :
613 : zval *user_func;
614 : zval *retval_ptr;
615 : zval **args[1];
616 : zval *arg_func_name;
617 :
618 131 : if (*start == 'C') {
619 8 : custom_object = 1;
620 : }
621 :
622 131 : INIT_PZVAL(*rval);
623 131 : len2 = len = parse_uiv(start + 2);
624 131 : maxlen = max - YYCURSOR;
625 131 : if (maxlen < len || len == 0) {
626 1 : *p = start + 2;
627 1 : return 0;
628 : }
629 :
630 130 : class_name = (char*)YYCURSOR;
631 :
632 130 : YYCURSOR += len;
633 :
634 130 : if (*(YYCURSOR) != '"') {
635 1 : *p = YYCURSOR;
636 1 : return 0;
637 : }
638 129 : if (*(YYCURSOR+1) != ':') {
639 1 : *p = YYCURSOR+1;
640 1 : return 0;
641 : }
642 :
643 128 : 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");
644 128 : if (len3 != len)
645 : {
646 0 : *p = YYCURSOR + len3 - len;
647 0 : return 0;
648 : }
649 :
650 128 : class_name = estrndup(class_name, len);
651 :
652 : do {
653 : /* Try to find class directly */
654 128 : if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
655 112 : ce = *pce;
656 112 : break;
657 : }
658 :
659 : /* Check for unserialize callback */
660 16 : if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
661 8 : incomplete_class = 1;
662 8 : ce = PHP_IC_ENTRY;
663 8 : break;
664 : }
665 :
666 : /* Call unserialize callback */
667 8 : MAKE_STD_ZVAL(user_func);
668 8 : ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
669 8 : args[0] = &arg_func_name;
670 8 : MAKE_STD_ZVAL(arg_func_name);
671 8 : ZVAL_STRING(arg_func_name, class_name, 1);
672 8 : if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
673 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
674 1 : incomplete_class = 1;
675 1 : ce = PHP_IC_ENTRY;
676 1 : zval_ptr_dtor(&user_func);
677 1 : zval_ptr_dtor(&arg_func_name);
678 1 : break;
679 : }
680 7 : if (retval_ptr) {
681 6 : zval_ptr_dtor(&retval_ptr);
682 : }
683 :
684 : /* The callback function may have defined the class */
685 7 : if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
686 4 : ce = *pce;
687 : } else {
688 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);
689 3 : incomplete_class = 1;
690 3 : ce = PHP_IC_ENTRY;
691 : }
692 :
693 7 : zval_ptr_dtor(&user_func);
694 7 : zval_ptr_dtor(&arg_func_name);
695 7 : break;
696 : } while (1);
697 :
698 128 : *p = YYCURSOR;
699 :
700 128 : if (custom_object) {
701 8 : efree(class_name);
702 8 : return object_custom(UNSERIALIZE_PASSTHRU, ce);
703 : }
704 :
705 120 : elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
706 :
707 120 : if (incomplete_class) {
708 11 : php_store_class_name(*rval, class_name, len2);
709 : }
710 120 : efree(class_name);
711 :
712 120 : return object_common2(UNSERIALIZE_PASSTHRU, elements);
713 : }
714 :
715 : "}" {
716 : /* this is the case where we have less data than planned */
717 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
718 0 : return 0; /* not sure if it should be 0 or 1 here? */
719 : }
720 :
721 41 : any { return 0; }
722 :
723 : */
724 :
725 : return 0;
726 : }
|