mirror of
https://github.com/valkey-io/valkey.git
synced 2026-10-28 16:34:55 +08:00
[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:
1 parent
b389985f27
commit
994d00702f
2 files changed
+9
-1
No files matched your search
+1
-1
@@ -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);
|
||||
|
||||
@@ -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} {
|
||||
|
||||
Reference in new issue
Block a user