summaryrefslogtreecommitdiff
path: root/src/bitops.c
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2017-02-23 22:38:44 +0800
committerSalvatore Sanfilippo <antirez@gmail.com>2017-02-23 22:38:44 +0800
commitd7826823c05ad82f710da74c3d5d402898187888 (patch)
tree3bc470a29825117f74d2f09446313857a2d9d49d /src/bitops.c
parent06263485d46696ba76a653d2b594f3493103c001 (diff)
downloadredis-d7826823c05ad82f710da74c3d5d402898187888.tar.gz
Fix BITPOS unaligned memory access.
Diffstat (limited to 'src/bitops.c')
-rw-r--r--src/bitops.c21
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