[tz] [PATCH 3/5] Refactor zic to simplify overflow checking

Paul Eggert eggert at cs.ucla.edu
Sun Nov 20 05:13:10 UTC 2022


* zic.c (size_product): Return ptrdiff_t not size_t.  The result
fits in both types, as any sizes greater than PTRDIFF_MAX will
cause problems elsewhere; and signed types are better in debugging
implementations that check signed integer overflow.
(align_to, growalloc): Refactor to simplify
future transition to ckd_add.
(grow_nitems_alloc): New static function, to simplify this
refactoring.
---
 zic.c | 44 +++++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/zic.c b/zic.c
index 0671889..9f5bd38 100644
--- a/zic.c
+++ b/zic.c
@@ -468,22 +468,22 @@ memory_exhausted(const char *msg)
 	exit(EXIT_FAILURE);
 }
 
-static ATTRIBUTE_PURE size_t
-size_product(size_t nitems, size_t itemsize)
+static ATTRIBUTE_PURE ptrdiff_t
+size_product(ptrdiff_t nitems, size_t itemsize)
 {
-	if (SIZE_MAX / itemsize < nitems)
-		memory_exhausted(_("size overflow"));
-	return nitems * itemsize;
+  ptrdiff_t nitems_max = min(PTRDIFF_MAX, SIZE_MAX) / itemsize;
+  if (nitems <= nitems_max)
+    return nitems * itemsize;
+  memory_exhausted(_("size overflow"));
 }
 
 static ATTRIBUTE_PURE size_t
 align_to(size_t size, size_t alignment)
 {
-  size_t aligned_size = size + alignment - 1;
-  aligned_size -= aligned_size % alignment;
-  if (aligned_size < size)
-    memory_exhausted(_("alignment overflow"));
-  return aligned_size;
+  size_t lo_bits = alignment - 1, addend = -size & lo_bits;
+  if (size <= SIZE_MAX - lo_bits)
+    return size + addend;
+  memory_exhausted(_("alignment overflow"));
 }
 
 #if !HAVE_STRDUP
@@ -521,18 +521,24 @@ estrdup(char const *str)
   return memcheck(strdup(str));
 }
 
+static ptrdiff_t
+grow_nitems_alloc(ptrdiff_t *nitems_alloc, ptrdiff_t itemsize)
+{
+  ptrdiff_t addend = (*nitems_alloc >> 1) + 1;
+  ptrdiff_t amax = min(PTRDIFF_MAX, SIZE_MAX);
+  if (*nitems_alloc <= ((amax - 1) / 3 * 2) / itemsize) {
+    *nitems_alloc += addend;
+    return *nitems_alloc * itemsize;
+  }
+  memory_exhausted(_("integer overflow"));
+}
+
 static void *
 growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
 {
-	if (nitems < *nitems_alloc)
-		return ptr;
-	else {
-		ptrdiff_t amax = min(PTRDIFF_MAX, SIZE_MAX);
-		if ((amax - 1) / 3 * 2 < *nitems_alloc)
-			memory_exhausted(_("integer overflow"));
-		*nitems_alloc += (*nitems_alloc >> 1) + 1;
-		return erealloc(ptr, size_product(*nitems_alloc, itemsize));
-	}
+  return (nitems < *nitems_alloc
+	  ? ptr
+	  : erealloc(ptr, grow_nitems_alloc(nitems_alloc, itemsize)));
 }
 
 /*
-- 
2.38.1



More information about the tz mailing list