Skip to content

Commit

Permalink
Validate ZRANGE indexes (microsoft#507)
Browse files Browse the repository at this point in the history
Validate index values for ZRANGE

---------

Co-authored-by: Vasileios Zois <[email protected]>
  • Loading branch information
yrajas and vazois committed Jul 2, 2024
1 parent 1f80504 commit b855682
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
25 changes: 19 additions & 6 deletions libs/server/Objects/SortedSet/SortedSetObjectImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,14 +449,27 @@ private void SortedSetRange(byte* input, int length, ref SpanByteAndMemory outpu
maxIndex = sortedSetDict.Count - 1;
}

// calculate number of elements
int n = maxIndex - minIndex + 1;
// No elements to return if both indexes fall outside the range or min is higher than max
if ((minIndex < 0 && maxIndex < 0) || (minIndex > maxIndex))
{
while (!RespWriteUtils.WriteEmptyArray(ref curr, end))
ObjectUtils.ReallocateOutput(ref output, ref isMemory, ref ptr, ref ptrHandle, ref curr, ref end);
countDone = _input->arg1;
count = 0;
}
else
{
// Clamp minIndex to 0, if it is beyond the number of elements
minIndex = Math.Max(0, minIndex);

var iterator = options.Reverse ? sortedSet.Reverse() : sortedSet;
iterator = iterator.Skip(minIndex).Take(n);
// calculate number of elements
int n = maxIndex - minIndex + 1;
var iterator = options.Reverse ? sortedSet.Reverse() : sortedSet;
iterator = iterator.Skip(minIndex).Take(n);

WriteSortedSetResult(options.WithScores, n, respProtocolVersion, iterator, ref output, ref isMemory, ref ptr, ref ptrHandle, ref curr, ref end);
countDone = _input->arg1;
WriteSortedSetResult(options.WithScores, n, respProtocolVersion, iterator, ref output, ref isMemory, ref ptr, ref ptrHandle, ref curr, ref end);
countDone = _input->arg1;
}
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions test/Garnet.test/RespSortedSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,31 @@ public void CanDoZRangeByIndexLC(int bytesSent)
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Assert.AreEqual(expectedResponse, actualValue);

response = lightClientRequest.SendCommand("ZRANGE board -50 -1 WITHSCORES", 7);
expectedResponse = "*6\r\n$3\r\none\r\n$1\r\n1\r\n$3\r\ntwo\r\n$1\r\n2\r\n$5\r\nthree\r\n$1\r\n3\r\n";
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Assert.AreEqual(expectedResponse, actualValue);

response = lightClientRequest.SendCommand("ZRANGE board -50 -10 WITHSCORES", 1);
expectedResponse = "*0\r\n";
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Assert.AreEqual(expectedResponse, actualValue);

response = lightClientRequest.SendCommand("ZRANGE board 2 1 WITHSCORES", 1);
expectedResponse = "*0\r\n";
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Assert.AreEqual(expectedResponse, actualValue);

response = lightClientRequest.SendCommand("ZRANGE board -1 -2 WITHSCORES", 1);
expectedResponse = "*0\r\n";
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Assert.AreEqual(expectedResponse, actualValue);

response = lightClientRequest.SendCommand("ZRANGE board 50 60 WITHSCORES", 1);
expectedResponse = "*0\r\n";
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Assert.AreEqual(expectedResponse, actualValue);

response = lightClientRequest.SendCommand("ZRANGE board (1 +inf BYSCORE LIMIT 1 1", 2);
expectedResponse = "*1\r\n$5\r\nthree\r\n";
actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length);
Expand Down

0 comments on commit b855682

Please sign in to comment.