diff --git a/src/ziplist.c b/src/ziplist.c index 62ffcb93d..0cd20630a 100644 --- a/src/ziplist.c +++ b/src/ziplist.c @@ -1506,6 +1506,9 @@ void ziplistRandomPair(unsigned char *zl, unsigned long total_count, ziplistEntr int ret; unsigned char *p; + /* Avoid div by zero on corrupt ziplist */ + assert(total_count); + /* Generate even numbers, because ziplist saved K-V pair */ int r = (rand() % total_count) * 2; p = ziplistIndex(zl, r); @@ -1545,6 +1548,9 @@ void ziplistRandomPairs(unsigned char *zl, int count, ziplistEntry *keys, ziplis rand_pick *picks = zmalloc(sizeof(rand_pick)*count); unsigned long total_size = ziplistLen(zl)/2; + /* Avoid div by zero on corrupt ziplist */ + assert(total_size); + /* create a pool of random indexes (some may be duplicate). */ for (int i = 0; i < count; i++) { picks[i].index = (rand() % total_size) * 2; /* Generate even indexes */ diff --git a/tests/integration/corrupt-dump.tcl b/tests/integration/corrupt-dump.tcl index cc597bb4d..f5079e5ed 100644 --- a/tests/integration/corrupt-dump.tcl +++ b/tests/integration/corrupt-dump.tcl @@ -507,5 +507,16 @@ test {corrupt payload: fuzzer findings - valgrind invalid read} { } } +test {corrupt payload: fuzzer findings - HRANDFIELD on bad ziplist} { + start_server [list overrides [list loglevel verbose use-exit-on-panic yes crash-memcheck-enabled no] ] { + r config set sanitize-dump-payload yes + r debug set-skip-checksum-validation 1 + r RESTORE _int 0 "\x04\xC0\x01\x09\x00\xF6\x8A\xB6\x7A\x85\x87\x72\x4D" + catch {r HRANDFIELD _int} + assert_equal [count_log_message 0 "crashed by signal"] 0 + assert_equal [count_log_message 0 "ASSERTION FAILED"] 1 + } +} + } ;# tags diff --git a/tests/support/util.tcl b/tests/support/util.tcl index 943f45a2b..80f8598ce 100644 --- a/tests/support/util.tcl +++ b/tests/support/util.tcl @@ -12,7 +12,11 @@ proc randstring {min max {type binary}} { set maxval 52 } while {$len} { - append output [format "%c" [expr {$minval+int(rand()*($maxval-$minval+1))}]] + set rr [expr {$minval+int(rand()*($maxval-$minval+1))}] + if {$type eq {alpha} && $rr eq 92} { + set rr 90; # avoid putting '\' char in the string, it can mess up TCL processing + } + append output [format "%c" $rr] incr len -1 } return $output