diff options
author | Binbin <binloveplay1314@qq.com> | 2022-11-22 17:20:24 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-22 11:20:24 +0200 |
commit | 3f8756a06ae48258779ffc7cbef605a3ec0a926f (patch) | |
tree | ed1c60b5e87fd74b030362b9b60ee43296eaaba6 /tests/integration | |
parent | 0f85713174150044e17d2c4dfbcaaf7f7475f333 (diff) | |
download | redis-3f8756a06ae48258779ffc7cbef605a3ec0a926f.tar.gz |
Fix set with duplicate elements causes sdiff to hang (#11530)
This payload produces a set with duplicate elements (listpack encoding):
```
restore _key 0 "\x14\x25\x25\x00\x00\x00\x0A\x00\x06\x01\x82\x5F\x35\x03\x04\x01\x82\x5F\x31\x03\x82\x5F\x33\x03\x00\x01\x82\x5F\x39\x03\x82\x5F\x33\x03\x08\x01\x02\x01\xFF\x0B\x00\x31\xBE\x7D\x41\x01\x03\x5B\xEC"
smembers key
1) "6"
2) "_5"
3) "4"
4) "_1"
5) "_3" ---> dup
6) "0"
7) "_9"
8) "_3" ---> dup
9) "8"
10) "2"
```
This kind of sets will cause SDIFF to hang, SDIFF generated a broken
protocol and left the client hung. (Expected ten elements, but only
got nine elements due to the duplication.)
If we set `sanitize-dump-payload` to yes, we will be able to find
the duplicate elements and report "ERR Bad data format".
Discovered and discussed in #11290.
This PR also improve prints when corrupt-dump-fuzzer hangs, it will
print the cmds and the payload, an example like:
```
Testing integration/corrupt-dump-fuzzer
[TIMEOUT]: clients state report follows.
sock6 => (SPAWNED SERVER) pid:28884
Killing still running Redis server 28884
commands caused test to hang:
SDIFF __key
payload that caused test to hang: "\x14\balabala"
```
Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'tests/integration')
-rw-r--r-- | tests/integration/corrupt-dump-fuzzer.tcl | 13 | ||||
-rw-r--r-- | tests/integration/corrupt-dump.tcl | 19 |
2 files changed, 31 insertions, 1 deletions
diff --git a/tests/integration/corrupt-dump-fuzzer.tcl b/tests/integration/corrupt-dump-fuzzer.tcl index 7c3b90969..9cd4ff913 100644 --- a/tests/integration/corrupt-dump-fuzzer.tcl +++ b/tests/integration/corrupt-dump-fuzzer.tcl @@ -147,10 +147,21 @@ foreach sanitize_dump {no yes} { if {$dbsize != [r dbsize]} { puts "unexpected keys" puts "keys: [r keys *]" - puts $sent + puts "commands leading to it:" + foreach cmd $sent { + foreach arg $cmd { + puts -nonewline "[string2printable $arg] " + } + puts "" + } exit 1 } } err ] } { + set err [format "%s" $err] ;# convert to string for pattern matching + if {[string match "*SIGTERM*" $err]} { + puts "payload that caused test to hang: $printable_dump" + exit 1 + } # if the server terminated update stats and restart it set report_and_restart true incr stat_terminated_in_traffic diff --git a/tests/integration/corrupt-dump.tcl b/tests/integration/corrupt-dump.tcl index ef878457a..35dca23be 100644 --- a/tests/integration/corrupt-dump.tcl +++ b/tests/integration/corrupt-dump.tcl @@ -810,5 +810,24 @@ test {corrupt payload: fuzzer findings - empty set listpack} { } } +test {corrupt payload: fuzzer findings - set with duplicate elements causes sdiff to hang} { + 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 + catch {r restore _key 0 "\x14\x25\x25\x00\x00\x00\x0A\x00\x06\x01\x82\x5F\x35\x03\x04\x01\x82\x5F\x31\x03\x82\x5F\x33\x03\x00\x01\x82\x5F\x39\x03\x82\x5F\x33\x03\x08\x01\x02\x01\xFF\x0B\x00\x31\xBE\x7D\x41\x01\x03\x5B\xEC" replace} err + assert_match "*Bad data format*" $err + r ping + + # In the past, it generated a broken protocol and left the client hung in sdiff + r config set sanitize-dump-payload no + assert_equal {OK} [r restore _key 0 "\x14\x25\x25\x00\x00\x00\x0A\x00\x06\x01\x82\x5F\x35\x03\x04\x01\x82\x5F\x31\x03\x82\x5F\x33\x03\x00\x01\x82\x5F\x39\x03\x82\x5F\x33\x03\x08\x01\x02\x01\xFF\x0B\x00\x31\xBE\x7D\x41\x01\x03\x5B\xEC" replace] + assert_type set _key + assert_encoding listpack _key + assert_equal 10 [r scard _key] + assert_equal {0 2 4 6 8 _1 _3 _3 _5 _9} [lsort [r smembers _key]] + assert_equal {0 2 4 6 8 _1 _3 _5 _9} [lsort [r sdiff _key]] + } +} + } ;# tags |