[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] sha512-buffer: port back to 32-bit-only hosts
From: |
Paul Eggert |
Subject: |
[PATCH] sha512-buffer: port back to 32-bit-only hosts |
Date: |
Sat, 18 May 2024 19:04:55 -0700 |
Port to platforms lacking 64-bit integers (something that Emacs
still attempts to do, in theory) by adding an u64bswap primitive
to u64.h and using that, instead of using bswap_64. This fixes a
bug I made in commit 0d45ec7c033c165ad73a6509c7fa84aa67edf4ea
dated Sun Jun 17 14:35:37 2018 -0700.
* lib/sha512.c (SWAP): Use u64bswap, not bswap_64, to port
to older platforms lacking 64-bit integers.
* lib/u64.h: Include stddef.h, for size_t.
Include byteswap.h, for bswap_64 (on platforms with 64-bit int),
bswap_32.
(u64rol): Now a function, not a macro, so that it evaluates
its args only once.
(u64uint32): New typedef.
(u64, u64hilo, u64lo): Use it.
(_GL_U64_MASK32): New macro.
(u64size, u64plus, u64shl, u64shr, u64plus): Use it as needed for
odd platforms where unsigned int is wider than 32 bits.
(u64lt): Return bool, not int.
* modules/u64 (Depends-on): Add byteswap, stdbool.
* tests/test-u64.c (main): Test u64bswap.
---
ChangeLog | 24 +++++++++++++++++++
lib/sha512.c | 2 +-
lib/u64.h | 60 ++++++++++++++++++++++++++++++++----------------
modules/u64 | 2 ++
tests/test-u64.c | 7 ++++++
5 files changed, 74 insertions(+), 21 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index fc2c42283c..b7f62031f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2024-05-18 Paul Eggert <eggert@cs.ucla.edu>
+
+ sha512-buffer: port back to 32-bit-only hosts
+ Port to platforms lacking 64-bit integers (something that Emacs
+ still attempts to do, in theory) by adding an u64bswap primitive
+ to u64.h and using that, instead of using bswap_64. This fixes a
+ bug I made in commit 0d45ec7c033c165ad73a6509c7fa84aa67edf4ea
+ dated Sun Jun 17 14:35:37 2018 -0700.
+ * lib/sha512.c (SWAP): Use u64bswap, not bswap_64, to port
+ to older platforms lacking 64-bit integers.
+ * lib/u64.h: Include stddef.h, for size_t.
+ Include byteswap.h, for bswap_64 (on platforms with 64-bit int),
+ bswap_32.
+ (u64rol): Now a function, not a macro, so that it evaluates
+ its args only once.
+ (u64uint32): New typedef.
+ (u64, u64hilo, u64lo): Use it.
+ (_GL_U64_MASK32): New macro.
+ (u64size, u64plus, u64shl, u64shr, u64plus): Use it as needed for
+ odd platforms where unsigned int is wider than 32 bits.
+ (u64lt): Return bool, not int.
+ * modules/u64 (Depends-on): Add byteswap, stdbool.
+ * tests/test-u64.c (main): Test u64bswap.
+
2024-05-18 Collin Funk <collin.funk1@gmail.com>
dup3: Update documentation and expected test results.
diff --git a/lib/sha512.c b/lib/sha512.c
index 9eb036fb32..6750041bc7 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -35,7 +35,7 @@
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
-# define SWAP(n) bswap_64 (n)
+# define SWAP(n) u64bswap (n)
#endif
#if ! HAVE_OPENSSL_SHA512
diff --git a/lib/u64.h b/lib/u64.h
index 4eca03e985..cfb5588757 100644
--- a/lib/u64.h
+++ b/lib/u64.h
@@ -22,8 +22,11 @@
#error "Please include config.h first."
#endif
+#include <stddef.h>
#include <stdint.h>
+#include <byteswap.h>
+
_GL_INLINE_HEADER_BEGIN
#ifndef _GL_U64_INLINE
# define _GL_U64_INLINE _GL_INLINE
@@ -34,9 +37,6 @@ extern "C" {
#endif
-/* Return X rotated left by N bits, where 0 < N < 64. */
-#define u64rol(x, n) u64or (u64shl (x, n), u64shr (x, 64 - n))
-
#ifdef UINT64_MAX
/* Native implementations are trivial. See below for comments on what
@@ -53,24 +53,30 @@ typedef uint64_t u64;
# define u64plus(x, y) ((x) + (y))
# define u64shl(x, n) ((x) << (n))
# define u64shr(x, n) ((x) >> (n))
+# define u64bswap(x) bswap_64 (x)
#else
-/* u64 is a 64-bit unsigned integer value.
+# define _GL_U64_MASK32 0xfffffffful /* 2**32 - 1. */
+
+/* u64 represents a 64-bit unsigned integer value equal to (HI << 32) + LO.
+ Implement it with unsigned int, which the GNU coding standards say
+ is wide enough to hold 32 bits, and which does not signal an error
+ when adding (theoretically possible with types like uint_fast32_t).
u64init (HI, LO), is like u64hilo (HI, LO), but for use in
initializer contexts. */
# ifdef WORDS_BIGENDIAN
-typedef struct { uint32_t hi, lo; } u64;
+typedef struct { unsigned int hi, lo; } u64;
# define u64init(hi, lo) { hi, lo }
# else
-typedef struct { uint32_t lo, hi; } u64;
+typedef struct { unsigned int lo, hi; } u64;
# define u64init(hi, lo) { lo, hi }
# endif
/* Given the high and low-order 32-bit quantities HI and LO, return a u64
value representing (HI << 32) + LO. */
_GL_U64_INLINE u64
-u64hilo (uint32_t hi, uint32_t lo)
+u64hilo (unsigned int hi, unsigned int lo)
{
u64 r;
r.hi = hi;
@@ -78,9 +84,9 @@ u64hilo (uint32_t hi, uint32_t lo)
return r;
}
-/* Return a u64 value representing LO. */
+/* Return a u64 value representing the 32-bit quantity LO. */
_GL_U64_INLINE u64
-u64lo (uint32_t lo)
+u64lo (unsigned int lo)
{
u64 r;
r.hi = 0;
@@ -88,18 +94,18 @@ u64lo (uint32_t lo)
return r;
}
-/* Return a u64 value representing SIZE. */
+/* Return a u64 value representing SIZE, where 0 <= SIZE < 2**64. */
_GL_U64_INLINE u64
u64size (size_t size)
{
u64 r;
r.hi = size >> 31 >> 1;
- r.lo = size;
+ r.lo = size & _GL_U64_MASK32;
return r;
}
/* Return X < Y. */
-_GL_U64_INLINE int
+_GL_U64_INLINE bool
u64lt (u64 x, u64 y)
{
return x.hi < y.hi || (x.hi == y.hi && x.lo < y.lo);
@@ -135,29 +141,29 @@ u64xor (u64 x, u64 y)
return r;
}
-/* Return X + Y. */
+/* Return X + Y, wrapping around on overflow. */
_GL_U64_INLINE u64
u64plus (u64 x, u64 y)
{
u64 r;
- r.lo = x.lo + y.lo;
- r.hi = x.hi + y.hi + (r.lo < x.lo);
+ r.lo = (x.lo + y.lo) & _GL_U64_MASK32;
+ r.hi = (x.hi + y.hi + (r.lo < x.lo)) & _GL_U64_MASK32;
return r;
}
-/* Return X << N. */
+/* Return X << N, where 0 <= N < 64. */
_GL_U64_INLINE u64
u64shl (u64 x, int n)
{
u64 r;
if (n < 32)
{
- r.hi = (x.hi << n) | (x.lo >> (32 - n));
- r.lo = x.lo << n;
+ r.hi = (x.hi << n & _GL_U64_MASK32) | x.lo >> (32 - n);
+ r.lo = x.lo << n & _GL_U64_MASK32;
}
else
{
- r.hi = x.lo << (n - 32);
+ r.hi = x.lo << (n - 32) & _GL_U64_MASK32;
r.lo = 0;
}
return r;
@@ -171,7 +177,7 @@ u64shr (u64 x, int n)
if (n < 32)
{
r.hi = x.hi >> n;
- r.lo = (x.hi << (32 - n)) | (x.lo >> n);
+ r.lo = (x.hi << (32 - n) & _GL_U64_MASK32) | x.lo >> n;
}
else
{
@@ -181,8 +187,22 @@ u64shr (u64 x, int n)
return r;
}
+/* Return X with bytes in reverse order. */
+_GL_U64_INLINE u64
+u64bswap (u64 x)
+{
+ return u64hilo (bswap_32 (x.lo), bswap_32 (x.hi));
+}
+
#endif
+/* Return X rotated left by N bits, where 0 < N < 64. */
+_GL_U64_INLINE u64
+u64rol (u64 x, int n)
+{
+ return u64or (u64shl (x, n), u64shr (x, 64 - n));
+}
+
#ifdef __cplusplus
}
diff --git a/modules/u64 b/modules/u64
index f678c32caa..1be7420bda 100644
--- a/modules/u64
+++ b/modules/u64
@@ -6,7 +6,9 @@ lib/u64.h
lib/u64.c
Depends-on:
+byteswap
extern-inline
+stdbool
stdint
configure.ac:
diff --git a/tests/test-u64.c b/tests/test-u64.c
index 1c84eb3e25..a78e66421a 100644
--- a/tests/test-u64.c
+++ b/tests/test-u64.c
@@ -43,5 +43,12 @@ main (void)
if (u64lt (k, l) || u64lt (l, k))
return 1;
+ u64
+ m = u64hilo (0x01020304, 0x05060708),
+ n = u64hilo (0x08070605, 0x04030201),
+ o = u64bswap (m);
+ if (u64lt (n, o) || u64lt (o, n))
+ return 1;
+
return 0;
}
--
2.40.1
- [PATCH] sha512-buffer: port back to 32-bit-only hosts,
Paul Eggert <=