From afc0917f884bbd15202443d13ebbb6c7a29f8803 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Thu, 1 Oct 2020 17:09:09 +0200 Subject: [PATCH] Bound checking fixes tccgen.c: - Fix 'tcc -b conftest.s' - Add offset during bound checking for struct return lib/bcheck.c: - Check overlap when reusing vla/alloca arm-gen.c: arm64-gen.c: riscv64-gen.c: lib/alloca86-bt.S: - add space for vla/alloca during bound checking tests/tests2/Makefile: tests/tests2/121_struct_return: tests/tests2/122_vla_reuse: - New test cases with bound checking enabled to test vla and struct return --- arm-gen.c | 4 +++ arm64-gen.c | 5 ++++ lib/alloca86-bt.S | 2 +- lib/bcheck.c | 16 ++++++++++-- riscv64-gen.c | 5 ++++ tccgen.c | 6 ++++- tests/tests2/121_struct_return.c | 35 +++++++++++++++++++++++++++ tests/tests2/121_struct_return.expect | 1 + tests/tests2/122_vla_reuse.c | 31 ++++++++++++++++++++++++ tests/tests2/122_vla_reuse.expect | 1 + tests/tests2/Makefile | 2 ++ 11 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 tests/tests2/121_struct_return.c create mode 100644 tests/tests2/121_struct_return.expect create mode 100644 tests/tests2/122_vla_reuse.c create mode 100644 tests/tests2/122_vla_reuse.expect diff --git a/arm-gen.c b/arm-gen.c index 784b2369..20ceac4e 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -2255,6 +2255,10 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { vpushv(vtop); #endif r = intr(gv(RC_INT)); +#if defined(CONFIG_TCC_BCHECK) + if (tcc_state->do_bounds_check) + o(0xe2800001 | (r<<16)|(r<<12)); /* add r,r,#1 */ +#endif o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */ #ifdef TCC_ARM_EABI if (align < 8) diff --git a/arm64-gen.c b/arm64-gen.c index aeef6ef8..ed09afef 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -2046,6 +2046,11 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { vpushv(vtop); #endif r = intr(gv(RC_INT)); +#if defined(CONFIG_TCC_BCHECK) + if (tcc_state->do_bounds_check) + o(0x91004000 | r | r << 5); // add x(r),x(r),#15+1 + else +#endif o(0x91003c00 | r | r << 5); // add x(r),x(r),#15 o(0x927cec00 | r | r << 5); // bic x(r),x(r),#15 o(0xcb2063ff | r << 16); // sub sp,sp,x(r) diff --git a/lib/alloca86-bt.S b/lib/alloca86-bt.S index 177838a8..ef674adc 100644 --- a/lib/alloca86-bt.S +++ b/lib/alloca86-bt.S @@ -12,7 +12,7 @@ _(__bound_alloca): pop %edx pop %eax mov %eax, %ecx - add $3,%eax + add $3+1,%eax and $-4,%eax jz p6 diff --git a/lib/bcheck.c b/lib/bcheck.c index 33e15fad..f19d4e87 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -212,6 +212,7 @@ struct tree_node { typedef struct alloca_list_struct { size_t fp; void *p; + size_t size; struct alloca_list_struct *next; } alloca_list_type; @@ -728,12 +729,22 @@ void __bound_new_region(void *p, size_t size) last = NULL; cur = alloca_list; while (cur) { - if (cur->fp == fp && cur->p == p) { +#if defined(__i386__) || (defined(__arm__) && !defined(TCC_ARM_EABI)) + int align = 4; +#elif defined(__arm__) + int align = 8; +#else + int align = 16; +#endif + void *cure = (void *)((char *)cur->p + ((cur->size + align) & -align)); + void *pe = (void *)((char *)p + ((size + align) & -align)); + if (cur->fp == fp && ((cur->p <= p && cure > p) || + (p <= cur->p && pe > cur->p))) { if (last) last->next = cur->next; else alloca_list = cur->next; - tree = splay_delete((size_t)p, tree); + tree = splay_delete((size_t)cur->p, tree); break; } last = cur; @@ -743,6 +754,7 @@ void __bound_new_region(void *p, size_t size) if (new) { new->fp = fp; new->p = p; + new->size = size; new->next = alloca_list; alloca_list = new; } diff --git a/riscv64-gen.c b/riscv64-gen.c index 2780eaa1..33e049ac 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -1327,6 +1327,11 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) vpushv(vtop); #endif rr = ireg(gv(RC_INT)); +#if defined(CONFIG_TCC_BCHECK) + if (tcc_state->do_bounds_check) + EI(0x13, 0, rr, rr, 15+1); // addi RR, RR, 15+1 + else +#endif EI(0x13, 0, rr, rr, 15); // addi RR, RR, 15 EI(0x13, 7, rr, rr, -16); // andi, RR, RR, -16 ER(0x33, 0, 2, 2, rr, 0x20); // sub sp, sp, rr diff --git a/tccgen.c b/tccgen.c index efdb8117..73bc7d72 100644 --- a/tccgen.c +++ b/tccgen.c @@ -413,7 +413,8 @@ ST_FUNC void tcc_debug_start(TCCState *s1) pstrcat(buf, sizeof(buf), "/"); put_stabs_r(s1, buf, N_SO, 0, 0, text_section->data_offset, text_section, section_sym); - put_stabs_r(s1, file->prev->filename, N_SO, 0, 0, + put_stabs_r(s1, file->prev ? file->prev->filename : file->filename, + N_SO, 0, 0, text_section->data_offset, text_section, section_sym); for (i = 0; i < sizeof (default_debug) / sizeof (default_debug[0]); i++) put_stabs(s1, default_debug[i].name, N_LSYM, 0, 0, 0); @@ -6100,6 +6101,9 @@ special_math_val: /* pass it as 'int' to avoid structure arg passing problems */ vseti(VT_LOCAL, loc); +#ifdef CONFIG_TCC_BCHECK + loc -= tcc_state->do_bounds_check != 0; +#endif ret.c = vtop->c; if (ret_nregs < 0) vtop--; diff --git a/tests/tests2/121_struct_return.c b/tests/tests2/121_struct_return.c new file mode 100644 index 00000000..147761b1 --- /dev/null +++ b/tests/tests2/121_struct_return.c @@ -0,0 +1,35 @@ +#include + +typedef struct { + int data[4]; + double d1; + double d2; +} Node; + +Node init(Node self) { + self.data[0] = 0; + self.data[1] = 1; + self.data[2] = 2; + self.data[3] = 3; + self.d1 = 1234; + self.d2 = 2345; + return self; +} + +void dummy(Node self) { +} + +void print_data(Node data) { + printf ("%d %d %d %d %g %g\n", + data.data[0], data.data[1], data.data[2], data.data[3], + data.d1, data.d2); +} + +int main(void) { + /* This code resulted in a bounds checking error */ + Node data; + dummy (data); + char val; + data = init (data); + print_data(data); +} diff --git a/tests/tests2/121_struct_return.expect b/tests/tests2/121_struct_return.expect new file mode 100644 index 00000000..fa68b11d --- /dev/null +++ b/tests/tests2/121_struct_return.expect @@ -0,0 +1 @@ +0 1 2 3 1234 2345 diff --git a/tests/tests2/122_vla_reuse.c b/tests/tests2/122_vla_reuse.c new file mode 100644 index 00000000..d894af87 --- /dev/null +++ b/tests/tests2/122_vla_reuse.c @@ -0,0 +1,31 @@ +#include + +int +main (void) +{ + int n = 0; + int first=1; + int *p[101]; + if (0) { + lab:; + } + int x[n % 100 + 1]; + if (first == 0) { + if (&x[0] != p[n % 100 + 1]) { + printf ("ERROR: %d %p $p\n", &x[0], p[n % 100 + 1]); + return(1); + } + } + else { + p[n % 100 + 1] = &x[0]; + first = n < 100; + } + x[0] = 1; + x[n % 100] = 2; + n++; + if (n < 100000) + goto lab; + printf ("OK\n"); + return 0; +} + diff --git a/tests/tests2/122_vla_reuse.expect b/tests/tests2/122_vla_reuse.expect new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/tests/tests2/122_vla_reuse.expect @@ -0,0 +1 @@ +OK diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 2403a121..bf4251c7 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -103,6 +103,8 @@ GEN-ALWAYS = 115_bound_setjmp.test: FLAGS += -b 116_bound_setjmp2.test: FLAGS += -b 117_builtins.test: T1 = ( $(TCC) -run $1 && $(TCC) -b -run $1 ) +121_struct_return.test: FLAGS += -b +122_vla_reuse.test: FLAGS += -b # Filter source directory in warnings/errors (out-of-tree builds) FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'