detect writes past the end of a TALLOC allocation

This commit is contained in:
dzaima 2022-12-27 02:29:24 +02:00
parent 1afdd89075
commit 75fe558f1c
10 changed files with 30 additions and 24 deletions

View File

@ -215,7 +215,7 @@ static void bsp_block_u32(u64* src, u32* dst, usz len, usz sum, usz off) {
static void bsp_u16(u64* src, u16* dst, usz len, usz sum) {
usz b = bsp_max;
usz bufsize = b<sum? b : sum;
TALLOC(u32, buf, bufsize);
TALLOC(u32, buf, bufsize+1);
for (usz j=0; j<bufsize; j++) buf[j]=0;
for (usz i=0; i<len; i+=b) {
if (b > len-i) b = len-i;

View File

@ -259,13 +259,14 @@ typedef struct {
SORT_TYPE *storage;
} TEMP_STORAGE_T;
static void TIM_SORT_RESIZE(TEMP_STORAGE_T *store, const size_t new_size) {
static void TIM_SORT_RESIZE(TEMP_STORAGE_T *store, size_t new_size) {
new_size*= 2;
if (store->storage == NULL) {
store->storage = TALLOCP(SORT_TYPE, new_size);
} else if (store->alloc < new_size) {
store->storage = (SORT_TYPE *)TREALLOC(store->storage, new_size * sizeof(SORT_TYPE));
} else return;
store->alloc = TSIZE(store->storage)/sizeof(SORT_TYPE);
store->alloc = new_size;
}
static void TIM_SORT_MERGE(SORT_TYPE *dst, const TIM_SORT_RUN_T *stack, const int stack_curr,

View File

@ -83,7 +83,7 @@ B bi_emptyHVec, bi_emptyIVec, bi_emptyCVec, bi_emptySVec;
NOINLINE TStack* ts_e(TStack* o, u32 elsz, u64 am) { u64 size = o->size;
u64 alsz = mm_round(fsizeof(TStack, data, u8, (size+am)*elsz));
TStack* n;
if (alsz==mm_size((Value*)o)) {
if (alsz==mm_sizeUsable((Value*)o)) {
n = o;
} else {
n = (TStack*)mm_alloc(alsz, t_temp);
@ -91,7 +91,7 @@ NOINLINE TStack* ts_e(TStack* o, u32 elsz, u64 am) { u64 size = o->size;
mm_free((Value*)o);
n->size = size;
}
n->cap = (mm_size((Value*)n)-offsetof(TStack,data))/elsz;
n->cap = (mm_sizeUsable((Value*)n)-offsetof(TStack,data))/elsz;
return n;
}

11
src/h.h
View File

@ -255,10 +255,10 @@ typedef union B {
/*31*/ F(bitarr) \
\
/*32*/ F(comp) F(block) F(body) F(scope) F(scopeExt) F(blBlocks) F(arbObj) F(ffiType) \
/*40*/ F(ns) F(nsDesc) F(fldAlias) F(arrMerge) F(vfyObj) F(hashmap) F(temp) F(nfn) F(nfnDesc) \
/*49*/ F(freed) F(harrPartial) F(customObj) F(mmapH) \
/*40*/ F(ns) F(nsDesc) F(fldAlias) F(arrMerge) F(vfyObj) F(hashmap) F(temp) F(talloc) F(nfn) F(nfnDesc) \
/*50*/ F(freed) F(harrPartial) F(customObj) F(mmapH) \
\
/*52*/ IF_WRAP(F(funWrap) F(md1Wrap) F(md2Wrap))
/*53*/ IF_WRAP(F(funWrap) F(md1Wrap) F(md2Wrap))
enum Type {
#define F(X) t_##X,
@ -354,9 +354,12 @@ extern B bi_emptyHVec, bi_emptyIVec, bi_emptyCVec, bi_emptySVec;
#define emptySVec() incG(bi_emptySVec)
ALLOC_FN void* mm_alloc(u64 sz, u8 type);
ALLOC_FN void mm_free(Value* x);
static u64 mm_size(Value* x);
static void mm_visit(B x);
static void mm_visitP(void* x);
static u64 mm_size(Value* x);
#if !VERIFY_TAIL
#define mm_sizeUsable mm_size
#endif
static void dec(B x);
static B inc(B x);
static void ptr_dec(void* x);

View File

@ -706,6 +706,7 @@ void base_init() { // very first init function
#endif
TIi(t_shape,visit) = noop_visit;
TIi(t_temp,visit) = noop_visit;
TIi(t_talloc,visit) = noop_visit;
TIi(t_funBI,visit) = TIi(t_md1BI,visit) = TIi(t_md2BI,visit) = noop_visit;
TIi(t_funBI,freeO) = TIi(t_md1BI,freeO) = TIi(t_md2BI,freeO) = builtin_free;
TIi(t_funBI,freeF) = TIi(t_md1BI,freeF) = TIi(t_md2BI,freeF) = builtin_free;

View File

@ -39,7 +39,7 @@ static void gc_tryFree(Value* v) {
if (t==t_freed) err("GC found t_freed\n");
#endif
if (t!=t_empty && !(v->mmInfo&0x80)) {
if (t==t_shape || t==t_temp) return;
if (t==t_shape || t==t_temp || t==t_talloc) return;
#ifdef DONT_FREE
v->flags = t;
#else

View File

@ -25,6 +25,7 @@ u64 mm_heapUsed() {
#undef BSZ
#if VERIFY_TAIL
#include "../utils/talloc.h"
FORCE_INLINE u64 ptrHash(void* ptr, usz off) {
u64 pv = ptr2u64(ptr) ^ off;
pv*= 0xa0761d6478bd642full;
@ -57,8 +58,8 @@ static void tailVerifyInit(void* ptr, u64 filled, u64 end, u64 allocEnd) {
}
void tailVerifyAlloc(void* ptr, u64 filled, i64 logAlloc, u8 type) {
u64 end = 1ULL<<logAlloc;
filled = 8; // permit decreasing used size without having written anything to the space
tailVerifyInit(ptr, filled, end, end);
tailVerifyInit(ptr, sizeof(Value), end, end); // `sizeof(Value)` instead of `filled` to permit, without reinit, decreasing used size without having written anything to the space
if (type==t_talloc) ((u64*)((u8*)ptr + end - 8))[0] = filled-8; // -8 because TALLOCP does a +8
}
void verifyEnd(void* ptr, u64 sz, u64 start, u64 end) {
if (end+64>sz) { printf("Bad used range: "N64u".."N64u", allocation size "N64u"\n", start, end, sz); exit(1); }
@ -100,6 +101,7 @@ NOINLINE NORETURN void tailFail(u64 got, u64 exp, void* ptr, u64 off, int len, u
}
void tailVerifyFree(void* ptr) {
u64 filled; u64 ia; Arr* xa = ptr;
u64 end = mm_size(ptr);
switch(PTY(xa)) { default: return;
case t_bitarr: filled = BITARR_SZ(ia=PIA(xa)); break;
case t_i8arr: filled = TYARR_SZ(I8, ia=PIA(xa)); break;
@ -108,8 +110,8 @@ void tailVerifyFree(void* ptr) {
case t_f64arr: filled = TYARR_SZ(F64, ia=PIA(xa)); break;
case t_harr: filled = fsizeof(HArr,a,B,ia=PIA(xa)); break;
case t_fillarr: filled = fsizeof(FillArr,a,B,ia=PIA(xa)); break;
case t_talloc: filled = ia = *(u64*)((u8*)ptr + end - 8); end-= 8; break;
}
u64 end = mm_size(ptr);
verifyEnd(ptr, end, 8, filled);
#define F(G, X, O, L) if ((G) != (X)) tailFail(G, X, ptr, O, L, filled, end, ia)
ITER_TAIL(F)

View File

@ -43,6 +43,11 @@ static u64 mm_round(usz sz) {
static u64 mm_size(Value* x) {
return BSZ(x->mmInfo&63);
}
#if VERIFY_TAIL
static u64 mm_sizeUsable(Value* x) {
return mm_size(x) - VERIFY_TAIL;
}
#endif
void mm_forHeap(V2v f);
void mm_dumpHeap(FILE* f);

View File

@ -166,10 +166,7 @@ FORCE_INLINE B arr_join_inline(B w, B x, bool consume, bool* reusedW) {
usz xia = IA(x);
u64 ria = wia+xia;
if (!reusable(w)) goto no;
u64 wsz = mm_size(v(w));
#if VERIFY_TAIL
wsz-= VERIFY_TAIL;
#endif
u64 wsz = mm_sizeUsable(v(w));
u8 wt = TY(w);
u8 we = TI(w, elType);
// TODO f64∾i32, i32∾i8, c32∾c8 etc
@ -206,10 +203,7 @@ static inline bool inplace_add(B w, B x) { // consumes x if returns true; fails
usz wia = IA(w);
usz ria = wia+1;
if (reusable(w)) {
u64 wsz = mm_size(v(w));
#if VERIFY_TAIL
wsz-= VERIFY_TAIL;
#endif
u64 wsz = mm_sizeUsable(v(w));
u8 wt = TY(w);
switch (wt) {
case t_bitarr: if (BITARR_SZ( ria)<wsz && q_bit(x)) { bitp_set(bitarr_ptr(w),wia,o2bG(x)); goto ok; } break;

View File

@ -5,14 +5,14 @@ typedef struct TAlloc {
u8 data[];
} TAlloc;
#define TOFF offsetof(TAlloc, data)
#define TALLOCP(T,AM) ((T*) ((TAlloc*)mm_alloc(TOFF + (AM)*sizeof(T) + 8, t_temp))->data) // +8 so mm is happy
#define TALLOCP(T,AM) ((T*) ((TAlloc*)mm_alloc(TOFF + (AM)*sizeof(T) + 8, t_talloc))->data) // +8 so mm is happy
#define TALLOC(T,N,AM) T* N = TALLOCP(T,AM);
#define TOBJ(N) (void*)((u8*)(N) - TOFF)
#define TFREE(N) mm_free((Value*)TOBJ(N));
#define TREALLOC(N, AM) talloc_realloc(TOBJ(N), AM)
#define TSIZE(N) (mm_size(TOBJ(N))-TOFF)
#define TSIZE(N) (mm_sizeUsable(TOBJ(N))-TOFF)
static inline void* talloc_realloc(TAlloc* t, u64 am) { // TODO maybe shouldn't be inline?
u64 stored = mm_size((Value*)t)-TOFF;
u64 stored = mm_sizeUsable((Value*)t)-TOFF;
if (stored > am) return t->data;
TALLOC(u8,r,am);
memcpy(r, t->data, stored);