History

Update bound checking code.

Add __attribute__((constructor)) to __bounds_init. - remove tcc_add_bcheck from i386-link.c and x86_64-link.c - add simplified tcc_add_bcheck to tccelf.c - Update tccrun.c to call constructor/destructor. Set dynsym sh_info to number of local symbols in tccelf.c Reduce stack size when bounds checking is enabled. Added variable TCC_LIBBCHECK for windows support. Add signal stack to detect stack overflow. Add all & parameters in lbound_section and remove them if not used. Close fd in tcc_relocate in tccrun.c Fix section type constructor/destructor in tccelf.c Add check code in tests/boundtest.c for mem/str functions. Remove -ba from documentation. Add bounds check signal info in documentation. bcheck.c: - Fix initial_pool alignment. . Fix printf statements. . Add prototypes for all external interface functions. - Add TCC_BOUNDS_WARN_POINTER_ADD environment variable. . Add ctype and errno data. - Fix alloca when multithreading is used. - Add lock for __bound_checking and __bound_never_fatal. - Catch pthread_create and use locks when called. - Detect in loaded in shared lib and use locks when found - Use spin locks instead of semaphore locks. - Make spin locked code as small as possible. - Fix mem/str functions checking. - Fix overlap checking mem/str functions.

herman ten brugge committed 6 years ago

Commit 38776181 parent 0d6801b13 files · +1197 −606Browse files

Unified · Split

13 files
  1. i386-gen.c +7 −2
  2. i386-link.c +0 −75
  3. lib/bcheck.c +732 −394
  4. tcc-doc.texi +38 −5
  5. tcc.h +8 −0
  6. tccelf.c +29 −4
  7. tccgen.c +122 −18
  8. tccpe.c +1 −1
  9. tccrun.c +48 −18
  10. tests/Makefile +1 −1
  11. tests/boundtest.c +197 −0
  12. x86_64-gen.c +14 −3
  13. x86_64-link.c +0 −85
i386-gen.c+7−2
@@ -95,7 +95,6 @@ ST_DATA const int reg_classes[NB_REGS] = { · 94 unmodified lines
95static unsigned long func_sub_sp_offset;95static unsigned long func_sub_sp_offset;
96static int func_ret_sub;96static int func_ret_sub;
97#ifdef CONFIG_TCC_BCHECK97#ifdef CONFIG_TCC_BCHECK
98static addr_t func_bound_offset;
99static unsigned long func_bound_ind;98static unsigned long func_bound_ind;
100#endif99#endif
101 100
@@ -402,8 +401,10 @@ ST_FUNC void gfunc_call(int nb_args) · 300 unmodified lines
402 Sym *func_sym;401 Sym *func_sym;
403 402
404#ifdef CONFIG_TCC_BCHECK403#ifdef CONFIG_TCC_BCHECK
405 if (tcc_state->do_bounds_check)404 if (tcc_state->do_bounds_check) {
405 save_temp_local (nb_args);
406 gbound_args(nb_args);406 gbound_args(nb_args);
407 }
407#endif408#endif
408 409
409 args_size = 0;410 args_size = 0;
@@ -485,6 +486,10 @@ ST_FUNC void gfunc_call(int nb_args) · 75 unmodified lines
485 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)486 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
486 gadd_sp(args_size);487 gadd_sp(args_size);
487 vtop--;488 vtop--;
489#ifdef CONFIG_TCC_BCHECK
490 if (tcc_state->do_bounds_check)
491 restore_temp_local ();
492#endif
488}493}
489 494
490#ifdef TCC_TARGET_PE495#ifdef TCC_TARGET_PE
i386-link.c+0−75
@@ -235,79 +235,4 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 234 unmodified lines
235 }235 }
236}236}
237 237
238#ifdef CONFIG_TCC_BCHECK
239ST_FUNC void tcc_add_bcheck(TCCState *s1)
240{
241 addr_t *ptr;
242 int loc_glob;
243 int sym_index;
244 int bsym_index;
245
246 if (0 == s1->do_bounds_check)
247 return;
248 /* XXX: add an object file to do that */
249 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
250 *ptr = 0;
251 loc_glob = s1->output_type != TCC_OUTPUT_MEMORY ? STB_LOCAL : STB_GLOBAL;
252 bsym_index = set_elf_sym(symtab_section, 0, 0,
253 ELFW(ST_INFO)(loc_glob, STT_NOTYPE), 0,
254 bounds_section->sh_num, "__bounds_start");
255 /* pull bcheck.o from libtcc1.a */
256 sym_index = set_elf_sym(symtab_section, 0, 0,
257 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
258 SHN_UNDEF, "__bound_init");
259 if (s1->output_type != TCC_OUTPUT_MEMORY) {
260 /* add 'call __bound_init()' in .init section */
261 Section *init_section = find_section(s1, ".init");
262 unsigned char *pinit;
263#ifdef TCC_TARGET_PE
264 pinit = section_ptr_add(init_section, 3);
265 pinit[0] = 0x55; /* push %rbp */
266 pinit[1] = 0x89; /* mov %esp,%ebp */
267 pinit[2] = 0xe5;
268#endif
269 pinit = section_ptr_add(init_section, 5);
270 pinit[0] = 0xe8;
271 write32le(pinit + 1, -4);
272 put_elf_reloc(symtab_section, init_section,
273 init_section->data_offset - 4, R_386_PC32, sym_index);
274 /* R_386_PC32 = R_X86_64_PC32 = 2 */
275 pinit = section_ptr_add(init_section, 6);
276 pinit[0] = 0xb8; /* mov xx,%eax */
277 write32le(pinit + 1, 0);
278 pinit[5] = 0x50; /* push %eax */
279 put_elf_reloc(symtab_section, init_section,
280 init_section->data_offset - 5, R_386_32, bsym_index);
281 sym_index = set_elf_sym(symtab_section, 0, 0,
282 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
283 SHN_UNDEF, "__bounds_add_static_var");
284 pinit = section_ptr_add(init_section, 5);
285 pinit[0] = 0xe8;
286 write32le(pinit + 1, -4);
287 put_elf_reloc(symtab_section, init_section,
288 init_section->data_offset - 4, R_386_PC32, sym_index);
289 /* R_386_PC32 = R_X86_64_PC32 = 2 */
290 pinit = section_ptr_add(init_section, 3);
291 pinit[0] = 0x83; /* add $0x4,%esp */
292 pinit[1] = 0xc4;
293 pinit[2] = 0x04;
294#ifdef TCC_TARGET_PE
295 {
296 int init_index = set_elf_sym(symtab_section,
297 0, 0,
298 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
299 init_section->sh_num, "__init_start");
300 Sym sym;
301 init_section->sh_flags |= SHF_EXECINSTR;
302 pinit = section_ptr_add(init_section, 2);
303 pinit[0] = 0xc9; /* leave */
304 pinit[1] = 0xc3; /* ret */
305 sym.c = init_index;
306 add_init_array (s1, &sym);
307 }
308#endif
309 }
310}
311#endif
312
313#endif /* !TARGET_DEFS_ONLY */238#endif /* !TARGET_DEFS_ONLY */
lib/bcheck.c+732−394
@@ -34,17 +34,20 @@ · 33 unmodified lines
34#include <unistd.h>34#include <unistd.h>
35#endif35#endif
36 36
37#define BOUND_DEBUG37#define BOUND_DEBUG (1)
38#define BOUND_STATISTIC38#define BOUND_STATISTIC (1)
39 39
40#ifdef BOUND_DEBUG40#if BOUND_DEBUG
41 #define dprintf(a...) if (print_calls) fprintf(a)41 #define dprintf(a...) if (print_calls) fprintf(a)
42#else42#else
43 #define dprintf(a...)43 #define dprintf(a...)
44#endif44#endif
45 45
46/* Check memalign */46#ifdef __attribute__
47#define HAVE_MEMALIGN47 /* an __attribute__ macro is defined in the system headers */
48 #undef __attribute__
49#endif
50#define FASTCALL __attribute__((regparm(3)))
48 51
49#if defined(__FreeBSD__) \52#if defined(__FreeBSD__) \
50 || defined(__FreeBSD_kernel__) \53 || defined(__FreeBSD_kernel__) \
@@ -52,43 +55,76 @@ · 1 unmodified line
52 || defined(__OpenBSD__) \55 || defined(__OpenBSD__) \
53 || defined(__NetBSD__) \56 || defined(__NetBSD__) \
54 || defined(__dietlibc__)57 || defined(__dietlibc__)
55#undef HAVE_MEMALIGN58
56#define INIT_SEM()59#define INIT_SEM()
57#define EXIT_SEM()60#define EXIT_SEM()
58#define WAIT_SEM()61#define WAIT_SEM()
59#define POST_SEM()62#define POST_SEM()
60#define HAS_ENVIRON 063#define HAVE_MEMALIGN (0)
61#define MALLOC_REDIR (0)64#define HAS_ENVIRON (0)
65#define MALLOC_REDIR (0)
66#define HAVE_PTHREAD_CREATE (0)
67#define HAVE_CTYPE (0)
68#define HAVE_ERRNO (0)
69
62#elif defined(_WIN32)70#elif defined(_WIN32)
71
63#include <windows.h>72#include <windows.h>
64#undef HAVE_MEMALIGN
65static CRITICAL_SECTION bounds_sem;73static CRITICAL_SECTION bounds_sem;
66#define INIT_SEM() InitializeCriticalSection(&bounds_sem)74#define INIT_SEM() InitializeCriticalSection(&bounds_sem)
67#define EXIT_SEM() DeleteCriticalSection(&bounds_sem)75#define EXIT_SEM() DeleteCriticalSection(&bounds_sem)
68#define WAIT_SEM() EnterCriticalSection(&bounds_sem)76#define WAIT_SEM() EnterCriticalSection(&bounds_sem)
69#define POST_SEM() LeaveCriticalSection(&bounds_sem)77#define POST_SEM() LeaveCriticalSection(&bounds_sem)
70#define HAS_ENVIRON 078#define HAVE_MEMALIGN (0)
71#define MALLOC_REDIR (0)79#define HAS_ENVIRON (0)
80#define MALLOC_REDIR (0)
81#define HAVE_PTHREAD_CREATE (0)
82#define HAVE_CTYPE (0)
83#define HAVE_ERRNO (0)
84
72#else85#else
86
87#define __USE_GNU /* get RTLD_NEXT */
73#include <sys/mman.h>88#include <sys/mman.h>
89#include <ctype.h>
90#include <pthread.h>
91#include <dlfcn.h>
74#include <errno.h>92#include <errno.h>
93#if 0
75#include <semaphore.h>94#include <semaphore.h>
76static sem_t bounds_sem;95static sem_t bounds_sem;
77#define INIT_SEM() sem_init (&bounds_sem, 0, 1)96#define INIT_SEM() sem_init (&bounds_sem, 0, 1)
78#define EXIT_SEM() sem_destroy (&bounds_sem)97#define EXIT_SEM() sem_destroy (&bounds_sem)
79#define WAIT_SEM() while (sem_wait (&bounds_sem) < 0 && errno == EINTR);98#define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \
80#define POST_SEM() sem_post (&bounds_sem)99 && errno == EINTR)
81#define HAS_ENVIRON 0 /* Disabled for now */100#define POST_SEM() if (use_sem) sem_post (&bounds_sem)
82#define __USE_GNU /* get RTLD_NEXT */101#else
83#include <dlfcn.h>102static pthread_spinlock_t bounds_spin;
84#define MALLOC_REDIR (1)103/* about 25% faster then semaphore. */
85static void *(*malloc_redir) (size_t) = NULL;104#define INIT_SEM() pthread_spin_init (&bounds_spin, 0)
86static void *(*calloc_redir) (size_t, size_t) = NULL;105#define EXIT_SEM() pthread_spin_destroy (&bounds_spin)
87static void (*free_redir) (void *) = NULL;106#define WAIT_SEM() if (use_sem) pthread_spin_lock (&bounds_spin)
88static void *(*realloc_redir) (void *, size_t) = NULL;107#define POST_SEM() if (use_sem) pthread_spin_unlock (&bounds_spin)
89static void *(*memalign_redir) (size_t, size_t) = NULL;108#endif
90static int pool_index = 0;109#define HAVE_MEMALIGN (1)
91static unsigned char initial_pool[256];110#define HAS_ENVIRON (1)
111#define MALLOC_REDIR (1)
112#define HAVE_PTHREAD_CREATE (1)
113#define HAVE_CTYPE (1)
114#define HAVE_ERRNO (1)
115
116static void *(*malloc_redir) (size_t);
117static void *(*calloc_redir) (size_t, size_t);
118static void (*free_redir) (void *);
119static void *(*realloc_redir) (void *, size_t);
120static void *(*memalign_redir) (size_t, size_t);
121static int (*pthread_create_redir) (pthread_t *thread,
122 const pthread_attr_t *attr,
123 void *(*start_routine)(void *), void *arg);
124static unsigned int pool_index;
125static unsigned char __attribute__((aligned(16))) initial_pool[256];
126static unsigned char use_sem;
127
92#endif128#endif
93 129
94#define TCC_TYPE_NONE (0)130#define TCC_TYPE_NONE (0)
@@ -106,8 +142,8 @@ struct tree_node { · 11 unmodified lines
106 Tree * left, * right;142 Tree * left, * right;
107 size_t start;143 size_t start;
108 size_t size;144 size_t size;
109 size_t type;145 unsigned char type;
110 size_t is_invalid; /* true if pointers outside region are invalid */146 unsigned char is_invalid; /* true if pointers outside region are invalid */
111};147};
112 148
113typedef struct alloca_list_struct {149typedef struct alloca_list_struct {
@@ -116,6 +152,7 @@ typedef struct alloca_list_struct { · 2 unmodified lines
116 struct alloca_list_struct *next;152 struct alloca_list_struct *next;
117} alloca_list_type;153} alloca_list_type;
118 154
155#define BOUND_STATISTIC_SPLAY (0)
119static Tree * splay (size_t addr, Tree *t);156static Tree * splay (size_t addr, Tree *t);
120static Tree * splay_end (size_t addr, Tree *t);157static Tree * splay_end (size_t addr, Tree *t);
121static Tree * splay_insert(size_t addr, size_t size, Tree * t);158static Tree * splay_insert(size_t addr, size_t size, Tree * t);
@@ -123,14 +160,38 @@ static Tree * splay_delete(size_t addr, Tree *t); · 1 unmodified line
123void splay_printtree(Tree * t, int d);160void splay_printtree(Tree * t, int d);
124 161
125/* external interface */162/* external interface */
163void __bound_checking (int no_check);
164void __bound_never_fatal (int no_check);
165void * __bound_ptr_add(void *p, size_t offset);
166void * __bound_ptr_indir1(void *p, size_t offset);
167void * __bound_ptr_indir2(void *p, size_t offset);
168void * __bound_ptr_indir4(void *p, size_t offset);
169void * __bound_ptr_indir8(void *p, size_t offset);
170void * __bound_ptr_indir12(void *p, size_t offset);
171void * __bound_ptr_indir16(void *p, size_t offset);
172void FASTCALL __bound_local_new(void *p1);
173void FASTCALL __bound_local_delete(void *p1);
126void __bound_init(void);174void __bound_init(void);
175void __bound_main_arg(char **p);
127void __bound_exit(void);176void __bound_exit(void);
128 177#if !defined(_WIN32)
129#ifdef __attribute__178void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd,
130 /* an __attribute__ macro is defined in the system headers */179 off_t offset);
131 #undef __attribute__ 180int __bound_munmap (void *start, size_t size);
132#endif181#endif
133#define FASTCALL __attribute__((regparm(3)))182void __bound_new_region(void *p, size_t size);
183void *__bound_memcpy(void *dst, const void *src, size_t size);
184int __bound_memcmp(const void *s1, const void *s2, size_t size);
185void *__bound_memmove(void *dst, const void *src, size_t size);
186void *__bound_memset(void *dst, int c, size_t size);
187int __bound_strlen(const char *s);
188char *__bound_strcpy(char *dst, const char *src);
189char *__bound_strncpy(char *dst, const char *src, size_t n);
190int __bound_strcmp(const char *s1, const char *s2);
191int __bound_strncmp(const char *s1, const char *s2, size_t n);
192char *__bound_strcat(char *dest, const char *src);
193char *__bound_strchr(const char *string, int ch);
194char *__bound_strdup(const char *s);
134 195
135#if !MALLOC_REDIR196#if !MALLOC_REDIR
136void *__bound_malloc(size_t size, const void *caller);197void *__bound_malloc(size_t size, const void *caller);
@@ -141,30 +202,30 @@ void *__bound_calloc(size_t nmemb, size_t size); · 4 unmodified lines
141#endif202#endif
142 203
143#define FREE_REUSE_SIZE (100)204#define FREE_REUSE_SIZE (100)
144static int free_reuse_index = 0;205static unsigned int free_reuse_index;
145static void *free_reuse_list[FREE_REUSE_SIZE];206static void *free_reuse_list[FREE_REUSE_SIZE];
146 207
147/* error message, just for TCC */208/* error message, just for TCC */
148const char *__bound_error_msg;209const char *__bound_error_msg;
149 210
150/* runtime error output */
151extern void rt_error(size_t pc, const char *fmt, ...);
152
153static Tree *tree = NULL;211static Tree *tree = NULL;
154#define TREE_REUSE (1)212#define TREE_REUSE (1)
155#if TREE_REUSE213#if TREE_REUSE
156static Tree *tree_free_list = NULL;214static Tree *tree_free_list;
157#endif215#endif
158static alloca_list_type *alloca_list = NULL;216static alloca_list_type *alloca_list;
159 217
160static int inited = 0;218static unsigned char inited;
161static int print_calls = 0;219static unsigned char print_warn_ptr_add;
162static int print_heap = 0;220static unsigned char print_calls;
163static int print_statistic = 0;221static unsigned char print_heap;
164static int never_fatal = 0;222static unsigned char print_statistic;
165static int no_checking = 0;223static unsigned char no_strdup;
166 224static signed char never_fatal;
167#ifdef BOUND_STATISTIC225static signed char no_checking = 1;
226static char exec[100];
227
228#if BOUND_STATISTIC
168static unsigned long long bound_ptr_add_count;229static unsigned long long bound_ptr_add_count;
169static unsigned long long bound_ptr_indir1_count;230static unsigned long long bound_ptr_indir1_count;
170static unsigned long long bound_ptr_indir2_count;231static unsigned long long bound_ptr_indir2_count;
@@ -194,46 +255,93 @@ static unsigned long long bound_strncmp_count; · 23 unmodified lines
194static unsigned long long bound_strcat_count;255static unsigned long long bound_strcat_count;
195static unsigned long long bound_strchr_count;256static unsigned long long bound_strchr_count;
196static unsigned long long bound_strdup_count;257static unsigned long long bound_strdup_count;
197#define INCR_COUNT(x) x++258static unsigned long long bound_not_found;
259#define INCR_COUNT(x) ++x
198#else260#else
199#define INCR_COUNT(x)261#define INCR_COUNT(x)
200#endif262#endif
263#if BOUND_STATISTIC_SPLAY
264static unsigned long long bound_splay;
265static unsigned long long bound_splay_end;
266static unsigned long long bound_splay_insert;
267static unsigned long long bound_splay_delete;
268#define INCR_COUNT_SPLAY(x) ++x
269#else
270#define INCR_COUNT_SPLAY(x)
271#endif
201 272
202/* enable/disable checking. This can be used for signal handlers. */273/* currently only i386/x86_64 supported. Change for other platforms */
274static void fetch_and_add(signed char* variable, signed char value)
275{
276#if defined __i386__ || defined __x86_64__
277 __asm__ volatile("lock; addb %0, %1"
278 : "+r" (value), "+m" (*variable) // input+output
279 : // No input-only
280 : "memory"
281 );
282#else
283 *variable += value;
284#endif
285}
286
287/* enable/disable checking. This can be used in signal handlers. */
203void __bound_checking (int no_check)288void __bound_checking (int no_check)
204{289{
205 no_checking = no_check;290 fetch_and_add (&no_checking, no_check);
206}291}
207 292
208#define no_FASTCALL293/* enable/disable checking. This can be used in signal handlers. */
209//#define no_checking 1294void __bound_never_fatal (int neverfatal)
295{
296 fetch_and_add (&never_fatal, neverfatal);
297}
210 298
211/* print a bound error message */299/* print a bound error message */
212static void bound_error(const char *fmt, ...)300static void bound_error(const char *error)
213{301{
214 __bound_error_msg = fmt;302 __bound_error_msg = error;
215 fprintf(stderr,"%s %s: %s\n", __FILE__, __FUNCTION__, fmt);303 fprintf(stderr,"%s%s %s: %s\n", exec, __FILE__, __FUNCTION__, error);
216 if (never_fatal == 0)304 if (never_fatal == 0)
217 *(void **)0 = 0; /* force a runtime error */305 *(void **)0 = 0; /* force a runtime error */
218}306}
219 307
220static void bound_alloc_error(void)308static void bound_alloc_error(const char *s)
309{
310 fprintf(stderr,"FATAL: %s\n",s);
311 exit (1);
312}
313
314static void bound_not_found_warning(const char *file, const char *function,
315 void *ptr)
316{
317 dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr);
318}
319
320static void bound_ptr_add_warning(const char *file, const char *function,
321 void *ptr)
221{322{
222 bound_error("not enough memory for bound checking code");323 fprintf(stderr,"%s%s %s(): %p is outside of the region\n",
324 exec, file, function, ptr);
325}
326
327static void bound_ptr_indir_error(const char *file, const char *function,
328 void *ptr)
329{
330 fprintf(stderr,"%s%s %s(): %p is outside of the region\n",
331 exec, file, function, ptr);
223}332}
224 333
225/* return '(p + offset)' for pointer arithmetic (a pointer can reach334/* return '(p + offset)' for pointer arithmetic (a pointer can reach
226 the end of a region in this case */335 the end of a region in this case */
227void * no_FASTCALL __bound_ptr_add(void *p, size_t offset)336void * __bound_ptr_add(void *p, size_t offset)
228{337{
229 size_t addr = (size_t)p;338 size_t addr = (size_t)p;
230 339
231 if (no_checking) {340 if (no_checking)
232 return p + offset;341 return p + offset;
233 }
234 342
235 dprintf(stderr, "%s %s : %p 0x%x\n",343 dprintf(stderr, "%s, %s(): %p 0x%lx\n",
236 __FILE__, __FUNCTION__, p, (unsigned)offset);344 __FILE__, __FUNCTION__, p, (unsigned long)offset);
237 345
238 WAIT_SEM ();346 WAIT_SEM ();
239 INCR_COUNT(bound_ptr_add_count);347 INCR_COUNT(bound_ptr_add_count);
@@ -250,18 +358,21 @@ void * no_FASTCALL __bound_ptr_add(void *p, size_t offset) · 10 unmodified lines
250 addr -= tree->start;358 addr -= tree->start;
251 }359 }
252 if (addr <= tree->size) {360 if (addr <= tree->size) {
253 addr += offset;361 if (tree->is_invalid || addr + offset > tree->size) {
254 if (tree->is_invalid || addr > tree->size) {362 POST_SEM ();
255 #if 0363 if (print_warn_ptr_add)
256 fprintf(stderr,"%s %s : %p is outside of the region\n",364 bound_ptr_add_warning (__FILE__, __FUNCTION__, p + offset);
257 __FILE__, __FUNCTION__, p + offset);365 if (never_fatal <= 0)
258 #endif
259 if (never_fatal == 0) {
260 POST_SEM ();
261 return INVALID_POINTER; /* return an invalid pointer */366 return INVALID_POINTER; /* return an invalid pointer */
262 }367 return p + offset;
263 }368 }
264 }369 }
370 else if (p) { /* Allow NULL + offset. offsetoff is using it. */
371 INCR_COUNT(bound_not_found);
372 POST_SEM ();
373 bound_not_found_warning (__FILE__, __FUNCTION__, p);
374 return p + offset;
375 }
265 }376 }
266 POST_SEM ();377 POST_SEM ();
267 return p + offset;378 return p + offset;
@@ -270,15 +381,15 @@ void * no_FASTCALL __bound_ptr_add(void *p, size_t offset) · 2 unmodified lines
270/* return '(p + offset)' for pointer indirection (the resulting must381/* return '(p + offset)' for pointer indirection (the resulting must
271 be strictly inside the region */382 be strictly inside the region */
272#define BOUND_PTR_INDIR(dsize) \383#define BOUND_PTR_INDIR(dsize) \
273void * no_FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \384void * __bound_ptr_indir ## dsize (void *p, size_t offset) \
274{ \385{ \
275 size_t addr = (size_t)p; \386 size_t addr = (size_t)p; \
276 \387 \
277 if (no_checking) { \388 if (no_checking) \
278 return p + offset; \389 return p + offset; \
279 } \390 \
280 dprintf(stderr, "%s %s : %p 0x%x start\n", \391 dprintf(stderr, "%s, %s(): %p 0x%lx\n", \
281 __FILE__, __FUNCTION__, p, (unsigned)offset); \392 __FILE__, __FUNCTION__, p, (unsigned long)offset); \
282 WAIT_SEM (); \393 WAIT_SEM (); \
283 INCR_COUNT(bound_ptr_indir ## dsize ## _count); \394 INCR_COUNT(bound_ptr_indir ## dsize ## _count); \
284 if (tree) { \395 if (tree) { \
@@ -294,16 +405,21 @@ void * no_FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 9 unmodified lines
294 addr -= tree->start; \405 addr -= tree->start; \
295 } \406 } \
296 if (addr <= tree->size) { \407 if (addr <= tree->size) { \
297 addr += offset + dsize; \408 if (tree->is_invalid || addr + offset + dsize > tree->size) { \
298 if (tree->is_invalid || addr > tree->size) { \409 POST_SEM (); \
299 fprintf(stderr,"%s %s : %p is outside of the region\n", \410 bound_ptr_indir_error (__FILE__, __FUNCTION__, \
300 __FILE__, __FUNCTION__, p + offset); \411 p + offset); \
301 if (never_fatal == 0) { \412 if (never_fatal <= 0) \
302 POST_SEM (); \
303 return INVALID_POINTER; /* return an invalid pointer */ \413 return INVALID_POINTER; /* return an invalid pointer */ \
304 } \414 return p + offset; \
305 } \415 } \
306 } \416 } \
417 else { \
418 INCR_COUNT(bound_not_found); \
419 POST_SEM (); \
420 bound_not_found_warning (__FILE__, __FUNCTION__, p); \
421 return p + offset; \
422 } \
307 } \423 } \
308 POST_SEM (); \424 POST_SEM (); \
309 return p + offset; \425 return p + offset; \
@@ -334,90 +450,180 @@ BOUND_PTR_INDIR(16) · 24 unmodified lines
334/* called when entering a function to add all the local regions */450/* called when entering a function to add all the local regions */
335void FASTCALL __bound_local_new(void *p1) 451void FASTCALL __bound_local_new(void *p1)
336{452{
337 size_t addr, size, fp, *p = p1;453 size_t addr, fp, *p = p1;
338 454
339 if (no_checking)455 if (no_checking)
340 return;456 return;
341 GET_CALLER_FP(fp);457 GET_CALLER_FP(fp);
342 dprintf(stderr, "%s, %s local new p1=%p fp=%p\n",458 dprintf(stderr, "%s, %s(): p1=%p fp=%p\n",
343 __FILE__, __FUNCTION__, p, (void *)fp);459 __FILE__, __FUNCTION__, p, (void *)fp);
344 WAIT_SEM ();460 WAIT_SEM ();
345 for(;;) {461 while ((addr = p[0])) {
346 addr = p[0];
347 if (addr == 0)
348 break;
349 INCR_COUNT(bound_local_new_count);462 INCR_COUNT(bound_local_new_count);
350 if (addr == 1) {463 if (addr != 1)
351 dprintf(stderr, "%s, %s() alloca/vla used\n",464 tree = splay_insert(addr + fp, p[1], tree);
352 __FILE__, __FUNCTION__);
353 }
354 else {
355 addr += fp;
356 size = p[1];
357 dprintf(stderr, "%s, %s() (%p 0x%lx)\n",
358 __FILE__, __FUNCTION__, (void *) addr, (unsigned long) size);
359 tree = splay_insert(addr, size, tree);
360 }
361 p += 2;465 p += 2;
362 }466 }
363 POST_SEM ();467 POST_SEM ();
468#if BOUND_DEBUG
469 if (print_calls) {
470 p = p1;
471 while ((addr = p[0])) {
472 if (addr == 1) {
473 dprintf(stderr, "%s, %s(): alloca/vla used\n",
474 __FILE__, __FUNCTION__);
475 }
476 else {
477 dprintf(stderr, "%s, %s(): %p 0x%lx\n",
478 __FILE__, __FUNCTION__,
479 (void *) (addr + fp), (unsigned long) p[1]);
480 }
481 p += 2;
482 }
483 }
484#endif
364}485}
365 486
366/* called when leaving a function to delete all the local regions */487/* called when leaving a function to delete all the local regions */
367void FASTCALL __bound_local_delete(void *p1) 488void FASTCALL __bound_local_delete(void *p1)
368{489{
369 size_t addr, fp, *p = p1;490 size_t addr, fp, *p = p1;
491 alloca_list_type *free_list = NULL;
370 492
371 if (no_checking)493 if (no_checking)
372 return;494 return;
373 GET_CALLER_FP(fp);495 GET_CALLER_FP(fp);
374 dprintf(stderr, "%s, %s local delete p1=%p fp=%p\n",496 dprintf(stderr, "%s, %s(): p1=%p fp=%p\n",
375 __FILE__, __FUNCTION__, p, (void *)fp);497 __FILE__, __FUNCTION__, p, (void *)fp);
376 WAIT_SEM ();498 WAIT_SEM ();
377 for(;;) {499 while ((addr = p[0])) {
378 addr = p[0];
379 if (addr == 0)
380 break;
381 INCR_COUNT(bound_local_delete_count);500 INCR_COUNT(bound_local_delete_count);
382 if (addr == 1) {501 if (addr == 1) {
383 while (alloca_list && alloca_list->fp == fp) {502 alloca_list_type *last = NULL;
384 alloca_list_type *next = alloca_list->next;503 alloca_list_type *cur = alloca_list;
504
505 while (cur) {
506 if (cur->fp == fp) {
507 if (last)
508 last->next = cur->next;
509 else
510 alloca_list = cur->next;
511 tree = splay_delete ((size_t) cur->p, tree);
512 cur->next = free_list;
513 free_list = cur;
514 cur = last ? last->next : alloca_list;
515 }
516 else {
517 last = cur;
518 cur = cur->next;
519 }
520 }
521 }
522 else
523 tree = splay_delete(addr + fp, tree);
524 p += 2;
525 }
526 POST_SEM ();
527 while (free_list) {
528 alloca_list_type *next = free_list->next;
385 529
386 dprintf(stderr, "%s, %s() remove alloca/vla %p\n",530 dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
387 __FILE__, __FUNCTION__, alloca_list->p);531 __FILE__, __FUNCTION__, free_list->p);
388 tree = splay_delete ((size_t) alloca_list->p, tree);
389#if MALLOC_REDIR532#if MALLOC_REDIR
390 free_redir (alloca_list);533 free_redir (free_list);
391#else534#else
392 free (alloca_list);535 free (free_list);
393#endif536#endif
394 alloca_list = next;537 free_list = next;
538 }
539#if BOUND_DEBUG
540 if (print_calls) {
541 p = p1;
542 while ((addr = p[0])) {
543 if (addr != 1) {
544 dprintf(stderr, "%s, %s(): %p 0x%lx\n",
545 __FILE__, __FUNCTION__,
546 (void *) (addr + fp), (unsigned long) p[1]);
395 }547 }
548 p+= 2;
396 }549 }
397 else {550 }
398 addr += fp;551#endif
399 dprintf(stderr, "%s, %s() (%p 0x%lx)\n",552}
400 __FILE__, __FUNCTION__, (void *) addr, (unsigned long) p[1]);553
401 tree = splay_delete(addr, tree);554/* used by alloca */
555void __bound_new_region(void *p, size_t size)
556{
557 size_t fp;
558 alloca_list_type *last;
559 alloca_list_type *cur;
560 alloca_list_type *new;
561
562 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
563 __FILE__, __FUNCTION__, p, (unsigned long)size);
564 GET_CALLER_FP (fp);
565#if MALLOC_REDIR
566 new = malloc_redir (sizeof (alloca_list_type));
567#else
568 new = malloc (sizeof (alloca_list_type));
569#endif
570 WAIT_SEM ();
571 INCR_COUNT(bound_alloca_count);
572 last = NULL;
573 cur = alloca_list;
574 while (cur) {
575 if (cur->fp == fp && cur->p == p) {
576 if (last)
577 last->next = cur->next;
578 else
579 alloca_list = cur->next;
580 tree = splay_delete((size_t)p, tree);
581 break;
402 }582 }
403 p += 2;583 last = cur;
584 cur = cur->next;
585 }
586 if (no_checking == 0)
587 tree = splay_insert((size_t)p, size, tree);
588 if (new) {
589 new->fp = fp;
590 new->p = p;
591 new->next = alloca_list;
592 alloca_list = new;
404 }593 }
405 POST_SEM ();594 POST_SEM ();
595 if (cur) {
596 dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
597 __FILE__, __FUNCTION__, cur->p);
598#if MALLOC_REDIR
599 free_redir (cur);
600#else
601 free (cur);
602#endif
603 }
406}604}
407 605
408void __bound_init(void)606#if defined(__GNUC__) && (__GNUC__ >= 6)
607#pragma GCC diagnostic pop
608#endif
609
610void __attribute__((constructor)) __bound_init(void)
409{611{
612 extern size_t __bounds_start[];
613 size_t *p;
614
410 if (inited)615 if (inited)
411 return;616 return;
412 617
413 inited = 1;618 inited = 1;
414 619
620 print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL;
415 print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL;621 print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL;
416 print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL;622 print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL;
417 print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;623 print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;
418 never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;624 never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;
419 625
420 dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);626 dprintf(stderr, "%s, %s(): start\n", __FILE__, __FUNCTION__);
421 627
422 INIT_SEM ();628 INIT_SEM ();
423 629
@@ -428,7 +634,7 @@ void __bound_init(void) · 4 unmodified lines
428 /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT */634 /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT */
429 *(void **) (&malloc_redir) = dlsym (addr, "malloc");635 *(void **) (&malloc_redir) = dlsym (addr, "malloc");
430 if (malloc_redir == NULL) {636 if (malloc_redir == NULL) {
431 dprintf(stderr, "%s, %s() use RTLD_DEFAULT\n",637 dprintf(stderr, "%s, %s(): use RTLD_DEFAULT\n",
432 __FILE__, __FUNCTION__);638 __FILE__, __FUNCTION__);
433 addr = RTLD_DEFAULT;639 addr = RTLD_DEFAULT;
434 *(void **) (&malloc_redir) = dlsym (addr, "malloc");640 *(void **) (&malloc_redir) = dlsym (addr, "malloc");
@@ -437,37 +643,109 @@ void __bound_init(void) · 2 unmodified lines
437 *(void **) (&free_redir) = dlsym (addr, "free");643 *(void **) (&free_redir) = dlsym (addr, "free");
438 *(void **) (&realloc_redir) = dlsym (addr, "realloc");644 *(void **) (&realloc_redir) = dlsym (addr, "realloc");
439 *(void **) (&memalign_redir) = dlsym (addr, "memalign");645 *(void **) (&memalign_redir) = dlsym (addr, "memalign");
440 dprintf(stderr, "%s, %s() malloc_redir %p\n",646 dprintf(stderr, "%s, %s(): malloc_redir %p\n",
441 __FILE__, __FUNCTION__, malloc_redir);647 __FILE__, __FUNCTION__, malloc_redir);
442 dprintf(stderr, "%s, %s() free_redir %p\n",648 dprintf(stderr, "%s, %s(): free_redir %p\n",
443 __FILE__, __FUNCTION__, free_redir);649 __FILE__, __FUNCTION__, free_redir);
444 dprintf(stderr, "%s, %s() realloc_redir %p\n",650 dprintf(stderr, "%s, %s(): realloc_redir %p\n",
445 __FILE__, __FUNCTION__, realloc_redir);651 __FILE__, __FUNCTION__, realloc_redir);
446 dprintf(stderr, "%s, %s() memalign_redir %p\n",652 dprintf(stderr, "%s, %s(): memalign_redir %p\n",
447 __FILE__, __FUNCTION__, memalign_redir);653 __FILE__, __FUNCTION__, memalign_redir);
654 if (malloc_redir == NULL || free_redir == NULL)
655 bound_alloc_error ("Cannot redirect malloc/free");
656#if HAVE_PTHREAD_CREATE
657 *(void **) (&pthread_create_redir) = dlsym (addr, "pthread_create");
658 dprintf(stderr, "%s, %s(): pthread_create_redir %p\n",
659 __FILE__, __FUNCTION__, pthread_create_redir);
660#endif
448 }661 }
449#endif662#endif
450 663
451 tree = NULL;664#ifdef __linux__
665 {
666 FILE *fp;
667 unsigned char found;
668 unsigned long long start;
669 unsigned long long end;
670 unsigned long long ad =
671 (unsigned long long) __builtin_return_address(0);
672 char line[1000];
673
674 /* Display exec name. Usefull when a lot of code is compiled with tcc */
675 fp = fopen ("/proc/self/comm", "r");
676 if (fp) {
677 memset (exec, 0, sizeof(exec));
678 fread (exec, 1, sizeof(exec) - 2, fp);
679 if (strchr(exec,'\n'))
680 *strchr(exec,'\n') = '\0';
681 strcat (exec, ":");
682 fclose (fp);
683 }
684 /* check if dlopen is used (is threre a better way?) */
685 found = 0;
686 fp = fopen ("/proc/self/maps", "r");
687 if (fp) {
688 while (fgets (line, sizeof(line), fp)) {
689 if (sscanf (line, "%Lx-%Lx", &start, &end) == 2 &&
690 ad >= start && ad < end) {
691 found = 1;
692 break;
693 }
694 if (strstr (line,"[heap]"))
695 break;
696 }
697 fclose (fp);
698 }
699 if (found == 0) {
700 use_sem = 1;
701 no_strdup = 1;
702 }
703 }
704#endif
452 705
453 /* save malloc hooks and install bound check hooks */706 WAIT_SEM ();
454 memset (free_reuse_list, 0, sizeof (free_reuse_list));
455 707
456 dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__);708#if HAVE_CTYPE
457}709 /* XXX: Does not work if locale is changed */
710 tree = splay_insert((size_t) __ctype_b_loc(),
711 sizeof (unsigned short *), tree);
712 tree = splay_insert((size_t) (*__ctype_b_loc() - 128),
713 384 * sizeof (unsigned short), tree);
714 tree = splay_insert((size_t) __ctype_tolower_loc(),
715 sizeof (__int32_t *), tree);
716 tree = splay_insert((size_t) (*__ctype_tolower_loc() - 128),
717 384 * sizeof (__int32_t), tree);
718 tree = splay_insert((size_t) __ctype_toupper_loc(),
719 sizeof (__int32_t *), tree);
720 tree = splay_insert((size_t) (*__ctype_toupper_loc() - 128),
721 384 * sizeof (__int32_t), tree);
722#endif
723#if HAVE_ERRNO
724 tree = splay_insert((size_t) (&errno), sizeof (int), tree);
725#endif
458 726
459void __bounds_add_static_var (size_t *p)
460{
461 dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
462 /* add all static bound check values */727 /* add all static bound check values */
463 WAIT_SEM ();728 p = __bounds_start;
464 while (p[0] != 0) {729 while (p[0] != 0) {
465 dprintf(stderr, "%s, %s() (%p 0x%lx)\n",
466 __FILE__, __FUNCTION__, (void *) p[0], (unsigned long) p[1]);
467 tree = splay_insert(p[0], p[1], tree);730 tree = splay_insert(p[0], p[1], tree);
468 p += 2;731 p += 2;
469 }732 }
470 POST_SEM ();733 POST_SEM ();
734#if BOUND_DEBUG
735 if (print_calls) {
736 p = __bounds_start;
737 while (p[0] != 0) {
738 dprintf(stderr, "%s, %s(): static var %p 0x%lx\n",
739 __FILE__, __FUNCTION__,
740 (void *) p[0], (unsigned long) p[1]);
741 p += 2;
742 }
743 }
744#endif
745
746 no_checking = 0;
747
748 dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__);
471}749}
472 750
473void __bound_main_arg(char **p)751void __bound_main_arg(char **p)
@@ -476,33 +754,55 @@ void __bound_main_arg(char **p) · 2 unmodified lines
476 754
477 WAIT_SEM ();755 WAIT_SEM ();
478 while (*p) {756 while (*p) {
479 dprintf(stderr, "%s, %s() (%p 0x%lx)\n",
480 __FILE__, __FUNCTION__, *p, (unsigned long)(strlen (*p) + 1));
481 tree = splay_insert((size_t) *p, strlen (*p) + 1, tree);757 tree = splay_insert((size_t) *p, strlen (*p) + 1, tree);
482 p++;758 ++p;
483 }759 }
484 dprintf(stderr, "%s, %s() argv (%p 0x%lx)\n",
485 __FILE__, __FUNCTION__, start, (unsigned long)((char *) p - start));
486 tree = splay_insert((size_t) start, (char *) p - start, tree);760 tree = splay_insert((size_t) start, (char *) p - start, tree);
761 POST_SEM ();
762#if BOUND_DEBUG
763 if (print_calls) {
764 p = (char **) start;
765 while (*p) {
766 dprintf(stderr, "%s, %s(): %p 0x%lx\n",
767 __FILE__, __FUNCTION__,
768 *p, (unsigned long)(strlen (*p) + 1));
769 ++p;
770 }
771 dprintf(stderr, "%s, %s(): argv %p 0x%lx\n",
772 __FILE__, __FUNCTION__,
773 start, (unsigned long)((char *) p - start));
774 }
775#endif
487 776
488#if HAS_ENVIRON777#if HAS_ENVIRON
489 {778 {
490 extern char **environ;779 extern char **environ;
491 780
781 WAIT_SEM ();
492 p = environ;782 p = environ;
493 start = (char *) p;783 start = (char *) p;
494 while (*p) {784 while (*p) {
495 dprintf(stderr, "%s, %s() (%p 0x%lx)\n",
496 __FILE__, __FUNCTION__, *p, (unsigned long)(strlen (*p) + 1));
497 tree = splay_insert((size_t) *p, strlen (*p) + 1, tree);785 tree = splay_insert((size_t) *p, strlen (*p) + 1, tree);
498 p++;786 ++p;
499 }787 }
500 dprintf(stderr, "%s, %s() environ(%p 0x%lx)\n",
501 __FILE__, __FUNCTION__, start, (unsigned long)((char *) p - start));
502 tree = splay_insert((size_t) start, (char *) p - start, tree);788 tree = splay_insert((size_t) start, (char *) p - start, tree);
789 POST_SEM ();
790#if BOUND_DEBUG
791 if (print_calls) {
792 p = environ;
793 while (*p) {
794 dprintf(stderr, "%s, %s(): %p 0x%lx\n",
795 __FILE__, __FUNCTION__,
796 *p, (unsigned long)(strlen (*p) + 1));
797 ++p;
798 }
799 dprintf(stderr, "%s, %s(): environ %p 0x%lx\n",
800 __FILE__, __FUNCTION__,
801 start, (unsigned long)((char *) p - start));
802 }
803#endif
503 }804 }
504#endif805#endif
505 POST_SEM ();
506}806}
507 807
508void __attribute__((destructor)) __bound_exit(void)808void __attribute__((destructor)) __bound_exit(void)
@@ -512,16 +812,30 @@ void __attribute__((destructor)) __bound_exit(void) · 3 unmodified lines
512 "", "malloc", "calloc", "realloc", "memalign", "strdup"812 "", "malloc", "calloc", "realloc", "memalign", "strdup"
513 };813 };
514 814
515 dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);815 dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__);
516 816
517 if (inited) {817 if (inited) {
518#if !defined(_WIN32)818#if !defined(_WIN32)
519 if (print_heap) {819 if (print_heap) {
520 extern void __libc_freeres ();820 extern void __libc_freeres (void);
521 __libc_freeres ();821 __libc_freeres ();
522 }822 }
523#endif823#endif
524 824
825 no_checking = 1;
826
827 WAIT_SEM ();
828 while (alloca_list) {
829 alloca_list_type *next = alloca_list->next;
830
831 tree = splay_delete ((size_t) alloca_list->p, tree);
832#if MALLOC_REDIR
833 free_redir (alloca_list);
834#else
835 free (alloca_list);
836#endif
837 alloca_list = next;
838 }
525 for (i = 0; i < FREE_REUSE_SIZE; i++) {839 for (i = 0; i < FREE_REUSE_SIZE; i++) {
526 if (free_reuse_list[i]) {840 if (free_reuse_list[i]) {
527 tree = splay_delete ((size_t) free_reuse_list[i], tree);841 tree = splay_delete ((size_t) free_reuse_list[i], tree);
@@ -533,11 +847,10 @@ void __attribute__((destructor)) __bound_exit(void) · 5 unmodified lines
533 }847 }
534 }848 }
535 while (tree) {849 while (tree) {
536 if (print_heap && tree->type != 0) {850 if (print_heap && tree->type != 0)
537 fprintf (stderr, "%s, %s() %s found size %lu\n",851 fprintf (stderr, "%s, %s(): %s found size %lu\n",
538 __FILE__, __FUNCTION__, alloc_type[tree->type],852 __FILE__, __FUNCTION__, alloc_type[tree->type],
539 (unsigned long) tree->size);853 (unsigned long) tree->size);
540 }
541 tree = splay_delete (tree->start, tree);854 tree = splay_delete (tree->start, tree);
542 }855 }
543#if TREE_REUSE856#if TREE_REUSE
@@ -551,10 +864,11 @@ void __attribute__((destructor)) __bound_exit(void) · 7 unmodified lines
551 tree_free_list = next;864 tree_free_list = next;
552 }865 }
553#endif866#endif
867 POST_SEM ();
554 EXIT_SEM ();868 EXIT_SEM ();
555 inited = 0;869 inited = 0;
556#ifdef BOUND_STATISTIC
557 if (print_statistic) {870 if (print_statistic) {
871#if BOUND_STATISTIC
558 fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count);872 fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count);
559 fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count);873 fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count);
560 fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count);874 fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count);
@@ -584,14 +898,28 @@ void __attribute__((destructor)) __bound_exit(void) · 23 unmodified lines
584 fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count);898 fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count);
585 fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count);899 fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count);
586 fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count);900 fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count);
587 }901 fprintf (stderr, "bound_not_found %llu\n", bound_not_found);
902#endif
903#if BOUND_STATISTIC_SPLAY
904 fprintf (stderr, "bound_splay %llu\n", bound_splay);
905 fprintf (stderr, "bound_splay_end %llu\n", bound_splay_end);
906 fprintf (stderr, "bound_splay_insert %llu\n", bound_splay_insert);
907 fprintf (stderr, "bound_splay_delete %llu\n", bound_splay_delete);
588#endif908#endif
909 }
589 }910 }
590}911}
591 912
592/* XXX: we should use a malloc which ensure that it is unlikely that913#if HAVE_PTHREAD_CREATE
593 two malloc'ed data have the same address if 'free' are made in914int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
594 between. */915 void *(*start_routine) (void *), void *arg)
916{
917 use_sem = 1;
918 dprintf (stderr, "%s, %s()n", __FILE__, __FUNCTION__);
919 return pthread_create_redir(thread, attr, start_routine, arg);
920}
921#endif
922
595#if MALLOC_REDIR923#if MALLOC_REDIR
596void *malloc(size_t size)924void *malloc(size_t size)
597#else925#else
@@ -603,34 +931,40 @@ void *__bound_malloc(size_t size, const void *caller) · 5 unmodified lines
603#if MALLOC_REDIR931#if MALLOC_REDIR
604 /* This will catch the first dlsym call from __bound_init */932 /* This will catch the first dlsym call from __bound_init */
605 if (malloc_redir == NULL) {933 if (malloc_redir == NULL) {
606 ptr = &initial_pool[pool_index];934 __bound_init ();
607 pool_index = (pool_index + size + 7) & ~8;935 if (malloc_redir == NULL) {
608 dprintf (stderr, "%s, %s initial (%p, 0x%x)\n",936 ptr = &initial_pool[pool_index];
609 __FILE__, __FUNCTION__, ptr, (unsigned)size);937 pool_index = (pool_index + size + 15) & ~15;
610 return ptr;938 if (pool_index >= sizeof (initial_pool))
939 bound_alloc_error ("initial memory pool too small");
940 dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n",
941 __FILE__, __FUNCTION__, ptr, (unsigned long)size);
942 return ptr;
943 }
611 }944 }
612#endif945#endif
613 /* we allocate one more byte to ensure the regions will be946 /* we allocate one more byte to ensure the regions will be
614 separated by at least one byte. With the glibc malloc, it may947 separated by at least one byte. With the glibc malloc, it may
615 be in fact not necessary */948 be in fact not necessary */
616 WAIT_SEM ();
617 INCR_COUNT(bound_malloc_count);
618#if MALLOC_REDIR949#if MALLOC_REDIR
619 ptr = malloc_redir (size);950 ptr = malloc_redir (size + 1);
620#else951#else
621 ptr = malloc(size + 1);952 ptr = malloc(size + 1);
622#endif953#endif
954 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
955 __FILE__, __FUNCTION__, ptr, (unsigned long)size);
623 956
624 dprintf(stderr, "%s, %s (%p, 0x%x)\n",957 if (no_checking == 0) {
625 __FILE__, __FUNCTION__, ptr, (unsigned)size);958 WAIT_SEM ();
959 INCR_COUNT(bound_malloc_count);
626 960
627 if (ptr) {961 if (ptr) {
628 tree = splay_insert ((size_t) ptr, size, tree);962 tree = splay_insert ((size_t) ptr, size, tree);
629 if (tree && tree->start == (size_t) ptr) {963 if (tree && tree->start == (size_t) ptr)
630 tree->type = TCC_TYPE_MALLOC;964 tree->type = TCC_TYPE_MALLOC;
631 }965 }
966 POST_SEM ();
632 }967 }
633 POST_SEM ();
634 return ptr;968 return ptr;
635}969}
636 970
@@ -642,10 +976,16 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 5 unmodified lines
642{976{
643 void *ptr;977 void *ptr;
644 978
645 WAIT_SEM ();979#if HAVE_MEMALIGN
646 INCR_COUNT(bound_memalign_count);980 /* we allocate one more byte to ensure the regions will be
647 981 separated by at least one byte. With the glibc malloc, it may
648#ifndef HAVE_MEMALIGN982 be in fact not necessary */
983#if MALLOC_REDIR
984 ptr = memalign_redir(size + 1, align);
985#else
986 ptr = memalign(size + 1, align);
987#endif
988#else
649 if (align > 4) {989 if (align > 4) {
650 /* XXX: handle it ? */990 /* XXX: handle it ? */
651 ptr = NULL;991 ptr = NULL;
@@ -657,25 +997,21 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 5 unmodified lines
657 ptr = malloc(size + 1);997 ptr = malloc(size + 1);
658#endif998#endif
659 }999 }
660#else
661 /* we allocate one more byte to ensure the regions will be
662 separated by at least one byte. With the glibc malloc, it may
663 be in fact not necessary */
664#if MALLOC_REDIR
665 ptr = memalign_redir(size + 1, align);
666#else
667 ptr = memalign(size + 1, align);
668#endif
669#endif1000#endif
670 if (ptr) {1001 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
671 dprintf(stderr, "%s, %s (%p, 0x%x)\n",1002 __FILE__, __FUNCTION__, ptr, (unsigned long)size);
672 __FILE__, __FUNCTION__, ptr, (unsigned)size);1003
673 tree = splay_insert((size_t) ptr, size, tree);1004 if (no_checking == 0) {
674 if (tree && tree->start == (size_t) ptr) {1005 WAIT_SEM ();
675 tree->type = TCC_TYPE_MEMALIGN;1006 INCR_COUNT(bound_memalign_count);
1007
1008 if (ptr) {
1009 tree = splay_insert((size_t) ptr, size, tree);
1010 if (tree && tree->start == (size_t) ptr)
1011 tree->type = TCC_TYPE_MEMALIGN;
676 }1012 }
1013 POST_SEM ();
677 }1014 }
678 POST_SEM ();
679 return ptr;1015 return ptr;
680}1016}
681 1017
@@ -688,7 +1024,7 @@ void __bound_free(void *ptr, const void *caller) · 6 unmodified lines
688 size_t addr = (size_t) ptr;1024 size_t addr = (size_t) ptr;
689 void *p;1025 void *p;
690 1026
691 if (ptr == NULL || tree == NULL1027 if (ptr == NULL || tree == NULL || no_checking
692#if MALLOC_REDIR1028#if MALLOC_REDIR
693 || ((unsigned char *) ptr >= &initial_pool[0] &&1029 || ((unsigned char *) ptr >= &initial_pool[0] &&
694 (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])1030 (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])
@@ -696,15 +1032,15 @@ void __bound_free(void *ptr, const void *caller) · 1 unmodified line
696 )1032 )
697 return;1033 return;
698 1034
699 dprintf(stderr, "%s, %s (%p)\n", __FILE__, __FUNCTION__, ptr);1035 dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr);
700 1036
701 WAIT_SEM ();1037 WAIT_SEM ();
702 INCR_COUNT(bound_free_count);1038 INCR_COUNT(bound_free_count);
703 tree = splay (addr, tree);1039 tree = splay (addr, tree);
704 if (tree->start == addr) {1040 if (tree->start == addr) {
705 if (tree->is_invalid) {1041 if (tree->is_invalid) {
706 bound_error("freeing invalid region");
707 POST_SEM ();1042 POST_SEM ();
1043 bound_error("freeing invalid region");
708 return;1044 return;
709 }1045 }
710 tree->is_invalid = 1;1046 tree->is_invalid = 1;
@@ -712,17 +1048,16 @@ void __bound_free(void *ptr, const void *caller) · 1 unmodified line
712 p = free_reuse_list[free_reuse_index];1048 p = free_reuse_list[free_reuse_index];
713 free_reuse_list[free_reuse_index] = ptr;1049 free_reuse_list[free_reuse_index] = ptr;
714 free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE;1050 free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE;
715 if (p) {1051 if (p)
716 tree = splay_delete((size_t)p, tree);1052 tree = splay_delete((size_t)p, tree);
717 }
718 ptr = p;1053 ptr = p;
719 }1054 }
1055 POST_SEM ();
720#if MALLOC_REDIR1056#if MALLOC_REDIR
721 free_redir (ptr);1057 free_redir (ptr);
722#else1058#else
723 free(ptr);1059 free(ptr);
724#endif1060#endif
725 POST_SEM ();
726}1061}
727 1062
728#if MALLOC_REDIR1063#if MALLOC_REDIR
@@ -731,6 +1066,8 @@ void *realloc(void *ptr, size_t size) · 2 unmodified lines
731void *__bound_realloc(void *ptr, size_t size, const void *caller)1066void *__bound_realloc(void *ptr, size_t size, const void *caller)
732#endif1067#endif
733{1068{
1069 void *new_ptr;
1070
734 if (size == 0) {1071 if (size == 0) {
735#if MALLOC_REDIR1072#if MALLOC_REDIR
736 free(ptr);1073 free(ptr);
@@ -739,40 +1076,29 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller) · 2 unmodified lines
739#endif1076#endif
740 return NULL;1077 return NULL;
741 }1078 }
742 else if (ptr == NULL) {1079
743#if MALLOC_REDIR1080#if MALLOC_REDIR
744 ptr = realloc_redir (ptr, size);1081 new_ptr = realloc_redir (ptr, size);
745#else1082#else
746 ptr = realloc (ptr, size);1083 new_ptr = realloc (ptr, size);
747#endif1084#endif
1085 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
1086 __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
1087
1088 if (no_checking == 0) {
748 WAIT_SEM ();1089 WAIT_SEM ();
749 INCR_COUNT(bound_realloc_count);1090 INCR_COUNT(bound_realloc_count);
750 if (ptr) {1091
751 tree = splay_insert ((size_t) ptr, size, tree);1092 if (ptr)
752 if (tree && tree->start == (size_t) ptr) {1093 tree = splay_delete ((size_t) ptr, tree);
753 tree->type = TCC_TYPE_REALLOC;1094 if (new_ptr) {
754 }1095 tree = splay_insert ((size_t) new_ptr, size, tree);
755 }1096 if (tree && tree->start == (size_t) new_ptr)
756 POST_SEM ();
757 return ptr;
758 }
759 else {
760 WAIT_SEM ();
761 tree = splay_delete ((size_t) ptr, tree);
762#if MALLOC_REDIR
763 ptr = realloc_redir (ptr, size);
764#else
765 ptr = realloc (ptr, size);
766#endif
767 if (ptr) {
768 tree = splay_insert ((size_t) ptr, size, tree);
769 if (tree && tree->start == (size_t) ptr) {
770 tree->type = TCC_TYPE_REALLOC;1097 tree->type = TCC_TYPE_REALLOC;
771 }
772 }1098 }
773 POST_SEM ();1099 POST_SEM ();
774 return ptr;
775 }1100 }
1101 return new_ptr;
776}1102}
777 1103
778#if MALLOC_REDIR1104#if MALLOC_REDIR
@@ -787,12 +1113,17 @@ void *__bound_calloc(size_t nmemb, size_t size) · 8 unmodified lines
787#if MALLOC_REDIR1113#if MALLOC_REDIR
788 /* This will catch the first dlsym call from __bound_init */1114 /* This will catch the first dlsym call from __bound_init */
789 if (malloc_redir == NULL) {1115 if (malloc_redir == NULL) {
790 ptr = &initial_pool[pool_index];1116 __bound_init ();
791 pool_index = (pool_index + size + 7) & ~8;1117 if (malloc_redir == NULL) {
792 dprintf (stderr, "%s, %s initial (%p, 0x%x)\n",1118 ptr = &initial_pool[pool_index];
793 __FILE__, __FUNCTION__, ptr, (unsigned)size);1119 pool_index = (pool_index + size + 15) & ~15;
794 memset (ptr, 0, size);1120 if (pool_index >= sizeof (initial_pool))
795 return ptr;1121 bound_alloc_error ("initial memory pool too small");
1122 dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n",
1123 __FILE__, __FUNCTION__, ptr, (unsigned long)size);
1124 memset (ptr, 0, size);
1125 return ptr;
1126 }
796 }1127 }
797#endif1128#endif
798#if MALLOC_REDIR1129#if MALLOC_REDIR
@@ -800,15 +1131,19 @@ void *__bound_calloc(size_t nmemb, size_t size) · 1 unmodified line
800#else1131#else
801 ptr = malloc(size + 1);1132 ptr = malloc(size + 1);
802#endif1133#endif
1134 dprintf (stderr, "%s, %s(): %p, 0x%lx\n",
1135 __FILE__, __FUNCTION__, ptr, (unsigned long)size);
1136
803 if (ptr) {1137 if (ptr) {
804 memset (ptr, 0, size);1138 memset (ptr, 0, size);
805 WAIT_SEM ();1139 if (no_checking == 0) {
806 INCR_COUNT(bound_calloc_count);1140 WAIT_SEM ();
807 tree = splay_insert ((size_t) ptr, size, tree);1141 INCR_COUNT(bound_calloc_count);
808 if (tree && tree->start == (size_t) ptr) {1142 tree = splay_insert ((size_t) ptr, size, tree);
809 tree->type = TCC_TYPE_CALLOC;1143 if (tree && tree->start == (size_t) ptr)
1144 tree->type = TCC_TYPE_CALLOC;
1145 POST_SEM ();
810 }1146 }
811 POST_SEM ();
812 }1147 }
813 return ptr;1148 return ptr;
814}1149}
@@ -819,10 +1154,10 @@ void *__bound_mmap (void *start, size_t size, int prot, · 4 unmodified lines
819{1154{
820 void *result;1155 void *result;
821 1156
822 dprintf(stderr, "%s, %s (%p, 0x%x)\n",1157 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
823 __FILE__, __FUNCTION__, start, (unsigned)size);1158 __FILE__, __FUNCTION__, start, (unsigned long)size);
824 result = mmap (start, size, prot, flags, fd, offset);1159 result = mmap (start, size, prot, flags, fd, offset);
825 if (result) {1160 if (result && no_checking == 0) {
826 WAIT_SEM ();1161 WAIT_SEM ();
827 INCR_COUNT(bound_mmap_count);1162 INCR_COUNT(bound_mmap_count);
828 tree = splay_insert((size_t)result, size, tree);1163 tree = splay_insert((size_t)result, size, tree);
@@ -835,161 +1170,151 @@ int __bound_munmap (void *start, size_t size) · 6 unmodified lines
835{1170{
836 int result;1171 int result;
837 1172
838 dprintf(stderr, "%s, %s (%p, 0x%x)\n",1173 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
839 __FILE__, __FUNCTION__, start, (unsigned)size);1174 __FILE__, __FUNCTION__, start, (unsigned long)size);
840 WAIT_SEM ();1175 if (start && no_checking == 0) {
841 INCR_COUNT(bound_munmap_count);1176 WAIT_SEM ();
842 tree = splay_delete ((size_t) start, tree);1177 INCR_COUNT(bound_munmap_count);
843 POST_SEM ();1178 tree = splay_delete ((size_t) start, tree);
1179 POST_SEM ();
1180 }
844 result = munmap (start, size);1181 result = munmap (start, size);
845 return result;1182 return result;
846}1183}
847#endif1184#endif
848 1185
849/* used by alloca */
850void __bound_new_region(void *p, size_t size)
851{
852 size_t fp;
853 alloca_list_type *last;
854 alloca_list_type *cur;
855
856 dprintf(stderr, "%s, %s (%p, 0x%x)\n",
857 __FILE__, __FUNCTION__, p, (unsigned)size);
858 WAIT_SEM ();
859 INCR_COUNT(bound_alloca_count);
860 GET_CALLER_FP (fp);
861 last = NULL;
862 cur = alloca_list;
863 while (cur && cur->fp == fp) {
864 if (cur->p == p) {
865 dprintf(stderr, "%s, %s() remove alloca/vla %p\n",
866 __FILE__, __FUNCTION__, alloca_list->p);
867 if (last) {
868 last->next = cur->next;
869 }
870 else {
871 alloca_list = cur->next;
872 }
873 tree = splay_delete((size_t)p, tree);
874#if MALLOC_REDIR
875 free_redir (cur);
876#else
877 free (cur);
878#endif
879 break;
880 }
881 last = cur;
882 cur = cur->next;
883 }
884 tree = splay_insert((size_t)p, size, tree);
885#if MALLOC_REDIR
886 cur = malloc_redir (sizeof (alloca_list_type));
887#else
888 cur = malloc (sizeof (alloca_list_type));
889#endif
890 if (cur) {
891 cur->fp = fp;
892 cur->p = p;
893 cur->next = alloca_list;
894 alloca_list = cur;
895 }
896 POST_SEM ();
897}
898
899#if defined(__GNUC__) && (__GNUC__ >= 6)
900#pragma GCC diagnostic pop
901#endif
902
903
904/* some useful checked functions */1186/* some useful checked functions */
905 1187
906/* check that (p ... p + size - 1) lies inside 'p' region, if any */1188/* check that (p ... p + size - 1) lies inside 'p' region, if any */
907static void __bound_check(const void *p, size_t size, const char *function)1189static void __bound_check(const void *p, size_t size, const char *function)
908{1190{
909 if (no_checking)1191 if (no_checking == 0 && size != 0 &&
910 return;1192 __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
911 if (size == 0)1193 static char line[100];
912 return;1194 sprintf(line, "invalid pointer %p, size 0x%lx in %s",
913 p = __bound_ptr_add((void *)p, size);1195 p, (unsigned long)size, function);
914 if (p == INVALID_POINTER)1196 bound_error(line);
915 bound_error("invalid pointer");1197 }
916}1198}
917 1199
918void *__bound_memcpy(void *dst, const void *src, size_t size)1200static int check_overlap (const void *p1, size_t n1,
1201 const void *p2, size_t n2,
1202 const char *function)
919{1203{
920 void* p;1204 const void *p1e = (const void *) ((const char *) p1 + n1);
1205 const void *p2e = (const void *) ((const char *) p2 + n2);
1206
1207 if (no_checking == 0 && n1 != 0 && n2 !=0 &&
1208 ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */
1209 (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */
1210 static char line[100];
1211 sprintf(line, "overlapping regions %p(0x%lx), %p(0x%lx) in %s",
1212 p1, (unsigned long)n1, p2, (unsigned long)n2, function);
1213 bound_error(line);
1214 return never_fatal < 0;
1215 }
1216 return 0;
1217}
921 1218
1219void *__bound_memcpy(void *dest, const void *src, size_t n)
1220{
1221 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1222 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
922 INCR_COUNT(bound_mempcy_count);1223 INCR_COUNT(bound_mempcy_count);
923 __bound_check(dst, size, "memcpy");1224 __bound_check(dest, n, "memcpy dest");
924 __bound_check(src, size, "memcpy");1225 __bound_check(src, n, "memcpy src");
925 /* check also region overlap */1226 if (check_overlap(dest, n, src, n, "memcpy"))
926 if (no_checking == 0 && src >= dst && src < dst + size)1227 return dest;
927 bound_error("overlapping regions in memcpy()");1228 return memcpy(dest, src, n);
928
929 p = memcpy(dst, src, size);
930
931 return p;
932}1229}
933 1230
934int __bound_memcmp(const void *s1, const void *s2, size_t size)1231int __bound_memcmp(const void *s1, const void *s2, size_t n)
935{1232{
1233 const unsigned char *u1 = (const unsigned char *) s1;
1234 const unsigned char *u2 = (const unsigned char *) s2;
1235 int retval = 0;
1236
1237 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1238 __FILE__, __FUNCTION__, s1, s2, (unsigned long)n);
936 INCR_COUNT(bound_memcmp_count);1239 INCR_COUNT(bound_memcmp_count);
937 __bound_check(s1, size, "memcmp");1240 for (;;) {
938 __bound_check(s2, size, "memcmp");1241 if ((ssize_t) --n == -1)
939 return memcmp(s1, s2, size);1242 break;
1243 else if (*u1 != *u2) {
1244 retval = *u1++ - *u2++;
1245 break;
1246 }
1247 ++u1;
1248 ++u2;
1249 }
1250 __bound_check(s1, (const void *)u1 - s1, "memcmp s1");
1251 __bound_check(s2, (const void *)u2 - s2, "memcmp s2");
1252 return retval;
940}1253}
941 1254
942void *__bound_memmove(void *dst, const void *src, size_t size)1255void *__bound_memmove(void *dest, const void *src, size_t n)
943{1256{
1257 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1258 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
944 INCR_COUNT(bound_memmove_count);1259 INCR_COUNT(bound_memmove_count);
945 __bound_check(dst, size, "memmove");1260 __bound_check(dest, n, "memmove dest");
946 __bound_check(src, size, "memmove");1261 __bound_check(src, n, "memmove src");
947 return memmove(dst, src, size);1262 return memmove(dest, src, n);
948}1263}
949 1264
950void *__bound_memset(void *dst, int c, size_t size)1265void *__bound_memset(void *s, int c, size_t n)
951{1266{
1267 dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
1268 __FILE__, __FUNCTION__, s, c, (unsigned long)n);
952 INCR_COUNT(bound_memset_count);1269 INCR_COUNT(bound_memset_count);
953 __bound_check(dst, size, "memset");1270 __bound_check(s, n, "memset");
954 return memset(dst, c, size);1271 return memset(s, c, n);
955}1272}
956 1273
957int __bound_strlen(const char *s)1274int __bound_strlen(const char *s)
958{1275{
959 const char *p = s;1276 const char *p = s;
960 size_t len;
961 1277
1278 dprintf(stderr, "%s, %s(): %p\n",
1279 __FILE__, __FUNCTION__, s);
962 INCR_COUNT(bound_strlen_count);1280 INCR_COUNT(bound_strlen_count);
963 while (*p++);1281 while (*p++);
964 len = (p - s) - 1;1282 __bound_check(s, p - s, "strlen");
965 p = __bound_ptr_indir1((char *)s, len);1283 return (p - s) - 1;
966 if (p == INVALID_POINTER)
967 bound_error("bad pointer in strlen()");
968 return len;
969}1284}
970 1285
971char *__bound_strcpy(char *dst, const char *src)1286char *__bound_strcpy(char *dest, const char *src)
972{1287{
973 size_t len;1288 size_t len;
974 void *p;1289 const char *p = src;
975 1290
1291 dprintf(stderr, "%s, %s(): %p, %p\n",
1292 __FILE__, __FUNCTION__, dest, src);
976 INCR_COUNT(bound_strcpy_count);1293 INCR_COUNT(bound_strcpy_count);
977 len = __bound_strlen(src);1294 while (*p++);
978 p = __bound_memcpy(dst, src, len + 1);1295 len = p - src;
979 return p;1296 __bound_check(dest, len, "strcpy dest");
1297 __bound_check(src, len, "strcpy src");
1298 if (check_overlap(dest, len, src, len, "strcpy"))
1299 return dest;
1300 return strcpy (dest, src);
980}1301}
981 1302
982char *__bound_strncpy(char *dst, const char *src, size_t n)1303char *__bound_strncpy(char *dest, const char *src, size_t n)
983{1304{
984 size_t len = n;1305 size_t len = n;
985 const char *p = src;1306 const char *p = src;
986 1307
1308 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1309 __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
1310 INCR_COUNT(bound_strncpy_count);
987 while (len-- && *p++);1311 while (len-- && *p++);
988 len = p - src;1312 len = p - src;
989 INCR_COUNT(bound_strncpy_count);1313 __bound_check(dest, len, "strncpy dest");
990 __bound_check(dst, len, "strncpy");1314 __bound_check(src, len, "strncpy src");
991 __bound_check(src, len, "strncpy");1315 if (check_overlap(dest, len, src, len, "strncpy"))
992 return strncpy (dst, src, n);1316 return dest;
1317 return strncpy(dest, src, n);
993}1318}
994 1319
995int __bound_strcmp(const char *s1, const char *s2)1320int __bound_strcmp(const char *s1, const char *s2)
@@ -997,14 +1322,16 @@ int __bound_strcmp(const char *s1, const char *s2) · 1 unmodified line
997 const unsigned char *u1 = (const unsigned char *) s1;1322 const unsigned char *u1 = (const unsigned char *) s1;
998 const unsigned char *u2 = (const unsigned char *) s2;1323 const unsigned char *u2 = (const unsigned char *) s2;
999 1324
1325 dprintf(stderr, "%s, %s(): %p, %p\n",
1326 __FILE__, __FUNCTION__, s1, s2);
1000 INCR_COUNT(bound_strcmp_count);1327 INCR_COUNT(bound_strcmp_count);
1001 while (*u1 && *u1 == *u2) {1328 while (*u1 && *u1 == *u2) {
1002 u1++;1329 ++u1;
1003 u2++;1330 ++u2;
1004 }1331 }
1005 __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp");1332 __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp s1");
1006 __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp");1333 __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp s2");
1007 return (*u1 - *u2);1334 return *u1 - *u2;
1008}1335}
1009 1336
1010int __bound_strncmp(const char *s1, const char *s2, size_t n)1337int __bound_strncmp(const char *s1, const char *s2, size_t n)
@@ -1013,18 +1340,20 @@ int __bound_strncmp(const char *s1, const char *s2, size_t n) · 2 unmodified lines
1013 const unsigned char *u2 = (const unsigned char *) s2;1340 const unsigned char *u2 = (const unsigned char *) s2;
1014 int retval = 0;1341 int retval = 0;
1015 1342
1343 dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
1344 __FILE__, __FUNCTION__, s1, s2, (unsigned long)n);
1016 INCR_COUNT(bound_strncmp_count);1345 INCR_COUNT(bound_strncmp_count);
1017 do {1346 do {
1018 if ((ssize_t) --n == -1)1347 if ((ssize_t) --n == -1)
1019 break;1348 break;
1020 else if (*u1 != *u2) {1349 else if (*u1 != *u2) {
1021 retval = *u1 - *u2;1350 retval = *u1++ - *u2++;
1022 break;1351 break;
1023 }1352 }
1024 u2++;1353 ++u2;
1025 } while (*u1++);1354 } while (*u1++);
1026 __bound_check(s1, ((const char *)u1 - s1) + 1, "strncmp");1355 __bound_check(s1, (const char *)u1 - s1, "strncmp s1");
1027 __bound_check(s2, ((const char *)u1 - s1) + 1, "strncmp");1356 __bound_check(s2, (const char *)u2 - s2, "strncmp s2");
1028 return retval;1357 return retval;
1029}1358}
1030 1359
@@ -1033,29 +1362,33 @@ char *__bound_strcat(char *dest, const char *src) · 2 unmodified lines
1033 char *r = dest;1362 char *r = dest;
1034 const char *s = src;1363 const char *s = src;
1035 1364
1365 dprintf(stderr, "%s, %s(): %p, %p\n",
1366 __FILE__, __FUNCTION__, dest, src);
1036 INCR_COUNT(bound_strcat_count);1367 INCR_COUNT(bound_strcat_count);
1037 while (*dest++);1368 while (*dest++);
1038 dest--;1369 while (*src++);
1039 while ((*dest++ = *src++) != 0);1370 __bound_check(r, (dest - r) + (src - s) - 1, "strcat dest");
1040 __bound_check(r, dest - r, "strcat");1371 __bound_check(s, src - s, "strcat src");
1041 __bound_check(s, src - s, "strcat");1372 if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strcat"))
1042 return r;1373 return dest;
1374 return strcat(r, s);
1043}1375}
1044 1376
1045char *__bound_strchr(const char *string, int ch)1377char *__bound_strchr(const char *s, int c)
1046{1378{
1047 const unsigned char *s = (const unsigned char *) string;1379 const unsigned char *str = (const unsigned char *) s;
1048 unsigned char c = ch;1380 unsigned char ch = c;
1049 1381
1382 dprintf(stderr, "%s, %s(): %p, %d\n",
1383 __FILE__, __FUNCTION__, s, ch);
1050 INCR_COUNT(bound_strchr_count);1384 INCR_COUNT(bound_strchr_count);
1051 while (*s) {1385 while (*str) {
1052 if (*s == c) {1386 if (*str == ch)
1053 break;1387 break;
1054 }1388 ++str;
1055 s++;
1056 }1389 }
1057 __bound_check(string, ((const char *)s - string) + 1, "strchr");1390 __bound_check(s, ((const char *)str - s) + 1, "strchr");
1058 return *s == c ? (char *) s : NULL;1391 return *str == ch ? (char *) str : NULL;
1059}1392}
1060 1393
1061char *__bound_strdup(const char *s)1394char *__bound_strdup(const char *s)
@@ -1067,18 +1400,21 @@ char *__bound_strdup(const char *s) · 5 unmodified lines
1067 while (*p++);1400 while (*p++);
1068 __bound_check(s, p - s, "strdup");1401 __bound_check(s, p - s, "strdup");
1069#if MALLOC_REDIR1402#if MALLOC_REDIR
1070 new = malloc_redir (p - s);1403 new = malloc_redir ((p - s) + 1);
1071#else1404#else
1072 new = malloc (p - s);1405 new = malloc ((p - s) + 1);
1073#endif1406#endif
1407 dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
1408 __FILE__, __FUNCTION__, new, (unsigned long)(p -s));
1074 if (new) {1409 if (new) {
1075 WAIT_SEM ();1410 if (no_checking == 0 && no_strdup == 0) {
1076 tree = splay_insert((size_t)new, p - s, tree);1411 WAIT_SEM ();
1077 if (tree && tree->start == (size_t) new) {1412 tree = splay_insert((size_t)new, p - s, tree);
1078 tree->type = TCC_TYPE_STRDUP;1413 if (tree && tree->start == (size_t) new)
1414 tree->type = TCC_TYPE_STRDUP;
1415 POST_SEM ();
1079 }1416 }
1080 memcpy (new, s, p - s);1417 memcpy (new, s, p - s);
1081 POST_SEM ();
1082 }1418 }
1083 return new;1419 return new;
1084}1420}
@@ -1136,16 +1472,14 @@ char *__bound_strdup(const char *s) · 51 unmodified lines
1136#define compare(start,tstart,tsize) (start < tstart ? -1 : \1472#define compare(start,tstart,tsize) (start < tstart ? -1 : \
1137 start >= tstart+tsize ? 1 : 0)1473 start >= tstart+tsize ? 1 : 0)
1138 1474
1139/* This is the comparison. */
1140/* Returns <0 if i<j, =0 if i=j, and >0 if i>j */
1141
1142static Tree * splay (size_t addr, Tree *t)1475static Tree * splay (size_t addr, Tree *t)
1143/* Splay using the key start (which may or may not be in the tree.) */1476/* Splay using the key start (which may or may not be in the tree.) */
1144/* The starting root is t, and the tree used is defined by rat */1477/* The starting root is t, and the tree used is defined by rat */
1145{1478{
1146 Tree N, *l, *r, *y;1479 Tree N, *l, *r, *y;
1147 int comp;1480 int comp;
1148 1481
1482 INCR_COUNT_SPLAY(bound_splay);
1149 if (t == NULL) return t;1483 if (t == NULL) return t;
1150 N.left = N.right = NULL;1484 N.left = N.right = NULL;
1151 l = r = &N;1485 l = r = &N;
@@ -1198,6 +1532,7 @@ static Tree * splay_end (size_t addr, Tree *t) · 46 unmodified lines
1198 Tree N, *l, *r, *y;1532 Tree N, *l, *r, *y;
1199 int comp;1533 int comp;
1200 1534
1535 INCR_COUNT_SPLAY(bound_splay_end);
1201 if (t == NULL) return t;1536 if (t == NULL) return t;
1202 N.left = N.right = NULL;1537 N.left = N.right = NULL;
1203 l = r = &N;1538 l = r = &N;
@@ -1242,10 +1577,11 @@ static Tree * splay_end (size_t addr, Tree *t) · 38 unmodified lines
1242 1577
1243static Tree * splay_insert(size_t addr, size_t size, Tree * t)1578static Tree * splay_insert(size_t addr, size_t size, Tree * t)
1244/* Insert key start into the tree t, if it is not already there. */1579/* Insert key start into the tree t, if it is not already there. */
1245/* Return a pointer to the resulting tree. */1580/* Return a pointer to the resulting tree. */
1246{1581{
1247 Tree * new;1582 Tree * new;
1248 1583
1584 INCR_COUNT_SPLAY(bound_splay_insert);
1249 if (t != NULL) {1585 if (t != NULL) {
1250 t = splay(addr,t);1586 t = splay(addr,t);
1251 if (compare(addr, t->start, t->size)==0) {1587 if (compare(addr, t->start, t->size)==0) {
@@ -1267,7 +1603,7 @@ static Tree * splay_insert(size_t addr, size_t size, Tree * t) · 15 unmodified lines
1267#endif1603#endif
1268 }1604 }
1269 if (new == NULL) {1605 if (new == NULL) {
1270 bound_alloc_error();1606 bound_alloc_error("not enough memory for bound checking code");
1271 }1607 }
1272 else {1608 else {
1273 if (t == NULL) {1609 if (t == NULL) {
@@ -1294,13 +1630,14 @@ static Tree * splay_insert(size_t addr, size_t size, Tree * t) · 20 unmodified lines
1294 1630
1295static Tree * splay_delete(size_t addr, Tree *t)1631static Tree * splay_delete(size_t addr, Tree *t)
1296/* Deletes addr from the tree if it's there. */1632/* Deletes addr from the tree if it's there. */
1297/* Return a pointer to the resulting tree. */1633/* Return a pointer to the resulting tree. */
1298{1634{
1299 Tree * x;1635 Tree * x;
1300 1636
1637 INCR_COUNT_SPLAY(bound_splay_delete);
1301 if (t==NULL) return NULL;1638 if (t==NULL) return NULL;
1302 t = splay(addr,t);1639 t = splay(addr,t);
1303 if (compare_destroy(addr, t->start) == 0) { /* found it */1640 if (compare_destroy(addr, t->start) == 0) { /* found it */
1304 if (t->left == NULL) {1641 if (t->left == NULL) {
1305 x = t->right;1642 x = t->right;
1306 } else {1643 } else {
@@ -1319,7 +1656,7 @@ static Tree * splay_delete(size_t addr, Tree *t) · 12 unmodified lines
1319#endif1656#endif
1320 return x;1657 return x;
1321 } else {1658 } else {
1322 return t; /* It wasn't there */1659 return t; /* It wasn't there */
1323 }1660 }
1324}1661}
1325 1662
@@ -1329,7 +1666,8 @@ void splay_printtree(Tree * t, int d) · 3 unmodified lines
1329 if (t == NULL) return;1666 if (t == NULL) return;
1330 splay_printtree(t->right, d+1);1667 splay_printtree(t->right, d+1);
1331 for (i=0; i<d; i++) fprintf(stderr," ");1668 for (i=0; i<d; i++) fprintf(stderr," ");
1332 fprintf(stderr,"%p(0x%lx:%u)\n",1669 fprintf(stderr,"%p(0x%lx:%u:%u)\n",
1333 (void *) t->start, (unsigned long) t->size, (unsigned)t->is_invalid);1670 (void *) t->start, (unsigned long) t->size,
1671 (unsigned)t->type, (unsigned)t->is_invalid);
1334 splay_printtree(t->left, d+1);1672 splay_printtree(t->left, d+1);
1335}1673}
tcc-doc.texi+38−5
@@ -356,8 +356,10 @@ memory allocations and array/pointer bounds. @option{-g} is implied. Note · 355 unmodified lines
356that the generated code is slower and bigger in this case.356that the generated code is slower and bigger in this case.
357The bound checking code is not included in shared libaries. The main executable should always be compiled with the @option{-b}.357The bound checking code is not included in shared libaries. The main executable should always be compiled with the @option{-b}.
358 358
359There are four environment variables that can be used:359There are five environment variables that can be used:
360@table @option360@table @option
361@item TCC_BOUNDS_WARN_POINTER_ADD
362Print warning when pointer add creates an illegal pointer.
361@item TCC_BOUNDS_PRINT_CALLS363@item TCC_BOUNDS_PRINT_CALLS
362Print bound checking calls. Can be used for debugging.364Print bound checking calls. Can be used for debugging.
363@item TCC_BOUNDS_PRINT_HEAP365@item TCC_BOUNDS_PRINT_HEAP
@@ -368,10 +370,7 @@ Print statistic information at exit of program. · 4 unmodified lines
368Try to continue in case of a bound checking error.370Try to continue in case of a bound checking error.
369@end table371@end table
370 372
371Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) when using libtcc for the moment.373Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment.
372
373@item -ba
374Generate address checking tests when using @option{-b}. This will be a lot slower but finds more errors.
375 374
376@item -bt N375@item -bt N
377Display N callers in stack traces. This is useful with @option{-g} or376Display N callers in stack traces. This is useful with @option{-g} or
@@ -947,6 +946,40 @@ Here are some examples of caught errors: · 569 unmodified lines
947 946
948@end table947@end table
949 948
949Signal handlers are not compatible with bounds checking. The code
950below can be used to protect signal handlers.
951The call to __bound_checking(1) will disable bounds checking in the
952whole application.
953
954The BOUNDS_CHECKING_OFF and BOUNDS_CHECKING_ON can also be used to
955disable bounds checking for some code. This is not recommended.
956It is better to fix the code.
957
958@example
959
960#ifdef __BOUNDS_CHECKING_ON
961extern void __bound_checking (int no_check);
962#define BOUNDS_CHECKING_OFF __bound_checking(1)
963#define BOUNDS_CHECKING_ON __bound_checking(-1)
964#else
965#define BOUNDS_CHECKING_OFF
966#define BOUNDS_CHECKING_ON
967#endif
968
969void real_signal_handler(int sig, siginfo_t *info, void *ucontext)
970@{
971 ...
972@}
973
974void signal_handler(int sig, void *info, void *ucontext)
975@{
976 BOUNDS_CHECKING_OFF;
977 real_signal_handler(sig, info, data);
978 BOUNDS_CHECKING_ON;
979@}
980
981@end example
982
950@node Libtcc983@node Libtcc
951@chapter The @code{libtcc} library984@chapter The @code{libtcc} library
952 985
tcc.h+8−0
@@ -292,6 +292,9 @@ extern long double strtold (const char *__nptr, char **__endptr); · 291 unmodified lines
292#ifndef TCC_LIBTCC1292#ifndef TCC_LIBTCC1
293# define TCC_LIBTCC1 "libtcc1.a"293# define TCC_LIBTCC1 "libtcc1.a"
294#endif294#endif
295#ifndef TCC_LIBBCHECK
296# define TCC_LIBBCHECK "bcheck.o"
297#endif
295 298
296/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */299/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
297#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC300#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
@@ -1375,6 +1378,9 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi · 1077 unmodified lines
1375ST_DATA int func_var; /* true if current function is variadic */1378ST_DATA int func_var; /* true if current function is variadic */
1376ST_DATA int func_vc;1379ST_DATA int func_vc;
1377ST_DATA const char *funcname;1380ST_DATA const char *funcname;
1381#ifdef CONFIG_TCC_BCHECK
1382ST_DATA addr_t func_bound_offset;
1383#endif
1378 1384
1379ST_FUNC void tcc_debug_start(TCCState *s1);1385ST_FUNC void tcc_debug_start(TCCState *s1);
1380ST_FUNC void tcc_debug_end(TCCState *s1);1386ST_FUNC void tcc_debug_end(TCCState *s1);
@@ -1440,6 +1446,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty); · 59 unmodified lines
1440#endif1446#endif
1441#ifdef CONFIG_TCC_BCHECK1447#ifdef CONFIG_TCC_BCHECK
1442ST_FUNC void gbound_args(int nb_args);1448ST_FUNC void gbound_args(int nb_args);
1449ST_FUNC void save_temp_local(int nb_args);
1450ST_FUNC void restore_temp_local(void);
1443#endif1451#endif
1444 1452
1445/* ------------ tccelf.c ------------ */1453/* ------------ tccelf.c ------------ */
tccelf.c+29−4
@@ -85,6 +85,23 @@ ST_FUNC void tccelf_bounds_new(TCCState *s) · 84 unmodified lines
85 lbounds_section = new_section(s, ".lbounds",85 lbounds_section = new_section(s, ".lbounds",
86 SHT_PROGBITS, SHF_ALLOC);86 SHT_PROGBITS, SHF_ALLOC);
87}87}
88
89ST_FUNC void tcc_add_bcheck(TCCState *s1)
90{
91 addr_t *ptr;
92
93 if (0 == s1->do_bounds_check)
94 return;
95 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
96 *ptr = 0;
97 set_elf_sym(symtab_section, 0, 0,
98 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
99 bounds_section->sh_num, "__bounds_start");
100 /* pull bcheck.o from libtcc1.a */
101 set_elf_sym(symtab_section, 0, 0,
102 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
103 SHN_UNDEF, "__bound_init");
104}
88#endif105#endif
89 106
90ST_FUNC void tccelf_stab_new(TCCState *s)107ST_FUNC void tccelf_stab_new(TCCState *s)
@@ -1288,7 +1305,7 @@ static int tcc_add_support(TCCState *s1, const char *filename) · 1197 unmodified lines
1288}1305}
1289#endif1306#endif
1290 1307
1291static void add_array (const char *section, TCCState *s1, Sym *sym)1308static void add_array (const char *section, TCCState *s1, Sym *sym, int sh_type)
1292{1309{
1293 Section *s;1310 Section *s;
1294 unsigned char *ptr;1311 unsigned char *ptr;
@@ -1296,6 +1313,9 @@ static void add_array (const char *section, TCCState *s1, Sym *sym) · 1 unmodified line
1296 s = find_section(s1, section);1313 s = find_section(s1, section);
1297 if (s) {1314 if (s) {
1298 s->sh_flags |= SHF_WRITE;1315 s->sh_flags |= SHF_WRITE;
1316#ifndef TCC_TARGET_PE
1317 s->sh_type = sh_type;
1318#endif
1299 ptr = section_ptr_add(s, PTR_SIZE);1319 ptr = section_ptr_add(s, PTR_SIZE);
1300 memset (ptr, 0, PTR_SIZE);1320 memset (ptr, 0, PTR_SIZE);
1301 put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);1321 put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
@@ -1304,12 +1324,12 @@ static void add_array (const char *section, TCCState *s1, Sym *sym) · 2 unmodified lines
1304 1324
1305ST_FUNC void add_init_array (TCCState *s1, Sym *sym)1325ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
1306{1326{
1307 add_array (".init_array", s1, sym);1327 add_array (".init_array", s1, sym, SHT_INIT_ARRAY);
1308}1328}
1309 1329
1310ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)1330ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
1311{1331{
1312 add_array (".fini_array", s1, sym);1332 add_array (".fini_array", s1, sym, SHT_FINI_ARRAY);
1313}1333}
1314 1334
1315/* add tcc runtime libraries */1335/* add tcc runtime libraries */
@@ -1336,7 +1356,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 20 unmodified lines
1336 if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {1356 if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
1337 tcc_add_library_err(s1, "pthread");1357 tcc_add_library_err(s1, "pthread");
1338 tcc_add_library_err(s1, "dl");1358 tcc_add_library_err(s1, "dl");
1339 tcc_add_support(s1, "bcheck.o");1359 tcc_add_support(s1, TCC_LIBBCHECK);
1340 }1360 }
1341#endif1361#endif
1342 tcc_add_support(s1, TCC_LIBTCC1);1362 tcc_add_support(s1, TCC_LIBTCC1);
@@ -2040,6 +2060,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 697 unmodified lines
2040 Section *s;2060 Section *s;
2041 ElfW(Ehdr) ehdr;2061 ElfW(Ehdr) ehdr;
2042 ElfW(Shdr) shdr, *sh;2062 ElfW(Shdr) shdr, *sh;
2063 ElfW(Sym) *sym;
2043 2064
2044 file_type = s1->output_type;2065 file_type = s1->output_type;
2045 shnum = s1->nb_sections;2066 shnum = s1->nb_sections;
@@ -2110,6 +2131,10 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 64 unmodified lines
2110 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));2131 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2111 2132
2112 sort_syms(s1, symtab_section);2133 sort_syms(s1, symtab_section);
2134 if (s1->dynsym)
2135 for_each_elem(s1->dynsym, 0, sym, ElfW(Sym))
2136 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
2137 s1->dynsym->sh_info++;
2113 for(i = 1; i < s1->nb_sections; i++) {2138 for(i = 1; i < s1->nb_sections; i++) {
2114 s = s1->sections[sec_order[i]];2139 s = s1->sections[sec_order[i]];
2115 if (s->sh_type != SHT_NOBITS) {2140 if (s->sh_type != SHT_NOBITS) {
tccgen.c+122−18
@@ -110,6 +110,16 @@ ST_DATA struct temp_local_variable { · 109 unmodified lines
110 short align;110 short align;
111} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];111} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
112short nb_temp_local_vars;112short nb_temp_local_vars;
113#ifdef CONFIG_TCC_BCHECK
114static short call_nesting;
115static char used_location[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
116static int nb_bound_local_param;
117struct {
118 unsigned long data_offset;
119 int v;
120} *bound_local_param;
121ST_DATA addr_t func_bound_offset;
122#endif
113 123
114static struct scope {124static struct scope {
115 struct scope *prev;125 struct scope *prev;
@@ -1383,11 +1393,6 @@ ST_FUNC void save_reg_upstack(int r, int n) · 1267 unmodified lines
1383 bt = VT_PTR;1393 bt = VT_PTR;
1384 sv.type.t = bt;1394 sv.type.t = bt;
1385 size = type_size(&sv.type, &align);1395 size = type_size(&sv.type, &align);
1386#ifdef CONFIG_TCC_BCHECK
1387 if (tcc_state->do_bounds_check)
1388 l = loc = (loc - size) & -align;
1389 else
1390#endif
1391 l = get_temp_local_var(size,align);1396 l = get_temp_local_var(size,align);
1392 sv.r = VT_LOCAL | VT_LVAL;1397 sv.r = VT_LOCAL | VT_LVAL;
1393 sv.c.i = l;1398 sv.c.i = l;
@@ -1496,7 +1501,11 @@ static int get_temp_local_var(int size,int align){ · 102 unmodified lines
1496 found=0;1501 found=0;
1497 for(i=0;i<nb_temp_local_vars;i++){1502 for(i=0;i<nb_temp_local_vars;i++){
1498 temp_var=&arr_temp_local_vars[i];1503 temp_var=&arr_temp_local_vars[i];
1499 if(temp_var->size<size||align!=temp_var->align){1504 if(temp_var->size<size||align!=temp_var->align
1505#ifdef CONFIG_TCC_BCHECK
1506 || (tcc_state->do_bounds_check && used_location[i])
1507#endif
1508 ){
1500 continue;1509 continue;
1501 }1510 }
1502 /*check if temp_var is free*/1511 /*check if temp_var is free*/
@@ -1596,6 +1605,50 @@ ST_FUNC void gbound_args(int nb_args) · 93 unmodified lines
1596 vrott(i);1605 vrott(i);
1597 }1606 }
1598}1607}
1608
1609ST_FUNC void save_temp_local(int nb_args)
1610{
1611 int i, j;
1612
1613 if (call_nesting++ == 0)
1614 for (i = 1; i <= nb_args; ++i)
1615 for (j = 0; j < nb_temp_local_vars; j++)
1616 if (vtop[1 - i].c.i == arr_temp_local_vars[j].location) {
1617 used_location[j] = 1;
1618 break;
1619 }
1620}
1621
1622ST_FUNC void restore_temp_local()
1623{
1624 if (--call_nesting == 0)
1625 memset (used_location, 0, sizeof (used_location));
1626}
1627
1628static void add_bound_param(CType *type, int size, int v, int c)
1629{
1630 addr_t *bounds_ptr;
1631 /* Add arrays/structs/unions because we always take address */
1632 int taken = (type->t & VT_ARRAY)
1633 || (type->t & VT_BTYPE) == VT_STRUCT;
1634
1635 if (taken == 0) {
1636 /* Add parameter to check */
1637 nb_bound_local_param++;
1638 bound_local_param =
1639 tcc_realloc (bound_local_param,
1640 nb_bound_local_param *
1641 sizeof (*bound_local_param));
1642 bound_local_param[nb_bound_local_param-1].data_offset =
1643 lbounds_section->data_offset;
1644 bound_local_param[nb_bound_local_param-1].v = v;
1645 }
1646 /* add local bound info */
1647 bounds_ptr = section_ptr_add(lbounds_section,
1648 2 * sizeof(addr_t));
1649 bounds_ptr[0] = c;
1650 bounds_ptr[1] = taken ? size : ~size;
1651}
1599#endif1652#endif
1600 1653
1601static void incr_bf_adr(int o)1654static void incr_bf_adr(int o)
@@ -3418,6 +3471,7 @@ ST_FUNC void vstore(void) · 1816 unmodified lines
3418 3471
3419 vswap();3472 vswap();
3420 /* source */3473 /* source */
3474 vtop->r &= ~VT_MUSTBOUND;
3421 vpushv(vtop - 2);3475 vpushv(vtop - 2);
3422 vtop->type.t = VT_PTR;3476 vtop->type.t = VT_PTR;
3423 gaddrof();3477 gaddrof();
@@ -5083,6 +5137,23 @@ ST_FUNC void unary(void) · 1659 unmodified lines
5083 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&5137 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
5084 !(vtop->type.t & VT_ARRAY))5138 !(vtop->type.t & VT_ARRAY))
5085 test_lvalue();5139 test_lvalue();
5140#ifdef CONFIG_TCC_BCHECK
5141 if (tcc_state->do_bounds_check && vtop->sym) {
5142 int i;
5143
5144 /* Mark parameter as being used for address off */
5145 for (i = 0; i < nb_bound_local_param; i++) {
5146 if (bound_local_param[i].v == vtop->sym->v) {
5147 addr_t *bounds_ptr =
5148 (addr_t *) (lbounds_section->data +
5149 bound_local_param[i].data_offset);
5150 bounds_ptr[1] = ~bounds_ptr[1];
5151 bound_local_param[i].v = 0;
5152 break;
5153 }
5154 }
5155 }
5156#endif
5086 mk_pointer(&vtop->type);5157 mk_pointer(&vtop->type);
5087 gaddrof();5158 gaddrof();
5088 break;5159 break;
@@ -7435,8 +7506,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2346 unmodified lines
7435 if ((r & VT_VALMASK) == VT_LOCAL) {7506 if ((r & VT_VALMASK) == VT_LOCAL) {
7436 sec = NULL;7507 sec = NULL;
7437#ifdef CONFIG_TCC_BCHECK7508#ifdef CONFIG_TCC_BCHECK
7438 if (bcheck && ((type->t & VT_ARRAY) ||7509 if (bcheck && v) {
7439 (type->t & VT_BTYPE) == VT_STRUCT)) {7510 /* add padding between stack variables */
7440 loc--;7511 loc--;
7441 }7512 }
7442#endif7513#endif
@@ -7444,17 +7515,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 1 unmodified line
7444 addr = loc;7515 addr = loc;
7445#ifdef CONFIG_TCC_BCHECK7516#ifdef CONFIG_TCC_BCHECK
7446 /* handles bounds */7517 /* handles bounds */
7447 /* XXX: currently, since we do only one pass, we cannot track7518 if (bcheck && v) {
7448 '&' operators, so we add only arrays/structs/unions */7519 add_bound_param (type, size, v, addr);
7449 if (bcheck && ((type->t & VT_ARRAY) ||7520 /* add padding between stack variables */
7450 (type->t & VT_BTYPE) == VT_STRUCT)) {
7451 addr_t *bounds_ptr;
7452 /* add padding between regions */
7453 loc--;7521 loc--;
7454 /* then add local bound info */
7455 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t));
7456 bounds_ptr[0] = addr;
7457 bounds_ptr[1] = size;
7458 }7522 }
7459#endif7523#endif
7460 if (v) {7524 if (v) {
@@ -7633,12 +7697,52 @@ static void gen_function(Sym *sym, AttributeDef *ad) · 172 unmodified lines
7633 sym_push2(&local_stack, SYM_FIELD, 0, 0);7697 sym_push2(&local_stack, SYM_FIELD, 0, 0);
7634 local_scope = 1; /* for function parameters */7698 local_scope = 1; /* for function parameters */
7635 gfunc_prolog(sym);7699 gfunc_prolog(sym);
7700#ifdef CONFIG_TCC_BCHECK
7701 if (tcc_state->do_bounds_check
7702 && sym->type.ref->f.func_type != FUNC_ELLIPSIS) {
7703 Sym *fpar;
7704
7705 /* Add function arguments in case & is used */
7706 for (fpar = sym->type.ref->next; fpar; fpar = fpar->next) {
7707 Sym *fsym = sym_find (fpar->v & ~SYM_FIELD);
7708
7709 if (fsym && (fsym->r & VT_VALMASK) == VT_LOCAL) {
7710 int align;
7711 int size = type_size(&fsym->type, &align);
7712
7713 if (size > 0)
7714 add_bound_param (&fsym->type, size, fsym->v, fsym->c);
7715 }
7716 }
7717 }
7718#endif
7636 local_scope = 0;7719 local_scope = 0;
7637 rsym = 0;7720 rsym = 0;
7638 clear_temp_local_var_list();7721 clear_temp_local_var_list();
7639 block(0);7722 block(0);
7640 gsym(rsym);7723 gsym(rsym);
7641 nocode_wanted = 0;7724 nocode_wanted = 0;
7725#ifdef CONFIG_TCC_BCHECK
7726 if (tcc_state->do_bounds_check) {
7727 addr_t o = func_bound_offset;
7728
7729 /* Remove parameters where address off is not used */
7730 while (o != lbounds_section->data_offset) {
7731 addr_t *bounds_ptr = (addr_t *) (lbounds_section->data + o);
7732 if ((ssize_t) bounds_ptr[1] < 0) {
7733 lbounds_section->data_offset -= 2 * sizeof (addr_t);
7734 memmove(bounds_ptr, bounds_ptr + 2,
7735 lbounds_section->data_offset - o);
7736 }
7737 else {
7738 o += 2 * sizeof (addr_t);
7739 }
7740 }
7741 tcc_free (bound_local_param);
7742 nb_bound_local_param = 0;
7743 bound_local_param = NULL;
7744 }
7745#endif
7642 gfunc_epilog();7746 gfunc_epilog();
7643 cur_text_section->data_offset = ind;7747 cur_text_section->data_offset = ind;
7644 /* reset local stack */7748 /* reset local stack */
tccpe.c+1−1
@@ -1897,7 +1897,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 1896 unmodified lines
1897 const char **pp, *p;1897 const char **pp, *p;
1898#ifdef TCC_IS_NATIVE1898#ifdef TCC_IS_NATIVE
1899 if (s1->do_bounds_check)1899 if (s1->do_bounds_check)
1900 tcc_add_support(s1, "bcheck.o");1900 tcc_add_support(s1, TCC_LIBBCHECK);
1901#endif1901#endif
1902 tcc_add_support(s1, TCC_LIBTCC1);1902 tcc_add_support(s1, TCC_LIBTCC1);
1903 for (pp = libs; 0 != (p = *pp); ++pp) {1903 for (pp = libs; 0 != (p = *pp); ++pp) {
tccrun.c+48−18
@@ -86,6 +86,7 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) · 85 unmodified lines
86 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);86 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
87 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx);87 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx);
88 ptr_diff = (char*)prx - (char*)ptr;88 ptr_diff = (char*)prx - (char*)ptr;
89 close(fd);
89}90}
90#else91#else
91 ptr = tcc_malloc(size);92 ptr = tcc_malloc(size);
@@ -119,6 +120,17 @@ ST_FUNC void tcc_run_free(TCCState *s1) · 27 unmodified lines
119/* launch the compiled program with the given arguments */120/* launch the compiled program with the given arguments */
120LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)121LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
121{122{
123/* PE target overwrites runtime_main */
124#ifndef TCC_TARGET_PE
125 typedef void (*init_array_func)(int, char **, char **);
126 typedef void (*fini_array_func)(void);
127 init_array_func *__init_array_start;
128 init_array_func *__init_array_end;
129 fini_array_func *__fini_array_start;
130 fini_array_func *__fini_array_end;
131#endif
132 int i;
133 int ret;
122 int (*prog_main)(int, char **);134 int (*prog_main)(int, char **);
123 135
124 s1->runtime_main = s1->nostdlib ? "_start" : "main";136 s1->runtime_main = s1->nostdlib ? "_start" : "main";
@@ -140,31 +152,34 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 15 unmodified lines
140 errno = 0; /* clean errno value */152 errno = 0; /* clean errno value */
141 153
142#ifdef CONFIG_TCC_BCHECK154#ifdef CONFIG_TCC_BCHECK
143 if (s1->do_bounds_check) {155 if (s1->do_bounds_check)
144 void (*bound_init)(void);
145 void (*bound_exit)(void);
146 void (*bounds_add_static_var)(size_t *p);
147 size_t *bounds_start;
148 int ret;
149
150 /* set error function */156 /* set error function */
151 s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");157 s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
152 /* XXX: use .init section so that it also work in binary ? */158#endif
153 bound_init = tcc_get_symbol_err(s1, "__bound_init");
154 bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
155 bounds_add_static_var = tcc_get_symbol_err(s1, "__bounds_add_static_var");
156 bounds_start = tcc_get_symbol_err(s1, "__bounds_start");
157 159
158 bound_init();160#ifndef TCC_TARGET_PE
159 bounds_add_static_var (bounds_start);161 __init_array_start = tcc_get_symbol_err(s1, "__init_array_start");
162 __init_array_end = tcc_get_symbol_err(s1, "__init_array_end");
163 __fini_array_start = tcc_get_symbol_err(s1, "__fini_array_start");
164 __fini_array_end = tcc_get_symbol_err(s1, "__fini_array_end");
165
166 if (__init_array_start && __init_array_end) {
167 i = 0;
168 while (&__init_array_start[i] != __init_array_end)
169 (*__init_array_start[i++])(argc, argv, environ);
170 }
171#endif
160 172
161 ret = (*prog_main)(argc, argv);173 ret = (*prog_main)(argc, argv);
162 174
163 bound_exit();175#ifndef TCC_TARGET_PE
164 return ret;176 if (__fini_array_start && __fini_array_end) {
177 i = 0;
178 while (&__fini_array_end[i] != __fini_array_start)
179 (*__fini_array_end[--i])();
165 }180 }
166#endif181#endif
167 return (*prog_main)(argc, argv);182 return ret;
168}183}
169 184
170#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64185#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
@@ -649,6 +664,9 @@ static void set_exception_handler(void) · 478 unmodified lines
649 /* install TCC signal handlers to print debug info on fatal664 /* install TCC signal handlers to print debug info on fatal
650 runtime errors */665 runtime errors */
651 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;666 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
667#ifdef SIGSTKSZ
668 sigact.sa_flags |= SA_ONSTACK;
669#endif
652 sigact.sa_sigaction = sig_error;670 sigact.sa_sigaction = sig_error;
653 sigemptyset(&sigact.sa_mask);671 sigemptyset(&sigact.sa_mask);
654 sigaction(SIGFPE, &sigact, NULL);672 sigaction(SIGFPE, &sigact, NULL);
@@ -656,6 +674,18 @@ static void set_exception_handler(void) · 1 unmodified line
656 sigaction(SIGSEGV, &sigact, NULL);674 sigaction(SIGSEGV, &sigact, NULL);
657 sigaction(SIGBUS, &sigact, NULL);675 sigaction(SIGBUS, &sigact, NULL);
658 sigaction(SIGABRT, &sigact, NULL);676 sigaction(SIGABRT, &sigact, NULL);
677#ifdef SIGSTKSZ
678 /* This allows stack overflow to be reported instead of a SEGV */
679 {
680 stack_t ss;
681 static unsigned char stack[SIGSTKSZ] __attribute__((aligned(16)));
682
683 ss.ss_sp = stack;
684 ss.ss_size = SIGSTKSZ;
685 ss.ss_flags = 0;
686 sigaltstack(&ss, NULL);
687 }
688#endif
659}689}
660 690
661#else /* WIN32 */691#else /* WIN32 */
tests/Makefile+1−1
@@ -168,7 +168,7 @@ memtest: · 167 unmodified lines
168 168
169 169
170# memory and bound check auto test170# memory and bound check auto test
171BOUNDS_OK = 1 4 8 10 14 16171BOUNDS_OK = 1 4 8 10 14 16 18
172BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17172BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17
173 173
174btest: boundtest.c174btest: boundtest.c
tests/boundtest.c+197−0
@@ -230,6 +230,202 @@ int test17() · 229 unmodified lines
230 return 0;230 return 0;
231}231}
232 232
233#define CHECK(s) if (strstr (__bound_error_msg, s) == 0) abort();
234
235extern void __bound_never_fatal (int neverfatal);
236extern const char *__bound_error_msg;
237
238static void init18(char *a, char *b)
239{
240 memset (a, 'a', 10);
241 a[3] = 0;
242 a[9] = 0;
243 memset (b, 'b', 10);
244 __bound_error_msg = "";
245}
246
247/* ok (catch all errors) */
248int test18()
249{
250 char pad1[10];
251 char a[10];
252 char pad2[10];
253 char b[10];
254 char pad3[10];
255
256 memset (pad1, 0, sizeof(pad1));
257 memset (pad2, 0, sizeof(pad2));
258 memset (pad3, 0, sizeof(pad3));
259
260 /* -2 in case TCC_BOUNDS_NEVER_FATAL is set */
261 __bound_never_fatal (-2);
262
263 /* memcpy */
264 init18(a,b);
265 memcpy(&a[1],&b[0],10);
266 CHECK("memcpy dest");
267 init18(a,b);
268 memcpy(&a[0],&b[1],10);
269 CHECK("memcpy src");
270 init18(a,b);
271 memcpy(&a[0],&a[3],4);
272 CHECK("overlapping regions");
273 init18(a,b);
274 memcpy(&a[3],&a[0],4);
275 CHECK("overlapping regions");
276
277 /* memcmp */
278 init18(a,b);
279 memcmp(&b[1],&b[0],10);
280 CHECK("memcmp s1");
281 init18(a,b);
282 memcmp(&b[0],&b[1],10);
283 CHECK("memcmp s2");
284
285 /* memmove */
286 init18(a,b);
287 memmove(&b[1],&b[0],10);
288 CHECK("memmove dest");
289 init18(a,b);
290 memmove(&b[0],&b[1],10);
291 CHECK("memmove src");
292
293 /* memset */
294 init18(a,b);
295 memset(&b[1],'b',10);
296 CHECK("memset");
297
298 /* strlen */
299 init18(a,b);
300 strlen(&b[0]);
301 CHECK("strlen");
302
303 /* strcpy */
304 init18(a,b);
305 strcpy(&a[7], &a[0]);
306 CHECK("strcpy dest");
307 init18(a,b);
308 strcpy(&a[0], &b[7]);
309 CHECK("strcpy src");
310 init18(a,b);
311 strcpy(&a[0], &a[1]);
312 CHECK("overlapping regions");
313 init18(a,b);
314 strcpy(&a[2], &a[0]);
315 CHECK("overlapping regions");
316
317 /* strncpy */
318 init18(a,b);
319 strncpy(&a[7], &a[0], 10);
320 CHECK("strncpy dest");
321 init18(a,b);
322 strncpy(&a[0], &b[7], 10);
323 CHECK("strncpy src");
324 init18(a,b);
325 strncpy(&a[0], &a[1], 10);
326 CHECK("overlapping regions");
327 strncpy(&a[2], &a[0], 10);
328 CHECK("overlapping regions");
329
330 /* strcmp */
331 init18(a,b);
332 strcmp(&b[2], &b[0]);
333 CHECK("strcmp s1");
334 init18(a,b);
335 strcmp(&b[0], &b[2]);
336 CHECK("strcmp s2");
337
338 /* strncmp */
339 init18(a,b);
340 strncmp(&b[5], &b[0], 10);
341 CHECK("strncmp s1");
342 init18(a,b);
343 strncmp(&b[0], &b[5], 10);
344 CHECK("strncmp s2");
345
346 /* strcat */
347 init18(a,b);
348 strcat(&a[7], &a[0]);
349 CHECK("strcat dest");
350 init18(a,b);
351 strcat(&a[0], &b[5]);
352 CHECK("strcat src");
353 init18(a,b);
354 strcat(&a[0], &a[4]);
355 CHECK("overlapping regions");
356 init18(a,b);
357 strcat(&a[3], &a[0]);
358 CHECK("overlapping regions");
359
360 /* strchr */
361 init18(a,b);
362 strchr(&b[0], 'a');
363 CHECK("strchr");
364
365 /* strdup */
366 init18(a,b);
367 free(strdup(&b[0]));
368 CHECK("strdup");
369
370 __bound_never_fatal (2);
371
372 /* memcpy */
373 init18(a,b);
374 memcpy(&a[0],&b[0],10);
375 init18(a,b);
376 memcpy(&a[0],&a[3],3);
377 init18(a,b);
378 memcpy(&a[3],&a[0],3);
379
380 /* memcmp */
381 init18(a,b);
382 memcmp(&b[0],&b[0],10);
383
384 /* memmove */
385 init18(a,b);
386 memmove(&b[0],&b[5],5);
387 init18(a,b);
388 memmove(&b[5],&b[0],5);
389
390 /* memset */
391 init18(a,b);
392 memset(&b[0],'b',10);
393
394 /* strlen */
395 init18(a,b);
396 strlen (&a[0]);
397
398 /* strcpy */
399 init18(a,b);
400 strcpy (&a[0], &a[7]);
401
402 /* strncpy */
403 init18(a,b);
404 strncpy (&a[0], &a[7], 4);
405
406 /* strcmp */
407 init18(a,b);
408 strcmp (&a[0], &a[4]);
409
410 /* strncmp */
411 init18(a,b);
412 strncmp (&a[0], &a[4], 10);
413
414 /* strcat */
415 init18(a,b);
416 strcat (&a[0], &a[7]);
417
418 /* strchr */
419 init18(a,b);
420 strchr (&a[0], 0);
421
422 /* strdup */
423 init18(a,b);
424 free (strdup (&a[0]));
425
426 return 0;
427}
428
233int (*table_test[])(void) = {429int (*table_test[])(void) = {
234 test1,430 test1,
235 test2,431 test2,
@@ -248,6 +444,7 @@ int (*table_test[])(void) = { · 12 unmodified lines
248 test15,444 test15,
249 test16,445 test16,
250 test17,446 test17,
447 test18,
251};448};
252 449
253int main(int argc, char **argv)450int main(int argc, char **argv)
x86_64-gen.c+14−3
@@ -637,7 +637,6 @@ static void gcall_or_jmp(int is_jmp) · 636 unmodified lines
637}637}
638 638
639#if defined(CONFIG_TCC_BCHECK)639#if defined(CONFIG_TCC_BCHECK)
640static addr_t func_bound_offset;
641static unsigned long func_bound_ind;640static unsigned long func_bound_ind;
642 641
643static void gen_bounds_call(int v)642static void gen_bounds_call(int v)
@@ -784,8 +783,10 @@ void gfunc_call(int nb_args) · 140 unmodified lines
784 int arg;783 int arg;
785 784
786#ifdef CONFIG_TCC_BCHECK785#ifdef CONFIG_TCC_BCHECK
787 if (tcc_state->do_bounds_check)786 if (tcc_state->do_bounds_check) {
787 save_temp_local (nb_args);
788 gbound_args(nb_args);788 gbound_args(nb_args);
789 }
789#endif790#endif
790 791
791 args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;792 args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
@@ -906,6 +907,10 @@ void gfunc_call(int nb_args) · 114 unmodified lines
906 907
907 }908 }
908 vtop--;909 vtop--;
910#ifdef CONFIG_TCC_BCHECK
911 if (tcc_state->do_bounds_check)
912 restore_temp_local ();
913#endif
909}914}
910 915
911 916
@@ -1271,8 +1276,10 @@ void gfunc_call(int nb_args) · 359 unmodified lines
1271 char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;1276 char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
1272 1277
1273#ifdef CONFIG_TCC_BCHECK1278#ifdef CONFIG_TCC_BCHECK
1274 if (tcc_state->do_bounds_check)1279 if (tcc_state->do_bounds_check) {
1280 save_temp_local (nb_args);
1275 gbound_args(nb_args);1281 gbound_args(nb_args);
1282 }
1276#endif1283#endif
1277 1284
1278 /* calculate the number of integer/float register arguments, remember1285 /* calculate the number of integer/float register arguments, remember
@@ -1453,6 +1460,10 @@ void gfunc_call(int nb_args) · 174 unmodified lines
1453 if (args_size)1460 if (args_size)
1454 gadd_sp(args_size);1461 gadd_sp(args_size);
1455 vtop--;1462 vtop--;
1463#ifdef CONFIG_TCC_BCHECK
1464 if (tcc_state->do_bounds_check)
1465 restore_temp_local ();
1466#endif
1456}1467}
1457 1468
1458#define FUNC_PROLOG_SIZE 111469#define FUNC_PROLOG_SIZE 11
x86_64-link.c+0−85
@@ -287,89 +287,4 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 286 unmodified lines
287 }287 }
288}288}
289 289
290#ifdef CONFIG_TCC_BCHECK
291ST_FUNC void tcc_add_bcheck(TCCState *s1)
292{
293 addr_t *ptr;
294 int loc_glob;
295 int sym_index;
296 int bsym_index;
297
298 if (0 == s1->do_bounds_check)
299 return;
300 /* XXX: add an object file to do that */
301 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
302 *ptr = 0;
303 loc_glob = s1->output_type != TCC_OUTPUT_MEMORY ? STB_LOCAL : STB_GLOBAL;
304 bsym_index = set_elf_sym(symtab_section, 0, 0,
305 ELFW(ST_INFO)(loc_glob, STT_NOTYPE), 0,
306 bounds_section->sh_num, "__bounds_start");
307 /* pull bcheck.o from libtcc1.a */
308 sym_index = set_elf_sym(symtab_section, 0, 0,
309 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
310 SHN_UNDEF, "__bound_init");
311 if (s1->output_type != TCC_OUTPUT_MEMORY) {
312 /* add 'call __bound_init()' in .init section */
313 Section *init_section = find_section(s1, ".init");
314 unsigned char *pinit;
315#ifdef TCC_TARGET_PE
316 pinit = section_ptr_add(init_section, 8);
317 pinit[0] = 0x55; /* push %rbp */
318 pinit[1] = 0x48; /* mov %rsp,%rpb */
319 pinit[2] = 0x89;
320 pinit[3] = 0xe5;
321 pinit[4] = 0x48; /* sub $0x10,%rsp */
322 pinit[5] = 0x83;
323 pinit[6] = 0xec;
324 pinit[7] = 0x10;
325#endif
326 pinit = section_ptr_add(init_section, 5);
327 pinit[0] = 0xe8;
328 write32le(pinit + 1, -4);
329 put_elf_reloc(symtab_section, init_section,
330 init_section->data_offset - 4, R_386_PC32, sym_index);
331 /* R_386_PC32 = R_X86_64_PC32 = 2 */
332 pinit = section_ptr_add(init_section, 13);
333 pinit[0] = 0x48; /* mov xx,%rax */
334 pinit[1] = 0xb8;
335 write64le(pinit + 2, 0);
336#ifdef TCC_TARGET_PE
337 pinit[10] = 0x48; /* mov %rax,%rcx */
338 pinit[11] = 0x89;
339 pinit[12] = 0xc1;
340#else
341 pinit[10] = 0x48; /* mov %rax,%rdi */
342 pinit[11] = 0x89;
343 pinit[12] = 0xc7;
344#endif
345 put_elf_reloc(symtab_section, init_section,
346 init_section->data_offset - 11, R_X86_64_64, bsym_index);
347 sym_index = set_elf_sym(symtab_section, 0, 0,
348 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
349 SHN_UNDEF, "__bounds_add_static_var");
350 pinit = section_ptr_add(init_section, 5);
351 pinit[0] = 0xe8;
352 write32le(pinit + 1, -4);
353 put_elf_reloc(symtab_section, init_section,
354 init_section->data_offset - 4, R_386_PC32, sym_index);
355 /* R_386_PC32 = R_X86_64_PC32 = 2 */
356#ifdef TCC_TARGET_PE
357 {
358 int init_index = set_elf_sym(symtab_section,
359 0, 0,
360 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
361 init_section->sh_num, "__init_start");
362 Sym sym;
363 init_section->sh_flags |= SHF_EXECINSTR;
364 pinit = section_ptr_add(init_section, 2);
365 pinit[0] = 0xc9; /* leave */
366 pinit[1] = 0xc3; /* ret */
367 sym.c = init_index;
368 add_init_array (s1, &sym);
369 }
370#endif
371 }
372}
373#endif
374
375#endif /* !TARGET_DEFS_ONLY */290#endif /* !TARGET_DEFS_ONLY */

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