History

Add attribute bound_no_checking

tcc-doc.texi: - Document attribute bound_no_checking tcctok.h: - Add bound_no_checking attribute tcc.h: - Add no_bcheck function attribute tccgen.c: - Use function attribute no_bcheck in merge_funcattr/parse_attribute/gen_function bcheck.c: - Fix no_checking in __bound_new_region/__bound_free/__bound_check tests/tests2/114_bound_signal.c: - Fix code with new attribute bound_no_checking tests/tests2/103_implicit_memmove.c: - Fix memmove prototype

herman ten brugge committed 6 years ago

Commit 50fe33f1 parent 5aaed437 files · +91 −53Browse files

Unified · Split

7 files
  1. lib/bcheck.c +31 −22
  2. tcc-doc.texi +29 −10
  3. tcc.h +2 −1
  4. tccgen.c +11 −0
  5. tcctok.h +2 −0
  6. tests/tests2/103_implicit_memmove.c +1 −1
  7. tests/tests2/114_bound_signal.c +15 −19
lib/bcheck.c+31−22
@@ -112,6 +112,12 @@ static sem_t bounds_sem; · 111 unmodified lines
112#define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \112#define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \
113 && errno == EINTR)113 && errno == EINTR)
114#define POST_SEM() if (use_sem) sem_post (&bounds_sem)114#define POST_SEM() if (use_sem) sem_post (&bounds_sem)
115#elif 0
116static pthread_mutex_t bounds_mtx;
117#define INIT_SEM() pthread_mutex_init (&bounds_mtx, NULL)
118#define EXIT_SEM() pthread_mutex_destroy (&bounds_mtx)
119#define WAIT_SEM() if (use_sem) pthread_mutex_lock (&bounds_mtx)
120#define POST_SEM() if (use_sem) pthread_mutex_unlock (&bounds_mtx)
115#else121#else
116static pthread_spinlock_t bounds_spin;122static pthread_spinlock_t bounds_spin;
117/* about 25% faster then semaphore. */123/* about 25% faster then semaphore. */
@@ -618,6 +624,9 @@ void __bound_new_region(void *p, size_t size) · 500 unmodified lines
618 alloca_list_type *cur;624 alloca_list_type *cur;
619 alloca_list_type *new;625 alloca_list_type *new;
620 626
627 if (no_checking)
628 return;
629
621 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",630 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
622 __FILE__, __FUNCTION__, p, (unsigned long)size);631 __FILE__, __FUNCTION__, p, (unsigned long)size);
623 GET_CALLER_FP (fp);632 GET_CALLER_FP (fp);
@@ -638,8 +647,7 @@ void __bound_new_region(void *p, size_t size) · 14 unmodified lines
638 last = cur;647 last = cur;
639 cur = cur->next;648 cur = cur->next;
640 }649 }
641 if (no_checking == 0)650 tree = splay_insert((size_t)p, size, tree);
642 tree = splay_insert((size_t)p, size, tree);
643 if (new) {651 if (new) {
644 new->fp = fp;652 new->fp = fp;
645 new->p = p;653 new->p = p;
@@ -1188,7 +1196,7 @@ void __bound_free(void *ptr, const void *caller) · 542 unmodified lines
1188 size_t addr = (size_t) ptr;1196 size_t addr = (size_t) ptr;
1189 void *p;1197 void *p;
1190 1198
1191 if (ptr == NULL || tree == NULL || no_checking1199 if (ptr == NULL || tree == NULL
1192#if MALLOC_REDIR1200#if MALLOC_REDIR
1193 || ((unsigned char *) ptr >= &initial_pool[0] &&1201 || ((unsigned char *) ptr >= &initial_pool[0] &&
1194 (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])1202 (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])
@@ -1198,25 +1206,27 @@ void __bound_free(void *ptr, const void *caller) · 3 unmodified lines
1198 1206
1199 dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr);1207 dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr);
1200 1208
1201 WAIT_SEM ();1209 if (no_checking == 0) {
1202 INCR_COUNT(bound_free_count);1210 WAIT_SEM ();
1203 tree = splay (addr, tree);1211 INCR_COUNT(bound_free_count);
1204 if (tree->start == addr) {1212 tree = splay (addr, tree);
1205 if (tree->is_invalid) {1213 if (tree->start == addr) {
1206 POST_SEM ();1214 if (tree->is_invalid) {
1207 bound_error("freeing invalid region");1215 POST_SEM ();
1208 return;1216 bound_error("freeing invalid region");
1217 return;
1218 }
1219 tree->is_invalid = 1;
1220 memset (ptr, 0x5a, tree->size);
1221 p = free_reuse_list[free_reuse_index];
1222 free_reuse_list[free_reuse_index] = ptr;
1223 free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE;
1224 if (p)
1225 tree = splay_delete((size_t)p, tree);
1226 ptr = p;
1209 }1227 }
1210 tree->is_invalid = 1;1228 POST_SEM ();
1211 memset (ptr, 0x5a, tree->size);
1212 p = free_reuse_list[free_reuse_index];
1213 free_reuse_list[free_reuse_index] = ptr;
1214 free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE;
1215 if (p)
1216 tree = splay_delete((size_t)p, tree);
1217 ptr = p;
1218 }1229 }
1219 POST_SEM ();
1220 BOUND_FREE (ptr);1230 BOUND_FREE (ptr);
1221}1231}
1222 1232
@@ -1340,8 +1350,7 @@ int __bound_munmap (void *start, size_t size) · 117 unmodified lines
1340/* check that (p ... p + size - 1) lies inside 'p' region, if any */1350/* check that (p ... p + size - 1) lies inside 'p' region, if any */
1341static void __bound_check(const void *p, size_t size, const char *function)1351static void __bound_check(const void *p, size_t size, const char *function)
1342{1352{
1343 if (no_checking == 0 && size != 0 &&1353 if (size != 0 && __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
1344 __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
1345 bound_error("invalid pointer %p, size 0x%lx in %s",1354 bound_error("invalid pointer %p, size 0x%lx in %s",
1346 p, (unsigned long)size, function);1355 p, (unsigned long)size, function);
1347 }1356 }
tcc-doc.texi+29−10
@@ -951,34 +951,53 @@ Here are some examples of caught errors: · 950 unmodified lines
951 951
952Signal handlers are not compatible with bounds checking. The code952Signal handlers are not compatible with bounds checking. The code
953below can be used to protect signal handlers.953below can be used to protect signal handlers.
954The call to __bound_checking(1) will disable bounds checking in the954The @code{__attribute__((bound_no_checking))} will prevent all bound checking
955whole application.955code generation. If a signal handler calls another function this
956function must also use @code{__attribute__((bound_no_checking))}.
956 957
957The BOUNDS_CHECKING_OFF and BOUNDS_CHECKING_ON can also be used to958The fork() function call in a multi threaded application is also a problem.
959To solve this all bounds checking can be disabled by calling
960@code{__bound_checking(1)}. The call to @code{__bound_checking(1)} will disable bounds
961checking in the whole application.
962
963The @code{BOUNDS_CHECKING_OFF} and @code{BOUNDS_CHECKING_ON} can also be used to
958disable bounds checking for some code. This is not recommended.964disable bounds checking for some code. This is not recommended.
959It is better to fix the code.965It is better to fix the code.
960 966
961@example967@example
962 968
963#ifdef __BOUNDS_CHECKING_ON969#if defined(__TINYC__) && __BOUNDS_CHECKING_ON
970#undef __attribute__
964extern void __bound_checking (int no_check);971extern void __bound_checking (int no_check);
965#define BOUNDS_CHECKING_OFF __bound_checking(1)972#define BOUNDS_CHECKING_OFF __bound_checking(1)
966#define BOUNDS_CHECKING_ON __bound_checking(-1)973#define BOUNDS_CHECKING_ON __bound_checking(-1)
974#define BOUNDS_NO_CHECKING __attribute__((bound_no_checking))
967#else975#else
968#define BOUNDS_CHECKING_OFF976#define BOUNDS_CHECKING_OFF
969#define BOUNDS_CHECKING_ON977#define BOUNDS_CHECKING_ON
978#define BOUNDS_NO_CHECKING
970#endif979#endif
971 980
972void real_signal_handler(int sig, siginfo_t *info, void *ucontext)981void signal_handler(int sig, void *info, void *ucontext) BOUNDS_NO_CHECKING
973@{982@{
974 ...983 ... signal handler code without generated bounds checking code.
975@}984@}
976 985
977void signal_handler(int sig, void *info, void *ucontext)986void run(const char *cmd)
978@{987@{
979 BOUNDS_CHECKING_OFF;988 switch (fork()) @{
980 real_signal_handler(sig, info, data);989 case 0:
981 BOUNDS_CHECKING_ON;990 BOUNDS_CHECKING_OFF;
991 ...
992 exec...
993 exit(1);
994 case -1:
995 ...
996 break;
997 default:
998 ...
999 break;
1000 @}
982@}1001@}
983 1002
984@end example1003@end example
tcc.h+2−1
@@ -505,7 +505,8 @@ struct FuncAttr { · 504 unmodified lines
505 func_dtor : 1, /* attribute((destructor)) */505 func_dtor : 1, /* attribute((destructor)) */
506 func_args : 8, /* PE __stdcall args */506 func_args : 8, /* PE __stdcall args */
507 func_alwinl : 1, /* always_inline */507 func_alwinl : 1, /* always_inline */
508 xxxx :15;508 no_bcheck : 1, /* no bound checking */
509 xxxx :14;
509};510};
510 511
511/* symbol management */512/* symbol management */
tccgen.c+11−0
@@ -1501,6 +1501,8 @@ static void merge_funcattr(struct FuncAttr *fa, struct FuncAttr *fa1) · 1500 unmodified lines
1501 fa->func_ctor = 1;1501 fa->func_ctor = 1;
1502 if (fa1->func_dtor)1502 if (fa1->func_dtor)
1503 fa->func_dtor = 1;1503 fa->func_dtor = 1;
1504 if (fa1->no_bcheck)
1505 fa->no_bcheck = 1;
1504}1506}
1505 1507
1506/* Merge attributes. */1508/* Merge attributes. */
@@ -4122,6 +4124,10 @@ redo: · 2615 unmodified lines
4122 case TOK_ALWAYS_INLINE2:4124 case TOK_ALWAYS_INLINE2:
4123 ad->f.func_alwinl = 1;4125 ad->f.func_alwinl = 1;
4124 break;4126 break;
4127 case TOK_NO_BOUND_CHECK1:
4128 case TOK_NO_BOUND_CHECK2:
4129 ad->f.no_bcheck = 1;
4130 break;
4125 case TOK_SECTION1:4131 case TOK_SECTION1:
4126 case TOK_SECTION2:4132 case TOK_SECTION2:
4127 skip('(');4133 skip('(');
@@ -8079,10 +8085,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 3951 unmodified lines
8079 'cur_text_section' */8085 'cur_text_section' */
8080static void gen_function(Sym *sym)8086static void gen_function(Sym *sym)
8081{8087{
8088 unsigned char save_bcheck = tcc_state->do_bounds_check;
8082 /* Initialize VLA state */8089 /* Initialize VLA state */
8083 struct scope f = { 0 };8090 struct scope f = { 0 };
8084 cur_scope = root_scope = &f;8091 cur_scope = root_scope = &f;
8085 8092
8093 if (sym->type.ref->f.no_bcheck)
8094 tcc_state->do_bounds_check = 0;
8095
8086 nocode_wanted = 0;8096 nocode_wanted = 0;
8087 ind = cur_text_section->data_offset;8097 ind = cur_text_section->data_offset;
8088 if (sym->a.aligned) {8098 if (sym->a.aligned) {
@@ -8135,6 +8145,7 @@ static void gen_function(Sym *sym) · 46 unmodified lines
8135 check_vstack();8145 check_vstack();
8136 /* do this after funcend debug info */8146 /* do this after funcend debug info */
8137 next();8147 next();
8148 tcc_state->do_bounds_check = save_bcheck;
8138}8149}
8139 8150
8140static void gen_inline_functions(TCCState *s)8151static void gen_inline_functions(TCCState *s)
tcctok.h+2−0
@@ -134,6 +134,8 @@ · 133 unmodified lines
134 DEF(TOK_DESTRUCTOR2, "__destructor__")134 DEF(TOK_DESTRUCTOR2, "__destructor__")
135 DEF(TOK_ALWAYS_INLINE1, "always_inline")135 DEF(TOK_ALWAYS_INLINE1, "always_inline")
136 DEF(TOK_ALWAYS_INLINE2, "__always_inline__")136 DEF(TOK_ALWAYS_INLINE2, "__always_inline__")
137 DEF(TOK_NO_BOUND_CHECK1, "bound_no_checking")
138 DEF(TOK_NO_BOUND_CHECK2, "__bound_no_checking__")
137 139
138 DEF(TOK_MODE, "__mode__")140 DEF(TOK_MODE, "__mode__")
139 DEF(TOK_MODE_QI, "__QI__")141 DEF(TOK_MODE_QI, "__QI__")
tests/tests2/103_implicit_memmove.c+1−1
@@ -8,7 +8,7 @@ int foo (struct S *a, struct S *b) · 7 unmodified lines
8 return 0;8 return 0;
9}9}
10 10
11void *memmove(void*,void*,long);11void *memmove(void*,const void*,__SIZE_TYPE__);
12void foo2 (struct S *a, struct S *b)12void foo2 (struct S *a, struct S *b)
13{13{
14 memmove(a, b, sizeof *a);14 memmove(a, b, sizeof *a);
tests/tests2/114_bound_signal.c+15−19
@@ -8,12 +8,25 @@ · 7 unmodified lines
8#include <errno.h>8#include <errno.h>
9#include <setjmp.h>9#include <setjmp.h>
10 10
11/* See tcc-doc.info */
12#if defined(__TINYC__) && __BOUNDS_CHECKING_ON
13#undef __attribute__
14extern void __bound_checking (int no_check);
15#define BOUNDS_CHECKING_OFF __bound_checking(1)
16#define BOUNDS_CHECKING_ON __bound_checking(-1)
17#define BOUNDS_NO_CHECKING __attribute__((bound_no_checking))
18#else
19#define BOUNDS_CHECKING_OFF
20#define BOUNDS_CHECKING_ON
21#define BOUNDS_NO_CHECKING
22#endif
23
11static volatile int run = 1;24static volatile int run = 1;
12static int dummy[10];25static int dummy[10];
13static sem_t sem;26static sem_t sem;
14 27
15static void28static void
16add (void)29add (void) BOUNDS_NO_CHECKING
17{30{
18 int i;31 int i;
19 32
@@ -41,29 +54,12 @@ do_signal (void *unused) · 21 unmodified lines
41 return NULL;54 return NULL;
42}55}
43 56
44/* See tcc-doc.info */57static void signal_handler(int sig) BOUNDS_NO_CHECKING
45#ifdef __BOUNDS_CHECKING_ON
46extern void __bound_checking (int no_check);
47#define BOUNDS_CHECKING_OFF __bound_checking(1)
48#define BOUNDS_CHECKING_ON __bound_checking(-1)
49#else
50#define BOUNDS_CHECKING_OFF
51#define BOUNDS_CHECKING_ON
52#endif
53
54static void real_signal_handler(int sig)
55{58{
56 add();59 add();
57 sem_post (&sem);60 sem_post (&sem);
58}61}
59 62
60static void signal_handler(int sig)
61{
62 BOUNDS_CHECKING_OFF;
63 real_signal_handler(sig);
64 BOUNDS_CHECKING_ON;
65}
66
67int63int
68main (void)64main (void)
69{65{

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