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