Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ int verifyDumpPayload(unsigned char *p, size_t len, uint16_t *rdbver_ptr) {
if (rdbver_ptr) {
*rdbver_ptr = rdbver;
}
if ((rdbver >= RDB_FOREIGN_VERSION_MIN && rdbver <= RDB_FOREIGN_VERSION_MAX) ||
(rdbver > RDB_VERSION && server.rdb_version_check == RDB_VERSION_CHECK_STRICT)) {
if (server.rdb_version_check == RDB_VERSION_CHECK_STRICT &&
(rdbver > RDB_VERSION ||
(rdbver >= RDB_FOREIGN_VERSION_MIN && rdbver <= RDB_FOREIGN_VERSION_MAX))) {
return C_ERR;
}

Expand Down Expand Up @@ -203,6 +204,7 @@ void dumpCommand(client *c) {
/* RESTORE key ttl serialized-value [REPLACE] [ABSTTL] [IDLETIME seconds] [FREQ frequency] */
void restoreCommand(client *c) {
long long ttl, lfu_freq = -1, lru_idle = -1, lru_clock = -1;
uint16_t rdbver = 0;
rio payload;
int j, type, replace = 0, absttl = 0;
robj *obj;
Expand Down Expand Up @@ -251,14 +253,28 @@ void restoreCommand(client *c) {
}

/* Verify RDB version and data checksum. */
if (verifyDumpPayload(c->argv[3]->ptr, sdslen(c->argv[3]->ptr), NULL) == C_ERR) {
if (verifyDumpPayload(c->argv[3]->ptr, sdslen(c->argv[3]->ptr), &rdbver) == C_ERR) {
addReplyError(c, "DUMP payload version or checksum are wrong");
return;
}

rioInitWithBuffer(&payload, c->argv[3]->ptr);
if (((type = rdbLoadObjectType(&payload)) == -1) ||
((obj = rdbLoadObject(type, &payload, key->ptr, c->db->id, NULL)) == NULL)) {
type = rdbLoadObjectType(&payload);
if (type == -1) {
addReplyError(c, "Bad data format");
return;
}

/* If it's a foreign RDB format. Only accept old data types that we know the
* meaning of. */
if (rdbver >= RDB_FOREIGN_VERSION_MIN && rdbver <= RDB_FOREIGN_VERSION_MAX &&
type >= RDB_FOREIGN_TYPE_MIN) {
addReplyError(c, "Unsupported foreign data format");
return;
}

obj = rdbLoadObject(type, &payload, key->ptr, c->db->id, NULL);
if (obj == NULL) {
addReplyError(c, "Bad data format");
return;
}
Expand Down
14 changes: 14 additions & 0 deletions src/rdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3103,6 +3103,13 @@ int rdbLoadRioWithLoadingCtx(rio *rdb, int rdbflags, rdbSaveInfo *rsi, rdbLoadin
/* Read type. */
if ((type = rdbLoadType(rdb)) == -1) goto eoferr;

/* Safeguard for unknown foreign opcode interpretations. */
if (is_redis_magic && type >= RDB_FOREIGN_TYPE_MIN && type <= RDB_FOREIGN_TYPE_MAX) {
serverLog(LL_WARNING, "Can't handle foreign type or opcode %d in RDB %d",
type, rdbver);
return C_ERR;
}

/* Handle special types. */
if (type == RDB_OPCODE_EXPIRETIME) {
/* EXPIRETIME: load an expire associated with the next key
Expand Down Expand Up @@ -3155,6 +3162,13 @@ int rdbLoadRioWithLoadingCtx(rio *rdb, int rdbflags, rdbSaveInfo *rsi, rdbLoadin
if ((expires_size = rdbLoadLen(rdb, NULL)) == RDB_LENERR) goto eoferr;
should_expand_db = 1;
continue; /* Read next opcode. */
} else if (type == RDB_OPCODE_SLOT_INFO) {
/* Ignore foreign RDB slot info size annotations.
* slot_id, slot_size, expires_slot_size. */
if (rdbLoadLen(rdb, NULL) == RDB_LENERR) goto eoferr;
if (rdbLoadLen(rdb, NULL) == RDB_LENERR) goto eoferr;
if (rdbLoadLen(rdb, NULL) == RDB_LENERR) goto eoferr;
continue; /* Ignore gracefully. */
} else if (type == RDB_OPCODE_AUX) {
/* AUX: generic string-string fields. Use to add state to RDB
* which is backward compatible. Implementations of RDB loading
Expand Down
11 changes: 9 additions & 2 deletions src/rdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,16 @@ enum RdbType {
RDB_TYPE_STREAM_LISTPACKS_2 = 19,
RDB_TYPE_SET_LISTPACK = 20,
RDB_TYPE_STREAM_LISTPACKS_3 = 21,
RDB_TYPE_HASH_2 = 22,
RDB_TYPE_HASH_2 = 22, /* Hash with field-level expiration (Valkey 9.0) */
RDB_TYPE_LAST
};
/* NOTE: WHEN ADDING NEW RDB TYPE, UPDATE rdb_type_string[] */

/* When our RDB format diverges, we need to reject types/opcodes for which we
* may have assigned a different meaning compared to other implementations. */
#define RDB_FOREIGN_TYPE_MIN 22
#define RDB_FOREIGN_TYPE_MAX 243

typedef int (*ChildSnapshotFunc)(int req, rio *rdb, void *privdata);
typedef struct rdbSnapshotOptions {
int connsnum; /* Number of connections. */
Expand All @@ -131,7 +136,9 @@ typedef struct rdbSnapshotOptions {
/* Test if a type is an object type. */
#define rdbIsObjectType(t) (((t) >= 0 && (t) <= 7) || ((t) >= 9 && (t) < RDB_TYPE_LAST))

/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType). */
/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType).
* These are special RDB types, but they start from 255 and grow down. */
#define RDB_OPCODE_SLOT_INFO 244 /* Foreign slot info, safe to ignore. */
#define RDB_OPCODE_FUNCTION2 245 /* function library data */
#define RDB_OPCODE_FUNCTION_PRE_GA 246 /* old function library data for 7.0 rc1 and rc2 */
#define RDB_OPCODE_MODULE_AUX 247 /* Module auxiliary data. */
Expand Down
Loading