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;
}
/* 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_*
* definitions in rdb.h for more information. */
uint64_t rdbLoadLen(rio *rdb, int *isencoded) {
/* Load an encoded length. If the loaded length is a normal length as stored
* with rdbSaveLen(), the read length is set to '*lenptr'. If instead the
* 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];
int type;
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;
if (type == RDB_ENCVAL) {
/* Read a 6 bit encoding type. */
if (isencoded) *isencoded = 1;
return buf[0]&0x3F;
*lenptr = buf[0]&0x3F;
} else if (type == RDB_6BITLEN) {
/* Read a 6 bit len. */
return buf[0]&0x3F;
*lenptr = buf[0]&0x3F;
} else if (type == RDB_14BITLEN) {
/* Read a 14 bit len. */
if (rioRead(rdb,buf+1,1) == 0) return RDB_LENERR;
return ((buf[0]&0x3F)<<8)|buf[1];
if (rioRead(rdb,buf+1,1) == 0) return -1;
*lenptr = ((buf[0]&0x3F)<<8)|buf[1];
} else if (buf[0] == RDB_32BITLEN) {
/* Read a 32 bit len. */
uint32_t len;
if (rioRead(rdb,&len,4) == 0) return RDB_LENERR;
return ntohl(len);
if (rioRead(rdb,&len,4) == 0) return -1;
*lenptr = ntohl(len);
} else if (buf[0] == RDB_64BITLEN) {
/* Read a 64 bit len. */
uint64_t len;
if (rioRead(rdb,&len,8) == 0) return RDB_LENERR;
return ntohu64(len);
if (rioRead(rdb,&len,8) == 0) return -1;
*lenptr = ntohu64(len);
} else {
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
@ -299,7 +318,7 @@ ssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
void *rdbLoadLzfStringObject(rio *rdb, int flags) {
int plain = flags & RDB_LOAD_PLAIN;
int sds = flags & RDB_LOAD_SDS;
unsigned int len, clen;
uint64_t len, clen;
unsigned char *c = NULL;
char *val = NULL;
@ -414,7 +433,7 @@ void *rdbGenericLoadStringObject(rio *rdb, int flags) {
int plain = flags & RDB_LOAD_PLAIN;
int sds = flags & RDB_LOAD_SDS;
int isencoded;
uint32_t len;
uint64_t len;
len = rdbLoadLen(rdb,&isencoded);
if (isencoded) {
@ -1291,7 +1310,7 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
}
int rdbLoad(char *filename) {
uint32_t dbid;
uint64_t dbid;
int type, rdbver;
redisDb *db = server.db+0;
char buf[1024];
@ -1364,7 +1383,7 @@ int rdbLoad(char *filename) {
} else if (type == RDB_OPCODE_RESIZEDB) {
/* RESIZEDB: Hint about the size of the keys in the currently
* 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)
goto eoferr;
if ((expires_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)

View File

@ -59,7 +59,7 @@
#define RDB_32BITLEN 0x80
#define RDB_64BITLEN 0x81
#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
* 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;
}
static uint32_t loadLength(int *isencoded) {
static uint64_t loadLength(int *isencoded) {
unsigned char buf[2];
uint32_t len;
int type;
@ -190,10 +190,16 @@ static uint32_t loadLength(int *isencoded) {
/* Read a 14 bit len */
if (!readBytes(buf+1,1)) return RDB_LENERR;
return ((buf[0] & 0x3F) << 8) | buf[1];
} else {
} else if (buf[0] == RDB_32BITLEN) {
/* Read a 32 bit len */
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() {
unsigned int slen, clen;
uint64_t slen, clen;
char *c, *s;
if ((clen = loadLength(NULL)) == RDB_LENERR) return NULL;
@ -254,9 +260,9 @@ static char* loadLzfStringObject() {
/* returns NULL when not processable, char* when valid */
static char* loadStringObject() {
uint32_t offset = CURR_OFFSET;
uint64_t offset = CURR_OFFSET;
uint64_t len;
int isencoded;
uint32_t len;
len = loadLength(&isencoded);
if (isencoded) {
@ -269,7 +275,7 @@ static char* loadStringObject() {
return loadLzfStringObject();
default:
/* unknown encoding */
SHIFT_ERROR(offset, "Unknown string encoding (0x%02x)", len);
SHIFT_ERROR(offset, "Unknown string encoding (0x%02llx)", len);
return NULL;
}
}
@ -344,8 +350,8 @@ static int processDoubleValue(double** store) {
}
static int loadPair(entry *e) {
uint32_t offset = CURR_OFFSET;
uint32_t i;
uint64_t offset = CURR_OFFSET;
uint64_t i;
/* read key first */
char *key;
@ -356,7 +362,7 @@ static int loadPair(entry *e) {
return 0;
}
uint32_t length = 0;
uint64_t length = 0;
if (e->type == RDB_TYPE_LIST ||
e->type == RDB_TYPE_SET ||
e->type == RDB_TYPE_ZSET ||
@ -384,7 +390,7 @@ static int loadPair(entry *e) {
for (i = 0; i < length; i++) {
offset = CURR_OFFSET;
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;
}
}
@ -393,12 +399,12 @@ static int loadPair(entry *e) {
for (i = 0; i < length; i++) {
offset = CURR_OFFSET;
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;
}
offset = CURR_OFFSET;
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;
}
}
@ -407,12 +413,12 @@ static int loadPair(entry *e) {
for (i = 0; i < length; i++) {
offset = CURR_OFFSET;
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;
}
offset = CURR_OFFSET;
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;
}
}
@ -428,7 +434,7 @@ static int loadPair(entry *e) {
static entry loadEntry() {
entry e = { NULL, -1, 0 };
uint32_t length, offset[4];
uint64_t length, offset[4];
/* reset error container */
errors.level = 0;
@ -445,7 +451,7 @@ static entry loadEntry() {
return e;
}
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;
}
} else if (e.type == RDB_OPCODE_EOF) {