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