Integer overflow / Memory allocation size risk leading to potential DoS
Description
The commit fixes an integer-overflow bypass in lpSafeToAdd by replacing the len + add > LISTPACK_MAX_SAFETY_SIZE check with an overflow-safe comparison (add > max or len > max - add). The old check could be bypassed when add is near SIZE_MAX and len is near the safety cap, allowing a listpack growth request that would exceed the 1GB safety cap to be considered valid. This addresses a memory-allocation size safety issue that could enable denial-of-service via large or crafted allocations.
Proof of Concept
C proof-of-concept harness illustrating the issue (old vs new). The PoC demonstrates how the pre-fix logic can incorrectly accept an addition when add is SIZE_MAX and len is chosen so that len + add wraps around, while the post-fix logic rejects it.
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#define LISTPACK_MAX_SAFETY_SIZE (1u<<30) // 1GB safety cap used by Redis listpack
int safe_to_add_old(size_t len, size_t add) {
// Vulnerable check (pre-fix): potential overflow bypass
return (len + add) > LISTPACK_MAX_SAFETY_SIZE;
}
int safe_to_add_new(size_t len, size_t add) {
// Fixed check (post-fix): overflow-safe
return (add > LISTPACK_MAX_SAFETY_SIZE) || (len > LISTPACK_MAX_SAFETY_SIZE - add);
}
int main(void) {
size_t len = LISTPACK_MAX_SAFETY_SIZE - 5; // near the cap
size_t add = SIZE_MAX; // near/at maximum of size_t
int old_result = safe_to_add_old(len, add);
int new_result = safe_to_add_new(len, add);
printf("old (vulnerable) = %d (len=%zu, add=%zu)\n", old_result, len, add);
printf("new (fixed) = %d (len=%zu, add=%zu)\n", new_result, len, add);
return 0;
}
Expected outcome:
- Before the fix: old_result evaluates to 1 (true), meaning the unsafe path would allow adding beyond the safety cap due to overflow semantics.
- After the fix: new_result evaluates to 0 (false), preventing the unsafe allocation path.
Commit Details
Author: Guy Korland
Date: 2026-03-16 11:51 UTC
Message:
Fix safety check in lpSafeToAdd size_t Addition Overflow Bypass (#14888)
Fixes an integer-overflow bypass in `lpSafeToAdd` by replacing the
`len + add` limit check with an overflow-safe comparison (`add > max` or
`len > max - add`). This ensures listpack growth is consistently
rejected when the requested addition would exceed the 1GB safety cap,
even when `add` is near `SIZE_MAX`.
Triage Assessment
Vulnerability Type: Integer overflow / Memory safety (allocation size) and potential DoS
Confidence: HIGH
Reasoning:
The commit fixes an integer-overflow bypass in the lpSafeToAdd function by replacing a simple len + add check with an overflow-safe comparison. This prevents creating an allocation size that exceeds the 1GB safety cap even when add is near SIZE_MAX, addressing a potential memory safety and denial-of-service risk.
Verification Assessment
Vulnerability Type: Integer overflow / Memory allocation size risk leading to potential DoS
Confidence: HIGH
Affected Versions: 8.6.2 and earlier in the 8.6.x series (e.g., 8.6.0, 8.6.1)
Code Diff
diff --git a/src/listpack.c b/src/listpack.c
index ca51c217a76..4d0e72c431d 100644
--- a/src/listpack.c
+++ b/src/listpack.c
@@ -123,7 +123,7 @@ static inline void lpAssertValidEntry(unsigned char* lp, size_t lpbytes, unsigne
#define LISTPACK_MAX_SAFETY_SIZE (1<<30)
int lpSafeToAdd(unsigned char* lp, size_t add) {
size_t len = lp? lpGetTotalBytes(lp): 0;
- if (len + add > LISTPACK_MAX_SAFETY_SIZE)
+ if (add > LISTPACK_MAX_SAFETY_SIZE || len > LISTPACK_MAX_SAFETY_SIZE - add)
return 0;
return 1;
}