Annotation of embedaddon/php/ext/standard/var_unserializer.re, revision 1.1.1.3

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:   | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       6:   +----------------------------------------------------------------------+
                      7:   | This source file is subject to version 3.01 of the PHP license,      |
                      8:   | that is bundled with this package in the file LICENSE, and is        |
                      9:   | available through the world-wide-web at the following url:           |
                     10:   | http://www.php.net/license/3_01.txt                                  |
                     11:   | If you did not receive a copy of the PHP license and are unable to   |
                     12:   | obtain it through the world-wide-web, please send a note to          |
                     13:   | license@php.net so we can mail you a copy immediately.               |
                     14:   +----------------------------------------------------------------------+
                     15:   | Author: Sascha Schumann <sascha@schumann.cx>                         |
                     16:   +----------------------------------------------------------------------+
                     17: */
                     18: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #include "php.h"
                     22: #include "ext/standard/php_var.h"
                     23: #include "php_incomplete_class.h"
                     24: 
                     25: /* {{{ reference-handling for unserializer: var_* */
                     26: #define VAR_ENTRIES_MAX 1024
                     27: 
                     28: typedef struct {
                     29:        zval *data[VAR_ENTRIES_MAX];
                     30:        long used_slots;
                     31:        void *next;
                     32: } var_entries;
                     33: 
                     34: static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
                     35: {
1.1.1.2   misho      36:        var_entries *var_hash = (*var_hashx)->last;
                     37: #if 0
                     38:        fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
                     39: #endif
1.1       misho      40: 
1.1.1.2   misho      41:        if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
1.1       misho      42:                var_hash = emalloc(sizeof(var_entries));
                     43:                var_hash->used_slots = 0;
                     44:                var_hash->next = 0;
                     45: 
1.1.1.2   misho      46:                if (!(*var_hashx)->first) {
                     47:                        (*var_hashx)->first = var_hash;
                     48:                } else {
                     49:                        ((var_entries *) (*var_hashx)->last)->next = var_hash;
                     50:                }
                     51: 
                     52:                (*var_hashx)->last = var_hash;
1.1       misho      53:        }
                     54: 
                     55:        var_hash->data[var_hash->used_slots++] = *rval;
                     56: }
                     57: 
                     58: PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
                     59: {
1.1.1.2   misho      60:        var_entries *var_hash = (*var_hashx)->last_dtor;
                     61: #if 0
                     62:        fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
                     63: #endif
1.1       misho      64: 
1.1.1.2   misho      65:        if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
1.1       misho      66:                var_hash = emalloc(sizeof(var_entries));
                     67:                var_hash->used_slots = 0;
                     68:                var_hash->next = 0;
                     69: 
1.1.1.2   misho      70:                if (!(*var_hashx)->first_dtor) {
                     71:                        (*var_hashx)->first_dtor = var_hash;
                     72:                } else {
                     73:                        ((var_entries *) (*var_hashx)->last_dtor)->next = var_hash;
                     74:                }
                     75: 
                     76:                (*var_hashx)->last_dtor = var_hash;
1.1       misho      77:        }
                     78: 
                     79:        Z_ADDREF_PP(rval);
                     80:        var_hash->data[var_hash->used_slots++] = *rval;
                     81: }
                     82: 
                     83: PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval)
                     84: {
                     85:        long i;
1.1.1.2   misho      86:        var_entries *var_hash = (*var_hashx)->first;
                     87: #if 0
                     88:        fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
                     89: #endif
1.1       misho      90:        
                     91:        while (var_hash) {
                     92:                for (i = 0; i < var_hash->used_slots; i++) {
                     93:                        if (var_hash->data[i] == ozval) {
                     94:                                var_hash->data[i] = *nzval;
                     95:                                /* do not break here */
                     96:                        }
                     97:                }
                     98:                var_hash = var_hash->next;
                     99:        }
                    100: }
                    101: 
                    102: static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store)
                    103: {
1.1.1.2   misho     104:        var_entries *var_hash = (*var_hashx)->first;
                    105: #if 0
                    106:        fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
                    107: #endif
                    108:                
1.1       misho     109:        while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
                    110:                var_hash = var_hash->next;
                    111:                id -= VAR_ENTRIES_MAX;
                    112:        }
                    113: 
                    114:        if (!var_hash) return !SUCCESS;
                    115: 
                    116:        if (id < 0 || id >= var_hash->used_slots) return !SUCCESS;
                    117: 
                    118:        *store = &var_hash->data[id];
                    119: 
                    120:        return SUCCESS;
                    121: }
                    122: 
                    123: PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
                    124: {
                    125:        void *next;
                    126:        long i;
1.1.1.2   misho     127:        var_entries *var_hash = (*var_hashx)->first;
                    128: #if 0
                    129:        fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
                    130: #endif
1.1       misho     131:        
                    132:        while (var_hash) {
                    133:                next = var_hash->next;
                    134:                efree(var_hash);
                    135:                var_hash = next;
                    136:        }
                    137: 
1.1.1.2   misho     138:        var_hash = (*var_hashx)->first_dtor;
1.1       misho     139:        
                    140:        while (var_hash) {
                    141:                for (i = 0; i < var_hash->used_slots; i++) {
                    142:                        zval_ptr_dtor(&var_hash->data[i]);
                    143:                }
                    144:                next = var_hash->next;
                    145:                efree(var_hash);
                    146:                var_hash = next;
                    147:        }
                    148: }
                    149: 
                    150: /* }}} */
                    151: 
                    152: static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen)
                    153: {
                    154:        size_t i, j;
                    155:        char *str = safe_emalloc(*len, 1, 1);
                    156:        unsigned char *end = *(unsigned char **)p+maxlen;
                    157: 
                    158:        if (end < *p) {
                    159:                efree(str);
                    160:                return NULL;
                    161:        }
                    162: 
                    163:        for (i = 0; i < *len; i++) {
                    164:                if (*p >= end) {
                    165:                        efree(str);
                    166:                        return NULL;
                    167:                }
                    168:                if (**p != '\\') {
                    169:                        str[i] = (char)**p;
                    170:                } else {
                    171:                        unsigned char ch = 0;
                    172: 
                    173:                        for (j = 0; j < 2; j++) {
                    174:                                (*p)++;
                    175:                                if (**p >= '0' && **p <= '9') {
                    176:                                        ch = (ch << 4) + (**p -'0');
                    177:                                } else if (**p >= 'a' && **p <= 'f') {
                    178:                                        ch = (ch << 4) + (**p -'a'+10);
                    179:                                } else if (**p >= 'A' && **p <= 'F') {
                    180:                                        ch = (ch << 4) + (**p -'A'+10);
                    181:                                } else {
                    182:                                        efree(str);
                    183:                                        return NULL;
                    184:                                }
                    185:                        }
                    186:                        str[i] = (char)ch;
                    187:                }
                    188:                (*p)++;
                    189:        }
                    190:        str[i] = 0;
                    191:        *len = i;
                    192:        return str;
                    193: }
                    194: 
                    195: #define YYFILL(n) do { } while (0)
                    196: #define YYCTYPE unsigned char
                    197: #define YYCURSOR cursor
                    198: #define YYLIMIT limit
                    199: #define YYMARKER marker
                    200: 
                    201: 
                    202: /*!re2c
                    203: uiv = [+]? [0-9]+;
                    204: iv = [+-]? [0-9]+;
                    205: nv = [+-]? ([0-9]* "." [0-9]+|[0-9]+ "." [0-9]*);
                    206: nvexp = (iv | nv) [eE] [+-]? iv;
                    207: any = [\000-\377];
                    208: object = [OC];
                    209: */
                    210: 
                    211: 
                    212: 
                    213: static inline long parse_iv2(const unsigned char *p, const unsigned char **q)
                    214: {
                    215:        char cursor;
                    216:        long result = 0;
                    217:        int neg = 0;
                    218: 
                    219:        switch (*p) {
                    220:                case '-':
                    221:                        neg++;
                    222:                        /* fall-through */
                    223:                case '+':
                    224:                        p++;
                    225:        }
                    226:        
                    227:        while (1) {
                    228:                cursor = (char)*p;
                    229:                if (cursor >= '0' && cursor <= '9') {
                    230:                        result = result * 10 + (size_t)(cursor - (unsigned char)'0');
                    231:                } else {
                    232:                        break;
                    233:                }
                    234:                p++;
                    235:        }
                    236:        if (q) *q = p;
                    237:        if (neg) return -result;
                    238:        return result;
                    239: }
                    240: 
                    241: static inline long parse_iv(const unsigned char *p)
                    242: {
                    243:        return parse_iv2(p, NULL);
                    244: }
                    245: 
                    246: /* no need to check for length - re2c already did */
                    247: static inline size_t parse_uiv(const unsigned char *p)
                    248: {
                    249:        unsigned char cursor;
                    250:        size_t result = 0;
                    251: 
                    252:        if (*p == '+') {
                    253:                p++;
                    254:        }
                    255:        
                    256:        while (1) {
                    257:                cursor = *p;
                    258:                if (cursor >= '0' && cursor <= '9') {
                    259:                        result = result * 10 + (size_t)(cursor - (unsigned char)'0');
                    260:                } else {
                    261:                        break;
                    262:                }
                    263:                p++;
                    264:        }
                    265:        return result;
                    266: }
                    267: 
                    268: #define UNSERIALIZE_PARAMETER zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC
                    269: #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash TSRMLS_CC
                    270: 
                    271: static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long elements, int objprops)
                    272: {
                    273:        while (elements-- > 0) {
                    274:                zval *key, *data, **old_data;
                    275: 
                    276:                ALLOC_INIT_ZVAL(key);
                    277: 
                    278:                if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
                    279:                        zval_dtor(key);
                    280:                        FREE_ZVAL(key);
                    281:                        return 0;
                    282:                }
                    283: 
                    284:                if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
                    285:                        zval_dtor(key);
                    286:                        FREE_ZVAL(key);
                    287:                        return 0;
                    288:                }
                    289: 
                    290:                ALLOC_INIT_ZVAL(data);
                    291: 
                    292:                if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
                    293:                        zval_dtor(key);
                    294:                        FREE_ZVAL(key);
                    295:                        zval_dtor(data);
                    296:                        FREE_ZVAL(data);
                    297:                        return 0;
                    298:                }
                    299: 
                    300:                if (!objprops) {
                    301:                        switch (Z_TYPE_P(key)) {
                    302:                        case IS_LONG:
                    303:                                if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)==SUCCESS) {
                    304:                                        var_push_dtor(var_hash, old_data);
                    305:                                }
                    306:                                zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL);
                    307:                                break;
                    308:                        case IS_STRING:
                    309:                                if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
                    310:                                        var_push_dtor(var_hash, old_data);
                    311:                                }
                    312:                                zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL);
                    313:                                break;
                    314:                        }
                    315:                } else {
                    316:                        /* object properties should include no integers */
                    317:                        convert_to_string(key);
                    318:                        zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data,
                    319:                                        sizeof data, NULL);
                    320:                }
                    321:                
                    322:                zval_dtor(key);
                    323:                FREE_ZVAL(key);
                    324: 
                    325:                if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
                    326:                        (*p)--;
                    327:                        return 0;
                    328:                }
                    329:        }
                    330: 
                    331:        return 1;
                    332: }
                    333: 
                    334: static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
                    335: {
                    336:        if (*((*p)++) == '}')
                    337:                return 1;
                    338: 
                    339: #if SOMETHING_NEW_MIGHT_LEAD_TO_CRASH_ENABLE_IF_YOU_ARE_BRAVE
                    340:        zval_ptr_dtor(rval);
                    341: #endif
                    342:        return 0;
                    343: }
                    344: 
                    345: static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
                    346: {
                    347:        long datalen;
                    348: 
                    349:        datalen = parse_iv2((*p) + 2, p);
                    350: 
                    351:        (*p) += 2;
                    352: 
                    353:        if (datalen < 0 || (*p) + datalen >= max) {
                    354:                zend_error(E_WARNING, "Insufficient data for unserializing - %ld required, %ld present", datalen, (long)(max - (*p)));
                    355:                return 0;
                    356:        }
                    357: 
                    358:        if (ce->unserialize == NULL) {
                    359:                zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
                    360:                object_init_ex(*rval, ce);
                    361:        } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
                    362:                return 0;
                    363:        }
                    364: 
                    365:        (*p) += datalen;
                    366: 
                    367:        return finish_nested_data(UNSERIALIZE_PASSTHRU);
                    368: }
                    369: 
                    370: static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
                    371: {
                    372:        long elements;
                    373:        
                    374:        elements = parse_iv2((*p) + 2, p);
                    375: 
                    376:        (*p) += 2;
                    377:        
                    378:        object_init_ex(*rval, ce);
                    379:        return elements;
                    380: }
                    381: 
1.1.1.2   misho     382: #ifdef PHP_WIN32
                    383: # pragma optimize("", off)
                    384: #endif
1.1       misho     385: static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
                    386: {
                    387:        zval *retval_ptr = NULL;
                    388:        zval fname;
                    389: 
                    390:        if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) {
                    391:                return 0;
                    392:        }
                    393: 
                    394:        if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY &&
                    395:                zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) {
                    396:                INIT_PZVAL(&fname);
                    397:                ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0);
1.1.1.2   misho     398:                BG(serialize_lock)++;
1.1       misho     399:                call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
1.1.1.2   misho     400:                BG(serialize_lock)--;
1.1       misho     401:        }
                    402: 
1.1.1.3 ! misho     403:        if (retval_ptr) {
1.1       misho     404:                zval_ptr_dtor(&retval_ptr);
1.1.1.3 ! misho     405:        }
        !           406: 
        !           407:        if (EG(exception)) {
        !           408:                return 0;
        !           409:        }
1.1       misho     410: 
                    411:        return finish_nested_data(UNSERIALIZE_PASSTHRU);
                    412: 
                    413: }
1.1.1.2   misho     414: #ifdef PHP_WIN32
                    415: # pragma optimize("", on)
                    416: #endif
1.1       misho     417: 
                    418: PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
                    419: {
                    420:        const unsigned char *cursor, *limit, *marker, *start;
                    421:        zval **rval_ref;
                    422: 
1.1.1.2   misho     423:        limit = max;
                    424:        cursor = *p;
                    425:        
                    426:        if (YYCURSOR >= YYLIMIT) {
                    427:                return 0;
                    428:        }
1.1       misho     429:        
                    430:        if (var_hash && cursor[0] != 'R') {
                    431:                var_push(var_hash, rval);
                    432:        }
                    433: 
                    434:        start = cursor;
                    435: 
                    436:        
                    437:        
                    438: /*!re2c
                    439: 
                    440: "R:" iv ";"            {
                    441:        long id;
                    442: 
                    443:        *p = YYCURSOR;
                    444:        if (!var_hash) return 0;
                    445: 
                    446:        id = parse_iv(start + 2) - 1;
                    447:        if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
                    448:                return 0;
                    449:        }
                    450: 
                    451:        if (*rval != NULL) {
                    452:                zval_ptr_dtor(rval);
                    453:        }
                    454:        *rval = *rval_ref;
                    455:        Z_ADDREF_PP(rval);
                    456:        Z_SET_ISREF_PP(rval);
                    457:        
                    458:        return 1;
                    459: }
                    460: 
                    461: "r:" iv ";"            {
                    462:        long id;
                    463: 
                    464:        *p = YYCURSOR;
                    465:        if (!var_hash) return 0;
                    466: 
                    467:        id = parse_iv(start + 2) - 1;
                    468:        if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
                    469:                return 0;
                    470:        }
                    471: 
                    472:        if (*rval == *rval_ref) return 0;
                    473: 
                    474:        if (*rval != NULL) {
                    475:                zval_ptr_dtor(rval);
                    476:        }
                    477:        *rval = *rval_ref;
                    478:        Z_ADDREF_PP(rval);
                    479:        Z_UNSET_ISREF_PP(rval);
                    480:        
                    481:        return 1;
                    482: }
                    483: 
                    484: "N;"   {
                    485:        *p = YYCURSOR;
                    486:        INIT_PZVAL(*rval);
                    487:        ZVAL_NULL(*rval);
                    488:        return 1;
                    489: }
                    490: 
                    491: "b:" [01] ";"  {
                    492:        *p = YYCURSOR;
                    493:        INIT_PZVAL(*rval);
                    494:        ZVAL_BOOL(*rval, parse_iv(start + 2));
                    495:        return 1;
                    496: }
                    497: 
                    498: "i:" iv ";"    {
                    499: #if SIZEOF_LONG == 4
                    500:        int digits = YYCURSOR - start - 3;
                    501: 
                    502:        if (start[2] == '-' || start[2] == '+') {
                    503:                digits--;
                    504:        }
                    505: 
                    506:        /* Use double for large long values that were serialized on a 64-bit system */
                    507:        if (digits >= MAX_LENGTH_OF_LONG - 1) {
                    508:                if (digits == MAX_LENGTH_OF_LONG - 1) {
                    509:                        int cmp = strncmp(YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
                    510: 
                    511:                        if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
                    512:                                goto use_double;
                    513:                        }
                    514:                } else {
                    515:                        goto use_double;
                    516:                }
                    517:        }
                    518: #endif
                    519:        *p = YYCURSOR;
                    520:        INIT_PZVAL(*rval);
                    521:        ZVAL_LONG(*rval, parse_iv(start + 2));
                    522:        return 1;
                    523: }
                    524: 
                    525: "d:" ("NAN" | "-"? "INF") ";"  {
                    526:        *p = YYCURSOR;
                    527:        INIT_PZVAL(*rval);
                    528: 
                    529:        if (!strncmp(start + 2, "NAN", 3)) {
                    530:                ZVAL_DOUBLE(*rval, php_get_nan());
                    531:        } else if (!strncmp(start + 2, "INF", 3)) {
                    532:                ZVAL_DOUBLE(*rval, php_get_inf());
                    533:        } else if (!strncmp(start + 2, "-INF", 4)) {
                    534:                ZVAL_DOUBLE(*rval, -php_get_inf());
                    535:        }
                    536: 
                    537:        return 1;
                    538: }
                    539: 
                    540: "d:" (iv | nv | nvexp) ";"     {
                    541: #if SIZEOF_LONG == 4
                    542: use_double:
                    543: #endif
                    544:        *p = YYCURSOR;
                    545:        INIT_PZVAL(*rval);
                    546:        ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
                    547:        return 1;
                    548: }
                    549: 
                    550: "s:" uiv ":" ["]       {
                    551:        size_t len, maxlen;
                    552:        char *str;
                    553: 
                    554:        len = parse_uiv(start + 2);
                    555:        maxlen = max - YYCURSOR;
                    556:        if (maxlen < len) {
                    557:                *p = start + 2;
                    558:                return 0;
                    559:        }
                    560: 
                    561:        str = (char*)YYCURSOR;
                    562: 
                    563:        YYCURSOR += len;
                    564: 
                    565:        if (*(YYCURSOR) != '"') {
                    566:                *p = YYCURSOR;
                    567:                return 0;
                    568:        }
                    569: 
                    570:        YYCURSOR += 2;
                    571:        *p = YYCURSOR;
                    572: 
                    573:        INIT_PZVAL(*rval);
                    574:        ZVAL_STRINGL(*rval, str, len, 1);
                    575:        return 1;
                    576: }
                    577: 
                    578: "S:" uiv ":" ["]       {
                    579:        size_t len, maxlen;
                    580:        char *str;
                    581: 
                    582:        len = parse_uiv(start + 2);
                    583:        maxlen = max - YYCURSOR;
                    584:        if (maxlen < len) {
                    585:                *p = start + 2;
                    586:                return 0;
                    587:        }
                    588: 
                    589:        if ((str = unserialize_str(&YYCURSOR, &len, maxlen)) == NULL) {
                    590:                return 0;
                    591:        }
                    592: 
                    593:        if (*(YYCURSOR) != '"') {
                    594:                efree(str);
                    595:                *p = YYCURSOR;
                    596:                return 0;
                    597:        }
                    598: 
                    599:        YYCURSOR += 2;
                    600:        *p = YYCURSOR;
                    601: 
                    602:        INIT_PZVAL(*rval);
                    603:        ZVAL_STRINGL(*rval, str, len, 0);
                    604:        return 1;
                    605: }
                    606: 
                    607: "a:" uiv ":" "{" {
                    608:        long elements = parse_iv(start + 2);
                    609:        /* use iv() not uiv() in order to check data range */
                    610:        *p = YYCURSOR;
                    611: 
                    612:        if (elements < 0) {
                    613:                return 0;
                    614:        }
                    615: 
                    616:        INIT_PZVAL(*rval);
                    617: 
                    618:        array_init_size(*rval, elements);
                    619: 
                    620:        if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_PP(rval), elements, 0)) {
                    621:                return 0;
                    622:        }
                    623: 
                    624:        return finish_nested_data(UNSERIALIZE_PASSTHRU);
                    625: }
                    626: 
                    627: "o:" iv ":" ["] {
                    628: 
                    629:        INIT_PZVAL(*rval);
                    630:        
                    631:        return object_common2(UNSERIALIZE_PASSTHRU,
                    632:                        object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
                    633: }
                    634: 
                    635: object ":" uiv ":" ["] {
                    636:        size_t len, len2, len3, maxlen;
                    637:        long elements;
                    638:        char *class_name;
                    639:        zend_class_entry *ce;
                    640:        zend_class_entry **pce;
                    641:        int incomplete_class = 0;
                    642: 
                    643:        int custom_object = 0;
                    644: 
                    645:        zval *user_func;
                    646:        zval *retval_ptr;
                    647:        zval **args[1];
                    648:        zval *arg_func_name;
                    649: 
                    650:        if (*start == 'C') {
                    651:                custom_object = 1;
                    652:        }
                    653:        
                    654:        INIT_PZVAL(*rval);
                    655:        len2 = len = parse_uiv(start + 2);
                    656:        maxlen = max - YYCURSOR;
                    657:        if (maxlen < len || len == 0) {
                    658:                *p = start + 2;
                    659:                return 0;
                    660:        }
                    661: 
                    662:        class_name = (char*)YYCURSOR;
                    663: 
                    664:        YYCURSOR += len;
                    665: 
                    666:        if (*(YYCURSOR) != '"') {
                    667:                *p = YYCURSOR;
                    668:                return 0;
                    669:        }
                    670:        if (*(YYCURSOR+1) != ':') {
                    671:                *p = YYCURSOR+1;
                    672:                return 0;
                    673:        }
                    674: 
                    675:        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\\");
                    676:        if (len3 != len)
                    677:        {
                    678:                *p = YYCURSOR + len3 - len;
                    679:                return 0;
                    680:        }
                    681: 
                    682:        class_name = estrndup(class_name, len);
                    683: 
                    684:        do {
                    685:                /* Try to find class directly */
1.1.1.3 ! misho     686:                BG(serialize_lock) = 1;
1.1       misho     687:                if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
1.1.1.3 ! misho     688:                        BG(serialize_lock) = 0;
        !           689:                        if (EG(exception)) {
        !           690:                                efree(class_name);
        !           691:                                return 0;
        !           692:                        }
1.1       misho     693:                        ce = *pce;
                    694:                        break;
                    695:                }
1.1.1.3 ! misho     696:                BG(serialize_lock) = 0;
        !           697: 
        !           698:                if (EG(exception)) {
        !           699:                        efree(class_name);
        !           700:                        return 0;
        !           701:                }
1.1       misho     702:                
                    703:                /* Check for unserialize callback */
                    704:                if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
                    705:                        incomplete_class = 1;
                    706:                        ce = PHP_IC_ENTRY;
                    707:                        break;
                    708:                }
                    709:                
                    710:                /* Call unserialize callback */
                    711:                MAKE_STD_ZVAL(user_func);
                    712:                ZVAL_STRING(user_func, PG(unserialize_callback_func), 1);
                    713:                args[0] = &arg_func_name;
                    714:                MAKE_STD_ZVAL(arg_func_name);
                    715:                ZVAL_STRING(arg_func_name, class_name, 1);
1.1.1.3 ! misho     716:                BG(serialize_lock) = 1;
1.1       misho     717:                if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
1.1.1.3 ! misho     718:                        BG(serialize_lock) = 0;
        !           719:                        if (EG(exception)) {
        !           720:                                efree(class_name);
        !           721:                                zval_ptr_dtor(&user_func);
        !           722:                                zval_ptr_dtor(&arg_func_name);
        !           723:                                return 0;
        !           724:                        }
1.1       misho     725:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
                    726:                        incomplete_class = 1;
                    727:                        ce = PHP_IC_ENTRY;
                    728:                        zval_ptr_dtor(&user_func);
                    729:                        zval_ptr_dtor(&arg_func_name);
                    730:                        break;
                    731:                }
1.1.1.3 ! misho     732:                BG(serialize_lock) = 0;
1.1       misho     733:                if (retval_ptr) {
                    734:                        zval_ptr_dtor(&retval_ptr);
                    735:                }
1.1.1.3 ! misho     736:                if (EG(exception)) {
        !           737:                        efree(class_name);
        !           738:                        zval_ptr_dtor(&user_func);
        !           739:                        zval_ptr_dtor(&arg_func_name);
        !           740:                        return 0;
        !           741:                }
1.1       misho     742:                
                    743:                /* The callback function may have defined the class */
                    744:                if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
                    745:                        ce = *pce;
                    746:                } else {
                    747:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function %s() hasn't defined the class it was called for", user_func->value.str.val);
                    748:                        incomplete_class = 1;
                    749:                        ce = PHP_IC_ENTRY;
                    750:                }
                    751: 
                    752:                zval_ptr_dtor(&user_func);
                    753:                zval_ptr_dtor(&arg_func_name);
                    754:                break;
                    755:        } while (1);
                    756: 
                    757:        *p = YYCURSOR;
                    758: 
                    759:        if (custom_object) {
                    760:                int ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
                    761: 
                    762:                if (ret && incomplete_class) {
                    763:                        php_store_class_name(*rval, class_name, len2);
                    764:                }
                    765:                efree(class_name);
                    766:                return ret;
                    767:        }
                    768:        
                    769:        elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
                    770: 
                    771:        if (incomplete_class) {
                    772:                php_store_class_name(*rval, class_name, len2);
                    773:        }
                    774:        efree(class_name);
                    775: 
                    776:        return object_common2(UNSERIALIZE_PASSTHRU, elements);
                    777: }
                    778: 
                    779: "}" {
                    780:        /* this is the case where we have less data than planned */
                    781:        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
                    782:        return 0; /* not sure if it should be 0 or 1 here? */
                    783: }
                    784: 
                    785: any    { return 0; }
                    786: 
                    787: */
                    788: 
                    789:        return 0;
                    790: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>