On 2025-08-31 06:48, Bruno Haible via Gnulib discussion list wrote:
I wouldn't have gone through the trouble of using the 'u64'
module. Lots of other code in Gnulib assumes an uint64_t type in <stdint.h>,
for more than 10 or 15 years. But this is not an objection.

I wrote u64 decades ago when there were still platforms of interest lacking uint64_t. And ISO C and POSIX have never required uint64_t; even C23 and POSIX.1-2024 require it only if the implementation already has the type available by some other means. So I've continued to use u64 when it's easy, as seems to be the case here. When exact-width arithmetic is not required (as is often the case) I instead use uint_fast64_t or uint_least64_t, both of which have long been required by ISO C and POSIX; these are easier to use than u64.

There's a similar issue involving whether signed int code should assume two's complement. Although C23 requires two's complement, older C standards (and therefore all POSIX versions) do not. And even C23 does not require that two's complement types lack padding bits. So when it's easy to write signed int code that does not assume two's complement with no padding bits, I do that.

A few C platforms dating from the 1960s do not support uint64_t or even two's complement signed integers. Unisys 2200[1] has 36- or 72-bit ones' complement, and Unisys Clearpath/MCP[2] has a 48-bit word holding 40-bit signed magnitude for signed int (only 39 bits for unsigned int) and 8 bits of padding. Ironically, modules like crypto/sha3-buffer are more likely to be portable to these quirky platforms, not that I expect they'll find much use there.

Come to think of it, in theory uint64_t, uint_fast64_t, and uint_least64_t can have undefined behavior on integer overflow, on theoretical platforms where INT_MAX is sufficiently large. Although I think it unlikely that this will ever be a real problem as too many apps would break on such a platform, it's easy to defend against it in u64, so I installed the attached patch.

[1]: https://public.support.unisys.com/2200/docs/CP19.0/78310422-013.pdf
[2]: https://public.support.unisys.com/aseries/docs/ClearPath-MCP-20.0/86002268-209/86002268-209.pdf
From a7cc3c035d76931aa03330196730b3cd8cab7833 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Sun, 31 Aug 2025 07:54:18 -0700
Subject: [PATCH] u64: avoid theoretical problem with >64-bit int

* lib/u64.h: Include limits.h, for INT_MAX.  Use uint64_t only if
INT_MAX < UINT64_MAX, to avoid undefined behavior on theoretical
platforms where adding two uint64_t expressions can have undefined
behavior on signed integer overflow.
---
 ChangeLog   | 8 ++++++++
 lib/u64.h   | 5 +++--
 modules/u64 | 2 +-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 33d9975bbe..70dc193626 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2025-08-31  Paul Eggert  <[email protected]>
+
+	u64: avoid theoretical problem with >64-bit int
+	* lib/u64.h: Include limits.h, for INT_MAX.  Use uint64_t only if
+	INT_MAX < UINT64_MAX, to avoid undefined behavior on theoretical
+	platforms where adding two uint64_t expressions can have undefined
+	behavior on signed integer overflow.
+
 2024-08-25  Bruno Haible  <[email protected]>
 
 	nstrftime tests: Test in the UTF-8 environment on native Windows.
diff --git a/lib/u64.h b/lib/u64.h
index 6ea08969c2..01135057c2 100644
--- a/lib/u64.h
+++ b/lib/u64.h
@@ -1,4 +1,4 @@
-/* uint64_t-like operations that work even on hosts lacking uint64_t
+/* Unsigned integers with arithmetic modulo 2**64
 
    Copyright (C) 2006, 2009-2025 Free Software Foundation, Inc.
 
@@ -22,6 +22,7 @@
  #error "Please include config.h first."
 #endif
 
+#include <limits.h>
 #include <stddef.h>
 #include <stdint.h>
 
@@ -37,7 +38,7 @@ extern "C" {
 #endif
 
 
-#ifdef UINT64_MAX
+#if defined UINT64_MAX && INT_MAX < UINT64_MAX
 
 /* Native implementations are trivial.  See below for comments on what
    these operations do.  */
diff --git a/modules/u64 b/modules/u64
index 3a78ce3691..4a7f36157a 100644
--- a/modules/u64
+++ b/modules/u64
@@ -1,5 +1,5 @@
 Description:
-uint64_t-like operations that work even on hosts lacking uint64_t
+Unsigned integers with arithmetic modulo 2**64
 
 Files:
 lib/u64.h
-- 
2.48.1

Reply via email to