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
112112 #define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \
113113 && errno == EINTR)
114114 #define POST_SEM() if (use_sem) sem_post (&bounds_sem)
115+#elif 0
116+static 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)
115121 #else
116122 static pthread_spinlock_t bounds_spin;
117123 /* about 25% faster then semaphore. */
@@ -618,6 +624,9 @@ void __bound_new_region(void *p, size_t size) · 500 unmodified lines
618624 alloca_list_type *cur;
619625 alloca_list_type *new;
620626
627+ if (no_checking)
628+ return;
629+
621630 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
622631 __FILE__, __FUNCTION__, p, (unsigned long)size);
623632 GET_CALLER_FP (fp);
@@ -638,8 +647,7 @@ void __bound_new_region(void *p, size_t size) · 14 unmodified lines
638647 last = cur;
639648 cur = cur->next;
640649 }
641− if (no_checking == 0)
642− tree = splay_insert((size_t)p, size, tree);
650+ tree = splay_insert((size_t)p, size, tree);
643651 if (new) {
644652 new->fp = fp;
645653 new->p = p;
@@ -1188,7 +1196,7 @@ void __bound_free(void *ptr, const void *caller) · 542 unmodified lines
11881196 size_t addr = (size_t) ptr;
11891197 void *p;
11901198
1191− if (ptr == NULL || tree == NULL || no_checking
1199+ if (ptr == NULL || tree == NULL
11921200 #if MALLOC_REDIR
11931201 || ((unsigned char *) ptr >= &initial_pool[0] &&
11941202 (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])
@@ -1198,25 +1206,27 @@ void __bound_free(void *ptr, const void *caller) · 3 unmodified lines
11981206
11991207 dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr);
12001208
1201− WAIT_SEM ();
1202− INCR_COUNT(bound_free_count);
1203− tree = splay (addr, tree);
1204− if (tree->start == addr) {
1205− if (tree->is_invalid) {
1206− POST_SEM ();
1207− bound_error("freeing invalid region");
1208− return;
1209+ if (no_checking == 0) {
1210+ WAIT_SEM ();
1211+ INCR_COUNT(bound_free_count);
1212+ tree = splay (addr, tree);
1213+ if (tree->start == addr) {
1214+ if (tree->is_invalid) {
1215+ POST_SEM ();
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;
12091227 }
1210− tree->is_invalid = 1;
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;
1228+ POST_SEM ();
12181229 }
1219− POST_SEM ();
12201230 BOUND_FREE (ptr);
12211231 }
12221232
@@ -1340,8 +1350,7 @@ int __bound_munmap (void *start, size_t size) · 117 unmodified lines
13401350 /* check that (p ... p + size - 1) lies inside 'p' region, if any */
13411351 static void __bound_check(const void *p, size_t size, const char *function)
13421352 {
1343− if (no_checking == 0 && size != 0 &&
1344− __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
1353+ if (size != 0 && __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
13451354 bound_error("invalid pointer %p, size 0x%lx in %s",
13461355 p, (unsigned long)size, function);
13471356 }
tcc-doc.texi+29−10
@@ -951,34 +951,53 @@ Here are some examples of caught errors: · 950 unmodified lines
951951
952952 Signal handlers are not compatible with bounds checking. The code
953953 below can be used to protect signal handlers.
954−The call to __bound_checking(1) will disable bounds checking in the
955−whole application.
954+The @code{__attribute__((bound_no_checking))} will prevent all bound checking
955+code generation. If a signal handler calls another function this
956+function must also use @code{__attribute__((bound_no_checking))}.
956957
957−The BOUNDS_CHECKING_OFF and BOUNDS_CHECKING_ON can also be used to
958+The fork() function call in a multi threaded application is also a problem.
959+To 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
961+checking in the whole application.
962+
963+The @code{BOUNDS_CHECKING_OFF} and @code{BOUNDS_CHECKING_ON} can also be used to
958964 disable bounds checking for some code. This is not recommended.
959965 It is better to fix the code.
960966
961967 @example
962968
963−#ifdef __BOUNDS_CHECKING_ON
969+#if defined(__TINYC__) && __BOUNDS_CHECKING_ON
970+#undef __attribute__
964971 extern void __bound_checking (int no_check);
965972 #define BOUNDS_CHECKING_OFF __bound_checking(1)
966973 #define BOUNDS_CHECKING_ON __bound_checking(-1)
974+#define BOUNDS_NO_CHECKING __attribute__((bound_no_checking))
967975 #else
968976 #define BOUNDS_CHECKING_OFF
969977 #define BOUNDS_CHECKING_ON
978+#define BOUNDS_NO_CHECKING
970979 #endif
971980
972−void real_signal_handler(int sig, siginfo_t *info, void *ucontext)
981+void signal_handler(int sig, void *info, void *ucontext) BOUNDS_NO_CHECKING
973982 @{
974− ...
983+ ... signal handler code without generated bounds checking code.
975984 @}
976985
977−void signal_handler(int sig, void *info, void *ucontext)
986+void run(const char *cmd)
978987 @{
979− BOUNDS_CHECKING_OFF;
980− real_signal_handler(sig, info, data);
981− BOUNDS_CHECKING_ON;
988+ switch (fork()) @{
989+ case 0:
990+ BOUNDS_CHECKING_OFF;
991+ ...
992+ exec...
993+ exit(1);
994+ case -1:
995+ ...
996+ break;
997+ default:
998+ ...
999+ break;
1000+ @}
9821001 @}
9831002
9841003 @end example
tcc.h+2−1
@@ -505,7 +505,8 @@ struct FuncAttr { · 504 unmodified lines
505505 func_dtor : 1, /* attribute((destructor)) */
506506 func_args : 8, /* PE __stdcall args */
507507 func_alwinl : 1, /* always_inline */
508− xxxx :15;
508+ no_bcheck : 1, /* no bound checking */
509+ xxxx :14;
509510 };
510511
511512 /* symbol management */
tccgen.c+11−0
@@ -1501,6 +1501,8 @@ static void merge_funcattr(struct FuncAttr *fa, struct FuncAttr *fa1) · 1500 unmodified lines
15011501 fa->func_ctor = 1;
15021502 if (fa1->func_dtor)
15031503 fa->func_dtor = 1;
1504+ if (fa1->no_bcheck)
1505+ fa->no_bcheck = 1;
15041506 }
15051507
15061508 /* Merge attributes. */
@@ -4122,6 +4124,10 @@ redo: · 2615 unmodified lines
41224124 case TOK_ALWAYS_INLINE2:
41234125 ad->f.func_alwinl = 1;
41244126 break;
4127+ case TOK_NO_BOUND_CHECK1:
4128+ case TOK_NO_BOUND_CHECK2:
4129+ ad->f.no_bcheck = 1;
4130+ break;
41254131 case TOK_SECTION1:
41264132 case TOK_SECTION2:
41274133 skip('(');
@@ -8079,10 +8085,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 3951 unmodified lines
80798085 'cur_text_section' */
80808086 static void gen_function(Sym *sym)
80818087 {
8088+ unsigned char save_bcheck = tcc_state->do_bounds_check;
80828089 /* Initialize VLA state */
80838090 struct scope f = { 0 };
80848091 cur_scope = root_scope = &f;
80858092
8093+ if (sym->type.ref->f.no_bcheck)
8094+ tcc_state->do_bounds_check = 0;
8095+
80868096 nocode_wanted = 0;
80878097 ind = cur_text_section->data_offset;
80888098 if (sym->a.aligned) {
@@ -8135,6 +8145,7 @@ static void gen_function(Sym *sym) · 46 unmodified lines
81358145 check_vstack();
81368146 /* do this after funcend debug info */
81378147 next();
8148+ tcc_state->do_bounds_check = save_bcheck;
81388149 }
81398150
81408151 static void gen_inline_functions(TCCState *s)
tcctok.h+2−0
@@ -134,6 +134,8 @@ · 133 unmodified lines
134134 DEF(TOK_DESTRUCTOR2, "__destructor__")
135135 DEF(TOK_ALWAYS_INLINE1, "always_inline")
136136 DEF(TOK_ALWAYS_INLINE2, "__always_inline__")
137+ DEF(TOK_NO_BOUND_CHECK1, "bound_no_checking")
138+ DEF(TOK_NO_BOUND_CHECK2, "__bound_no_checking__")
137139
138140 DEF(TOK_MODE, "__mode__")
139141 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
88 return 0;
99 }
1010
11−void *memmove(void*,void*,long);
11+void *memmove(void*,const void*,__SIZE_TYPE__);
1212 void foo2 (struct S *a, struct S *b)
1313 {
1414 memmove(a, b, sizeof *a);
tests/tests2/114_bound_signal.c+15−19
@@ -8,12 +8,25 @@ · 7 unmodified lines
88 #include <errno.h>
99 #include <setjmp.h>
1010
11+/* See tcc-doc.info */
12+#if defined(__TINYC__) && __BOUNDS_CHECKING_ON
13+#undef __attribute__
14+extern 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+
1124 static volatile int run = 1;
1225 static int dummy[10];
1326 static sem_t sem;
1427
1528 static void
16−add (void)
29+add (void) BOUNDS_NO_CHECKING
1730 {
1831 int i;
1932
@@ -41,29 +54,12 @@ do_signal (void *unused) · 21 unmodified lines
4154 return NULL;
4255 }
4356
44−/* See tcc-doc.info */
45−#ifdef __BOUNDS_CHECKING_ON
46−extern 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−
54−static void real_signal_handler(int sig)
57+static void signal_handler(int sig) BOUNDS_NO_CHECKING
5558 {
5659 add();
5760 sem_post (&sem);
5861 }
5962
60−static void signal_handler(int sig)
61−{
62− BOUNDS_CHECKING_OFF;
63− real_signal_handler(sig);
64− BOUNDS_CHECKING_ON;
65−}
66−
6763 int
6864 main (void)
6965 {

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