mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 00:28:26 -05:00
check WRONGTYPE in BITFIELD before looping on the operations.
optimization: lookup key only once, and grow at once to the max need fixes #3259 and #3221, and also an early return if wrongtype is discovered by SET
This commit is contained in:
parent
c4433d2a6a
commit
5d96b7ed4f
27
src/bitops.c
27
src/bitops.c
@ -895,6 +895,8 @@ void bitfieldCommand(client *c) {
|
||||
int j, numops = 0, changes = 0;
|
||||
struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */
|
||||
int owtype = BFOVERFLOW_WRAP; /* Overflow type. */
|
||||
int readonly = 1;
|
||||
long highestWriteOffset = 0;
|
||||
|
||||
for (j = 2; j < c->argc; j++) {
|
||||
int remargs = c->argc-j-1; /* Remaining args other than current. */
|
||||
@ -942,8 +944,10 @@ void bitfieldCommand(client *c) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* INCRBY and SET require another argument. */
|
||||
if (opcode != BITFIELDOP_GET) {
|
||||
readonly = 0;
|
||||
highestWriteOffset = bitoffset + bits - 1;
|
||||
/* INCRBY and SET require another argument. */
|
||||
if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL) != C_OK){
|
||||
zfree(ops);
|
||||
return;
|
||||
@ -963,6 +967,18 @@ void bitfieldCommand(client *c) {
|
||||
j += 3 - (opcode == BITFIELDOP_GET);
|
||||
}
|
||||
|
||||
if (readonly) {
|
||||
/* Lookup for read is ok if key doesn't exit, but errors
|
||||
* if it's not a string*/
|
||||
o = lookupKeyRead(c->db,c->argv[1]);
|
||||
if (o != NULL && checkType(c,o,OBJ_STRING)) return;
|
||||
} else {
|
||||
/* Lookup by making room up to the farest bit reached by
|
||||
* this operation. */
|
||||
if ((o = lookupStringForBitCommand(c,
|
||||
highestWriteOffset)) == NULL) return;
|
||||
}
|
||||
|
||||
addReplyMultiBulkLen(c,numops);
|
||||
|
||||
/* Actually process the operations. */
|
||||
@ -977,11 +993,6 @@ void bitfieldCommand(client *c) {
|
||||
* for simplicity. SET return value is the previous value so
|
||||
* we need fetch & store as well. */
|
||||
|
||||
/* Lookup by making room up to the farest bit reached by
|
||||
* this operation. */
|
||||
if ((o = lookupStringForBitCommand(c,
|
||||
thisop->offset + (thisop->bits-1))) == NULL) return;
|
||||
|
||||
/* We need two different but very similar code paths for signed
|
||||
* and unsigned operations, since the set of functions to get/set
|
||||
* the integers and the used variables types are different. */
|
||||
@ -1053,10 +1064,8 @@ void bitfieldCommand(client *c) {
|
||||
unsigned char *src = NULL;
|
||||
char llbuf[LONG_STR_SIZE];
|
||||
|
||||
if ((o = lookupKeyRead(c->db,c->argv[1])) != NULL) {
|
||||
if (checkType(c,o,OBJ_STRING)) continue;
|
||||
if (o != NULL)
|
||||
src = getObjectReadOnlyString(o,&strlen,llbuf);
|
||||
}
|
||||
|
||||
/* For GET we use a trick: before executing the operation
|
||||
* copy up to 9 bytes to a local buffer, so that we can easily
|
||||
|
Loading…
Reference in New Issue
Block a user