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
This commit is contained in:
		
							parent
							
								
									352e1d0fc4
								
							
						
					
					
						commit
						afc0917f88
					
				
					 11 changed files with 104 additions and 4 deletions
				
			
		| 
						 | 
					@ -2255,6 +2255,10 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
 | 
				
			||||||
        vpushv(vtop);
 | 
					        vpushv(vtop);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    r = intr(gv(RC_INT));
 | 
					    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 */
 | 
					    o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */
 | 
				
			||||||
#ifdef TCC_ARM_EABI
 | 
					#ifdef TCC_ARM_EABI
 | 
				
			||||||
    if (align < 8)
 | 
					    if (align < 8)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2046,6 +2046,11 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
 | 
				
			||||||
        vpushv(vtop);
 | 
					        vpushv(vtop);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    r = intr(gv(RC_INT));
 | 
					    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(0x91003c00 | r | r << 5); // add x(r),x(r),#15
 | 
				
			||||||
    o(0x927cec00 | r | r << 5); // bic 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)
 | 
					    o(0xcb2063ff | r << 16); // sub sp,sp,x(r)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ _(__bound_alloca):
 | 
				
			||||||
    pop     %edx
 | 
					    pop     %edx
 | 
				
			||||||
    pop     %eax
 | 
					    pop     %eax
 | 
				
			||||||
    mov     %eax, %ecx
 | 
					    mov     %eax, %ecx
 | 
				
			||||||
    add     $3,%eax
 | 
					    add     $3+1,%eax
 | 
				
			||||||
    and     $-4,%eax
 | 
					    and     $-4,%eax
 | 
				
			||||||
    jz      p6
 | 
					    jz      p6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								lib/bcheck.c
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								lib/bcheck.c
									
										
									
									
									
								
							| 
						 | 
					@ -212,6 +212,7 @@ struct tree_node {
 | 
				
			||||||
typedef struct alloca_list_struct {
 | 
					typedef struct alloca_list_struct {
 | 
				
			||||||
    size_t fp;
 | 
					    size_t fp;
 | 
				
			||||||
    void *p;
 | 
					    void *p;
 | 
				
			||||||
 | 
					    size_t size;
 | 
				
			||||||
    struct alloca_list_struct *next;
 | 
					    struct alloca_list_struct *next;
 | 
				
			||||||
} alloca_list_type;
 | 
					} alloca_list_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -728,12 +729,22 @@ void __bound_new_region(void *p, size_t size)
 | 
				
			||||||
    last = NULL;
 | 
					    last = NULL;
 | 
				
			||||||
    cur = alloca_list;
 | 
					    cur = alloca_list;
 | 
				
			||||||
    while (cur) {
 | 
					    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)
 | 
					            if (last)
 | 
				
			||||||
                last->next = cur->next;
 | 
					                last->next = cur->next;
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                alloca_list = cur->next;
 | 
					                alloca_list = cur->next;
 | 
				
			||||||
            tree = splay_delete((size_t)p, tree);
 | 
					            tree = splay_delete((size_t)cur->p, tree);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        last = cur;
 | 
					        last = cur;
 | 
				
			||||||
| 
						 | 
					@ -743,6 +754,7 @@ void __bound_new_region(void *p, size_t size)
 | 
				
			||||||
    if (new) {
 | 
					    if (new) {
 | 
				
			||||||
        new->fp = fp;
 | 
					        new->fp = fp;
 | 
				
			||||||
        new->p = p;
 | 
					        new->p = p;
 | 
				
			||||||
 | 
					        new->size = size;
 | 
				
			||||||
        new->next = alloca_list;
 | 
					        new->next = alloca_list;
 | 
				
			||||||
        alloca_list = new;
 | 
					        alloca_list = new;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1327,6 +1327,11 @@ ST_FUNC void gen_vla_alloc(CType *type, int align)
 | 
				
			||||||
        vpushv(vtop);
 | 
					        vpushv(vtop);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    rr = ireg(gv(RC_INT));
 | 
					    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, 0, rr, rr, 15);   // addi RR, RR, 15
 | 
				
			||||||
    EI(0x13, 7, rr, rr, -16);  // andi, RR, RR, -16
 | 
					    EI(0x13, 7, rr, rr, -16);  // andi, RR, RR, -16
 | 
				
			||||||
    ER(0x33, 0, 2, 2, rr, 0x20); // sub sp, sp, rr
 | 
					    ER(0x33, 0, 2, 2, rr, 0x20); // sub sp, sp, rr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								tccgen.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								tccgen.c
									
										
									
									
									
								
							| 
						 | 
					@ -413,7 +413,8 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
 | 
				
			||||||
        pstrcat(buf, sizeof(buf), "/");
 | 
					        pstrcat(buf, sizeof(buf), "/");
 | 
				
			||||||
        put_stabs_r(s1, buf, N_SO, 0, 0,
 | 
					        put_stabs_r(s1, buf, N_SO, 0, 0,
 | 
				
			||||||
                    text_section->data_offset, text_section, section_sym);
 | 
					                    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);
 | 
					                    text_section->data_offset, text_section, section_sym);
 | 
				
			||||||
        for (i = 0; i < sizeof (default_debug) / sizeof (default_debug[0]); i++)
 | 
					        for (i = 0; i < sizeof (default_debug) / sizeof (default_debug[0]); i++)
 | 
				
			||||||
            put_stabs(s1, default_debug[i].name, N_LSYM, 0, 0, 0);
 | 
					            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
 | 
					                    /* pass it as 'int' to avoid structure arg passing
 | 
				
			||||||
                       problems */
 | 
					                       problems */
 | 
				
			||||||
                    vseti(VT_LOCAL, loc);
 | 
					                    vseti(VT_LOCAL, loc);
 | 
				
			||||||
 | 
					#ifdef CONFIG_TCC_BCHECK
 | 
				
			||||||
 | 
					                    loc -= tcc_state->do_bounds_check != 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
                    ret.c = vtop->c;
 | 
					                    ret.c = vtop->c;
 | 
				
			||||||
                    if (ret_nregs < 0)
 | 
					                    if (ret_nregs < 0)
 | 
				
			||||||
                      vtop--;
 | 
					                      vtop--;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										35
									
								
								tests/tests2/121_struct_return.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tests/tests2/121_struct_return.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,35 @@
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								tests/tests2/121_struct_return.expect
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/tests2/121_struct_return.expect
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					0 1 2 3 1234 2345
 | 
				
			||||||
							
								
								
									
										31
									
								
								tests/tests2/122_vla_reuse.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/tests2/122_vla_reuse.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								tests/tests2/122_vla_reuse.expect
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/tests2/122_vla_reuse.expect
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					OK
 | 
				
			||||||
| 
						 | 
					@ -103,6 +103,8 @@ GEN-ALWAYS =
 | 
				
			||||||
115_bound_setjmp.test: FLAGS += -b
 | 
					115_bound_setjmp.test: FLAGS += -b
 | 
				
			||||||
116_bound_setjmp2.test: FLAGS += -b
 | 
					116_bound_setjmp2.test: FLAGS += -b
 | 
				
			||||||
117_builtins.test: T1 = ( $(TCC) -run $1 && $(TCC) -b -run $1 )
 | 
					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 source directory in warnings/errors (out-of-tree builds)
 | 
				
			||||||
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
 | 
					FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue