History

Repair bounds-checking runtime

On this weekend a thought came to me again that tinycc could be used for scripting. Only its bounds-checking mode turned out to be broken, which is a pity because bounds-checking is sometimes handy especially for quickly written scripts. Since tinycc is one of those small beautiful things, seldomly happening in our times, I couldn't resist trying to fix it. Thanks, Kirill * bcheck: Now btest pass! lib/bcheck: Prevent __bound_local_new / __bound_local_delete from being miscompiled lib/bcheck: Prevent libc_malloc/libc_free etc from being miscompiled

Kirill Smelkov committed 14 years ago

Commit 40a54c42 parents 1af3bca 5d648482 files · +8 −16Browse files

Unified · Split

2 files
  1. lib/bcheck.c +8 −15
  2. tests/Makefile +0 −1
lib/bcheck.c+8−15
@@ -208,25 +208,11 @@ BOUND_PTR_INDIR(8) · 207 unmodified lines
208BOUND_PTR_INDIR(12)208BOUND_PTR_INDIR(12)
209BOUND_PTR_INDIR(16)209BOUND_PTR_INDIR(16)
210 210
211#ifdef __i386__
212/* return the frame pointer of the caller */211/* return the frame pointer of the caller */
213#define GET_CALLER_FP(fp)\212#define GET_CALLER_FP(fp)\
214{\213{\
215 unsigned long *fp1;\214 fp = (unsigned long)__builtin_frame_address(1);\
216 __asm__ __volatile__ ("movl %%ebp,%0" :"=g" (fp1));\
217 fp = fp1[0];\
218}215}
219#elif defined(__x86_64__)
220/* TCC always creates %rbp frames also on x86_64, so use them. */
221#define GET_CALLER_FP(fp)\
222{\
223 unsigned long *fp1;\
224 __asm__ __volatile__ ("movq %%rbp,%0" :"=g" (fp1));\
225 fp = fp1[0];\
226}
227#else
228#error put code to extract the calling frame pointer
229#endif
230 216
231/* called when entering a function to add all the local regions */217/* called when entering a function to add all the local regions */
232void FASTCALL __bound_local_new(void *p1) 218void FASTCALL __bound_local_new(void *p1)
@@ -638,6 +624,9 @@ static unsigned long get_region_size(void *p) · 405 unmodified lines
638 624
639/* patched memory functions */625/* patched memory functions */
640 626
627/* force compiler to perform stores coded up to this point */
628#define barrier() __asm__ __volatile__ ("": : : "memory")
629
641static void install_malloc_hooks(void)630static void install_malloc_hooks(void)
642{631{
643#ifdef CONFIG_TCC_MALLOC_HOOKS632#ifdef CONFIG_TCC_MALLOC_HOOKS
@@ -649,6 +638,8 @@ static void install_malloc_hooks(void) · 5 unmodified lines
649 __free_hook = __bound_free;638 __free_hook = __bound_free;
650 __realloc_hook = __bound_realloc;639 __realloc_hook = __bound_realloc;
651 __memalign_hook = __bound_memalign;640 __memalign_hook = __bound_memalign;
641
642 barrier();
652#endif643#endif
653}644}
654 645
@@ -659,6 +650,8 @@ static void restore_malloc_hooks(void) · 4 unmodified lines
659 __free_hook = saved_free_hook;650 __free_hook = saved_free_hook;
660 __realloc_hook = saved_realloc_hook;651 __realloc_hook = saved_realloc_hook;
661 __memalign_hook = saved_memalign_hook;652 __memalign_hook = saved_memalign_hook;
653
654 barrier();
662#endif655#endif
663}656}
664 657
tests/Makefile+0−1
@@ -22,7 +22,6 @@ TESTS = libtest \ · 21 unmodified lines
22 22
23# some tests do not pass on all platforms, remove them for now23# some tests do not pass on all platforms, remove them for now
24ifeq ($(TARGETOS),Linux)24ifeq ($(TARGETOS),Linux)
25 TESTS := $(filter-out btest,$(TESTS))
26 TESTS := $(filter-out weaktest,$(TESTS))25 TESTS := $(filter-out weaktest,$(TESTS))
27endif26endif
28ifeq ($(TARGETOS),Darwin)27ifeq ($(TARGETOS),Darwin)