RDB v8: fix rdbLoadLen() return value.

This commit is contained in:
antirez 2016-06-01 20:18:28 +02:00
parent e6554bed92
commit 27e5f385c1
3 changed files with 61 additions and 36 deletions

View File

@ -128,41 +128,60 @@ int rdbSaveLen(rio *rdb, uint64_t len) {
return nwritten; return nwritten;
} }
/* Load an encoded length. The "isencoded" argument is set to 1 if the length
* is not actually a length but an "encoding type". See the RDB_ENC_* /* Load an encoded length. If the loaded length is a normal length as stored
* definitions in rdb.h for more information. */ * with rdbSaveLen(), the read length is set to '*lenptr'. If instead the
uint64_t rdbLoadLen(rio *rdb, int *isencoded) { * loaded length describes a special encoding that follows, then '*isencoded'
* is set to 1 and the encoding format is stored at '*lenptr'.
*
* See the RDB_ENC_* definitions in rdb.h for more information on special
* encodings.
*
* The function returns -1 on error, 0 on success. */
int rdbLoadLenByRef(rio *rdb, int *isencoded, uint64_t *lenptr) {
unsigned char buf[2]; unsigned char buf[2];
int type; int type;
if (isencoded) *isencoded = 0; if (isencoded) *isencoded = 0;
if (rioRead(rdb,buf,1) == 0) return RDB_LENERR; if (rioRead(rdb,buf,1) == 0) return -1;
type = (buf[0]&0xC0)>>6; type = (buf[0]&0xC0)>>6;
if (type == RDB_ENCVAL) { if (type == RDB_ENCVAL) {
/* Read a 6 bit encoding type. */ /* Read a 6 bit encoding type. */
if (isencoded) *isencoded = 1; if (isencoded) *isencoded = 1;
return buf[0]&0x3F; *lenptr = buf[0]&0x3F;
} else if (type == RDB_6BITLEN) { } else if (type == RDB_6BITLEN) {
/* Read a 6 bit len. */ /* Read a 6 bit len. */
return buf[0]&0x3F; *lenptr = buf[0]&0x3F;
} else if (type == RDB_14BITLEN) { } else if (type == RDB_14BITLEN) {
/* Read a 14 bit len. */ /* Read a 14 bit len. */
if (rioRead(rdb,buf+1,1) == 0) return RDB_LENERR; if (rioRead(rdb,buf+1,1) == 0) return -1;
return ((buf[0]&0x3F)<<8)|buf[1]; *lenptr = ((buf[0]&0x3F)<<8)|buf[1];
} else if (buf[0] == RDB_32BITLEN) { } else if (buf[0] == RDB_32BITLEN) {
/* Read a 32 bit len. */ /* Read a 32 bit len. */
uint32_t len; uint32_t len;
if (rioRead(rdb,&len,4) == 0) return RDB_LENERR; if (rioRead(rdb,&len,4) == 0) return -1;
return ntohl(len); *lenptr = ntohl(len);
} else if (buf[0] == RDB_64BITLEN) { } else if (buf[0] == RDB_64BITLEN) {
/* Read a 64 bit len. */ /* Read a 64 bit len. */
uint64_t len; uint64_t len;
if (rioRead(rdb,&len,8) == 0) return RDB_LENERR; if (rioRead(rdb,&len,8) == 0) return -1;
return ntohu64(len); *lenptr = ntohu64(len);
} else { } else {
rdbExitReportCorruptRDB("Unknown length encoding in rdbLoadLen()"); rdbExitReportCorruptRDB("Unknown length encoding in rdbLoadLen()");
return 0; /* Never reached. */ return -1; /* Never reached. */
} }
return 0;
}
/* This is like rdbLoadLenByRef() but directly returns the value read
* from the RDB stream, signaling an error by returning RDB_LENERR
* (since it is a too large count to be applicable in any Redis data
* structure). */
uint64_t rdbLoadLen(rio *rdb, int *isencoded) {
uint64_t len;
if (rdbLoadLenByRef(rdb,isencoded,&len) == -1) return RDB_LENERR;
return len;
} }
/* Encodes the "value" argument as integer when it fits in the supported ranges /* Encodes the "value" argument as integer when it fits in the supported ranges
@ -299,7 +318,7 @@ ssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
void *rdbLoadLzfStringObject(rio *rdb, int flags) { void *rdbLoadLzfStringObject(rio *rdb, int flags) {
int plain = flags & RDB_LOAD_PLAIN; int plain = flags & RDB_LOAD_PLAIN;
int sds = flags & RDB_LOAD_SDS; int sds = flags & RDB_LOAD_SDS;
unsigned int len, clen; uint64_t len, clen;
unsigned char *c = NULL; unsigned char *c = NULL;
char *val = NULL; char *val = NULL;
@ -414,7 +433,7 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags) {
int plain = flags & RDB_LOAD_PLAIN; int plain = flags & RDB_LOAD_PLAIN;
int sds = flags & RDB_LOAD_SDS; int sds = flags & RDB_LOAD_SDS;
int isencoded; int isencoded;
uint32_t len; uint64_t len;
len = rdbLoadLen(rdb,&isencoded); len = rdbLoadLen(rdb,&isencoded);
if (isencoded) { if (isencoded) {
@ -1291,7 +1310,7 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
} }
int rdbLoad(char *filename) { int rdbLoad(char *filename) {
uint32_t dbid; uint64_t dbid;
int type, rdbver; int type, rdbver;
redisDb *db = server.db+0; redisDb *db = server.db+0;
char buf[1024]; char buf[1024];
@ -1364,7 +1383,7 @@ int rdbLoad(char *filename) {
} else if (type == RDB_OPCODE_RESIZEDB) { } else if (type == RDB_OPCODE_RESIZEDB) {
/* RESIZEDB: Hint about the size of the keys in the currently /* RESIZEDB: Hint about the size of the keys in the currently
* selected data base, in order to avoid useless rehashing. */ * selected data base, in order to avoid useless rehashing. */
uint32_t db_size, expires_size; uint64_t db_size, expires_size;
if ((db_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR) if ((db_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)
goto eoferr; goto eoferr;
if ((expires_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR) if ((expires_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)

View File

@ -59,7 +59,7 @@
#define RDB_32BITLEN 0x80 #define RDB_32BITLEN 0x80
#define RDB_64BITLEN 0x81 #define RDB_64BITLEN 0x81
#define RDB_ENCVAL 3 #define RDB_ENCVAL 3
#define RDB_LENERR UINT_MAX #define RDB_LENERR UINT64_MAX
/* When a length of a string object stored on disk has the first two bits /* When a length of a string object stored on disk has the first two bits
* set, the remaining six bits specify a special encoding for the object * set, the remaining six bits specify a special encoding for the object

View File

@ -171,7 +171,7 @@ static int processTime(int type) {
return 0; return 0;
} }
static uint32_t loadLength(int *isencoded) { static uint64_t loadLength(int *isencoded) {
unsigned char buf[2]; unsigned char buf[2];
uint32_t len; uint32_t len;
int type; int type;
@ -190,10 +190,16 @@ static uint32_t loadLength(int *isencoded) {
/* Read a 14 bit len */ /* Read a 14 bit len */
if (!readBytes(buf+1,1)) return RDB_LENERR; if (!readBytes(buf+1,1)) return RDB_LENERR;
return ((buf[0] & 0x3F) << 8) | buf[1]; return ((buf[0] & 0x3F) << 8) | buf[1];
} else { } else if (buf[0] == RDB_32BITLEN) {
/* Read a 32 bit len */ /* Read a 32 bit len */
if (!readBytes(&len, 4)) return RDB_LENERR; if (!readBytes(&len, 4)) return RDB_LENERR;
return (unsigned int)ntohl(len); return ntohl(len);
} else if (buf[0] == RDB_64BITLEN) {
/* Read a 64 bit len */
if (!readBytes(&len, 8)) return RDB_LENERR;
return ntohu64(len);
} else {
return RDB_LENERR;
} }
} }
@ -230,7 +236,7 @@ static char *loadIntegerObject(int enctype) {
} }
static char* loadLzfStringObject() { static char* loadLzfStringObject() {
unsigned int slen, clen; uint64_t slen, clen;
char *c, *s; char *c, *s;
if ((clen = loadLength(NULL)) == RDB_LENERR) return NULL; if ((clen = loadLength(NULL)) == RDB_LENERR) return NULL;
@ -254,9 +260,9 @@ static char* loadLzfStringObject() {
/* returns NULL when not processable, char* when valid */ /* returns NULL when not processable, char* when valid */
static char* loadStringObject() { static char* loadStringObject() {
uint32_t offset = CURR_OFFSET; uint64_t offset = CURR_OFFSET;
uint64_t len;
int isencoded; int isencoded;
uint32_t len;
len = loadLength(&isencoded); len = loadLength(&isencoded);
if (isencoded) { if (isencoded) {
@ -269,7 +275,7 @@ static char* loadStringObject() {
return loadLzfStringObject(); return loadLzfStringObject();
default: default:
/* unknown encoding */ /* unknown encoding */
SHIFT_ERROR(offset, "Unknown string encoding (0x%02x)", len); SHIFT_ERROR(offset, "Unknown string encoding (0x%02llx)", len);
return NULL; return NULL;
} }
} }
@ -344,8 +350,8 @@ static int processDoubleValue(double** store) {
} }
static int loadPair(entry *e) { static int loadPair(entry *e) {
uint32_t offset = CURR_OFFSET; uint64_t offset = CURR_OFFSET;
uint32_t i; uint64_t i;
/* read key first */ /* read key first */
char *key; char *key;
@ -356,7 +362,7 @@ static int loadPair(entry *e) {
return 0; return 0;
} }
uint32_t length = 0; uint64_t length = 0;
if (e->type == RDB_TYPE_LIST || if (e->type == RDB_TYPE_LIST ||
e->type == RDB_TYPE_SET || e->type == RDB_TYPE_SET ||
e->type == RDB_TYPE_ZSET || e->type == RDB_TYPE_ZSET ||
@ -384,7 +390,7 @@ static int loadPair(entry *e) {
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
offset = CURR_OFFSET; offset = CURR_OFFSET;
if (!processStringObject(NULL)) { if (!processStringObject(NULL)) {
SHIFT_ERROR(offset, "Error reading element at index %d (length: %d)", i, length); SHIFT_ERROR(offset, "Error reading element at index %llu (length: %llu)", i, length);
return 0; return 0;
} }
} }
@ -393,12 +399,12 @@ static int loadPair(entry *e) {
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
offset = CURR_OFFSET; offset = CURR_OFFSET;
if (!processStringObject(NULL)) { if (!processStringObject(NULL)) {
SHIFT_ERROR(offset, "Error reading element key at index %d (length: %d)", i, length); SHIFT_ERROR(offset, "Error reading element key at index %llu (length: %llu)", i, length);
return 0; return 0;
} }
offset = CURR_OFFSET; offset = CURR_OFFSET;
if (!processDoubleValue(NULL)) { if (!processDoubleValue(NULL)) {
SHIFT_ERROR(offset, "Error reading element value at index %d (length: %d)", i, length); SHIFT_ERROR(offset, "Error reading element value at index %llu (length: %llu)", i, length);
return 0; return 0;
} }
} }
@ -407,12 +413,12 @@ static int loadPair(entry *e) {
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
offset = CURR_OFFSET; offset = CURR_OFFSET;
if (!processStringObject(NULL)) { if (!processStringObject(NULL)) {
SHIFT_ERROR(offset, "Error reading element key at index %d (length: %d)", i, length); SHIFT_ERROR(offset, "Error reading element key at index %llu (length: %llu)", i, length);
return 0; return 0;
} }
offset = CURR_OFFSET; offset = CURR_OFFSET;
if (!processStringObject(NULL)) { if (!processStringObject(NULL)) {
SHIFT_ERROR(offset, "Error reading element value at index %d (length: %d)", i, length); SHIFT_ERROR(offset, "Error reading element value at index %llu (length: %llu)", i, length);
return 0; return 0;
} }
} }
@ -428,7 +434,7 @@ static int loadPair(entry *e) {
static entry loadEntry() { static entry loadEntry() {
entry e = { NULL, -1, 0 }; entry e = { NULL, -1, 0 };
uint32_t length, offset[4]; uint64_t length, offset[4];
/* reset error container */ /* reset error container */
errors.level = 0; errors.level = 0;
@ -445,7 +451,7 @@ static entry loadEntry() {
return e; return e;
} }
if (length > 63) { if (length > 63) {
SHIFT_ERROR(offset[1], "Database number out of range (%d)", length); SHIFT_ERROR(offset[1], "Database number out of range (%llu)", length);
return e; return e;
} }
} else if (e.type == RDB_OPCODE_EOF) { } else if (e.type == RDB_OPCODE_EOF) {