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