History

a bounds checking code for the ARCH=x86_64

seyko committed 11 years ago

Commit 559675b1 parent e92dc598 files · +319 −64Browse files

Unified · Split

8 files
  1. lib/Makefile +1 −1
  2. lib/alloca86_64-bt.S +60 −0
  3. lib/bcheck.c +58 −53
  4. tcc.h +1 −1
  5. tccelf.c +0 −2
  6. tccgen.c +17 −2
  7. tests/boundtest.c +56 −5
  8. x86_64-gen.c +126 −0
lib/Makefile+1−1
@@ -44,7 +44,7 @@ native : TCC = $(TOP)/tcc$(EXESUF) · 43 unmodified lines
44cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)44cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
45 45
46I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)46I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
47X86_64_O = libtcc1.o alloca86_64.o47X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
48ARM_O = libtcc1.o armeabi.o alloca-arm.o48ARM_O = libtcc1.o armeabi.o alloca-arm.o
49WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o49WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
50WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o50WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
lib/alloca86_64-bt.S+60−0
@@ -0,0 +1,60 @@
1/* ---------------------------------------------- */
2/* alloca86_64.S */
3
4.globl __bound_alloca
5__bound_alloca:
6
7#ifdef TCC_TARGET_PE
8 # bound checking is not implemented
9 pop %rdx
10 mov %rcx,%rax
11 add $15,%rax
12 and $-16,%rax
13 jz p3
14
15p1:
16 cmp $4096,%rax
17 jbe p2
18 test %rax,-4096(%rsp)
19 sub $4096,%rsp
20 sub $4096,%rax
21 jmp p1
22p2:
23
24 sub %rax,%rsp
25 mov %rsp,%rax
26 add $32,%rax
27
28p3:
29 push %rdx
30 ret
31#else
32 pop %rdx
33 mov %rdi,%rax
34 movl %rax,%rsi # size, a second parm to the __bound_new_region
35
36 add $15,%rax
37 and $-16,%rax
38 jz p3
39
40
41 sub %rax,%rsp
42 mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
43 mov %rsp,%rax
44
45 push %rdx
46 push %rax
47 call __bound_new_region
48 pop %rax
49 pop %rdx
50
51p3:
52 push %rdx
53 ret
54#endif
55
56/* mark stack as nonexecutable */
57#if defined __ELF__ && defined __linux__
58 .section .note.GNU-stack,"",@progbits
59#endif
60/* ---------------------------------------------- */
lib/bcheck.c+58−53
@@ -31,6 +31,12 @@ · 30 unmodified lines
31 31
32/* #define BOUND_DEBUG */32/* #define BOUND_DEBUG */
33 33
34#ifdef BOUND_DEBUG
35 #define dprintf(a...) fprintf(a)
36#else
37 #define dprintf(a...)
38#endif
39
34/* define so that bound array is static (faster, but use memory if40/* define so that bound array is static (faster, but use memory if
35 bound checking not used) */41 bound checking not used) */
36/* #define BOUND_STATIC */42/* #define BOUND_STATIC */
@@ -50,12 +56,12 @@ · 13 unmodified lines
50 56
51#define BOUND_T1_BITS 1357#define BOUND_T1_BITS 13
52#define BOUND_T2_BITS 1158#define BOUND_T2_BITS 11
53#define BOUND_T3_BITS (32 - BOUND_T1_BITS - BOUND_T2_BITS)59#define BOUND_T3_BITS (sizeof(size_t)*8 - BOUND_T1_BITS - BOUND_T2_BITS)
60#define BOUND_E_BITS (sizeof(size_t))
54 61
55#define BOUND_T1_SIZE (1 << BOUND_T1_BITS)62#define BOUND_T1_SIZE (1 << BOUND_T1_BITS)
56#define BOUND_T2_SIZE (1 << BOUND_T2_BITS)63#define BOUND_T2_SIZE (1 << BOUND_T2_BITS)
57#define BOUND_T3_SIZE (1 << BOUND_T3_BITS)64#define BOUND_T3_SIZE (1 << BOUND_T3_BITS)
58#define BOUND_E_BITS 4
59 65
60#define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS)66#define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS)
61#define BOUND_T23_SIZE (1 << BOUND_T23_BITS)67#define BOUND_T23_SIZE (1 << BOUND_T23_BITS)
@@ -64,7 +70,7 @@ · 2 unmodified lines
64/* this pointer is generated when bound check is incorrect */70/* this pointer is generated when bound check is incorrect */
65#define INVALID_POINTER ((void *)(-2))71#define INVALID_POINTER ((void *)(-2))
66/* size of an empty region */72/* size of an empty region */
67#define EMPTY_SIZE 0xffffffff73#define EMPTY_SIZE ((size_t)(-1))
68/* size of an invalid region */74/* size of an invalid region */
69#define INVALID_SIZE 075#define INVALID_SIZE 0
70 76
@@ -168,9 +174,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) · 97 unmodified lines
168 174
169 __bound_init();175 __bound_init();
170 176
171#if defined(BOUND_DEBUG)177 dprintf(stderr, "%s %s: %p %p\n", __FILE__, __FUNCTION__, p, offset);
172 printf("%s %s: 0x%x %d\n", __FILE__, __FUNCTION__, (int)p, offset);
173#endif
174 178
175 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];179 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
176 e = (BoundEntry *)((char *)e + 180 e = (BoundEntry *)((char *)e +
@@ -197,6 +201,8 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 20 unmodified lines
197 size_t addr = (size_t)p; \201 size_t addr = (size_t)p; \
198 BoundEntry *e; \202 BoundEntry *e; \
199 \203 \
204 dprintf(stderr, "%s %s: %p %p start\n", __FILE__, __FUNCTION__, p, offset); \
205 \
200 __bound_init(); \206 __bound_init(); \
201 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \207 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \
202 e = (BoundEntry *)((char *)e + \208 e = (BoundEntry *)((char *)e + \
@@ -212,6 +218,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 9 unmodified lines
212 fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); \218 fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); \
213 return INVALID_POINTER; /* return an invalid pointer */ \219 return INVALID_POINTER; /* return an invalid pointer */ \
214 } \220 } \
221 dprintf(stderr, "%s %s: return p+offset = %p\n", __FILE__, __FUNCTION__, p + offset); \
215 return p + offset; \222 return p + offset; \
216}223}
217 224
@@ -232,9 +239,8 @@ BOUND_PTR_INDIR(16) · 14 unmodified lines
232void FASTCALL __bound_local_new(void *p1) 239void FASTCALL __bound_local_new(void *p1)
233{240{
234 size_t addr, size, fp, *p = p1;241 size_t addr, size, fp, *p = p1;
235#ifdef BOUND_DEBUG242
236 fprintf(stderr, "%s, %s start p1=%p *p1=%p\n", __FILE__, __FUNCTION__, p, *p);243 dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p);
237#endif
238 GET_CALLER_FP(fp);244 GET_CALLER_FP(fp);
239 for(;;) {245 for(;;) {
240 addr = p[0];246 addr = p[0];
@@ -245,9 +251,7 @@ void FASTCALL __bound_local_new(void *p1) · 4 unmodified lines
245 p += 2;251 p += 2;
246 __bound_new_region((void *)addr, size);252 __bound_new_region((void *)addr, size);
247 }253 }
248#ifdef BOUND_DEBUG254 dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
249 fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
250#endif
251}255}
252 256
253/* called when leaving a function to delete all the local regions */257/* called when leaving a function to delete all the local regions */
@@ -268,7 +272,7 @@ void FASTCALL __bound_local_delete(void *p1) · 14 unmodified lines
268static BoundEntry *__bound_new_page(void)272static BoundEntry *__bound_new_page(void)
269{273{
270 BoundEntry *page;274 BoundEntry *page;
271 int i;275 size_t i;
272 276
273 page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE);277 page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE);
274 if (!page)278 if (!page)
@@ -296,11 +300,11 @@ static void bound_free_entry(BoundEntry *e) · 21 unmodified lines
296 libc_free(e);300 libc_free(e);
297}301}
298 302
299static inline BoundEntry *get_page(int index)303static BoundEntry *get_page(size_t index)
300{304{
301 BoundEntry *page;305 BoundEntry *page;
302 page = __bound_t1[index];306 page = __bound_t1[index];
303 if (page == __bound_empty_t2 || page == __bound_invalid_t2) {307 if (!page || page == __bound_empty_t2 || page == __bound_invalid_t2) {
304 /* create a new page if necessary */308 /* create a new page if necessary */
305 page = __bound_new_page();309 page = __bound_new_page();
306 __bound_t1[index] = page;310 __bound_t1[index] = page;
@@ -325,7 +329,7 @@ static void mark_invalid(size_t addr, size_t size) · 18 unmodified lines
325 t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS);329 t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS);
326 330
327#if 0331#if 0
328 printf("mark_invalid: start = %x %x\n", t2_start, t2_end);332 dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end);
329#endif333#endif
330 334
331 /* first we handle full pages */335 /* first we handle full pages */
@@ -364,7 +368,7 @@ static void mark_invalid(size_t addr, size_t size) · 32 unmodified lines
364 368
365void __bound_init(void)369void __bound_init(void)
366{370{
367 int i;371 size_t i;
368 BoundEntry *page;372 BoundEntry *page;
369 size_t start, size;373 size_t start, size;
370 size_t *p;374 size_t *p;
@@ -375,9 +379,7 @@ void __bound_init(void) · 4 unmodified lines
375 379
376 inited = 1;380 inited = 1;
377 381
378#ifdef BOUND_DEBUG382 dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
379 fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
380#endif
381 383
382 /* save malloc hooks and install bound check hooks */384 /* save malloc hooks and install bound check hooks */
383 install_malloc_hooks();385 install_malloc_hooks();
@@ -445,19 +447,18 @@ void __bound_init(void) · 61 unmodified lines
445 __bound_new_region((void *)p[0], p[1]);447 __bound_new_region((void *)p[0], p[1]);
446 p += 2;448 p += 2;
447 }449 }
448#ifdef BOUND_DEBUG450
449 fprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__);451 dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__);
450#endif
451}452}
452 453
453void __bound_main_arg(void **p)454void __bound_main_arg(void **p)
454{455{
455 void *start = p;456 void *start = p;
456 while (*p++);457 while (*p++);
457#ifdef BOUND_DEBUG458
458 fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", 459 dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n",
459 __FILE__, __FUNCTION__, (void *) p - start);460 __FILE__, __FUNCTION__, (void *) p - start);
460#endif461
461 __bound_new_region(start, (void *) p - start);462 __bound_new_region(start, (void *) p - start);
462}463}
463 464
@@ -495,10 +496,8 @@ void __bound_new_region(void *p, size_t size) · 31 unmodified lines
495 496
496 __bound_init();497 __bound_init();
497 498
498#ifdef BOUND_DEBUG499 dprintf(stderr, "%s, %s(%p, %p) start\n",
499 fprintf(stderr, "%s, %s(%p, %p) start\n",
500 __FILE__, __FUNCTION__, p, size);500 __FILE__, __FUNCTION__, p, size);
501#endif
502 501
503 start = (size_t)p;502 start = (size_t)p;
504 end = start + size;503 end = start + size;
@@ -553,9 +552,8 @@ void __bound_new_region(void *p, size_t size) · 48 unmodified lines
553 }552 }
554 add_region(e, start, size);553 add_region(e, start, size);
555 }554 }
556#ifdef BOUND_DEBUG555
557 fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);556 dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
558#endif
559}557}
560 558
561/* delete a region */559/* delete a region */
@@ -610,9 +608,7 @@ int __bound_delete_region(void *p) · 48 unmodified lines
610 608
611 __bound_init();609 __bound_init();
612 610
613#ifdef BOUND_DEBUG611 dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__);
614 fprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__);
615#endif
616 612
617 start = (size_t)p;613 start = (size_t)p;
618 t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);614 t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
@@ -681,9 +677,7 @@ int __bound_delete_region(void *p) · 62 unmodified lines
681 delete_region(e, p, empty_size);677 delete_region(e, p, empty_size);
682 }678 }
683 679
684#ifdef BOUND_DEBUG680 dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__);
685 fprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__);
686#endif
687 681
688 return 0;682 return 0;
689}683}
@@ -771,10 +765,9 @@ void *__bound_malloc(size_t size, const void *caller) · 81 unmodified lines
771 if (!ptr)765 if (!ptr)
772 return NULL;766 return NULL;
773 767
774#ifdef BOUND_DEBUG768 dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n",
775 fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n",
776 __FILE__, __FUNCTION__, ptr, size);769 __FILE__, __FUNCTION__, ptr, size);
777#endif770
778 __bound_new_region(ptr, size);771 __bound_new_region(ptr, size);
779 return ptr;772 return ptr;
780}773}
@@ -805,10 +798,9 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 24 unmodified lines
805 if (!ptr)798 if (!ptr)
806 return NULL;799 return NULL;
807 800
808#ifdef BOUND_DEBUG801 dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n",
809 fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n",
810 __FILE__, __FUNCTION__, ptr, size);802 __FILE__, __FUNCTION__, ptr, size);
811#endif803
812 __bound_new_region(ptr, size);804 __bound_new_region(ptr, size);
813 return ptr;805 return ptr;
814}806}
@@ -861,23 +853,23 @@ void *__bound_calloc(size_t nmemb, size_t size) · 46 unmodified lines
861static void bound_dump(void)853static void bound_dump(void)
862{854{
863 BoundEntry *page, *e;855 BoundEntry *page, *e;
864 int i, j;856 size_t i, j;
865 857
866 printf("region dump:\n");858 fprintf(stderr, "region dump:\n");
867 for(i=0;i<BOUND_T1_SIZE;i++) {859 for(i=0;i<BOUND_T1_SIZE;i++) {
868 page = __bound_t1[i];860 page = __bound_t1[i];
869 for(j=0;j<BOUND_T2_SIZE;j++) {861 for(j=0;j<BOUND_T2_SIZE;j++) {
870 e = page + j;862 e = page + j;
871 /* do not print invalid or empty entries */863 /* do not print invalid or empty entries */
872 if (e->size != EMPTY_SIZE && e->start != 0) {864 if (e->size != EMPTY_SIZE && e->start != 0) {
873 printf("%08x:", 865 fprintf(stderr, "%08x:",
874 (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + 866 (i << (BOUND_T2_BITS + BOUND_T3_BITS)) +
875 (j << BOUND_T3_BITS));867 (j << BOUND_T3_BITS));
876 do {868 do {
877 printf(" %08lx:%08lx", e->start, e->start + e->size);869 fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size);
878 e = e->next;870 e = e->next;
879 } while (e != NULL);871 } while (e != NULL);
880 printf("\n");872 fprintf(stderr, "\n");
881 }873 }
882 }874 }
883 }875 }
@@ -891,19 +883,27 @@ static void __bound_check(const void *p, size_t size) · 7 unmodified lines
891{883{
892 if (size == 0)884 if (size == 0)
893 return;885 return;
894 p = __bound_ptr_add((void *)p, size);886 p = __bound_ptr_add((void *)p, size - 1);
895 if (p == INVALID_POINTER)887 if (p == INVALID_POINTER)
896 bound_error("invalid pointer");888 bound_error("invalid pointer");
897}889}
898 890
899void *__bound_memcpy(void *dst, const void *src, size_t size)891void *__bound_memcpy(void *dst, const void *src, size_t size)
900{892{
893 void* p;
894
895 dprintf(stderr, "%s %s: start, dst=%p src=%p size=%p\n", __FILE__, __FUNCTION__, dst, src, size);
896
901 __bound_check(dst, size);897 __bound_check(dst, size);
902 __bound_check(src, size);898 __bound_check(src, size);
903 /* check also region overlap */899 /* check also region overlap */
904 if (src >= dst && src < dst + size)900 if (src >= dst && src < dst + size)
905 bound_error("overlapping regions in memcpy()");901 bound_error("overlapping regions in memcpy()");
906 return memcpy(dst, src, size);902
903 p = memcpy(dst, src, size);
904
905 dprintf(stderr, "%s %s: end, p=%p\n", __FILE__, __FUNCTION__, p);
906 return p;
907}907}
908 908
909void *__bound_memmove(void *dst, const void *src, size_t size)909void *__bound_memmove(void *dst, const void *src, size_t size)
@@ -939,7 +939,12 @@ int __bound_strlen(const char *s) · 29 unmodified lines
939 939
940char *__bound_strcpy(char *dst, const char *src)940char *__bound_strcpy(char *dst, const char *src)
941{941{
942 int len;942 size_t len;
943 void *p;
944
945 dprintf(stderr, "%s %s: strcpy start, dst=%p src=%p\n", __FILE__, __FUNCTION__, dst, src);
943 len = __bound_strlen(src);946 len = __bound_strlen(src);
944 return __bound_memcpy(dst, src, len + 1);947 p = __bound_memcpy(dst, src, len + 1);
948 dprintf(stderr, "%s %s: strcpy end, p=%p\n", __FILE__, __FUNCTION__, dst, src, p);
949 return p;
945}950}
tcc.h+1−1
@@ -164,7 +164,7 @@ · 163 unmodified lines
164 164
165#if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \165#if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
166 !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \166 !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \
167 !defined(TCC_TARGET_X86_64) && !defined(CONFIG_USE_LIBGCC)167 !defined(CONFIG_USE_LIBGCC)
168#define CONFIG_TCC_BCHECK /* enable bound checking code */168#define CONFIG_TCC_BCHECK /* enable bound checking code */
169#endif169#endif
170 170
tccelf.c+0−2
@@ -1579,7 +1579,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 1578 unmodified lines
1579 add_elf_sym(symtab_section, 0, 0,1579 add_elf_sym(symtab_section, 0, 0,
1580 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,1580 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1581 bounds_section->sh_num, "__bounds_start");1581 bounds_section->sh_num, "__bounds_start");
1582#ifdef TCC_TARGET_I386
1583 if (s1->output_type != TCC_OUTPUT_MEMORY) {1582 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1584 /* add 'call __bound_init()' in .init section */1583 /* add 'call __bound_init()' in .init section */
1585 1584
@@ -1601,7 +1600,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 15 unmodified lines
1601 tcc_warning("__bound_init not defined");1600 tcc_warning("__bound_init not defined");
1602 }1601 }
1603#endif1602#endif
1604#endif
1605}1603}
1606 1604
1607/* add tcc runtime libraries */1605/* add tcc runtime libraries */
tccgen.c+17−2
@@ -708,7 +708,7 @@ static void gbound(void) · 707 unmodified lines
708 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);708 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
709 /* must save type because we must set it to int to get pointer */709 /* must save type because we must set it to int to get pointer */
710 type1 = vtop->type;710 type1 = vtop->type;
711 vtop->type.t = VT_INT;711 vtop->type.t = VT_PTR;
712 gaddrof();712 gaddrof();
713 vpushi(0);713 vpushi(0);
714 gen_bounded_ptr_add();714 gen_bounded_ptr_add();
@@ -1752,7 +1752,22 @@ ST_FUNC void gen_op(int op) · 1037 unmodified lines
1752#endif1752#endif
1753 }1753 }
1754 gen_op('*');1754 gen_op('*');
1755#ifdef CONFIG_TCC_BCHECK1755#if 0
1756/* #ifdef CONFIG_TCC_BCHECK
1757 The main reason to removing this code:
1758 #include <stdio.h>
1759 int main ()
1760 {
1761 int v[10];
1762 int i = 10;
1763 int j = 9;
1764 fprintf(stderr, "v+i-j = %p\n", v+i-j);
1765 fprintf(stderr, "v+(i-j) = %p\n", v+(i-j));
1766 }
1767 When this code is on. then the output looks like
1768 v+i-j = 0xfffffffe
1769 v+(i-j) = 0xbff84000
1770 */
1756 /* if evaluating constant expression, no code should be1771 /* if evaluating constant expression, no code should be
1757 generated, so no bound check */1772 generated, so no bound check */
1758 if (tcc_state->do_bounds_check && !const_wanted) {1773 if (tcc_state->do_bounds_check && !const_wanted) {
tests/boundtest.c+56−5
@@ -50,12 +50,15 @@ int test4(void) · 49 unmodified lines
50 int i, sum = 0;50 int i, sum = 0;
51 int *tab4;51 int *tab4;
52 52
53 fprintf(stderr, "%s start\n", __FUNCTION__);
54
53 tab4 = malloc(20 * sizeof(int));55 tab4 = malloc(20 * sizeof(int));
54 for(i=0;i<20;i++) {56 for(i=0;i<20;i++) {
55 sum += tab4[i];57 sum += tab4[i];
56 }58 }
57 free(tab4);59 free(tab4);
58 60
61 fprintf(stderr, "%s end\n", __FUNCTION__);
59 return sum;62 return sum;
60}63}
61 64
@@ -65,12 +68,15 @@ int test5(void) · 3 unmodified lines
65 int i, sum = 0;68 int i, sum = 0;
66 int *tab4;69 int *tab4;
67 70
71 fprintf(stderr, "%s start\n", __FUNCTION__);
72
68 tab4 = malloc(20 * sizeof(int));73 tab4 = malloc(20 * sizeof(int));
69 for(i=0;i<21;i++) {74 for(i=0;i<21;i++) {
70 sum += tab4[i];75 sum += tab4[i];
71 }76 }
72 free(tab4);77 free(tab4);
73 78
79 fprintf(stderr, "%s end\n", __FUNCTION__);
74 return sum;80 return sum;
75}81}
76 82
@@ -187,8 +193,43 @@ int test15(void) · 110 unmodified lines
187 return strlen(p);193 return strlen(p);
188}194}
189 195
196/* ok */
197int test16()
198{
199 char *demo = "This is only a test.";
200 char *p;
201
202 fprintf(stderr, "%s start\n", __FUNCTION__);
203
204 p = alloca(16);
205 strcpy(p,"12345678901234");
206 printf("alloca: p is %s\n", p);
207
208 /* Test alloca embedded in a larger expression */
209 printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
210
211 fprintf(stderr, "%s end\n", __FUNCTION__);
212}
213
214/* error */
215int test17()
216{
217 char *demo = "This is only a test.";
218 char *p;
219
220 fprintf(stderr, "%s start\n", __FUNCTION__);
221
222 p = alloca(16);
223 strcpy(p,"12345678901234");
224 printf("alloca: p is %s\n", p);
225
226 /* Test alloca embedded in a larger expression */
227 printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) );
228
229 fprintf(stderr, "%s end\n", __FUNCTION__);
230}
231
190int (*table_test[])(void) = {232int (*table_test[])(void) = {
191 test1,
192 test1,233 test1,
193 test2,234 test2,
194 test3,235 test3,
@@ -204,23 +245,33 @@ int (*table_test[])(void) = { · 9 unmodified lines
204 test13,245 test13,
205 test14,246 test14,
206 test15,247 test15,
248 test16,
249 test17,
207};250};
208 251
209int main(int argc, char **argv)252int main(int argc, char **argv)
210{253{
211 int index;254 int index;
212 int (*ftest)(void);255 int (*ftest)(void);
256 int index_max = sizeof(table_test)/sizeof(table_test[0]);
213 257
214 if (argc < 2) {258 if (argc < 2) {
215 printf("usage: boundtest n\n"259 printf(
216 "test TCC bound checking system\n"260 "test TCC bound checking system\n"
217 );261 "usage: boundtest N\n"
262 " 1 <= N <= %d\n", index_max);
218 exit(1);263 exit(1);
219 }264 }
220 265
221 index = 0;266 index = 0;
222 if (argc >= 2)267 if (argc >= 2)
223 index = atoi(argv[1]);268 index = atoi(argv[1]) - 1;
269
270 if ((index < 0) || (index >= index_max)) {
271 printf("N is outside of the valid range (%d)\n", index);
272 exit(2);
273 }
274
224 /* well, we also use bounds on this ! */275 /* well, we also use bounds on this ! */
225 ftest = table_test[index];276 ftest = table_test[index];
226 ftest();277 ftest();
x86_64-gen.c+126−0
@@ -625,6 +625,90 @@ static void gcall_or_jmp(int is_jmp) · 624 unmodified lines
625 }625 }
626}626}
627 627
628#if defined(CONFIG_TCC_BCHECK)
629#ifndef TCC_TARGET_PE
630static addr_t func_bound_offset;
631static unsigned long func_bound_ind;
632#endif
633
634static void gen_static_call(int v)
635{
636 Sym *sym = external_global_sym(v, &func_old_type, 0);
637 oad(0xe8, -4);
638 greloc(cur_text_section, sym, ind-4, R_X86_64_PC32);
639}
640
641/* generate a bounded pointer addition */
642ST_FUNC void gen_bounded_ptr_add(void)
643{
644 /* save all temporary registers */
645 save_regs(0);
646
647 /* prepare fast x86_64 function call */
648 gv(RC_RAX);
649 o(0xc68948); // mov %rax,%rsi ## second arg in %rsi, this must be size
650 vtop--;
651
652 gv(RC_RAX);
653 o(0xc78948); // mov %rax,%rdi ## first arg in %rdi, this must be ptr
654 vtop--;
655
656 /* do a fast function call */
657 gen_static_call(TOK___bound_ptr_add);
658
659 /* returned pointer is in rax */
660 vtop++;
661 vtop->r = TREG_RAX | VT_BOUNDED;
662
663
664 /* relocation offset of the bounding function call point */
665 vtop->c.ull = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela)));
666}
667
668/* patch pointer addition in vtop so that pointer dereferencing is
669 also tested */
670ST_FUNC void gen_bounded_ptr_deref(void)
671{
672 addr_t func;
673 int size, align;
674 ElfW(Rela) *rel;
675 Sym *sym;
676
677 size = 0;
678 /* XXX: put that code in generic part of tcc */
679 if (!is_float(vtop->type.t)) {
680 if (vtop->r & VT_LVAL_BYTE)
681 size = 1;
682 else if (vtop->r & VT_LVAL_SHORT)
683 size = 2;
684 }
685 if (!size)
686 size = type_size(&vtop->type, &align);
687 switch(size) {
688 case 1: func = TOK___bound_ptr_indir1; break;
689 case 2: func = TOK___bound_ptr_indir2; break;
690 case 4: func = TOK___bound_ptr_indir4; break;
691 case 8: func = TOK___bound_ptr_indir8; break;
692 case 12: func = TOK___bound_ptr_indir12; break;
693 case 16: func = TOK___bound_ptr_indir16; break;
694 default:
695 tcc_error("unhandled size when dereferencing bounded pointer");
696 func = 0;
697 break;
698 }
699
700 sym = external_global_sym(func, &func_old_type, 0);
701 if (!sym->c)
702 put_extern_sym(sym, NULL, 0, 0);
703
704 /* patch relocation */
705 /* XXX: find a better solution ? */
706
707 rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.ull);
708 rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
709}
710#endif
711
628#ifdef TCC_TARGET_PE712#ifdef TCC_TARGET_PE
629 713
630#define REGN 4714#define REGN 4
@@ -1520,6 +1604,17 @@ void gfunc_prolog(CType *func_type) · 889 unmodified lines
1520 sym_push(sym->v & ~SYM_FIELD, type,1604 sym_push(sym->v & ~SYM_FIELD, type,
1521 VT_LOCAL | VT_LVAL, param_addr);1605 VT_LOCAL | VT_LVAL, param_addr);
1522 }1606 }
1607
1608#ifdef CONFIG_TCC_BCHECK
1609 /* leave some room for bound checking code */
1610 if (tcc_state->do_bounds_check) {
1611 func_bound_offset = lbounds_section->data_offset;
1612 func_bound_ind = ind;
1613 oad(0xb8, 0); /* lbound section pointer */
1614 o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
1615 oad(0xb8, 0); /* call to function */
1616 }
1617#endif
1523}1618}
1524 1619
1525/* generate function epilog */1620/* generate function epilog */
@@ -1527,6 +1622,37 @@ void gfunc_epilog(void) · 1 unmodified line
1527{1622{
1528 int v, saved_ind;1623 int v, saved_ind;
1529 1624
1625#ifdef CONFIG_TCC_BCHECK
1626 if (tcc_state->do_bounds_check
1627 && func_bound_offset != lbounds_section->data_offset)
1628 {
1629 addr_t saved_ind;
1630 addr_t *bounds_ptr;
1631 Sym *sym_data;
1632
1633 /* add end of table info */
1634 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
1635 *bounds_ptr = 0;
1636
1637 /* generate bound local allocation */
1638 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
1639 func_bound_offset, lbounds_section->data_offset);
1640 saved_ind = ind;
1641 ind = func_bound_ind;
1642 greloc(cur_text_section, sym_data, ind + 1, R_386_32);
1643 ind = ind + 5 + 3;
1644 gen_static_call(TOK___bound_local_new);
1645 ind = saved_ind;
1646
1647 /* generate bound check local freeing */
1648 o(0x5250); /* save returned value, if any */
1649 greloc(cur_text_section, sym_data, ind + 1, R_386_32);
1650 oad(0xb8, 0); /* mov xxx, %rax */
1651 o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
1652 gen_static_call(TOK___bound_local_delete);
1653 o(0x585a); /* restore returned value, if any */
1654 }
1655#endif
1530 o(0xc9); /* leave */1656 o(0xc9); /* leave */
1531 if (func_ret_sub == 0) {1657 if (func_ret_sub == 0) {
1532 o(0xc3); /* ret */1658 o(0xc3); /* ret */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t