summaryrefslogtreecommitdiff
path: root/src/bitops.c
diff options
context:
space:
mode:
authorSun He <sunheehnus@gmail.com>2016-03-02 18:11:30 +0800
committerSun He <sunheehnus@gmail.com>2016-03-02 18:11:30 +0800
commit93cc8baf1ae5e3d028b4847b711b07c7e20cef4c (patch)
tree78999b652e9eec84d4cd885fb640b36a8d597a8b /src/bitops.c
parent32289d57194f2173dda5089a773f3ea4c4dd0c7a (diff)
downloadredis-93cc8baf1ae5e3d028b4847b711b07c7e20cef4c.tar.gz
bitops/bitfield: fix length, overflow condition and *sign
Diffstat (limited to 'src/bitops.c')
-rw-r--r--src/bitops.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/bitops.c b/src/bitops.c
index 51f9cc00f..28405a3bf 100644
--- a/src/bitops.c
+++ b/src/bitops.c
@@ -318,7 +318,8 @@ int checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int
int64_t maxincr = max-value;
int64_t minincr = min-value;
- if (value > max || (value >= 0 && incr > 0 && incr > maxincr)) {
+ if (value > max || (bits == 64 && value >= 0 && incr > 0 && incr > maxincr)
+ || (bits < 64 && incr > 0 && incr > maxincr)) {
if (limit) {
if (owtype == BFOVERFLOW_WRAP) {
goto handle_wrap;
@@ -327,7 +328,8 @@ int checkSignedBitfieldOverflow(int64_t value, int64_t incr, uint64_t bits, int
}
}
return 1;
- } else if (value < min || (value < 0 && incr < 0 && incr < minincr)) {
+ } else if (value < min || (bits == 64 && value < 0 && incr < 0 && incr < minincr)
+ || (bits < 64 && incr < 0 && incr < minincr)) {
if (limit) {
if (owtype == BFOVERFLOW_WRAP) {
goto handle_wrap;
@@ -445,8 +447,8 @@ int getBitfieldTypeFromArgument(client *c, robj *o, int *sign, int *bits) {
if ((string2ll(p+1,strlen(p+1),&llbits)) == 0 ||
llbits < 1 ||
- (*sign == 1 && llbits > 63) ||
- (*sign == 0 && llbits > 64))
+ (*sign == 1 && llbits > 64) ||
+ (*sign == 0 && llbits > 63))
{
addReplyError(c,err);
return C_ERR;
@@ -963,7 +965,8 @@ void bitfieldCommand(client *c) {
* for simplicity. SET return value is the previous value so
* we need fetch & store as well. */
- if ((o = lookupStringForBitCommand(c,bitoffset)) == NULL) return;
+ if ((o = lookupStringForBitCommand(c,thisop->offset + thisop->bits))
+ == NULL) return;
/* We need two different but very similar code paths for signed
* and unsigned operations, since the set of functions to get/set