Load a Redis object of the specified type from the specified file. * On success a newly allocated object is returned, otherwise NULL. * When the function returns NULL and if 'error' is not NULL, the * integer pointed by 'error' is set to the type of error that occurred */
| 1525 | * When the function returns NULL and if 'error' is not NULL, the |
| 1526 | * integer pointed by 'error' is set to the type of error that occurred */ |
| 1527 | robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int *error) { |
| 1528 | robj *o = NULL, *ele, *dec; |
| 1529 | uint64_t len; |
| 1530 | unsigned int i; |
| 1531 | |
| 1532 | /* Set default error of load object, it will be set to 0 on success. */ |
| 1533 | if (error) *error = RDB_LOAD_ERR_OTHER; |
| 1534 | |
| 1535 | int deep_integrity_validation = server.sanitize_dump_payload == SANITIZE_DUMP_YES; |
| 1536 | if (server.sanitize_dump_payload == SANITIZE_DUMP_CLIENTS) { |
| 1537 | /* Skip sanitization when loading (an RDB), or getting a RESTORE command |
| 1538 | * from either the master or a client using an ACL user with the skip-sanitize-payload flag. */ |
| 1539 | int skip = server.loading || |
| 1540 | (server.current_client && (server.current_client->flags & CLIENT_MASTER)); |
| 1541 | if (!skip && server.current_client && server.current_client->user) |
| 1542 | skip = !!(server.current_client->user->flags & USER_FLAG_SANITIZE_PAYLOAD_SKIP); |
| 1543 | deep_integrity_validation = !skip; |
| 1544 | } |
| 1545 | |
| 1546 | if (rdbtype == RDB_TYPE_STRING) { |
| 1547 | /* Read string value */ |
| 1548 | if ((o = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL; |
| 1549 | o = tryObjectEncoding(o); |
| 1550 | } else if (rdbtype == RDB_TYPE_LIST) { |
| 1551 | /* Read list value */ |
| 1552 | if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL; |
| 1553 | if (len == 0) goto emptykey; |
| 1554 | |
| 1555 | o = createQuicklistObject(); |
| 1556 | quicklistSetOptions(o->ptr, server.list_max_ziplist_size, |
| 1557 | server.list_compress_depth); |
| 1558 | |
| 1559 | /* Load every single element of the list */ |
| 1560 | while(len--) { |
| 1561 | if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) { |
| 1562 | decrRefCount(o); |
| 1563 | return NULL; |
| 1564 | } |
| 1565 | dec = getDecodedObject(ele); |
| 1566 | size_t len = sdslen(dec->ptr); |
| 1567 | quicklistPushTail(o->ptr, dec->ptr, len); |
| 1568 | decrRefCount(dec); |
| 1569 | decrRefCount(ele); |
| 1570 | } |
| 1571 | } else if (rdbtype == RDB_TYPE_SET) { |
| 1572 | /* Read Set value */ |
| 1573 | if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL; |
| 1574 | if (len == 0) goto emptykey; |
| 1575 | |
| 1576 | /* Use a regular set when there are too many entries. */ |
| 1577 | size_t max_entries = server.set_max_intset_entries; |
| 1578 | if (max_entries >= 1<<30) max_entries = 1<<30; |
| 1579 | if (len > max_entries) { |
| 1580 | o = createSetObject(); |
| 1581 | /* It's faster to expand the dict to the right size asap in order |
| 1582 | * to avoid rehashing */ |
| 1583 | if (len > DICT_HT_INITIAL_SIZE && dictTryExpand(o->ptr,len) != DICT_OK) { |
| 1584 | rdbReportCorruptRDB("OOM in dictTryExpand %llu", (unsigned long long)len); |
no test coverage detected