Skip to content

Commit 0fa8098

Browse files
Additional overflow protection for MAP/ATTR
There is already overflow protection for multibulk `elements` but the new RESP3 `MAP` and `ATTR` types subsequently double the count. This meant that a malicious or erroneous count of `LLONG_MAX / 2 + 1` would end up overflowing when maxelements = 0. Signed-off-by: michael-grunder <michael.grunder@gmail.com>
1 parent cb0aa80 commit 0fa8098

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/read.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,23 @@ static int processAggregateItem(valkeyReader *r) {
556556

557557
moveToNextTask(r);
558558
} else {
559-
if (cur->type == VALKEY_REPLY_MAP || cur->type == VALKEY_REPLY_ATTR)
559+
if (cur->type == VALKEY_REPLY_MAP ||
560+
cur->type == VALKEY_REPLY_ATTR) {
561+
562+
long long maxelements = LLONG_MAX / 2;
563+
if (LLONG_MAX > SIZE_MAX &&
564+
maxelements > (long long)(SIZE_MAX / 2)) {
565+
maxelements = (long long)(SIZE_MAX / 2);
566+
}
567+
568+
if (elements > maxelements) {
569+
valkeyReaderSetError(r, VALKEY_ERR_PROTOCOL,
570+
"Multi-bulk length out of range");
571+
return VALKEY_ERR;
572+
}
573+
560574
elements *= 2;
575+
}
561576

562577
if (r->fn && r->fn->createArray)
563578
obj = r->fn->createArray(cur, elements);

tests/client_test.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,16 @@ static void test_reply_reader(void) {
872872
freeReplyObject(reply);
873873
valkeyReaderFree(reader);
874874

875+
/* RESP3 MAP/ATTR types double the element count being key-value pairs */
876+
test("A RESP3 MAP/ATTR can't overflow: ");
877+
reader = valkeyReaderCreate();
878+
reader->maxelements = 0; /* Don't rely on default limit */
879+
valkeyReaderFeed(reader, "%4611686018427387904\r\n", 22);
880+
ret = valkeyReaderGetReply(reader, &reply);
881+
test_cond(ret == VALKEY_ERR &&
882+
strcasecmp(reader->errstr, "Multi-bulk length out of range") == 0);
883+
valkeyReaderFree(reader);
884+
875885
test("Can parse RESP3 attribute: ");
876886
reader = valkeyReaderCreate();
877887
valkeyReaderFeed(reader, "|2\r\n+foo\r\n:123\r\n+bar\r\n#t\r\n", 26);

0 commit comments

Comments
 (0)