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: moticless <moticless@github.com> Co-authored-by: Oran Agra <oran@redislabs.com> Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
This commit is contained in:
parent
b08ebff31f
commit
210ad2e4db
@ -164,12 +164,19 @@ void handleBlockedClientsTimeout(void) {
|
||||
int getTimeoutFromObjectOrReply(client *c, robj *object, mstime_t *timeout, int unit) {
|
||||
long long tval;
|
||||
long double ftval;
|
||||
mstime_t now = mstime();
|
||||
|
||||
if (unit == UNIT_SECONDS) {
|
||||
if (getLongDoubleFromObjectOrReply(c,object,&ftval,
|
||||
"timeout is not a float or out of range") != C_OK)
|
||||
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 {
|
||||
if (getLongLongFromObjectOrReply(c,object,&tval,
|
||||
"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
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -1215,6 +1215,14 @@ foreach {pop} {BLPOP BLMPOP_LEFT} {
|
||||
} {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} {
|
||||
test "$pop: with single empty list argument" {
|
||||
set rd [redis_deferring_client]
|
||||
|
@ -18,7 +18,20 @@ start_server {} {
|
||||
fail "Replication not started."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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} {
|
||||
$master set foo 0
|
||||
$master incr foo
|
||||
|
Loading…
x
Reference in New Issue
Block a user