From 9204a9b2c2f6eb59767ab0bddcde62c75e8c20b0 Mon Sep 17 00:00:00 2001 From: Valentino Geron Date: Thu, 20 Aug 2020 18:48:09 +0300 Subject: [PATCH] Fix LPOS command when RANK is greater than matches When calling to LPOS command when RANK is higher than matches, the return value is non valid response. For example: ``` LPUSH l a :1 LPOS l b RANK 5 COUNT 10 *-4 ``` It may break client-side parser. Now, we count how many replies were replied in the array. ``` LPUSH l a :1 LPOS l b RANK 5 COUNT 10 *0 ``` --- src/t_list.c | 5 +++-- tests/unit/type/list.tcl | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/t_list.c b/src/t_list.c index 7737da771..ecf09cd94 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -571,13 +571,14 @@ void lposCommand(client *c) { li = listTypeInitIterator(o,direction == LIST_HEAD ? -1 : 0,direction); listTypeEntry entry; long llen = listTypeLength(o); - long index = 0, matches = 0, matchindex = -1; + long index = 0, matches = 0, matchindex = -1, arraylen = 0; while (listTypeNext(li,&entry) && (maxlen == 0 || index < maxlen)) { if (listTypeEqual(&entry,ele)) { matches++; matchindex = (direction == LIST_TAIL) ? index : llen - index - 1; if (matches >= rank) { if (arraylenptr) { + arraylen++; addReplyLongLong(c,matchindex); if (count && matches-rank+1 >= count) break; } else { @@ -593,7 +594,7 @@ void lposCommand(client *c) { /* Reply to the client. Note that arraylenptr is not NULL only if * the COUNT option was selected. */ if (arraylenptr != NULL) { - setDeferredArrayLen(c,arraylenptr,matches-rank+1); + setDeferredArrayLen(c,arraylenptr,arraylen); } else { if (matchindex != -1) addReplyLongLong(c,matchindex); diff --git a/tests/unit/type/list.tcl b/tests/unit/type/list.tcl index 0e39d7d95..5ea2b9cd1 100644 --- a/tests/unit/type/list.tcl +++ b/tests/unit/type/list.tcl @@ -50,6 +50,12 @@ start_server { assert {[r LPOS mylist c COUNT 0 MAXLEN 7 RANK 2] == {6}} } + test {LPOS when RANK is greater than matches} { + r DEL mylist + r LPUSH l a + assert {[r LPOS mylist b COUNT 10 RANK 5] eq {}} + } + test {LPUSH, RPUSH, LLENGTH, LINDEX, LPOP - ziplist} { # first lpush then rpush assert_equal 1 [r lpush myziplist1 aa]