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

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

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