xsize: port to SIZE_MAX <= INT_MAX
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 14 Jun 2024 21:29:18 +0000 (14:29 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 14 Jun 2024 21:29:55 +0000 (14:29 -0700)
* lib/xsize.h (xsum): Port to oddball platforms where SIZE_MAX <=
INT_MAX.  Although no such platform is a current Gnulib porting
problems, it’s easy enough to port to them.

ChangeLog
lib/xsize.h

index 52a8ae3d279522c2745463fdd6997ae6c854a07a..3f07da88ba38877cec57f98fd0f9a08f8219fc1f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2024-06-14  Paul Eggert  <eggert@cs.ucla.edu>
 
+       xsize: port to SIZE_MAX <= INT_MAX
+       * lib/xsize.h (xsum): Port to oddball platforms where SIZE_MAX <=
+       INT_MAX.  Although no such platform is a current Gnulib porting
+       problems, it’s easy enough to port to them.
+
        ssfmalloc-tests: simplify by using sysconf
        * tests/test-ssfmalloc.c (getpagesize) [__hpux]: Remove decl.
        (init_pagesize): Use sysconf instead of getpagesize.
index 619c0edc2b98ab87af27027e76969487cad71da8..5ae86006d953721242a5550c5d76d0566bdfcb54 100644 (file)
@@ -26,7 +26,7 @@
 /* Get size_t.  */
 #include <stddef.h>
 
-/* Get SIZE_MAX.  */
+/* Get INT_MAX, SIZE_MAX.  */
 #include <limits.h>
 #if HAVE_STDINT_H
 # include <stdint.h>
@@ -61,7 +61,8 @@ extern "C" {
       void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
 */
 
-/* Convert an arbitrary value >= 0 to type size_t.  */
+/* Convert an arbitrary N >= 0 to type size_t.
+   N should not have side effects.  */
 #define xcast_size_t(N) \
   ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
 
@@ -69,8 +70,15 @@ extern "C" {
 XSIZE_INLINE size_t ATTRIBUTE_PURE
 xsum (size_t size1, size_t size2)
 {
-  size_t sum = size1 + size2;
-  return (sum >= size1 ? sum : SIZE_MAX);
+  if (INT_MAX < SIZE_MAX)
+    {
+      /* Optimize for the common case where size_t arithmetic wraps
+         around without undefined behavior.  */
+      size_t sum = size1 + size2;
+      return size1 <= sum ? sum : SIZE_MAX;
+    }
+
+  return size1 <= SIZE_MAX - size2 ? size1 + size2 : SIZE_MAX;
 }
 
 /* Sum of three sizes, with overflow check.  */
@@ -98,6 +106,8 @@ xmax (size_t size1, size_t size2)
 
 /* Multiplication of a count with an element size, with overflow check.
    The count must be >= 0 and the element size must be > 0.
+   Arguments should not have side effects.
+   The element size's type should be no wider than size_t.
    This is a macro, not a function, so that it works correctly even
    when N is of a wider type and N > SIZE_MAX.  */
 #define xtimes(N, ELSIZE) \