diff options
author | Salvatore Sanfilippo <antirez@gmail.com> | 2017-02-23 22:38:44 +0800 |
---|---|---|
committer | Salvatore Sanfilippo <antirez@gmail.com> | 2017-02-23 22:38:44 +0800 |
commit | d7826823c05ad82f710da74c3d5d402898187888 (patch) | |
tree | 3bc470a29825117f74d2f09446313857a2d9d49d /src/bitops.c | |
parent | 06263485d46696ba76a653d2b594f3493103c001 (diff) | |
download | redis-d7826823c05ad82f710da74c3d5d402898187888.tar.gz |
Fix BITPOS unaligned memory access.
Diffstat (limited to 'src/bitops.c')
-rw-r--r-- | src/bitops.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/bitops.c b/src/bitops.c index 7ab72633c..d5b96ce1e 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -104,6 +104,7 @@ long redisBitpos(void *s, unsigned long count, int bit) { unsigned long skipval, word = 0, one; long pos = 0; /* Position of bit, to return to the caller. */ unsigned long j; + int found; /* Process whole words first, seeking for first word that is not * all ones or all zeros respectively if we are lookig for zeros @@ -117,21 +118,27 @@ long redisBitpos(void *s, unsigned long count, int bit) { /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */ skipval = bit ? 0 : UCHAR_MAX; c = (unsigned char*) s; + found = 0; while((unsigned long)c & (sizeof(*l)-1) && count) { - if (*c != skipval) break; + if (*c != skipval) { + found = 1; + break; + } c++; count--; pos += 8; } /* Skip bits with full word step. */ - skipval = bit ? 0 : ULONG_MAX; l = (unsigned long*) c; - while (count >= sizeof(*l)) { - if (*l != skipval) break; - l++; - count -= sizeof(*l); - pos += sizeof(*l)*8; + if (!found) { + skipval = bit ? 0 : ULONG_MAX; + while (count >= sizeof(*l)) { + if (*l != skipval) break; + l++; + count -= sizeof(*l); + pos += sizeof(*l)*8; + } } /* Load bytes into "word" considering the first byte as the most significant |