Improve dbid range check for SELECT, MOVE, COPY ()

SELECT used to read the index into a `long` variable, and then pass it to a function
that takes an `int`, possibly causing an overflow before the range check.

Now all these commands use better and cleaner range check, and that also results in
a slight change of the error response in case of an invalid database index.

SELECT:
in the past it would have returned either `-ERR invalid DB index` (if not a number),
or `-ERR DB index is out of range` (if not between 1..16 or alike).
now it'll return either `-ERR value is out of range` (if not a number), or
`-ERR value is out of range, value must between -2147483648 and 2147483647`
(if not in the range for an int), or `-ERR DB index is out of range`
(if not between 0..16 or alike)


MOVE:
in the past it would only fail with `-ERR index out of range` no matter the reason.
now return the same errors as the new ones for SELECT mentioned above.
(i.e. unlike for SELECT even for a value like 17 we changed the error message)

COPY:
doesn't really matter how it behaved in the past (new command), new behavior is
like the above two.
This commit is contained in:
sundb 2020-12-02 03:41:26 +08:00 committed by GitHub
parent c1b1e8c329
commit 3ba2281f96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 19 deletions

@ -600,10 +600,9 @@ void existsCommand(client *c) {
}
void selectCommand(client *c) {
long id;
int id;
if (getLongFromObjectOrReply(c, c->argv[1], &id,
"invalid DB index") != C_OK)
if (getIntFromObjectOrReply(c, c->argv[1], &id, NULL) != C_OK)
return;
if (server.cluster_enabled && id != 0) {
@ -1022,8 +1021,8 @@ void renamenxCommand(client *c) {
void moveCommand(client *c) {
robj *o;
redisDb *src, *dst;
int srcid;
long long dbid, expire;
int srcid, dbid;
long long expire;
if (server.cluster_enabled) {
addReplyError(c,"MOVE is not allowed in cluster mode");
@ -1034,11 +1033,11 @@ void moveCommand(client *c) {
src = c->db;
srcid = c->db->id;
if (getLongLongFromObject(c->argv[2],&dbid) == C_ERR ||
dbid < INT_MIN || dbid > INT_MAX ||
selectDb(c,dbid) == C_ERR)
{
addReply(c,shared.outofrangeerr);
if (getIntFromObjectOrReply(c, c->argv[2], &dbid, NULL) != C_OK)
return;
if (selectDb(c,dbid) == C_ERR) {
addReplyError(c,"DB index is out of range");
return;
}
dst = c->db;
@ -1084,8 +1083,8 @@ void moveCommand(client *c) {
void copyCommand(client *c) {
robj *o;
redisDb *src, *dst;
int srcid;
long long dbid, expire;
int srcid, dbid;
long long expire;
int j, replace = 0, delete = 0;
/* Obtain source and target DB pointers
@ -1100,11 +1099,11 @@ void copyCommand(client *c) {
if (!strcasecmp(c->argv[j]->ptr,"replace")) {
replace = 1;
} else if (!strcasecmp(c->argv[j]->ptr, "db") && additional >= 1) {
if (getLongLongFromObject(c->argv[j+1], &dbid) == C_ERR ||
dbid < INT_MIN || dbid > INT_MAX ||
selectDb(c, dbid) == C_ERR)
{
addReplyError(c,"invalid DB index");
if (getIntFromObjectOrReply(c, c->argv[j+1], &dbid, NULL) != C_OK)
return;
if (selectDb(c, dbid) == C_ERR) {
addReplyError(c,"DB index is out of range");
return;
}
dst = c->db;

@ -747,6 +747,16 @@ int getPositiveLongFromObjectOrReply(client *c, robj *o, long *target, const cha
return getRangeLongFromObjectOrReply(c, o, 0, LONG_MAX, target, msg);
}
int getIntFromObjectOrReply(client *c, robj *o, int *target, const char *msg) {
long value;
if (getRangeLongFromObjectOrReply(c, o, INT_MIN, INT_MAX, &value, msg) != C_OK)
return C_ERR;
*target = value;
return C_OK;
}
char *strEncoding(int encoding) {
switch(encoding) {
case OBJ_ENCODING_RAW: return "raw";

@ -1872,6 +1872,7 @@ int getDoubleFromObject(const robj *o, double *target);
int getLongLongFromObject(robj *o, long long *target);
int getLongDoubleFromObject(robj *o, long double *target);
int getLongDoubleFromObjectOrReply(client *c, robj *o, long double *target, const char *msg);
int getIntFromObjectOrReply(client *c, robj *o, int *target, const char *msg);
char *strEncoding(int encoding);
int compareStringObjects(robj *a, robj *b);
int collateStringObjects(robj *a, robj *b);

@ -217,7 +217,7 @@ start_server {tags {"keyspace"}} {
r set mykey foobar
catch {r copy mykey mynewkey DB notanumber} e
set e
} {*ERR*invalid DB index}
} {ERR value is not an integer or out of range}
test {COPY can copy key expire metadata as well} {
r set mykey foobar ex 100
@ -398,7 +398,7 @@ start_server {tags {"keyspace"}} {
r set mykey hello
catch {r move mykey notanumber} e
set e
} {*ERR*index out of range}
} {ERR value is not an integer or out of range}
test {MOVE can move key expire metadata as well} {
r select 10