diff --git a/Makefile b/Makefile index a96be506b59f2d..66b7270fc0d2a4 100644 --- a/Makefile +++ b/Makefile @@ -1551,6 +1551,7 @@ CLAR_TEST_SUITES += u-reftable-block CLAR_TEST_SUITES += u-reftable-merged CLAR_TEST_SUITES += u-reftable-pq CLAR_TEST_SUITES += u-reftable-readwrite +CLAR_TEST_SUITES += u-reftable-record CLAR_TEST_SUITES += u-reftable-stack CLAR_TEST_SUITES += u-reftable-table CLAR_TEST_SUITES += u-reftable-tree diff --git a/reftable/basics.c b/reftable/basics.c index f0442a46cf7c13..6103b72b447a4a 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -44,18 +44,19 @@ void reftable_free(void *p) free(p); } -void *reftable_calloc(size_t nelem, size_t elsize) +void *reftable_calloc(uintmax_t nelem, uintmax_t elsize) { + size_t size; void *p; - if (nelem && elsize > SIZE_MAX / nelem) + if (reftable_alloc_size(nelem, elsize, &size) < 0) return NULL; - p = reftable_malloc(nelem * elsize); + p = reftable_malloc(size); if (!p) return NULL; - memset(p, 0, nelem * elsize); + memset(p, 0, size); return p; } diff --git a/reftable/basics.h b/reftable/basics.h index e4b83b2b03ff8a..29d2b799cae028 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -184,10 +184,11 @@ size_t names_length(const char **names); void *reftable_malloc(size_t sz); void *reftable_realloc(void *p, size_t sz); void reftable_free(void *p); -void *reftable_calloc(size_t nelem, size_t elsize); +void *reftable_calloc(uintmax_t nelem, uintmax_t elsize); char *reftable_strdup(const char *str); -static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out) +static inline int reftable_alloc_size(uintmax_t nelem, uintmax_t elsize, + size_t *out) { if (nelem && elsize > SIZE_MAX / nelem) return -1; diff --git a/t/unit-tests/u-reftable-basics.c b/t/unit-tests/u-reftable-basics.c index c5d83b6714d2eb..37bf1ade5a45a3 100644 --- a/t/unit-tests/u-reftable-basics.c +++ b/t/unit-tests/u-reftable-basics.c @@ -200,6 +200,24 @@ void test_reftable_basics__put_get_be16(void) cl_assert_equal_i(in, out); } +void test_reftable_basics__alloc_size(void) +{ + size_t out; + + cl_assert_equal_i(reftable_alloc_size(3, 5, &out), 0); + cl_assert_equal_i(out, 15); + cl_assert(reftable_alloc_size(SIZE_MAX, 2, &out) < 0); + + /* Counts that do not fit in a size_t. */ + if (SIZE_MAX < UINTMAX_MAX) { + cl_assert(reftable_alloc_size((uintmax_t)SIZE_MAX + 1, + 1, &out) < 0); + cl_assert(reftable_alloc_size(1, (uintmax_t)SIZE_MAX + 1, + &out) < 0); + cl_assert(reftable_calloc((uintmax_t)SIZE_MAX + 1, 1) == NULL); + } +} + void test_reftable_basics__alloc_grow(void) { int *arr = NULL, *old_arr;