Clean up lookahead-related code#34
Conversation
Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
Review Summary by QodoRefactor cluster slot handling and unify slot extraction logic
WalkthroughsDescription• Rename GETSLOT_CROSSSLOT constant to CLUSTER_CROSSSLOT for consistency • Unify slot extraction logic by refactoring getSlotFromCommand to use extractSlotFromKeysResult • Fix cluster slot status check by replacing magic number -1 with INVALID_CLUSTER_SLOT • Improve extractSlotFromKeysResult to handle cluster disabled state and return proper error codes Diagramflowchart LR
A["getSlotFromCommand"] -->|"now uses"| B["extractSlotFromKeysResult"]
B -->|"returns"| C["CLUSTER_CROSSSLOT or INVALID_CLUSTER_SLOT"]
D["Magic number -1"] -->|"replaced with"| E["INVALID_CLUSTER_SLOT constant"]
F["GETSLOT_CROSSSLOT"] -->|"renamed to"| G["CLUSTER_CROSSSLOT"]
File Changes1. src/cluster.h
|
Code Review by Qodo
1. Direct malloc/free in extractSlotFromKeysResult
|
| int *slot_buffer = malloc(sizeof(int) * keys_result->numkeys); | ||
|
|
||
| for (int j = 0; j <= keys_result->numkeys; j++) { | ||
| robj *this_key = argv[keys_result->keys[j].pos]; | ||
| int this_slot = (int)keyHashSlot((char*)this_key->ptr, sdslen(this_key->ptr)); | ||
| slot_buffer[j] = this_slot; | ||
|
|
||
| if (first_slot == INVALID_CLUSTER_SLOT) | ||
| first_slot = this_slot; | ||
| else if (first_slot != this_slot) { | ||
| return INVALID_CLUSTER_SLOT; | ||
| free(slot_buffer); | ||
| return CLUSTER_CROSSSLOT; | ||
| } | ||
| } | ||
| free(slot_buffer); |
There was a problem hiding this comment.
1. Direct malloc/free in extractslotfromkeysresult 📘 Rule violation ⛯ Reliability
The new code allocates and frees memory using malloc()/free() in src/, which bypasses Redis memory tracking. This violates the requirement to use the zmalloc/zfree family for all dynamic allocations in src/.
Agent Prompt
## Issue description
`src/cluster.c` introduces a new temporary buffer allocated with `malloc()` and released with `free()`, which violates the requirement to use Redis's `zmalloc`/`zfree` family in `src/` for memory tracking.
## Issue Context
Redis requires `zmalloc`-family allocators in `src/` to ensure memory accounting and consistent allocation behavior.
## Fix Focus Areas
- src/cluster.c[1110-1124]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| /* Allocate temporary buffer for slot tracking */ | ||
| int *slot_buffer = malloc(sizeof(int) * keys_result->numkeys); | ||
|
|
||
| for (int j = 0; j <= keys_result->numkeys; j++) { | ||
| robj *this_key = argv[keys_result->keys[j].pos]; | ||
| int this_slot = (int)keyHashSlot((char*)this_key->ptr, sdslen(this_key->ptr)); | ||
| slot_buffer[j] = this_slot; | ||
|
|
There was a problem hiding this comment.
2. Slot loop buffer overflow 🐞 Bug ⛨ Security
extractSlotFromKeysResult allocates slot_buffer for numkeys elements but loops with j <= numkeys, reading keys_result->keys[numkeys] and writing slot_buffer[numkeys], causing out-of-bounds memory access and potential heap corruption/crash during command processing. It also uses plain malloc without Redis’s OOM handler, so malloc failure would lead to NULL dereference.
Agent Prompt
### Issue description
`extractSlotFromKeysResult()` currently performs out-of-bounds reads/writes due to an off-by-one loop (`j <= numkeys`) combined with a buffer sized for exactly `numkeys`. This can corrupt the heap or crash Redis on common multi-key commands in cluster mode; it also introduces an unchecked `malloc()` in a hot path.
### Issue Context
`getKeysResult->keys` is indexed by `numkeys` count, so valid indices are `[0..numkeys-1]`. The current code also allocates `slot_buffer` but never uses it for logic, so it can be removed entirely.
### Fix Focus Areas
- src/cluster.c[1103-1125]
### Expected fix
- Change the loop to `for (int j = 0; j < keys_result->numkeys; j++)`.
- Remove `slot_buffer` completely (since it is not used) to avoid per-call heap allocation and eliminate NULL/OOM handling concerns.
- If a buffer is truly needed, use `zmalloc` and check sizes/indices carefully, but prefer no allocation here.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Benchmark PR from agentic-review-benchmarks#3