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