commit a707b3a1778293e34c9dd879e30f6aa5b453882a
parent 56cd1562904aa0fa8b98d19c0fa4dc28ae107454
Author: robert <robertrussell.72001@gmail.com>
Date: Wed, 10 Aug 2022 14:00:45 -0700
Fix vector overflow and stop using -f allocators
Diffstat:
4 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/Makefile b/Makefile
@@ -16,7 +16,7 @@ libcext.a: $(SRC:.c=.o)
.c.o:
$(CC) -c -o $@ $(CFLAGS) $<
-src/alloc.o: src/alloc.c inc/cext/alloc.h inc/cext/cext.h inc/cext/def.h inc/cext/log.h config.mk
+src/alloc.o: src/alloc.c inc/cext/alloc.h inc/cext/cext.h inc/cext/def.h inc/cext/log.h inc/cext/internal/util.h config.mk
src/bench.o: src/bench.c inc/cext/bench.h inc/cext/cext.h inc/cext/def.h inc/cext/log.h config.mk
src/log.o: src/log.c inc/cext/cext.h inc/cext/def.h inc/cext/log.h config.mk
src/opt.o: src/opt.c inc/cext/cext.h inc/cext/def.h inc/cext/opt.h config.mk
diff --git a/inc/cext/internal/util.h b/inc/cext/internal/util.h
@@ -0,0 +1,12 @@
+/* If s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW, then s1*s2 <= USIZE_MAX
+ * (but not conversely). This lets us avoid division in overflow checks. */
+#define MUL_NO_OVERFLOW ((usize) 1 << (sizeof(usize) * 4))
+
+/* This is exposed to user when included in vector.h, so try to hide it. */
+static inline bool
+cext_mul_will_overflow_(usize a, usize b) {
+ return (a >= MUL_NO_OVERFLOW || b >= MUL_NO_OVERFLOW)
+ && a > 0 && USIZE_MAX/a < b;
+}
+
+#undef MUL_NO_OVERFLOW
diff --git a/inc/cext/vector.h b/inc/cext/vector.h
@@ -1,10 +1,14 @@
#pragma once
+#include <errno.h>
#include <string.h>
#include "cext/alloc.h"
#include "cext/def.h"
+#include "cext/internal/util.h"
+
+/* TODO: this should be namespaced */
typedef struct {
usize len;
usize cap;
@@ -17,7 +21,7 @@ typedef struct {
#define VECTOR_STATIC
#define METHOD(name, prefix) JOIN(JOIN(prefix,_),name)
#define VECTOR_MIN_CAP 8
-#define VECTOR_REALLOCF ereallocf
+#define VECTOR_REALLOC erealloc
#define VECTOR_FREE free
#define VECTOR_DECLARE(T, ...)\
@@ -50,9 +54,14 @@ int METHOD(resize,##__VA_ARGS__)(T **v, usize cap) { \
cap = MAX(cap, VECTOR_MIN_CAP); \
vechdr *h = *v ? VECHDR(*v) : 0; \
usize len = h ? h->len : 0; \
- h = VECTOR_REALLOCF(h, sizeof *h, cap, sizeof (*v)[0]); \
- if (!h) \
+ usize arrsize = cap * sizeof (*v)[0]; \
+ if (cext_mul_will_overflow_(cap, sizeof (*v)[0]) \
+ || sizeof *h > USIZE_MAX - arrsize) { \
+ errno = ENOMEM; \
return -1; \
+ } \
+ h = VECTOR_REALLOC(h, sizeof *h + arrsize); \
+ if (!h) return -1; \
h->len = MIN(len, cap); \
h->cap = cap; \
*v = (void *)(h + 1); \
@@ -64,8 +73,11 @@ int METHOD(reserve,##__VA_ARGS__)(T **v, usize n) { \
usize rem = h ? h->cap - h->len : 0; \
if (n > rem) { \
usize need = n - rem; \
- /* TODO: overflow check */ \
usize cap = h ? h->cap + MAX(h->cap, need) : need; \
+ if (h && cap < h->cap) { /* Overflow? */ \
+ errno = ENOMEM; \
+ return -1; \
+ } \
return METHOD(resize,##__VA_ARGS__)(v, cap); \
} else { \
return 0; \
diff --git a/src/alloc.c b/src/alloc.c
@@ -6,15 +6,7 @@
#include "cext/cext.h"
#include "cext/log.h"
-/* If s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW, then s1*s2 <= USIZE_MAX
- * (but not conversely). This lets us avoid division in overflow checks. */
-#define MUL_NO_OVERFLOW ((usize) 1 << (sizeof(usize) * 4))
-
-static inline bool
-mul_will_overflow(usize a, usize b) {
- return (a >= MUL_NO_OVERFLOW || b >= MUL_NO_OVERFLOW)
- && a > 0 && USIZE_MAX/a < b;
-}
+#include "cext/internal/util.h"
void *
alloc(usize size) {
@@ -28,7 +20,7 @@ allocz(usize size) {
void *
allocn(usize len, usize size) {
- if (mul_will_overflow(len, size)) {
+ if (cext_mul_will_overflow_(len, size)) {
errno = ENOMEM;
return 0;
}
@@ -50,7 +42,7 @@ reallocz(void *p, usize osize, usize nsize) {
void *
reallocn(void *p, usize len, usize size) {
- if (mul_will_overflow(len, size)) {
+ if (cext_mul_will_overflow_(len, size)) {
errno = ENOMEM;
return 0;
}
@@ -59,7 +51,7 @@ reallocn(void *p, usize len, usize size) {
void *
reallocnz(void *p, usize olen, usize nlen, usize size) {
- if (mul_will_overflow(nlen, size)) {
+ if (cext_mul_will_overflow_(nlen, size)) {
errno = ENOMEM;
return 0;
}