Skip to content

Commit

Permalink
Improve GETRANGE command behavior (redis#12272)
Browse files Browse the repository at this point in the history
Fixed the issue about GETRANGE and SUBSTR command
return unexpected result caused by the `start` and `end` out of
definition range of string.

---
## break change
Before this PR, when negative `end` was out of range (i.e., end <
-strlen), we would fix it to 0 to get the substring, which also resulted
in the first character still being returned for this kind of out of
range.
After this PR, we ensure that `GETRANGE` returns an empty bulk when the
negative end index is out of range.

Closes redis#11738

---------

Co-authored-by: debing.sun <[email protected]>
  • Loading branch information
linzihao1999 and sundb authored Aug 20, 2024
1 parent 7f0a7f0 commit 6ceadfb
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 14 deletions.
19 changes: 5 additions & 14 deletions src/t_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,24 +499,15 @@ void getrangeCommand(client *c) {
strlen = sdslen(str);
}

/* Convert negative indexes */
if (start < 0 && end < 0 && start > end) {
if (start < 0) start += strlen;
if (end < 0) end += strlen;
if (strlen == 0 || start >= (long long)strlen || end < 0 || start > end) {
addReply(c,shared.emptybulk);
return;
}
if (start < 0) start = strlen+start;
if (end < 0) end = strlen+end;
if (start < 0) start = 0;
if (end < 0) end = 0;
if ((unsigned long long)end >= strlen) end = strlen-1;

/* Precondition: end >= 0 && end < strlen, so the only condition where
* nothing can be returned is: start > end. */
if (start > end || strlen == 0) {
addReply(c,shared.emptybulk);
} else {
addReplyBulkCBuffer(c,(char*)str+start,end-start+1);
}
if (end >= (long long)strlen) end = strlen-1;
addReplyBulkCBuffer(c,(char*)str+start,end-start+1);
}

void mgetCommand(client *c) {
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/type/string.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,12 @@ start_server {tags {"string"}} {
assert_equal "" [r getrange mykey 5 3]
assert_equal " World" [r getrange mykey 5 5000]
assert_equal "Hello World" [r getrange mykey -5000 10000]
assert_equal "" [r getrange mykey 0 -100]
assert_equal "" [r getrange mykey 1 -100]
assert_equal "" [r getrange mykey -1 -100]
assert_equal "" [r getrange mykey -100 -99]
assert_equal "" [r getrange mykey -100 -100]
assert_equal "" [r getrange mykey -100 -101]
}

test "GETRANGE against integer-encoded value" {
Expand All @@ -474,6 +480,12 @@ start_server {tags {"string"}} {
assert_equal "" [r getrange mykey 5 3]
assert_equal "4" [r getrange mykey 3 5000]
assert_equal "1234" [r getrange mykey -5000 10000]
assert_equal "" [r getrange mykey 0 -100]
assert_equal "" [r getrange mykey 1 -100]
assert_equal "" [r getrange mykey -1 -100]
assert_equal "" [r getrange mykey -100 -99]
assert_equal "" [r getrange mykey -100 -100]
assert_equal "" [r getrange mykey -100 -101]
}

test "GETRANGE fuzzing" {
Expand Down

0 comments on commit 6ceadfb

Please sign in to comment.