From b69f619f17af5c474643e222a63a89d5df1c7bad Mon Sep 17 00:00:00 2001 From: sundb Date: Fri, 20 Aug 2021 15:37:45 +0800 Subject: [PATCH] Sanitize dump payload: fix double free after insert dup nodekey to stream rax and returns 0 (#9399) (cherry picked from commit 492d8d09613cff88f15dcef98732392b8d509eb1) --- src/rdb.c | 7 ++++--- tests/integration/corrupt-dump.tcl | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/rdb.c b/src/rdb.c index 3cc84f64f..3a1eeb915 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -2072,7 +2072,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int *error) { } /* Insert the key in the radix tree. */ - int retval = raxInsert(s->rax, + int retval = raxTryInsert(s->rax, (unsigned char*)nodekey,sizeof(streamID),lp,NULL); sdsfree(nodekey); if (!retval) { @@ -2161,7 +2161,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int *error) { streamFreeNACK(nack); return NULL; } - if (!raxInsert(cgroup->pel,rawid,sizeof(rawid),nack,NULL)) { + if (!raxTryInsert(cgroup->pel,rawid,sizeof(rawid),nack,NULL)) { rdbReportCorruptRDB("Duplicated global PEL entry " "loading stream consumer group"); decrRefCount(o); @@ -2225,11 +2225,12 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int *error) { * loading the global PEL. Then set the same shared * NACK structure also in the consumer-specific PEL. */ nack->consumer = consumer; - if (!raxInsert(consumer->pel,rawid,sizeof(rawid),nack,NULL)) { + if (!raxTryInsert(consumer->pel,rawid,sizeof(rawid),nack,NULL)) { rdbReportCorruptRDB("Duplicated consumer PEL entry " " loading a stream consumer " "group"); decrRefCount(o); + streamFreeNACK(nack); return NULL; } } diff --git a/tests/integration/corrupt-dump.tcl b/tests/integration/corrupt-dump.tcl index 75bdf0f7f..fbdd3c373 100644 --- a/tests/integration/corrupt-dump.tcl +++ b/tests/integration/corrupt-dump.tcl @@ -688,5 +688,15 @@ test {corrupt payload: fuzzer findings - hash with len of 0} { } } +test {corrupt payload: fuzzer findings - stream double free listpack when insert dup node to rax returns 0} { + start_server [list overrides [list loglevel verbose use-exit-on-panic yes crash-memcheck-enabled no] ] { + r debug set-skip-checksum-validation 1 + r config set sanitize-dump-payload yes + catch { r restore _stream 0 "\x0F\x03\x10\x00\x00\x01\x7B\x60\x5A\x23\x79\x00\x00\x00\x00\x00\x00\x00\x00\xC3\x40\x4F\x40\x5C\x18\x5C\x00\x00\x00\x24\x00\x05\x01\x00\x01\x02\x01\x84\x69\x74\x65\x6D\x05\x85\x76\x61\x6C\x75\x65\x06\x40\x10\x00\x00\x20\x01\x00\x01\x20\x03\x00\x05\x20\x1C\x40\x09\x05\x01\x01\x82\x5F\x31\x03\x80\x0D\x00\x02\x20\x0D\x00\x02\xA0\x19\x00\x03\x20\x0B\x02\x82\x5F\x33\xA0\x19\x00\x04\x20\x0D\x00\x04\x20\x19\x00\xFF\x10\x00\x00\x01\x7B\x60\x5A\x23\x79\x00\x00\x00\x00\x00\x00\x00\x05\xC3\x40\x51\x40\x5E\x18\x5E\x00\x00\x00\x24\x00\x05\x01\x00\x01\x02\x01\x84\x69\x74\x65\x6D\x05\x85\x76\x61\x6C\x75\x65\x06\x40\x10\x00\x00\x20\x01\x06\x01\x01\x82\x5F\x35\x03\x05\x20\x1E\x40\x0B\x03\x01\x01\x06\x01\x80\x0B\x00\x02\x20\x0B\x02\x82\x5F\x37\xA0\x19\x00\x03\x20\x0D\x00\x08\xA0\x19\x00\x04\x20\x0B\x02\x82\x5F\x39\x20\x19\x00\xFF\x10\x00\x00\x01\x7B\x60\x5A\x23\x79\x00\x00\x00\x00\x00\x00\x00\x00\xC3\x3B\x40\x49\x18\x49\x00\x00\x00\x15\x00\x02\x01\x00\x01\x02\x01\x84\x69\x74\x65\x6D\x05\x85\x76\x61\x6C\x75\x65\x06\x40\x10\x00\x00\x20\x01\x40\x00\x00\x05\x20\x07\x40\x09\xC0\x22\x09\x01\x01\x86\x75\x6E\x69\x71\x75\x65\x07\xA0\x2C\x02\x08\x01\xFF\x0C\x81\x00\x00\x01\x7B\x60\x5A\x23\x7A\x01\x00\x09\x00\x9C\x8F\x1E\xBF\x2E\x05\x59\x09" replace } err + assert_match "*Bad data format*" $err + r ping + } +} + } ;# tags