diff --git a/ChangeLog b/ChangeLog index c0fd85be672cd92ad3c85ca8d6709171fb40d434..37bbec202b868d13ba5c4509880eb5562b720f72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ * memxor.c (memxor_different_alignment): Avoid out-of-bounds reads, corresponding to valgrind's --partial-loads-ok. Use READ_PARTIAL. + * memxor3.c: Analogous changes for unaligned operations. * configure.ac (asm_replace_list): Deleted memxor.asm, now incompatible with the memxor/memxor3 split. diff --git a/memxor3.c b/memxor3.c index 06d3eca2e274696a37f864be50b8c3e7a426f43f..7c9ca045246a59d9df286d6d754dc302aead7c1c 100644 --- a/memxor3.c +++ b/memxor3.c @@ -37,6 +37,7 @@ # include "config.h" #endif +#include <assert.h> #include <limits.h> #include "memxor.h" @@ -65,29 +66,37 @@ memxor3_common_alignment (word_t *dst, static void memxor3_different_alignment_b (word_t *dst, - const word_t *a, const char *b, unsigned offset, size_t n) + const word_t *a, const unsigned char *b, + unsigned offset, size_t n) { int shl, shr; const word_t *b_word; word_t s0, s1; + assert (n > 0); + shl = CHAR_BIT * offset; shr = CHAR_BIT * (sizeof(word_t) - offset); b_word = (const word_t *) ((uintptr_t) b & -sizeof(word_t)); + /* Read top offset bytes, in native byte order. */ + READ_PARTIAL (s0, (unsigned char *) &b_word[n], offset); +#ifdef WORDS_BIGENDIAN + s0 <<= shr; +#endif + if (n & 1) + s1 = s0; + else { n--; s1 = b_word[n]; - s0 = b_word[n+1]; dst[n] = a[n] ^ MERGE (s1, shl, s0, shr); } - else - s1 = b_word[n]; - while (n > 0) + while (n > 2) { n -= 2; s0 = b_word[n+1]; @@ -95,18 +104,28 @@ memxor3_different_alignment_b (word_t *dst, s1 = b_word[n]; dst[n] = a[n] ^ MERGE(s1, shl, s0, shr); } + assert (n == 1); + /* Read low wordsize - offset bytes */ + READ_PARTIAL (s0, b, sizeof(word_t) - offset); +#ifndef WORDS_BIGENDIAN + s0 <<= shl; +#endif /* !WORDS_BIGENDIAN */ + + dst[0] = a[0] ^ MERGE(s0, shl, s1, shr); } static void memxor3_different_alignment_ab (word_t *dst, - const char *a, const char *b, + const unsigned char *a, const unsigned char *b, unsigned offset, size_t n) { int shl, shr; const word_t *a_word; const word_t *b_word; - word_t s0, s1; + word_t s0, s1, t; + + assert (n > 0); shl = CHAR_BIT * offset; shr = CHAR_BIT * (sizeof(word_t) - offset); @@ -114,17 +133,24 @@ memxor3_different_alignment_ab (word_t *dst, a_word = (const word_t *) ((uintptr_t) a & -sizeof(word_t)); b_word = (const word_t *) ((uintptr_t) b & -sizeof(word_t)); + /* Read top offset bytes, in native byte order. */ + READ_PARTIAL (s0, (unsigned char *) &a_word[n], offset); + READ_PARTIAL (t, (unsigned char *) &b_word[n], offset); + s0 ^= t; +#ifdef WORDS_BIGENDIAN + s0 <<= shr; +#endif + if (n & 1) + s1 = s0; + else { n--; s1 = a_word[n] ^ b_word[n]; - s0 = a_word[n+1] ^ b_word[n+1]; dst[n] = MERGE (s1, shl, s0, shr); } - else - s1 = a_word[n] ^ b_word[n]; - while (n > 0) + while (n > 2) { n -= 2; s0 = a_word[n+1] ^ b_word[n+1]; @@ -132,11 +158,21 @@ memxor3_different_alignment_ab (word_t *dst, s1 = a_word[n] ^ b_word[n]; dst[n] = MERGE(s1, shl, s0, shr); } + assert (n == 1); + /* Read low wordsize - offset bytes */ + READ_PARTIAL (s0, a, sizeof(word_t) - offset); + READ_PARTIAL (t, b, sizeof(word_t) - offset); + s0 ^= t; +#ifndef WORDS_BIGENDIAN + s0 <<= shl; +#endif /* !WORDS_BIGENDIAN */ + + dst[0] = MERGE(s0, shl, s1, shr); } static void memxor3_different_alignment_all (word_t *dst, - const char *a, const char *b, + const unsigned char *a, const unsigned char *b, unsigned a_offset, unsigned b_offset, size_t n) { @@ -154,21 +190,27 @@ memxor3_different_alignment_all (word_t *dst, a_word = (const word_t *) ((uintptr_t) a & -sizeof(word_t)); b_word = (const word_t *) ((uintptr_t) b & -sizeof(word_t)); + /* Read top offset bytes, in native byte order. */ + READ_PARTIAL (a0, (unsigned char *) &a_word[n], a_offset); + READ_PARTIAL (b0, (unsigned char *) &b_word[n], b_offset); +#ifdef WORDS_BIGENDIAN + a0 <<= ar; + b0 <<= br; +#endif + if (n & 1) { - n--; - a1 = a_word[n]; a0 = a_word[n+1]; - b1 = b_word[n]; b0 = b_word[n+1]; - - dst[n] = MERGE (a1, al, a0, ar) ^ MERGE (b1, bl, b0, br); + a1 = a0; b1 = b0; } else { + n--; a1 = a_word[n]; b1 = b_word[n]; - } - while (n > 0) + dst[n] = MERGE (a1, al, a0, ar) ^ MERGE (b1, bl, b0, br); + } + while (n > 2) { n -= 2; a0 = a_word[n+1]; b0 = b_word[n+1]; @@ -176,6 +218,16 @@ memxor3_different_alignment_all (word_t *dst, a1 = a_word[n]; b1 = b_word[n]; dst[n] = MERGE(a1, al, a0, ar) ^ MERGE(b1, bl, b0, br); } + assert (n == 1); + /* Read low wordsize - offset bytes */ + READ_PARTIAL (a0, a, sizeof(word_t) - a_offset); + READ_PARTIAL (b0, b, sizeof(word_t) - b_offset); +#ifndef WORDS_BIGENDIAN + a0 <<= al; + b0 <<= bl; +#endif /* !WORDS_BIGENDIAN */ + + dst[0] = MERGE(a0, al, a1, ar) ^ MERGE(b0, bl, b1, br); } /* Current implementation processes data in descending order, to @@ -186,9 +238,9 @@ memxor3_different_alignment_all (word_t *dst, void * memxor3(void *dst_in, const void *a_in, const void *b_in, size_t n) { - char *dst = dst_in; - const char *a = a_in; - const char *b = b_in; + unsigned char *dst = dst_in; + const unsigned char *a = a_in; + const unsigned char *b = b_in; if (n >= WORD_T_THRESH) {