Unverified Commit 210ad2e4 authored by Moti Cohen's avatar Moti Cohen Committed by GitHub
Browse files

Improve BLMPOP/BZMPOP/WAIT timeout overflow handling and error messages (#11338)



Refine getTimeoutFromObjectOrReply() out-of-range check.

Timeout is parsed (and verifies out of range) as double and
multiplied by 1000, added mstime() and stored in long-long
which might lead to out-of-range value of long-long.
Co-authored-by: default avatarmoticless <moticless@github.com>
Co-authored-by: default avatarOran Agra <oran@redislabs.com>
Co-authored-by: default avatarOzan Tezcan <ozantezcan@gmail.com>
parent b08ebff3
...@@ -164,12 +164,19 @@ void handleBlockedClientsTimeout(void) { ...@@ -164,12 +164,19 @@ void handleBlockedClientsTimeout(void) {
int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit) { int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit) {
long long tval; long long tval;
long double ftval; long double ftval;
mstime_t now = mstime();
if (unit == UNIT_SECONDS) { if (unit == UNIT_SECONDS) {
if (getLongDoubleFromObjectOrReply(c,object,&ftval, if (getLongDoubleFromObjectOrReply(c,object,&ftval,
"timeout is not a float or out of range") != C_OK) "timeout is not a float or out of range") != C_OK)
return C_ERR; return C_ERR;
tval = (long long) (ftval * 1000.0);
ftval *= 1000.0; /* seconds => millisec */
if (ftval > LLONG_MAX) {
addReplyError(c, "timeout is out of range");
return C_ERR;
}
tval = (long long) ftval;
} else { } else {
if (getLongLongFromObjectOrReply(c,object,&tval, if (getLongLongFromObjectOrReply(c,object,&tval,
"timeout is not an integer or out of range") != C_OK) "timeout is not an integer or out of range") != C_OK)
...@@ -182,7 +189,11 @@ int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int ...@@ -182,7 +189,11 @@ int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int
} }
if (tval > 0) { if (tval > 0) {
tval += mstime(); if (tval > LLONG_MAX - now) {
addReplyError(c,"timeout is out of range"); /* 'tval+now' would overflow */
return C_ERR;
}
tval += now;
} }
*timeout = tval; *timeout = tval;
......
...@@ -1215,6 +1215,14 @@ foreach {pop} {BLPOP BLMPOP_LEFT} { ...@@ -1215,6 +1215,14 @@ foreach {pop} {BLPOP BLMPOP_LEFT} {
} {foo{t} aguacate} } {foo{t} aguacate}
} }
test "BLPOP: timeout value out of range" {
# Timeout is parsed as float and multiplied by 1000, added mstime()
# and stored in long-long which might lead to out-of-range value.
# (Even though given timeout is smaller than LLONG_MAX, the result
# will be bigger)
assert_error "ERR *is out of range*" {r BLPOP blist1 0x7FFFFFFFFFFFFF}
}
foreach {pop} {BLPOP BRPOP BLMPOP_LEFT BLMPOP_RIGHT} { foreach {pop} {BLPOP BRPOP BLMPOP_LEFT BLMPOP_RIGHT} {
test "$pop: with single empty list argument" { test "$pop: with single empty list argument" {
set rd [redis_deferring_client] set rd [redis_deferring_client]
......
...@@ -19,6 +19,19 @@ start_server {} { ...@@ -19,6 +19,19 @@ start_server {} {
} }
} }
test {WAIT out of range timeout (milliseconds)} {
# Timeout is parsed as milliseconds by getLongLongFromObjectOrReply().
# Verify we get out of range message if value is behind LLONG_MAX
# (decimal value equals to 0x8000000000000000)
assert_error "*or out of range*" {$master wait 2 9223372036854775808}
# expected to fail by later overflow condition after addition
# of mstime(). (decimal value equals to 0x7FFFFFFFFFFFFFFF)
assert_error "*timeout is out of range*" {$master wait 2 9223372036854775807}
assert_error "*timeout is negative*" {$master wait 2 -1}
}
test {WAIT should acknowledge 1 additional copy of the data} { test {WAIT should acknowledge 1 additional copy of the data} {
$master set foo 0 $master set foo 0
$master incr foo $master incr foo
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment