1 /* Generated by re2c 1.0.1 */
2 #line 1 "ext/standard/var_unserializer.re"
3 /*
4 +----------------------------------------------------------------------+
5 | PHP Version 7 |
6 +----------------------------------------------------------------------+
7 | Copyright (c) 1997-2018 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_portability.h"
27
28 struct php_unserialize_data {
29 void *first;
30 void *last;
31 void *first_dtor;
32 void *last_dtor;
33 HashTable *allowed_classes;
34 };
35
php_var_unserialize_init()36 PHPAPI php_unserialize_data_t php_var_unserialize_init() {
37 php_unserialize_data_t d;
38 /* fprintf(stderr, "UNSERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
39 if (BG(serialize_lock) || !BG(unserialize).level) {
40 d = ecalloc(1, sizeof(struct php_unserialize_data));
41 if (!BG(serialize_lock)) {
42 BG(unserialize).data = d;
43 BG(unserialize).level = 1;
44 }
45 } else {
46 d = BG(unserialize).data;
47 ++BG(unserialize).level;
48 }
49 return d;
50 }
51
php_var_unserialize_destroy(php_unserialize_data_t d)52 PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
53 /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
54 if (BG(serialize_lock) || BG(unserialize).level == 1) {
55 var_destroy(&d);
56 efree(d);
57 }
58 if (!BG(serialize_lock) && !--BG(unserialize).level) {
59 BG(unserialize).data = NULL;
60 }
61 }
62
php_var_unserialize_get_allowed_classes(php_unserialize_data_t d)63 PHPAPI HashTable *php_var_unserialize_get_allowed_classes(php_unserialize_data_t d) {
64 return d->allowed_classes;
65 }
php_var_unserialize_set_allowed_classes(php_unserialize_data_t d,HashTable * classes)66 PHPAPI void php_var_unserialize_set_allowed_classes(php_unserialize_data_t d, HashTable *classes) {
67 d->allowed_classes = classes;
68 }
69
70
71 /* {{{ reference-handling for unserializer: var_* */
72 #define VAR_ENTRIES_MAX 1024
73 #define VAR_ENTRIES_DBG 0
74
75 /* VAR_FLAG used in var_dtor entries to signify an entry on which __wakeup should be called */
76 #define VAR_WAKEUP_FLAG 1
77
78 typedef struct {
79 zval *data[VAR_ENTRIES_MAX];
80 zend_long used_slots;
81 void *next;
82 } var_entries;
83
84 typedef struct {
85 zval data[VAR_ENTRIES_MAX];
86 zend_long used_slots;
87 void *next;
88 } var_dtor_entries;
89
var_push(php_unserialize_data_t * var_hashx,zval * rval)90 static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
91 {
92 var_entries *var_hash = (*var_hashx)->last;
93 #if VAR_ENTRIES_DBG
94 fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval));
95 #endif
96
97 if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
98 var_hash = emalloc(sizeof(var_entries));
99 var_hash->used_slots = 0;
100 var_hash->next = 0;
101
102 if (!(*var_hashx)->first) {
103 (*var_hashx)->first = var_hash;
104 } else {
105 ((var_entries *) (*var_hashx)->last)->next = var_hash;
106 }
107
108 (*var_hashx)->last = var_hash;
109 }
110
111 var_hash->data[var_hash->used_slots++] = rval;
112 }
113
var_push_dtor(php_unserialize_data_t * var_hashx,zval * rval)114 PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
115 {
116 zval *tmp_var = var_tmp_var(var_hashx);
117 if (!tmp_var) {
118 return;
119 }
120 ZVAL_COPY(tmp_var, rval);
121 }
122
var_tmp_var(php_unserialize_data_t * var_hashx)123 PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
124 {
125 var_dtor_entries *var_hash;
126
127 if (!var_hashx || !*var_hashx) {
128 return NULL;
129 }
130
131 var_hash = (*var_hashx)->last_dtor;
132 if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
133 var_hash = emalloc(sizeof(var_dtor_entries));
134 var_hash->used_slots = 0;
135 var_hash->next = 0;
136
137 if (!(*var_hashx)->first_dtor) {
138 (*var_hashx)->first_dtor = var_hash;
139 } else {
140 ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
141 }
142
143 (*var_hashx)->last_dtor = var_hash;
144 }
145 ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]);
146 Z_EXTRA(var_hash->data[var_hash->used_slots]) = 0;
147 return &var_hash->data[var_hash->used_slots++];
148 }
149
var_replace(php_unserialize_data_t * var_hashx,zval * ozval,zval * nzval)150 PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
151 {
152 zend_long i;
153 var_entries *var_hash = (*var_hashx)->first;
154 #if VAR_ENTRIES_DBG
155 fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(nzval));
156 #endif
157
158 while (var_hash) {
159 for (i = 0; i < var_hash->used_slots; i++) {
160 if (var_hash->data[i] == ozval) {
161 var_hash->data[i] = nzval;
162 /* do not break here */
163 }
164 }
165 var_hash = var_hash->next;
166 }
167 }
168
var_access(php_unserialize_data_t * var_hashx,zend_long id)169 static zval *var_access(php_unserialize_data_t *var_hashx, zend_long id)
170 {
171 var_entries *var_hash = (*var_hashx)->first;
172 #if VAR_ENTRIES_DBG
173 fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
174 #endif
175
176 while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
177 var_hash = var_hash->next;
178 id -= VAR_ENTRIES_MAX;
179 }
180
181 if (!var_hash) return NULL;
182
183 if (id < 0 || id >= var_hash->used_slots) return NULL;
184
185 return var_hash->data[id];
186 }
187
var_destroy(php_unserialize_data_t * var_hashx)188 PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
189 {
190 void *next;
191 zend_long i;
192 var_entries *var_hash = (*var_hashx)->first;
193 var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
194 zend_bool wakeup_failed = 0;
195 zval wakeup_name;
196 ZVAL_UNDEF(&wakeup_name);
197
198 #if VAR_ENTRIES_DBG
199 fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
200 #endif
201
202 while (var_hash) {
203 next = var_hash->next;
204 efree_size(var_hash, sizeof(var_entries));
205 var_hash = next;
206 }
207
208 while (var_dtor_hash) {
209 for (i = 0; i < var_dtor_hash->used_slots; i++) {
210 zval *zv = &var_dtor_hash->data[i];
211 #if VAR_ENTRIES_DBG
212 fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
213 #endif
214
215 /* Perform delayed __wakeup calls */
216 if (Z_EXTRA_P(zv) == VAR_WAKEUP_FLAG) {
217 if (!wakeup_failed) {
218 zval retval;
219 if (Z_ISUNDEF(wakeup_name)) {
220 ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1);
221 }
222
223 BG(serialize_lock)++;
224 if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
225 wakeup_failed = 1;
226 GC_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED;
227 }
228 BG(serialize_lock)--;
229
230 zval_ptr_dtor(&retval);
231 } else {
232 GC_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED;
233 }
234 }
235
236 i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC);
237 }
238 next = var_dtor_hash->next;
239 efree_size(var_dtor_hash, sizeof(var_dtor_entries));
240 var_dtor_hash = next;
241 }
242
243 zval_ptr_dtor_nogc(&wakeup_name);
244 }
245
246 /* }}} */
247
unserialize_str(const unsigned char ** p,size_t len,size_t maxlen)248 static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen)
249 {
250 size_t i, j;
251 zend_string *str = zend_string_safe_alloc(1, len, 0, 0);
252 unsigned char *end = *(unsigned char **)p+maxlen;
253
254 if (end < *p) {
255 zend_string_free(str);
256 return NULL;
257 }
258
259 for (i = 0; i < len; i++) {
260 if (*p >= end) {
261 zend_string_free(str);
262 return NULL;
263 }
264 if (**p != '\\') {
265 ZSTR_VAL(str)[i] = (char)**p;
266 } else {
267 unsigned char ch = 0;
268
269 for (j = 0; j < 2; j++) {
270 (*p)++;
271 if (**p >= '0' && **p <= '9') {
272 ch = (ch << 4) + (**p -'0');
273 } else if (**p >= 'a' && **p <= 'f') {
274 ch = (ch << 4) + (**p -'a'+10);
275 } else if (**p >= 'A' && **p <= 'F') {
276 ch = (ch << 4) + (**p -'A'+10);
277 } else {
278 zend_string_free(str);
279 return NULL;
280 }
281 }
282 ZSTR_VAL(str)[i] = (char)ch;
283 }
284 (*p)++;
285 }
286 ZSTR_VAL(str)[i] = 0;
287 ZSTR_LEN(str) = i;
288 return str;
289 }
290
unserialize_allowed_class(zend_string * class_name,php_unserialize_data_t * var_hashx)291 static inline int unserialize_allowed_class(
292 zend_string *class_name, php_unserialize_data_t *var_hashx)
293 {
294 HashTable *classes = (*var_hashx)->allowed_classes;
295 zend_string *lcname;
296 int res;
297 ALLOCA_FLAG(use_heap)
298
299 if(classes == NULL) {
300 return 1;
301 }
302 if(!zend_hash_num_elements(classes)) {
303 return 0;
304 }
305
306 ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap);
307 zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
308 res = zend_hash_exists(classes, lcname);
309 ZSTR_ALLOCA_FREE(lcname, use_heap);
310 return res;
311 }
312
313 #define YYFILL(n) do { } while (0)
314 #define YYCTYPE unsigned char
315 #define YYCURSOR cursor
316 #define YYLIMIT limit
317 #define YYMARKER marker
318
319
320 #line 325 "ext/standard/var_unserializer.re"
321
322
323
324
parse_iv2(const unsigned char * p,const unsigned char ** q)325 static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **q)
326 {
327 zend_long result = 0;
328 char *end;
329
330 errno = 0;
331 result = ZEND_STRTOL((const char*)p, &end, 0);
332
333 if (q) {
334 *q = (const unsigned char *)end;
335 }
336
337 if (errno) {
338 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
339 return result;
340 }
341
342 return result;
343 }
344
parse_iv(const unsigned char * p)345 static inline zend_long parse_iv(const unsigned char *p)
346 {
347 return parse_iv2(p, NULL);
348 }
349
350 /* no need to check for length - re2c already did */
parse_uiv(const unsigned char * p)351 static inline size_t parse_uiv(const unsigned char *p)
352 {
353 unsigned char cursor;
354 size_t result = 0;
355
356 while (1) {
357 cursor = *p;
358 if (cursor >= '0' && cursor <= '9') {
359 result = result * 10 + (size_t)(cursor - (unsigned char)'0');
360 } else {
361 break;
362 }
363 p++;
364 }
365 return result;
366 }
367
368 #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash
369 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash
370
371 static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
372
process_nested_data(UNSERIALIZE_PARAMETER,HashTable * ht,zend_long elements,int objprops)373 static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
374 {
375 while (elements-- > 0) {
376 zval key, *data, d, *old_data;
377 zend_ulong idx;
378
379 ZVAL_UNDEF(&key);
380
381 if (!php_var_unserialize_internal(&key, p, max, NULL)) {
382 zval_ptr_dtor(&key);
383 return 0;
384 }
385
386 data = NULL;
387 ZVAL_UNDEF(&d);
388
389 if (!objprops) {
390 if (Z_TYPE(key) == IS_LONG) {
391 idx = Z_LVAL(key);
392 numeric_key:
393 if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
394 //??? update hash
395 var_push_dtor(var_hash, old_data);
396 data = zend_hash_index_update(ht, idx, &d);
397 } else {
398 data = zend_hash_index_add_new(ht, idx, &d);
399 }
400 } else if (Z_TYPE(key) == IS_STRING) {
401 if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
402 goto numeric_key;
403 }
404 if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
405 //??? update hash
406 var_push_dtor(var_hash, old_data);
407 data = zend_hash_update(ht, Z_STR(key), &d);
408 } else {
409 data = zend_hash_add_new(ht, Z_STR(key), &d);
410 }
411 } else {
412 zval_ptr_dtor(&key);
413 return 0;
414 }
415 } else {
416 if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
417 string_key:
418 {
419 zend_property_info *existing_propinfo;
420 zend_string *new_key, *unmangled;
421 const char *unmangled_class = NULL;
422 const char *unmangled_prop;
423 size_t unmangled_prop_len;
424
425 if (UNEXPECTED(zend_unmangle_property_name_ex(Z_STR(key), &unmangled_class, &unmangled_prop, &unmangled_prop_len) == FAILURE)) {
426 zval_ptr_dtor(&key);
427 return 0;
428 }
429
430 unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);
431 if (Z_TYPE_P(rval) == IS_OBJECT
432 && (unmangled_class == NULL || !strcmp(unmangled_class, "*") || !strcasecmp(unmangled_class, ZSTR_VAL(Z_OBJCE_P(rval)->name)))
433 && ((existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled)) != NULL)
434 && (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) {
435 if (existing_propinfo->flags & ZEND_ACC_PROTECTED) {
436 new_key = zend_mangle_property_name(
437 "*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), Z_OBJCE_P(rval)->type & ZEND_INTERNAL_CLASS);
438 zend_string_release(unmangled);
439 } else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) {
440 if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) {
441 new_key = zend_mangle_property_name(
442 unmangled_class, strlen(unmangled_class),
443 ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
444 Z_OBJCE_P(rval)->type & ZEND_INTERNAL_CLASS);
445 } else {
446 new_key = zend_mangle_property_name(
447 ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name),
448 ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
449 Z_OBJCE_P(rval)->type & ZEND_INTERNAL_CLASS);
450 }
451 zend_string_release(unmangled);
452 } else {
453 ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
454 new_key = unmangled;
455 }
456 zend_string_release(Z_STR(key));
457 ZVAL_STR(&key, new_key);
458 } else {
459 zend_string_release(unmangled);
460 }
461
462 if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
463 if (Z_TYPE_P(old_data) == IS_INDIRECT) {
464 old_data = Z_INDIRECT_P(old_data);
465 }
466 var_push_dtor(var_hash, old_data);
467 data = zend_hash_update_ind(ht, Z_STR(key), &d);
468 } else {
469 data = zend_hash_add_new(ht, Z_STR(key), &d);
470 }
471 }
472 } else if (Z_TYPE(key) == IS_LONG) {
473 /* object properties should include no integers */
474 convert_to_string(&key);
475 goto string_key;
476 } else {
477 zval_ptr_dtor(&key);
478 return 0;
479 }
480 }
481
482 if (!php_var_unserialize_internal(data, p, max, var_hash)) {
483 zval_ptr_dtor(&key);
484 return 0;
485 }
486
487 var_push_dtor(var_hash, data);
488 zval_ptr_dtor(&key);
489
490 if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
491 (*p)--;
492 return 0;
493 }
494 }
495
496 return 1;
497 }
498
finish_nested_data(UNSERIALIZE_PARAMETER)499 static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
500 {
501 if (*p >= max || **p != '}') {
502 return 0;
503 }
504
505 (*p)++;
506 return 1;
507 }
508
object_custom(UNSERIALIZE_PARAMETER,zend_class_entry * ce)509 static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
510 {
511 zend_long datalen;
512
513 datalen = parse_iv2((*p) + 2, p);
514
515 (*p) += 2;
516
517 if (datalen < 0 || (max - (*p)) <= datalen) {
518 zend_error(E_WARNING, "Insufficient data for unserializing - " ZEND_LONG_FMT " required, " ZEND_LONG_FMT " present", datalen, (zend_long)(max - (*p)));
519 return 0;
520 }
521
522 /* Check that '}' is present before calling ce->unserialize() to mitigate issues
523 * with unserialize reading past the end of the passed buffer if the string is not
524 * appropriately terminated (usually NUL terminated, but '}' is also sufficient.) */
525 if ((*p)[datalen] != '}') {
526 return 0;
527 }
528
529 if (ce->unserialize == NULL) {
530 zend_error(E_WARNING, "Class %s has no unserializer", ZSTR_VAL(ce->name));
531 object_init_ex(rval, ce);
532 } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
533 return 0;
534 }
535
536 (*p) += datalen + 1; /* +1 for '}' */
537 return 1;
538 }
539
object_common1(UNSERIALIZE_PARAMETER,zend_class_entry * ce)540 static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
541 {
542 zend_long elements;
543
544 if( *p >= max - 2) {
545 zend_error(E_WARNING, "Bad unserialize data");
546 return -1;
547 }
548
549 elements = parse_iv2((*p) + 2, p);
550
551 (*p) += 2;
552
553 if (ce->serialize == NULL) {
554 object_init_ex(rval, ce);
555 } else {
556 /* If this class implements Serializable, it should not land here but in object_custom(). The passed string
557 obviously doesn't descend from the regular serializer. */
558 zend_error(E_WARNING, "Erroneous data format for unserializing '%s'", ZSTR_VAL(ce->name));
559 return -1;
560 }
561
562 return elements;
563 }
564
565 #ifdef PHP_WIN32
566 # pragma optimize("", off)
567 #endif
object_common2(UNSERIALIZE_PARAMETER,zend_long elements)568 static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
569 {
570 HashTable *ht;
571 zend_bool has_wakeup;
572
573 if (Z_TYPE_P(rval) != IS_OBJECT) {
574 return 0;
575 }
576
577 has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
578 && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
579
580 ht = Z_OBJPROP_P(rval);
581 if (elements >= HT_MAX_SIZE - zend_hash_num_elements(ht)) {
582 return 0;
583 }
584
585 zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
586 if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
587 if (has_wakeup) {
588 ZVAL_DEREF(rval);
589 GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
590 }
591 return 0;
592 }
593
594 ZVAL_DEREF(rval);
595 if (has_wakeup) {
596 /* Delay __wakeup call until end of serialization */
597 zval *wakeup_var = var_tmp_var(var_hash);
598 ZVAL_COPY(wakeup_var, rval);
599 Z_EXTRA_P(wakeup_var) = VAR_WAKEUP_FLAG;
600 }
601
602 return finish_nested_data(UNSERIALIZE_PASSTHRU);
603 }
604 #ifdef PHP_WIN32
605 # pragma optimize("", on)
606 #endif
607
php_var_unserialize(UNSERIALIZE_PARAMETER)608 PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
609 {
610 var_entries *orig_var_entries = (*var_hash)->last;
611 zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
612 int result;
613
614 result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
615
616 if (!result) {
617 /* If the unserialization failed, mark all elements that have been added to var_hash
618 * as NULL. This will forbid their use by other unserialize() calls in the same
619 * unserialization context. */
620 var_entries *e = orig_var_entries;
621 zend_long s = orig_used_slots;
622 while (e) {
623 for (; s < e->used_slots; s++) {
624 e->data[s] = NULL;
625 }
626
627 e = e->next;
628 s = 0;
629 }
630 }
631
632 return result;
633 }
634
php_var_unserialize_internal(UNSERIALIZE_PARAMETER)635 static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
636 {
637 const unsigned char *cursor, *limit, *marker, *start;
638 zval *rval_ref;
639
640 limit = max;
641 cursor = *p;
642
643 if (YYCURSOR >= YYLIMIT) {
644 return 0;
645 }
646
647 if (var_hash && (*p)[0] != 'R') {
648 var_push(var_hash, rval);
649 }
650
651 start = cursor;
652
653
654 #line 655 "ext/standard/var_unserializer.c"
655 {
656 YYCTYPE yych;
657 static const unsigned char yybm[] = {
658 0, 0, 0, 0, 0, 0, 0, 0,
659 0, 0, 0, 0, 0, 0, 0, 0,
660 0, 0, 0, 0, 0, 0, 0, 0,
661 0, 0, 0, 0, 0, 0, 0, 0,
662 0, 0, 0, 0, 0, 0, 0, 0,
663 0, 0, 0, 0, 0, 0, 0, 0,
664 128, 128, 128, 128, 128, 128, 128, 128,
665 128, 128, 0, 0, 0, 0, 0, 0,
666 0, 0, 0, 0, 0, 0, 0, 0,
667 0, 0, 0, 0, 0, 0, 0, 0,
668 0, 0, 0, 0, 0, 0, 0, 0,
669 0, 0, 0, 0, 0, 0, 0, 0,
670 0, 0, 0, 0, 0, 0, 0, 0,
671 0, 0, 0, 0, 0, 0, 0, 0,
672 0, 0, 0, 0, 0, 0, 0, 0,
673 0, 0, 0, 0, 0, 0, 0, 0,
674 0, 0, 0, 0, 0, 0, 0, 0,
675 0, 0, 0, 0, 0, 0, 0, 0,
676 0, 0, 0, 0, 0, 0, 0, 0,
677 0, 0, 0, 0, 0, 0, 0, 0,
678 0, 0, 0, 0, 0, 0, 0, 0,
679 0, 0, 0, 0, 0, 0, 0, 0,
680 0, 0, 0, 0, 0, 0, 0, 0,
681 0, 0, 0, 0, 0, 0, 0, 0,
682 0, 0, 0, 0, 0, 0, 0, 0,
683 0, 0, 0, 0, 0, 0, 0, 0,
684 0, 0, 0, 0, 0, 0, 0, 0,
685 0, 0, 0, 0, 0, 0, 0, 0,
686 0, 0, 0, 0, 0, 0, 0, 0,
687 0, 0, 0, 0, 0, 0, 0, 0,
688 0, 0, 0, 0, 0, 0, 0, 0,
689 0, 0, 0, 0, 0, 0, 0, 0,
690 };
691 if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
692 yych = *YYCURSOR;
693 switch (yych) {
694 case 'C':
695 case 'O': goto yy4;
696 case 'N': goto yy5;
697 case 'R': goto yy6;
698 case 'S': goto yy7;
699 case 'a': goto yy8;
700 case 'b': goto yy9;
701 case 'd': goto yy10;
702 case 'i': goto yy11;
703 case 'o': goto yy12;
704 case 'r': goto yy13;
705 case 's': goto yy14;
706 case '}': goto yy15;
707 default: goto yy2;
708 }
709 yy2:
710 ++YYCURSOR;
711 yy3:
712 #line 1042 "ext/standard/var_unserializer.re"
713 { return 0; }
714 #line 715 "ext/standard/var_unserializer.c"
715 yy4:
716 yych = *(YYMARKER = ++YYCURSOR);
717 if (yych == ':') goto yy17;
718 goto yy3;
719 yy5:
720 yych = *++YYCURSOR;
721 if (yych == ';') goto yy19;
722 goto yy3;
723 yy6:
724 yych = *(YYMARKER = ++YYCURSOR);
725 if (yych == ':') goto yy21;
726 goto yy3;
727 yy7:
728 yych = *(YYMARKER = ++YYCURSOR);
729 if (yych == ':') goto yy22;
730 goto yy3;
731 yy8:
732 yych = *(YYMARKER = ++YYCURSOR);
733 if (yych == ':') goto yy23;
734 goto yy3;
735 yy9:
736 yych = *(YYMARKER = ++YYCURSOR);
737 if (yych == ':') goto yy24;
738 goto yy3;
739 yy10:
740 yych = *(YYMARKER = ++YYCURSOR);
741 if (yych == ':') goto yy25;
742 goto yy3;
743 yy11:
744 yych = *(YYMARKER = ++YYCURSOR);
745 if (yych == ':') goto yy26;
746 goto yy3;
747 yy12:
748 yych = *(YYMARKER = ++YYCURSOR);
749 if (yych == ':') goto yy27;
750 goto yy3;
751 yy13:
752 yych = *(YYMARKER = ++YYCURSOR);
753 if (yych == ':') goto yy28;
754 goto yy3;
755 yy14:
756 yych = *(YYMARKER = ++YYCURSOR);
757 if (yych == ':') goto yy29;
758 goto yy3;
759 yy15:
760 ++YYCURSOR;
761 #line 1036 "ext/standard/var_unserializer.re"
762 {
763 /* this is the case where we have less data than planned */
764 php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
765 return 0; /* not sure if it should be 0 or 1 here? */
766 }
767 #line 768 "ext/standard/var_unserializer.c"
768 yy17:
769 yych = *++YYCURSOR;
770 if (yybm[0+yych] & 128) {
771 goto yy30;
772 }
773 yy18:
774 YYCURSOR = YYMARKER;
775 goto yy3;
776 yy19:
777 ++YYCURSOR;
778 #line 708 "ext/standard/var_unserializer.re"
779 {
780 *p = YYCURSOR;
781 ZVAL_NULL(rval);
782 return 1;
783 }
784 #line 785 "ext/standard/var_unserializer.c"
785 yy21:
786 yych = *++YYCURSOR;
787 if (yych <= '/') goto yy18;
788 if (yych <= '9') goto yy32;
789 goto yy18;
790 yy22:
791 yych = *++YYCURSOR;
792 if (yych <= '/') goto yy18;
793 if (yych <= '9') goto yy34;
794 goto yy18;
795 yy23:
796 yych = *++YYCURSOR;
797 if (yych <= '/') goto yy18;
798 if (yych <= '9') goto yy36;
799 goto yy18;
800 yy24:
801 yych = *++YYCURSOR;
802 if (yych <= '/') goto yy18;
803 if (yych <= '1') goto yy38;
804 goto yy18;
805 yy25:
806 yych = *++YYCURSOR;
807 if (yych <= '/') {
808 if (yych <= ',') {
809 if (yych == '+') goto yy39;
810 goto yy18;
811 } else {
812 if (yych <= '-') goto yy40;
813 if (yych <= '.') goto yy41;
814 goto yy18;
815 }
816 } else {
817 if (yych <= 'I') {
818 if (yych <= '9') goto yy42;
819 if (yych <= 'H') goto yy18;
820 goto yy44;
821 } else {
822 if (yych == 'N') goto yy45;
823 goto yy18;
824 }
825 }
826 yy26:
827 yych = *++YYCURSOR;
828 if (yych <= ',') {
829 if (yych == '+') goto yy46;
830 goto yy18;
831 } else {
832 if (yych <= '-') goto yy46;
833 if (yych <= '/') goto yy18;
834 if (yych <= '9') goto yy47;
835 goto yy18;
836 }
837 yy27:
838 yych = *++YYCURSOR;
839 if (yych <= '/') goto yy18;
840 if (yych <= '9') goto yy49;
841 goto yy18;
842 yy28:
843 yych = *++YYCURSOR;
844 if (yych <= '/') goto yy18;
845 if (yych <= '9') goto yy51;
846 goto yy18;
847 yy29:
848 yych = *++YYCURSOR;
849 if (yych <= '/') goto yy18;
850 if (yych <= '9') goto yy53;
851 goto yy18;
852 yy30:
853 ++YYCURSOR;
854 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
855 yych = *YYCURSOR;
856 if (yybm[0+yych] & 128) {
857 goto yy30;
858 }
859 if (yych <= '/') goto yy18;
860 if (yych <= ':') goto yy55;
861 goto yy18;
862 yy32:
863 ++YYCURSOR;
864 if (YYLIMIT <= YYCURSOR) YYFILL(1);
865 yych = *YYCURSOR;
866 if (yych <= '/') goto yy18;
867 if (yych <= '9') goto yy32;
868 if (yych == ';') goto yy56;
869 goto yy18;
870 yy34:
871 ++YYCURSOR;
872 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
873 yych = *YYCURSOR;
874 if (yych <= '/') goto yy18;
875 if (yych <= '9') goto yy34;
876 if (yych <= ':') goto yy58;
877 goto yy18;
878 yy36:
879 ++YYCURSOR;
880 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
881 yych = *YYCURSOR;
882 if (yych <= '/') goto yy18;
883 if (yych <= '9') goto yy36;
884 if (yych <= ':') goto yy59;
885 goto yy18;
886 yy38:
887 yych = *++YYCURSOR;
888 if (yych == ';') goto yy60;
889 goto yy18;
890 yy39:
891 yych = *++YYCURSOR;
892 if (yych == '.') goto yy41;
893 if (yych <= '/') goto yy18;
894 if (yych <= '9') goto yy42;
895 goto yy18;
896 yy40:
897 yych = *++YYCURSOR;
898 if (yych <= '/') {
899 if (yych != '.') goto yy18;
900 } else {
901 if (yych <= '9') goto yy42;
902 if (yych == 'I') goto yy44;
903 goto yy18;
904 }
905 yy41:
906 yych = *++YYCURSOR;
907 if (yych <= '/') goto yy18;
908 if (yych <= '9') goto yy62;
909 goto yy18;
910 yy42:
911 ++YYCURSOR;
912 if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
913 yych = *YYCURSOR;
914 if (yych <= ':') {
915 if (yych <= '.') {
916 if (yych <= '-') goto yy18;
917 goto yy62;
918 } else {
919 if (yych <= '/') goto yy18;
920 if (yych <= '9') goto yy42;
921 goto yy18;
922 }
923 } else {
924 if (yych <= 'E') {
925 if (yych <= ';') goto yy64;
926 if (yych <= 'D') goto yy18;
927 goto yy66;
928 } else {
929 if (yych == 'e') goto yy66;
930 goto yy18;
931 }
932 }
933 yy44:
934 yych = *++YYCURSOR;
935 if (yych == 'N') goto yy67;
936 goto yy18;
937 yy45:
938 yych = *++YYCURSOR;
939 if (yych == 'A') goto yy68;
940 goto yy18;
941 yy46:
942 yych = *++YYCURSOR;
943 if (yych <= '/') goto yy18;
944 if (yych >= ':') goto yy18;
945 yy47:
946 ++YYCURSOR;
947 if (YYLIMIT <= YYCURSOR) YYFILL(1);
948 yych = *YYCURSOR;
949 if (yych <= '/') goto yy18;
950 if (yych <= '9') goto yy47;
951 if (yych == ';') goto yy69;
952 goto yy18;
953 yy49:
954 ++YYCURSOR;
955 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
956 yych = *YYCURSOR;
957 if (yych <= '/') goto yy18;
958 if (yych <= '9') goto yy49;
959 if (yych <= ':') goto yy71;
960 goto yy18;
961 yy51:
962 ++YYCURSOR;
963 if (YYLIMIT <= YYCURSOR) YYFILL(1);
964 yych = *YYCURSOR;
965 if (yych <= '/') goto yy18;
966 if (yych <= '9') goto yy51;
967 if (yych == ';') goto yy72;
968 goto yy18;
969 yy53:
970 ++YYCURSOR;
971 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
972 yych = *YYCURSOR;
973 if (yych <= '/') goto yy18;
974 if (yych <= '9') goto yy53;
975 if (yych <= ':') goto yy74;
976 goto yy18;
977 yy55:
978 yych = *++YYCURSOR;
979 if (yych == '"') goto yy75;
980 goto yy18;
981 yy56:
982 ++YYCURSOR;
983 #line 659 "ext/standard/var_unserializer.re"
984 {
985 zend_long id;
986
987 *p = YYCURSOR;
988 if (!var_hash) return 0;
989
990 id = parse_uiv(start + 2) - 1;
991 if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
992 return 0;
993 }
994
995 if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
996 return 0;
997 }
998
999 if (Z_ISREF_P(rval_ref)) {
1000 ZVAL_COPY(rval, rval_ref);
1001 } else {
1002 ZVAL_NEW_REF(rval_ref, rval_ref);
1003 ZVAL_COPY(rval, rval_ref);
1004 }
1005
1006 return 1;
1007 }
1008 #line 1009 "ext/standard/var_unserializer.c"
1009 yy58:
1010 yych = *++YYCURSOR;
1011 if (yych == '"') goto yy77;
1012 goto yy18;
1013 yy59:
1014 yych = *++YYCURSOR;
1015 if (yych == '{') goto yy79;
1016 goto yy18;
1017 yy60:
1018 ++YYCURSOR;
1019 #line 714 "ext/standard/var_unserializer.re"
1020 {
1021 *p = YYCURSOR;
1022 ZVAL_BOOL(rval, parse_iv(start + 2));
1023 return 1;
1024 }
1025 #line 1026 "ext/standard/var_unserializer.c"
1026 yy62:
1027 ++YYCURSOR;
1028 if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
1029 yych = *YYCURSOR;
1030 if (yych <= ';') {
1031 if (yych <= '/') goto yy18;
1032 if (yych <= '9') goto yy62;
1033 if (yych <= ':') goto yy18;
1034 } else {
1035 if (yych <= 'E') {
1036 if (yych <= 'D') goto yy18;
1037 goto yy66;
1038 } else {
1039 if (yych == 'e') goto yy66;
1040 goto yy18;
1041 }
1042 }
1043 yy64:
1044 ++YYCURSOR;
1045 #line 762 "ext/standard/var_unserializer.re"
1046 {
1047 #if SIZEOF_ZEND_LONG == 4
1048 use_double:
1049 #endif
1050 *p = YYCURSOR;
1051 ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
1052 return 1;
1053 }
1054 #line 1055 "ext/standard/var_unserializer.c"
1055 yy66:
1056 yych = *++YYCURSOR;
1057 if (yych <= ',') {
1058 if (yych == '+') goto yy81;
1059 goto yy18;
1060 } else {
1061 if (yych <= '-') goto yy81;
1062 if (yych <= '/') goto yy18;
1063 if (yych <= '9') goto yy82;
1064 goto yy18;
1065 }
1066 yy67:
1067 yych = *++YYCURSOR;
1068 if (yych == 'F') goto yy84;
1069 goto yy18;
1070 yy68:
1071 yych = *++YYCURSOR;
1072 if (yych == 'N') goto yy84;
1073 goto yy18;
1074 yy69:
1075 ++YYCURSOR;
1076 #line 720 "ext/standard/var_unserializer.re"
1077 {
1078 #if SIZEOF_ZEND_LONG == 4
1079 int digits = YYCURSOR - start - 3;
1080
1081 if (start[2] == '-' || start[2] == '+') {
1082 digits--;
1083 }
1084
1085 /* Use double for large zend_long values that were serialized on a 64-bit system */
1086 if (digits >= MAX_LENGTH_OF_LONG - 1) {
1087 if (digits == MAX_LENGTH_OF_LONG - 1) {
1088 int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
1089
1090 if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
1091 goto use_double;
1092 }
1093 } else {
1094 goto use_double;
1095 }
1096 }
1097 #endif
1098 *p = YYCURSOR;
1099 ZVAL_LONG(rval, parse_iv(start + 2));
1100 return 1;
1101 }
1102 #line 1103 "ext/standard/var_unserializer.c"
1103 yy71:
1104 yych = *++YYCURSOR;
1105 if (yych == '"') goto yy85;
1106 goto yy18;
1107 yy72:
1108 ++YYCURSOR;
1109 #line 684 "ext/standard/var_unserializer.re"
1110 {
1111 zend_long id;
1112
1113 *p = YYCURSOR;
1114 if (!var_hash) return 0;
1115
1116 id = parse_uiv(start + 2) - 1;
1117 if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
1118 return 0;
1119 }
1120
1121 if (rval_ref == rval) {
1122 return 0;
1123 }
1124
1125 if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
1126 return 0;
1127 }
1128
1129 ZVAL_COPY(rval, rval_ref);
1130
1131 return 1;
1132 }
1133 #line 1134 "ext/standard/var_unserializer.c"
1134 yy74:
1135 yych = *++YYCURSOR;
1136 if (yych == '"') goto yy87;
1137 goto yy18;
1138 yy75:
1139 ++YYCURSOR;
1140 #line 884 "ext/standard/var_unserializer.re"
1141 {
1142 size_t len, len2, len3, maxlen;
1143 zend_long elements;
1144 char *str;
1145 zend_string *class_name;
1146 zend_class_entry *ce;
1147 int incomplete_class = 0;
1148
1149 int custom_object = 0;
1150
1151 zval user_func;
1152 zval retval;
1153 zval args[1];
1154
1155 if (!var_hash) return 0;
1156 if (*start == 'C') {
1157 custom_object = 1;
1158 }
1159
1160 len2 = len = parse_uiv(start + 2);
1161 maxlen = max - YYCURSOR;
1162 if (maxlen < len || len == 0) {
1163 *p = start + 2;
1164 return 0;
1165 }
1166
1167 str = (char*)YYCURSOR;
1168
1169 YYCURSOR += len;
1170
1171 if (*(YYCURSOR) != '"') {
1172 *p = YYCURSOR;
1173 return 0;
1174 }
1175 if (*(YYCURSOR+1) != ':') {
1176 *p = YYCURSOR+1;
1177 return 0;
1178 }
1179
1180 len3 = strspn(str, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
1181 if (len3 != len)
1182 {
1183 *p = YYCURSOR + len3 - len;
1184 return 0;
1185 }
1186
1187 class_name = zend_string_init(str, len, 0);
1188
1189 do {
1190 if(!unserialize_allowed_class(class_name, var_hash)) {
1191 incomplete_class = 1;
1192 ce = PHP_IC_ENTRY;
1193 break;
1194 }
1195
1196 /* Try to find class directly */
1197 BG(serialize_lock)++;
1198 ce = zend_lookup_class(class_name);
1199 if (ce) {
1200 BG(serialize_lock)--;
1201 if (EG(exception)) {
1202 zend_string_release(class_name);
1203 return 0;
1204 }
1205 break;
1206 }
1207 BG(serialize_lock)--;
1208
1209 if (EG(exception)) {
1210 zend_string_release(class_name);
1211 return 0;
1212 }
1213
1214 /* Check for unserialize callback */
1215 if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
1216 incomplete_class = 1;
1217 ce = PHP_IC_ENTRY;
1218 break;
1219 }
1220
1221 /* Call unserialize callback */
1222 ZVAL_STRING(&user_func, PG(unserialize_callback_func));
1223
1224 ZVAL_STR_COPY(&args[0], class_name);
1225 BG(serialize_lock)++;
1226 if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
1227 BG(serialize_lock)--;
1228 if (EG(exception)) {
1229 zend_string_release(class_name);
1230 zval_ptr_dtor(&user_func);
1231 zval_ptr_dtor(&args[0]);
1232 return 0;
1233 }
1234 php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
1235 incomplete_class = 1;
1236 ce = PHP_IC_ENTRY;
1237 zval_ptr_dtor(&user_func);
1238 zval_ptr_dtor(&args[0]);
1239 break;
1240 }
1241 BG(serialize_lock)--;
1242 zval_ptr_dtor(&retval);
1243 if (EG(exception)) {
1244 zend_string_release(class_name);
1245 zval_ptr_dtor(&user_func);
1246 zval_ptr_dtor(&args[0]);
1247 return 0;
1248 }
1249
1250 /* The callback function may have defined the class */
1251 BG(serialize_lock)++;
1252 if ((ce = zend_lookup_class(class_name)) == NULL) {
1253 php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
1254 incomplete_class = 1;
1255 ce = PHP_IC_ENTRY;
1256 }
1257 BG(serialize_lock)--;
1258
1259 zval_ptr_dtor(&user_func);
1260 zval_ptr_dtor(&args[0]);
1261 break;
1262 } while (1);
1263
1264 *p = YYCURSOR;
1265
1266 if (custom_object) {
1267 int ret;
1268
1269 ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
1270
1271 if (ret && incomplete_class) {
1272 php_store_class_name(rval, ZSTR_VAL(class_name), len2);
1273 }
1274 zend_string_release(class_name);
1275 return ret;
1276 }
1277
1278 elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
1279
1280 if (elements < 0) {
1281 zend_string_release(class_name);
1282 return 0;
1283 }
1284
1285 if (incomplete_class) {
1286 php_store_class_name(rval, ZSTR_VAL(class_name), len2);
1287 }
1288 zend_string_release(class_name);
1289
1290 return object_common2(UNSERIALIZE_PASSTHRU, elements);
1291 }
1292 #line 1293 "ext/standard/var_unserializer.c"
1293 yy77:
1294 ++YYCURSOR;
1295 #line 809 "ext/standard/var_unserializer.re"
1296 {
1297 size_t len, maxlen;
1298 zend_string *str;
1299
1300 len = parse_uiv(start + 2);
1301 maxlen = max - YYCURSOR;
1302 if (maxlen < len) {
1303 *p = start + 2;
1304 return 0;
1305 }
1306
1307 if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
1308 return 0;
1309 }
1310
1311 if (*(YYCURSOR) != '"') {
1312 zend_string_free(str);
1313 *p = YYCURSOR;
1314 return 0;
1315 }
1316
1317 if (*(YYCURSOR + 1) != ';') {
1318 efree(str);
1319 *p = YYCURSOR + 1;
1320 return 0;
1321 }
1322
1323 YYCURSOR += 2;
1324 *p = YYCURSOR;
1325
1326 ZVAL_STR(rval, str);
1327 return 1;
1328 }
1329 #line 1330 "ext/standard/var_unserializer.c"
1330 yy79:
1331 ++YYCURSOR;
1332 #line 843 "ext/standard/var_unserializer.re"
1333 {
1334 zend_long elements = parse_iv(start + 2);
1335 /* use iv() not uiv() in order to check data range */
1336 *p = YYCURSOR;
1337 if (!var_hash) return 0;
1338
1339 if (elements < 0 || elements >= HT_MAX_SIZE) {
1340 return 0;
1341 }
1342
1343 array_init_size(rval, elements);
1344 if (elements) {
1345 /* we can't convert from packed to hash during unserialization, because
1346 reference to some zvals might be keept in var_hash (to support references) */
1347 zend_hash_real_init(Z_ARRVAL_P(rval), 0);
1348 }
1349
1350 /* The array may contain references to itself, in which case we'll be modifying an
1351 * rc>1 array. This is okay, since the array is, ostensibly, only visible to
1352 * unserialize (in practice unserialization handlers also see it). Ideally we should
1353 * prohibit "r:" references to non-objects, as we only generate them for objects. */
1354 HT_ALLOW_COW_VIOLATION(Z_ARRVAL_P(rval));
1355
1356 if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
1357 return 0;
1358 }
1359
1360 return finish_nested_data(UNSERIALIZE_PASSTHRU);
1361 }
1362 #line 1363 "ext/standard/var_unserializer.c"
1363 yy81:
1364 yych = *++YYCURSOR;
1365 if (yych <= '/') goto yy18;
1366 if (yych >= ':') goto yy18;
1367 yy82:
1368 ++YYCURSOR;
1369 if (YYLIMIT <= YYCURSOR) YYFILL(1);
1370 yych = *YYCURSOR;
1371 if (yych <= '/') goto yy18;
1372 if (yych <= '9') goto yy82;
1373 if (yych == ';') goto yy64;
1374 goto yy18;
1375 yy84:
1376 yych = *++YYCURSOR;
1377 if (yych == ';') goto yy89;
1378 goto yy18;
1379 yy85:
1380 ++YYCURSOR;
1381 #line 873 "ext/standard/var_unserializer.re"
1382 {
1383 zend_long elements;
1384 if (!var_hash) return 0;
1385
1386 elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
1387 if (elements < 0 || elements >= HT_MAX_SIZE) {
1388 return 0;
1389 }
1390 return object_common2(UNSERIALIZE_PASSTHRU, elements);
1391 }
1392 #line 1393 "ext/standard/var_unserializer.c"
1393 yy87:
1394 ++YYCURSOR;
1395 #line 771 "ext/standard/var_unserializer.re"
1396 {
1397 size_t len, maxlen;
1398 char *str;
1399
1400 len = parse_uiv(start + 2);
1401 maxlen = max - YYCURSOR;
1402 if (maxlen < len) {
1403 *p = start + 2;
1404 return 0;
1405 }
1406
1407 str = (char*)YYCURSOR;
1408
1409 YYCURSOR += len;
1410
1411 if (*(YYCURSOR) != '"') {
1412 *p = YYCURSOR;
1413 return 0;
1414 }
1415
1416 if (*(YYCURSOR + 1) != ';') {
1417 *p = YYCURSOR + 1;
1418 return 0;
1419 }
1420
1421 YYCURSOR += 2;
1422 *p = YYCURSOR;
1423
1424 if (len == 0) {
1425 ZVAL_EMPTY_STRING(rval);
1426 } else if (len == 1) {
1427 ZVAL_INTERNED_STR(rval, ZSTR_CHAR((zend_uchar)*str));
1428 } else {
1429 ZVAL_STRINGL(rval, str, len);
1430 }
1431 return 1;
1432 }
1433 #line 1434 "ext/standard/var_unserializer.c"
1434 yy89:
1435 ++YYCURSOR;
1436 #line 746 "ext/standard/var_unserializer.re"
1437 {
1438 *p = YYCURSOR;
1439
1440 if (!strncmp((char*)start + 2, "NAN", 3)) {
1441 ZVAL_DOUBLE(rval, ZEND_NAN);
1442 } else if (!strncmp((char*)start + 2, "INF", 3)) {
1443 ZVAL_DOUBLE(rval, ZEND_INFINITY);
1444 } else if (!strncmp((char*)start + 2, "-INF", 4)) {
1445 ZVAL_DOUBLE(rval, -ZEND_INFINITY);
1446 } else {
1447 ZVAL_NULL(rval);
1448 }
1449
1450 return 1;
1451 }
1452 #line 1453 "ext/standard/var_unserializer.c"
1453 }
1454 #line 1044 "ext/standard/var_unserializer.re"
1455
1456
1457 return 0;
1458 }
1459