detect writes past the end of a TALLOC allocation
This commit is contained in:
parent
1afdd89075
commit
75fe558f1c
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
11
src/h.h
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user