rcx

library of miscellaneous bits of C code
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

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:
MMakefile | 2+-
Ainc/cext/internal/util.h | 12++++++++++++
Minc/cext/vector.h | 20++++++++++++++++----
Msrc/alloc.c | 16++++------------
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; }