From 77f8c34cbf8f8ad826fce3f412b67f05f78c68d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Thu, 23 Oct 2014 15:26:38 +0200
Subject: [PATCH] Simplify unaligned memxor using READ_PARTIAL macro.

---
 ChangeLog         |  4 +++-
 memxor-internal.h | 18 ++++++++++++++++++
 memxor.c          | 22 ++++++----------------
 3 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 65364068..c0fd85be 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,9 @@
 2014-10-23  Niels Möller  <nisse@lysator.liu.se>
 
+	* memxor-internal.h (READ_PARTIAL): New macro.
 	* memxor.c (memxor_different_alignment): Avoid out-of-bounds
-	reads, corresponding to valgrind's --partial-loads-ok.
+	reads, corresponding to valgrind's --partial-loads-ok. Use
+	READ_PARTIAL.
 
 	* configure.ac (asm_replace_list): Deleted memxor.asm, now
 	incompatible with the memxor/memxor3 split.
diff --git a/memxor-internal.h b/memxor-internal.h
index e868c181..dbb5e990 100644
--- a/memxor-internal.h
+++ b/memxor-internal.h
@@ -52,4 +52,22 @@ typedef unsigned long int word_t;
   (((w0) << (sh_1)) | ((w1) >> (sh_2)))
 #endif
 
+#ifndef WORDS_BIGENDIAN
+#define READ_PARTIAL(r,p,n) do {			\
+    word_t _rp_x;					\
+    unsigned _rp_i;					\
+    for (_rp_i = (n), _rp_x = (p)[--_rp_i]; _rp_i > 0;)	\
+      _rp_x = (_rp_x << CHAR_BIT) | (p)[--_rp_i];	\
+    (r) = _rp_x;					\
+  } while (0)
+#else
+#define READ_PARTIAL(r,p,n) do {			\
+    word_t _rp_x;						\
+    unsigned _rp_i;						\
+    for (_rp_x = (p)[0], _rp_i = 1; _rp_i < (n); _rp_i++)	\
+      _rp_x = (_rp_x << CHAR_BIT) | (p)[_rp_i];			\
+    (r) = _rp_x;						\
+  } while (0)
+#endif
+
 #endif /* NETTLE_MEMXOR_INTERNAL_H_INCLUDED */
diff --git a/memxor.c b/memxor.c
index e2e300d3..36306ac8 100644
--- a/memxor.c
+++ b/memxor.c
@@ -76,8 +76,6 @@ memxor_different_alignment (word_t *dst, const unsigned char *src, size_t n)
   const word_t *src_word;
   unsigned offset = ALIGN_OFFSET (src);
   word_t s0, s1;
-  const unsigned char *part;
-  unsigned i;
 
   assert (n > 0);
   shl = CHAR_BIT * offset;
@@ -86,15 +84,10 @@ memxor_different_alignment (word_t *dst, const unsigned char *src, size_t n)
   src_word = (const word_t *) ((uintptr_t) src & -sizeof(word_t));
 
   /* Read top offset bytes, in native byte order. */
-  part = src + n*sizeof(word_t) - offset;
-#if WORDS_BIGENDIAN
-  for (s0 = part[0], i = 1; i < offset; i++)
-    s0 = (s0 << CHAR_BIT) | part[i];
+  READ_PARTIAL (s0, (unsigned char *) &src_word[n], offset);
+#ifdef WORDS_BIGENDIAN
   s0 <<= shr; /* FIXME: Eliminate this shift? */
-#else /* !WORDS_BIGENDIAN */
-  for (i = offset, s0 = part[--i]; i > 0 ; )
-    s0 = (s0 << CHAR_BIT) | part[--i];
-#endif /* !WORDS_BIGENDIAN */
+#endif
 
   /* Do n-1 regular iterations */
   if (n & 1)
@@ -117,14 +110,11 @@ memxor_different_alignment (word_t *dst, const unsigned char *src, size_t n)
     }
   assert (n == 1);
   /* Read low wordsize - offset bytes */
-#if WORDS_BIGENDIAN
-  for (s0 = src[0], i = 1; i < sizeof(word_t) - offset; i++)
-    s0 = (s0 << CHAR_BIT) | src[i];
-#else /* !WORDS_BIGENDIAN */
-  for (i = sizeof(word_t) - offset, s0 = src[--i]; i > 0 ; )
-    s0 = (s0 << CHAR_BIT) | src[--i];
+  READ_PARTIAL (s0, src, sizeof(word_t) - offset);
+#ifndef WORDS_BIGENDIAN
   s0 <<= shl; /* FIXME: eliminate shift? */
 #endif /* !WORDS_BIGENDIAN */
+
   dst[0] ^= MERGE(s0, shl, s1, shr);
 }
 
-- 
GitLab