Skip to content

Fix invalid memory access in RESTORE with malformed zipmap (CVE-2026-25243)#3621

Merged
madolson merged 2 commits into
valkey-io:9.0from
ranshid:9.0.0-CVE-2026-25243
May 5, 2026
Merged

Fix invalid memory access in RESTORE with malformed zipmap (CVE-2026-25243)#3621
madolson merged 2 commits into
valkey-io:9.0from
ranshid:9.0.0-CVE-2026-25243

Conversation

@ranshid

@ranshid ranshid commented May 5, 2026

Copy link
Copy Markdown
Member

Changes applied (3 files):

  1. src/zipmap.c: Add sanity checks in zipmapValidateIntegrity() to reject entries where the decoded length < ZIPMAP_BIGLEN (254) but the encoding uses more than 1 byte. This prevents a pointer arithmetic mismatch between validation and zipmapNext() that leads to heap buffer over-reads.

  2. src/rdb.c (hash zipmap conversion): Reorder the hashtableAdd()/lpSafeToAdd() checks so lpSafeToAdd() is evaluated before hashtableAdd() takes ownership of the field SDS. Add missing lpFree(lp) in the error path to fix a memory leak when the conversion fails.

  3. src/rdb.c (stream consumer PEL): Remove erroneous streamFreeNACK(nack) in the "Duplicated consumer PEL entry" error path. The nack is a shared reference from the global PEL (obtained via raxFind), so freeing it here causes a double-free when the stream object is later destroyed.

Test: added a regression test in tests/unit/dump.tcl that crafts a RESTORE payload with a 2-entry zipmap where the first field uses an overlong 5-byte length encoding for value 3. Post-patch, this is cleanly rejected by zipmapValidateIntegrity(). Pre-patch, the misaligned zipmapNext() reads garbage (confirmed via server log: "Hash zipmap with dup elements, or big length (0)") which also produces an error, so the test serves as a defense-in-depth regression anchor rather than a strict pass/fail differentiator. The actual heap over-read is detectable with AddressSanitizer builds.

ikolomi and others added 2 commits April 29, 2026 14:06
…25243)

Changes applied (3 files):

1. src/zipmap.c: Add sanity checks in zipmapValidateIntegrity() to reject
   entries where the decoded length < ZIPMAP_BIGLEN (254) but the encoding
   uses more than 1 byte. This prevents a pointer arithmetic mismatch
   between validation and zipmapNext() that leads to heap buffer over-reads.

2. src/rdb.c (hash zipmap conversion): Reorder the hashtableAdd()/lpSafeToAdd()
   checks so lpSafeToAdd() is evaluated before hashtableAdd() takes ownership
   of the field SDS. Add missing lpFree(lp) in the error path to fix a memory
   leak when the conversion fails.

3. src/rdb.c (stream consumer PEL): Remove erroneous streamFreeNACK(nack)
   in the "Duplicated consumer PEL entry" error path. The nack is a shared
   reference from the global PEL (obtained via raxFind), so freeing it here
   causes a double-free when the stream object is later destroyed.

Test: added a regression test in tests/unit/dump.tcl that crafts a
RESTORE payload with a 2-entry zipmap where the first field uses an
overlong 5-byte length encoding for value 3. Post-patch, this is
cleanly rejected by zipmapValidateIntegrity(). Pre-patch, the misaligned
zipmapNext() reads garbage (confirmed via server log: "Hash zipmap with
dup elements, or big length (0)") which also produces an error, so the
test serves as a defense-in-depth regression anchor rather than a strict
pass/fail differentiator. The actual heap over-read is detectable with
AddressSanitizer builds.

Signed-off-by: ikolomi <ikolomin@amazon.com>
@madolson madolson marked this pull request as ready for review May 5, 2026 23:34
@madolson madolson merged commit 949de2a into valkey-io:9.0 May 5, 2026
55 of 68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants