[correctness] Fix LSET modifying elements for out-of-range 64-bit indexes (#4823)

## Problem

  On 64-bit builds, `LSET` parses its index as `long`, but
  `listTypeReplaceAtIndex()` narrowed it to `int`. An out-of-range index
such as `4294967296` became `0`, causing `LSET` to return `OK` and
modify
  the first element instead of returning `ERR index out of range`.

This is a correctness issue affecting both listpack and quicklist lists.

  ## Fix

  Preserve the `long` index through `listTypeReplaceAtIndex()` so an
  out-of-range index returns an error without modifying the list. Add
regression tests for large positive and negative indexes in both
encodings.

  ## Tests

  - `./runtest --single unit/type/list --quiet`: 289 passed, 0 failed.
- Confirmed the command returns `ERR index out of range` and leaves the
    list unchanged after the fix.

  On 32-bit builds, these values are rejected when parsing the `long`
  index; the narrowing bug occurs on 64-bit builds.

---------

Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
Backport-Source-PR: 4823
This commit is contained in:
charsyam authored and Sarthak Aggarwal committed 2026-10-26 15:17:36 -07:00
1 parent b389985f27
commit 994d00702f
2 files changed
+9 -1

No files matched your search

+1 -1
View File
@@ -363,7 +363,7 @@ void listTypeReplace(listTypeEntry *entry, robj *value) {
*
* Returns 1 if replace happened.
* Returns 0 if replace failed and no changes happened. */
int listTypeReplaceAtIndex(robj *o, int index, robj *value) {
int listTypeReplaceAtIndex(robj *o, long index, robj *value) {
value = getDecodedObject(value);
sds vstr = value->ptr;
size_t vlen = sdslen(vstr);
+8
View File
@@ -1971,6 +1971,14 @@ foreach {type large} [array get largevalue] {
test "LSET out of range index - $type" {
assert_error ERR*range* {r lset mylist 10 foo}
}
test "LSET does not truncate large indexes - $type" {
create_$type mylist "a $large"
foreach index {4294967295 4294967296 -4294967296 -4294967297} {
assert_error ERR*range* {r lset mylist $index changed} "LSET index $index"
assert_equal "a $large" [r lrange mylist 0 -1] "LSET index $index"
}
}
}
test {LSET against non existing key} {