Skip to content

Commit

Permalink
fix: variable length parameter judge error (#137)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukas Maas <contact@lukasmaas.com>
  • Loading branch information
Zzhiter and lmaas committed Mar 26, 2024
1 parent 2740b49 commit 2aea8fb
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 193 deletions.
91 changes: 50 additions & 41 deletions libs/server/Resp/Objects/HashCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,61 +38,70 @@ private unsafe bool HashSet<TGarnetApi>(int count, byte* ptr, HashOperation hop,
{
ptr += hop == HashOperation.HSET ? 10 : (hop == HashOperation.HSETNX ? 12 : 11);

// Get the key for Hash
if (!RespReadUtils.ReadByteArrayWithLengthHeader(out var key, ref ptr, recvBufferPtr + bytesRead))
return false;

if (NetworkSingleKeySlotVerify(key, false))
if (((hop == HashOperation.HSET || hop == HashOperation.HMSET)
&& (count < 3 || count % 2 != 0)) ||
(hop == HashOperation.HSETNX && count != 4))
{
var bufSpan = new ReadOnlySpan<byte>(recvBufferPtr, bytesRead);
if (!DrainCommands(bufSpan, count))
return false;
return true;
return AbortWithWrongNumberOfArguments(hop.ToString(), count);
}
else
{
// Get the key for Hash
if (!RespReadUtils.ReadByteArrayWithLengthHeader(out var key, ref ptr, recvBufferPtr + bytesRead))
return false;

// Prepare input
var inputPtr = (ObjectInputHeader*)(ptr - sizeof(ObjectInputHeader));
if (NetworkSingleKeySlotVerify(key, false))
{
var bufSpan = new ReadOnlySpan<byte>(recvBufferPtr, bytesRead);
if (!DrainCommands(bufSpan, count))
return false;
return true;
}

// Save old values on buffer for possible revert
var save = *inputPtr;
// Prepare input
var inputPtr = (ObjectInputHeader*)(ptr - sizeof(ObjectInputHeader));

// Prepare length of header in input buffer
var inputLength = (int)(recvBufferPtr + bytesRead - ptr) + sizeof(ObjectInputHeader);
// Save old values on buffer for possible revert
var save = *inputPtr;

var inputCount = (count - 2) / 2;
// Prepare length of header in input buffer
var inputLength = (int)(recvBufferPtr + bytesRead - ptr) + sizeof(ObjectInputHeader);

// Prepare header in input buffer
inputPtr->header.type = GarnetObjectType.Hash;
inputPtr->header.HashOp = hop;
inputPtr->count = inputCount;
inputPtr->done = hashOpsCount;
var inputCount = (count - 2) / 2;

storageApi.HashSet(key, new ArgSlice((byte*)inputPtr, inputLength), out ObjectOutputHeader output);
// Prepare header in input buffer
inputPtr->header.type = GarnetObjectType.Hash;
inputPtr->header.HashOp = hop;
inputPtr->count = inputCount;
inputPtr->done = hashOpsCount;

*inputPtr = save; // reset input buffer
storageApi.HashSet(key, new ArgSlice((byte*)inputPtr, inputLength), out ObjectOutputHeader output);

hashItemsDoneCount += output.countDone;
hashOpsCount += output.opsDone;
*inputPtr = save; // reset input buffer

// Reset buffer and return if HSET did not process the entire command tokens
if (hashItemsDoneCount < inputCount)
return false;
hashItemsDoneCount += output.countDone;
hashOpsCount += output.opsDone;

// Move head, write result to output, reset session counters
ptr += output.bytesDone;
readHead = (int)(ptr - recvBufferPtr);
// Reset buffer and return if HSET did not process the entire command tokens
if (hashItemsDoneCount < inputCount)
return false;

if (hop == HashOperation.HMSET)
{
while (!RespWriteUtils.WriteResponse(CmdStrings.RESP_OK, ref dcurr, dend))
SendAndReset();
}
else
{
while (!RespWriteUtils.WriteInteger(hashOpsCount, ref dcurr, dend))
SendAndReset();
}
// Move head, write result to output, reset session counters
ptr += output.bytesDone;
readHead = (int)(ptr - recvBufferPtr);

if (hop == HashOperation.HMSET)
{
while (!RespWriteUtils.WriteResponse(CmdStrings.RESP_OK, ref dcurr, dend))
SendAndReset();
}
else
{
while (!RespWriteUtils.WriteInteger(hashOpsCount, ref dcurr, dend))
SendAndReset();
}
}

hashItemsDoneCount = hashOpsCount = 0;
return true;
}
Expand Down
75 changes: 41 additions & 34 deletions libs/server/Resp/Objects/ListCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,50 +202,57 @@ private unsafe bool ListLength<TGarnetApi>(int count, byte* ptr, ref TGarnetApi
{
ptr += 10;

// Get the key for List
if (!RespReadUtils.ReadByteArrayWithLengthHeader(out var key, ref ptr, recvBufferPtr + bytesRead))
return false;

if (NetworkSingleKeySlotVerify(key, true))
if (count != 2)
{
var bufSpan = new ReadOnlySpan<byte>(recvBufferPtr, bytesRead);
if (!DrainCommands(bufSpan, count))
return false;
return true;
return AbortWithWrongNumberOfArguments("LLEN", count);
}
else
{
// Get the key for List
if (!RespReadUtils.ReadByteArrayWithLengthHeader(out var key, ref ptr, recvBufferPtr + bytesRead))
return false;

// Prepare input
var inputPtr = (ObjectInputHeader*)(ptr - sizeof(ObjectInputHeader));
if (NetworkSingleKeySlotVerify(key, true))
{
var bufSpan = new ReadOnlySpan<byte>(recvBufferPtr, bytesRead);
if (!DrainCommands(bufSpan, count))
return false;
return true;
}

// save old values
var save = *inputPtr;
// Prepare input
var inputPtr = (ObjectInputHeader*)(ptr - sizeof(ObjectInputHeader));

// Prepare length of header in input buffer
var inputLength = (int)(recvBufferPtr + bytesRead - ptr) + sizeof(ObjectInputHeader);
// save old values
var save = *inputPtr;

// Prepare header in input buffer
inputPtr->header.type = GarnetObjectType.List;
inputPtr->header.ListOp = ListOperation.LLEN;
inputPtr->count = count;
inputPtr->done = 0;
// Prepare length of header in input buffer
var inputLength = (int)(recvBufferPtr + bytesRead - ptr) + sizeof(ObjectInputHeader);

var status = storageApi.ListLength(key, new ArgSlice((byte*)inputPtr, inputLength), out var output);
// Prepare header in input buffer
inputPtr->header.type = GarnetObjectType.List;
inputPtr->header.ListOp = ListOperation.LLEN;
inputPtr->count = count;
inputPtr->done = 0;

//restore input buffer
*inputPtr = save;
var status = storageApi.ListLength(key, new ArgSlice((byte*)inputPtr, inputLength), out var output);

if (status == GarnetStatus.NOTFOUND)
{
while (!RespWriteUtils.WriteResponse(CmdStrings.RESP_RETURN_VAL_0, ref dcurr, dend))
SendAndReset();
}
else
{
// Process output
while (!RespWriteUtils.WriteInteger(output.countDone, ref dcurr, dend))
SendAndReset();
}
//restore input buffer
*inputPtr = save;

if (status == GarnetStatus.NOTFOUND)
{
while (!RespWriteUtils.WriteResponse(CmdStrings.RESP_RETURN_VAL_0, ref dcurr, dend))
SendAndReset();
}
else
{
// Process output
while (!RespWriteUtils.WriteInteger(output.countDone, ref dcurr, dend))
SendAndReset();
}
}

// Move input head, write result to output
readHead = (int)(ptr - recvBufferPtr);

Expand Down

0 comments on commit 2aea8fb

Please sign in to comment.