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