-
Notifications
You must be signed in to change notification settings - Fork 0
Code Review Bench PR #14562 - Clean up lookahead-related code #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: base_pr_14562_20260125_2033
Are you sure you want to change the base?
Code Review Bench PR #14562 - Clean up lookahead-related code #3
Conversation
Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
| /* Allocate temporary buffer for slot tracking */ | ||
| int *slot_buffer = malloc(sizeof(int) * keys_result->numkeys); | ||
|
|
||
| for (int j = 0; j <= keys_result->numkeys; j++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨 Bug: Off-by-one: loop reads past end of keys array and slot_buffer
The loop condition j <= keys_result->numkeys iterates one time too many. When numkeys is N, this accesses keys_result->keys[N] which is out-of-bounds (valid indices are 0..N-1), and writes to slot_buffer[N] which is also out-of-bounds (buffer was allocated for exactly N elements).
This causes:
- Heap buffer overflow writing to
slot_buffer[numkeys](1 element past allocation) - Out-of-bounds read of
keys_result->keys[numkeys].pos, leading to undefined behavior — could crash, corrupt data, or read garbage producing incorrect slot calculations
This is a guaranteed bug for any command with 1+ keys.
Was this helpful? React with 👍 / 👎
| for (int j = 0; j <= keys_result->numkeys; j++) { | |
| for (int j = 0; j < keys_result->numkeys; j++) { |
- Apply suggested fix
| for (int j = 0; j < keys_result->numkeys; j++) { | ||
|
|
||
| /* Allocate temporary buffer for slot tracking */ | ||
| int *slot_buffer = malloc(sizeof(int) * keys_result->numkeys); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚠️ Quality: Unnecessary heap allocation: slot_buffer is written but never read
The slot_buffer array is allocated via malloc, populated in the loop, and then freed — but its contents are never read or used for any purpose. The cross-slot check is done entirely through the first_slot variable.
This introduces:
- An unnecessary
malloc/freepair on every command execution — a hot path in Redis - A potential memory leak if
mallocreturns NULL (no NULL check) — though on Linux with overcommit this is unlikely, it's still undefined behavior to write to a NULL pointer - Additional complexity with no functional benefit
The entire slot_buffer allocation and writes should be removed.
Was this helpful? React with 👍 / 👎
| int *slot_buffer = malloc(sizeof(int) * keys_result->numkeys); | |
| int first_slot = INVALID_CLUSTER_SLOT; | |
| 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)); | |
| if (first_slot == INVALID_CLUSTER_SLOT) | |
| first_slot = this_slot; | |
| else if (first_slot != this_slot) { | |
| return CLUSTER_CROSSSLOT; | |
| } | |
| } | |
| return first_slot; |
- Apply suggested fix
Code Review 🚫 Blocked 0 resolved / 3 findingsClean refactoring of slot constants and logic consolidation, but 🚨 Bug: Off-by-one: loop reads past end of keys array and slot_bufferThe loop condition This causes:
This is a guaranteed bug for any command with 1+ keys. Suggested fix
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
Code Review Bench PR redis#14562 - Clean up lookahead-related code
Benchmark PR for Gitar evaluation
Original PR: agentic-review-benchmarks#3
Clean up lookahead-related code
Summary by Gitar
This PR refactors Redis cluster slot handling to consolidate scattered logic and improve maintainability:
extractSlotFromKeysResult()now returns three distinct values (INVALID_CLUSTER_SLOT, valid slot number, orCLUSTER_CROSSSLOT), eliminating duplicate validation in callersGETSLOT_CROSSSLOT→CLUSTER_CROSSSLOTandGETSLOT_NOKEYS→INVALID_CLUSTER_SLOT, moving them fromserver.htocluster.hgetSlotFromCommand()from 15+ lines to 6 lines by leveraging centralized logic-1comparisons with named constants throughoutcluster_slot_stats.cand other filesCLIENT_READ_CROSS_SLOTflag while unifying the underlying implementation