#include <unistd.h>
#include <shared/strbuf.h>
+#include <shared/util.h>
#include "libkmod.h"
#include "libkmod-internal.h"
static char **strbuf_to_vector(struct strbuf *buf, size_t count)
{
- /* size required for string vector + terminating NULL */
- const size_t vecsz = sizeof(char *) * (count + 1);
+ size_t vec_size, total_size;
char **vector;
char *s;
size_t n;
- /* make sure that vector and strings fit into memory constraints */
- if (SIZE_MAX / sizeof(char *) - 1 < count || SIZE_MAX - buf->used < vecsz) {
+ /* (string vector + NULL) * sizeof(char *) + buf->used */
+ if (uaddsz_overflow(count, 1, &n) ||
+ umulsz_overflow(sizeof(char *), n, &vec_size) ||
+ uaddsz_overflow(buf->used, vec_size, &total_size)) {
errno = ENOMEM;
return NULL;
}
- vector = realloc(buf->bytes, vecsz + buf->used);
+ vector = realloc(buf->bytes, total_size);
if (vector == NULL)
return NULL;
buf->bytes = NULL;
int kmod_elf_get_strings(const struct kmod_elf *elf, const char *section, char ***array)
{
size_t i, j, count;
- size_t vecsz;
+ size_t tmp_size, vec_size, total_size;
uint64_t size;
const void *buf;
const char *strings;
if (strings[i - 1] != '\0')
count++;
- /* make sure that vector and strings fit into memory constraints */
- vecsz = sizeof(char *) * (count + 1);
- if (SIZE_MAX / sizeof(char *) - 1 < count || SIZE_MAX - size <= vecsz) {
+ /* (string vector + NULL) * sizeof(char *) + size + NUL */
+ if (uaddsz_overflow(count, 1, &tmp_size) ||
+ umulsz_overflow(sizeof(char *), tmp_size, &vec_size) ||
+ uaddsz_overflow(size, vec_size, &tmp_size) ||
+ uaddsz_overflow(1, tmp_size, &total_size)) {
return -ENOMEM;
}
- *array = a = malloc(vecsz + size + 1);
+ *array = a = malloc(total_size);
if (*array == NULL)
return -errno;
#include <string.h>
#include <shared/array.h>
+#include <shared/util.h>
/* basic pointer array growing in steps */
static int array_realloc(struct array *array, size_t new_total)
{
+ size_t total_size;
void *tmp;
- if (SIZE_MAX / sizeof(void *) < new_total)
+ if (umulsz_overflow(sizeof(void *), new_total, &total_size))
return -ENOMEM;
- tmp = realloc(array->array, sizeof(void *) * new_total);
+ tmp = realloc(array->array, total_size);
if (tmp == NULL)
return -ENOMEM;
array->array = tmp;
size_t idx;
if (array->count + 1 >= array->total) {
+ size_t new_size;
int r;
- if (SIZE_MAX - array->total < array->step)
+ if (uaddsz_overflow(array->total, array->step, &new_size))
return -ENOMEM;
- r = array_realloc(array, array->total + array->step);
+ r = array_realloc(array, new_size);
if (r < 0)
return r;
}
#endif
}
+static inline bool uaddsz_overflow(size_t a, size_t b, size_t *res)
+{
+#if __SIZEOF_SIZE_T__ == 8
+ return uadd64_overflow(a, b, res);
+#elif __SIZEOF_SIZE_T__ == 4
+ return uadd32_overflow(a, b, res);
+#else
+#error "Unknown sizeof(size_t)"
+#endif
+}
+
static inline bool umul32_overflow(uint32_t a, uint32_t b, uint32_t *res)
{
#if (HAVE___BUILTIN_UMUL_OVERFLOW && __SIZEOF_INT__ == 4)
return UINT64_MAX / a < b;
#endif
}
+
+static inline bool umulsz_overflow(size_t a, size_t b, size_t *res)
+{
+#if __SIZEOF_SIZE_T__ == 8
+ return umul64_overflow(a, b, res);
+#elif __SIZEOF_SIZE_T__ == 4
+ return umul32_overflow(a, b, res);
+#else
+#error "Unknown sizeof(size_t)"
+#endif
+}