[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