Add setjmp/longjmp bound checking support

tcctok.h:
- Add __bound_setjmp/setjmp/_setjmp/longjmp

tccgen.c:
- redirect setjmp/longjmp to bcheck.c code

i386-gen.c/x86_64-gen.c
- Change func_bound_alloca_used into func_bound_add_epilog
- Set func_bound_add_epilog also when setjmp is called

bcheck.c:
- Add __bound_setjmp/__bound_longjmp
- __bound_local_delete: remove setjmp if used in function
- __bound_exit: clear setjmp list and print statistic
- make malloc_redir more readable (unrelated)

New testcases:
- 115_bound_setjmp
- 116_bound_setjmp2
This commit is contained in:
herman ten brugge 2020-05-23 20:02:41 +02:00
parent 4429cef9f6
commit b5b92c7d6d
10 changed files with 509 additions and 108 deletions

View File

@ -97,7 +97,7 @@ static int func_ret_sub;
#ifdef CONFIG_TCC_BCHECK
static addr_t func_bound_offset;
static unsigned long func_bound_ind;
static int func_bound_alloca_used;
static int func_bound_add_epilog;
static void gen_bounds_prolog(void);
static void gen_bounds_epilog(void);
#endif
@ -359,8 +359,11 @@ static void gcall_or_jmp(int is_jmp)
greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check && vtop->sym->v == TOK_alloca)
func_bound_alloca_used = 1;
if (tcc_state->do_bounds_check &&
(vtop->sym->v == TOK_alloca ||
vtop->sym->v == TOK_setjmp ||
vtop->sym->v == TOK__setjmp))
func_bound_add_epilog = 1;
#endif
} else {
/* otherwise, indirect call */
@ -1069,7 +1072,7 @@ static void gen_bounds_prolog(void)
/* leave some room for bound checking code */
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
func_bound_alloca_used = 0;
func_bound_add_epilog = 0;
oad(0xb8, 0); /* lbound section pointer */
oad(0xb8, 0); /* call to function */
}
@ -1080,7 +1083,7 @@ static void gen_bounds_epilog(void)
addr_t *bounds_ptr;
Sym *sym_data;
if (func_bound_offset == lbounds_section->data_offset && !func_bound_alloca_used)
if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)
return;
/* add end of table info */

View File

@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <setjmp.h>
#if !defined(__FreeBSD__) \
&& !defined(__FreeBSD_kernel__) \
@ -32,6 +33,7 @@
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/syscall.h>
#endif
#define BOUND_DEBUG (1)
@ -158,6 +160,25 @@ typedef struct alloca_list_struct {
struct alloca_list_struct *next;
} alloca_list_type;
#if defined(_WIN32)
#define BOUND_TID_TYPE DWORD
#define BOUND_GET_TID GetCurrentThreadId()
#elif defined(__i386__) || defined(__x86_64__)
#define BOUND_TID_TYPE pid_t
#define BOUND_GET_TID syscall (SYS_gettid)
#else
#define BOUND_TID_TYPE int
#define BOUND_GET_TID 0
#endif
typedef struct jmp_list_struct {
void *penv;
size_t fp;
size_t end_fp;
BOUND_TID_TYPE tid;
struct jmp_list_struct *next;
} jmp_list_type;
#define BOUND_STATISTIC_SPLAY (0)
static Tree * splay (size_t addr, Tree *t);
static Tree * splay_end (size_t addr, Tree *t);
@ -186,6 +207,8 @@ void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd,
int __bound_munmap (void *start, size_t size);
#endif
DLL_EXPORT void __bound_new_region(void *p, size_t size);
DLL_EXPORT void __bound_setjmp(jmp_buf env);
DLL_EXPORT void __bound_longjmp(jmp_buf env, int val);
DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size);
DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size);
DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size);
@ -199,7 +222,18 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
DLL_EXPORT char *__bound_strchr(const char *string, int ch);
DLL_EXPORT char *__bound_strdup(const char *s);
#if !MALLOC_REDIR
#if MALLOC_REDIR
#define BOUND_MALLOC(a) malloc_redir(a)
#define BOUND_MEMALIGN(a,b) memalign_redir(a,b)
#define BOUND_FREE(a) free_redir(a)
#define BOUND_REALLOC(a,b) realloc_redir(a,b)
#define BOUND_CALLOC(a,b) calloc_redir(a,b)
#else
#define BOUND_MALLOC(a) malloc(a)
#define BOUND_MEMALIGN(a,b) memalign(a,b)
#define BOUND_FREE(a) free(a)
#define BOUND_REALLOC(a,b) realloc(a,b)
#define BOUND_CALLOC(a,b) calloc(a,b)
DLL_EXPORT void *__bound_malloc(size_t size, const void *caller);
DLL_EXPORT void *__bound_memalign(size_t size, size_t align, const void *caller);
DLL_EXPORT void __bound_free(void *ptr, const void *caller);
@ -217,6 +251,7 @@ static Tree *tree = NULL;
static Tree *tree_free_list;
#endif
static alloca_list_type *alloca_list;
static jmp_list_type *jmp_list;
static unsigned char inited;
static unsigned char print_warn_ptr_add;
@ -246,6 +281,8 @@ static unsigned long long bound_memalign_count;
static unsigned long long bound_mmap_count;
static unsigned long long bound_munmap_count;
static unsigned long long bound_alloca_count;
static unsigned long long bound_setjmp_count;
static unsigned long long bound_longjmp_count;
static unsigned long long bound_mempcy_count;
static unsigned long long bound_memcmp_count;
static unsigned long long bound_memmove_count;
@ -473,7 +510,8 @@ void FASTCALL __bound_local_new(void *p1)
void FASTCALL __bound_local_delete(void *p1)
{
size_t addr, fp, *p = p1;
alloca_list_type *free_list = NULL;
alloca_list_type *alloca_free_list = NULL;
jmp_list_type *jmp_free_list = NULL;
if (no_checking)
return;
@ -487,39 +525,63 @@ void FASTCALL __bound_local_delete(void *p1)
p += 2;
}
{
alloca_list_type *last = NULL;
alloca_list_type *cur = alloca_list;
alloca_list_type *last = NULL;
alloca_list_type *cur = alloca_list;
while (cur) {
if (cur->fp == fp) {
if (last)
last->next = cur->next;
else
alloca_list = cur->next;
tree = splay_delete ((size_t) cur->p, tree);
cur->next = free_list;
free_list = cur;
cur = last ? last->next : alloca_list;
}
else {
last = cur;
cur = cur->next;
}
while (cur) {
if (cur->fp == fp) {
if (last)
last->next = cur->next;
else
alloca_list = cur->next;
tree = splay_delete ((size_t) cur->p, tree);
cur->next = alloca_free_list;
alloca_free_list = cur;
cur = last ? last->next : alloca_list;
}
else {
last = cur;
cur = cur->next;
}
}
}
{
jmp_list_type *last = NULL;
jmp_list_type *cur = jmp_list;
while (cur) {
if (cur->fp == fp) {
if (last)
last->next = cur->next;
else
jmp_list = cur->next;
cur->next = jmp_free_list;
jmp_free_list = cur;
cur = last ? last->next : jmp_list;
}
else {
last = cur;
cur = cur->next;
}
}
}
POST_SEM ();
while (free_list) {
alloca_list_type *next = free_list->next;
while (alloca_free_list) {
alloca_list_type *next = alloca_free_list->next;
dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
__FILE__, __FUNCTION__, free_list->p);
#if MALLOC_REDIR
free_redir (free_list);
#else
free (free_list);
#endif
free_list = next;
__FILE__, __FUNCTION__, alloca_free_list->p);
BOUND_FREE (alloca_free_list);
alloca_free_list = next;
}
while (jmp_free_list) {
jmp_list_type *next = jmp_free_list->next;
dprintf(stderr, "%s, %s(): remove setjmp %p\n",
__FILE__, __FUNCTION__, jmp_free_list->penv);
BOUND_FREE (jmp_free_list);
jmp_free_list = next;
}
#if BOUND_DEBUG
if (print_calls) {
@ -547,11 +609,7 @@ void __bound_new_region(void *p, size_t size)
dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
__FILE__, __FUNCTION__, p, (unsigned long)size);
GET_CALLER_FP (fp);
#if MALLOC_REDIR
new = malloc_redir (sizeof (alloca_list_type));
#else
new = malloc (sizeof (alloca_list_type));
#endif
new = BOUND_MALLOC (sizeof (alloca_list_type));
WAIT_SEM ();
INCR_COUNT(bound_alloca_count);
last = NULL;
@ -580,14 +638,116 @@ void __bound_new_region(void *p, size_t size)
if (cur) {
dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
__FILE__, __FUNCTION__, cur->p);
#if MALLOC_REDIR
free_redir (cur);
#else
free (cur);
#endif
BOUND_FREE (cur);
}
}
void __bound_setjmp(jmp_buf env)
{
jmp_list_type *jl;
void *e = (void *) env;
dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e);
WAIT_SEM ();
INCR_COUNT(bound_setjmp_count);
jl = jmp_list;
while (jl) {
if (jl->penv == e)
break;
jl = jl->next;
}
if (jl == NULL) {
jl = BOUND_MALLOC (sizeof (jmp_list_type));
if (jl) {
jl->penv = e;
jl->next = jmp_list;
jmp_list = jl;
}
}
if (jl) {
size_t fp;
GET_CALLER_FP (fp);
jl->fp = fp;
jl->end_fp = (size_t)__builtin_frame_address(0);
jl->tid = BOUND_GET_TID;
}
POST_SEM ();
}
void __bound_longjmp(jmp_buf env, int val)
{
jmp_list_type *jl;
void *e = (void *)env;
BOUND_TID_TYPE tid = BOUND_GET_TID;
dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e);
WAIT_SEM();
INCR_COUNT(bound_longjmp_count);
jl = jmp_list;
while (jl) {
if (jl->penv == e && jl->tid == tid) {
size_t start_fp = (size_t)__builtin_frame_address(0);
size_t end_fp = jl->end_fp;
jmp_list_type *cur = jmp_list;
jmp_list_type *last = NULL;
while (cur->penv != e || cur->tid != tid) {
if (cur->tid == tid) {
dprintf(stderr, "%s, %s(): remove setjmp %p\n",
__FILE__, __FUNCTION__, cur->penv);
if (last)
last->next = cur->next;
else
jmp_list = cur->next;
BOUND_FREE (cur);
cur = last ? last->next : jmp_list;
}
else {
last = cur;
cur = cur->next;
}
}
for (;;) {
Tree *t = tree;
alloca_list_type *last;
alloca_list_type *cur;
while (t && (t->start < start_fp || t->start > end_fp))
if (t->start < start_fp)
t = t->right;
else
t = t->left;
if (t == NULL)
break;
last = NULL;
cur = alloca_list;
while (cur) {
if ((size_t) cur->p == t->start) {
dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
__FILE__, __FUNCTION__, cur->p);
if (last)
last->next = cur->next;
else
alloca_list = cur->next;
BOUND_FREE (cur);
break;
}
last = cur;
cur = cur->next;
}
dprintf(stderr, "%s, %s(): delete %p\n",
__FILE__, __FUNCTION__, (void *) t->start);
tree = splay_delete(t->start, tree);
}
break;
}
jl = jl->next;
}
POST_SEM();
longjmp (env, val);
}
#if defined(__GNUC__) && (__GNUC__ >= 6)
#pragma GCC diagnostic pop
#endif
@ -811,21 +971,19 @@ void __attribute__((destructor)) __bound_exit(void)
alloca_list_type *next = alloca_list->next;
tree = splay_delete ((size_t) alloca_list->p, tree);
#if MALLOC_REDIR
free_redir (alloca_list);
#else
free (alloca_list);
#endif
BOUND_FREE (alloca_list);
alloca_list = next;
}
while (jmp_list) {
jmp_list_type *next = jmp_list->next;
BOUND_FREE (jmp_list);
jmp_list = next;
}
for (i = 0; i < FREE_REUSE_SIZE; i++) {
if (free_reuse_list[i]) {
tree = splay_delete ((size_t) free_reuse_list[i], tree);
#if MALLOC_REDIR
free_redir (free_reuse_list[i]);
#else
free (free_reuse_list[i]);
#endif
BOUND_FREE (free_reuse_list[i]);
}
}
while (tree) {
@ -838,11 +996,7 @@ void __attribute__((destructor)) __bound_exit(void)
#if TREE_REUSE
while (tree_free_list) {
Tree *next = tree_free_list->left;
#if MALLOC_REDIR
free_redir (tree_free_list);
#else
free (tree_free_list);
#endif
BOUND_FREE (tree_free_list);
tree_free_list = next;
}
#endif
@ -868,6 +1022,8 @@ void __attribute__((destructor)) __bound_exit(void)
fprintf (stderr, "bound_mmap_count %llu\n", bound_mmap_count);
fprintf (stderr, "bound_munmap_count %llu\n", bound_munmap_count);
fprintf (stderr, "bound_alloca_count %llu\n", bound_alloca_count);
fprintf (stderr, "bound_setjmp_count %llu\n", bound_setjmp_count);
fprintf (stderr, "bound_longjmp_count %llu\n", bound_longjmp_count);
fprintf (stderr, "bound_mempcy_count %llu\n", bound_mempcy_count);
fprintf (stderr, "bound_memcmp_count %llu\n", bound_memcmp_count);
fprintf (stderr, "bound_memmove_count %llu\n", bound_memmove_count);
@ -928,11 +1084,7 @@ void *__bound_malloc(size_t size, const void *caller)
/* we allocate one more byte to ensure the regions will be
separated by at least one byte. With the glibc malloc, it may
be in fact not necessary */
#if MALLOC_REDIR
ptr = malloc_redir (size + 1);
#else
ptr = malloc(size + 1);
#endif
ptr = BOUND_MALLOC (size + 1);
dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
__FILE__, __FUNCTION__, ptr, (unsigned long)size);
@ -962,22 +1114,14 @@ void *__bound_memalign(size_t size, size_t align, const void *caller)
/* we allocate one more byte to ensure the regions will be
separated by at least one byte. With the glibc malloc, it may
be in fact not necessary */
#if MALLOC_REDIR
ptr = memalign_redir(size + 1, align);
#else
ptr = memalign(size + 1, align);
#endif
ptr = BOUND_MEMALIGN(size + 1, align);
#else
if (align > 4) {
/* XXX: handle it ? */
ptr = NULL;
} else {
/* we suppose that malloc aligns to at least four bytes */
#if MALLOC_REDIR
ptr = malloc_redir(size + 1);
#else
ptr = malloc(size + 1);
#endif
ptr = BOUND_MALLOC(size + 1);
}
#endif
dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
@ -1035,11 +1179,7 @@ void __bound_free(void *ptr, const void *caller)
ptr = p;
}
POST_SEM ();
#if MALLOC_REDIR
free_redir (ptr);
#else
free(ptr);
#endif
BOUND_FREE (ptr);
}
#if MALLOC_REDIR
@ -1059,11 +1199,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
return NULL;
}
#if MALLOC_REDIR
new_ptr = realloc_redir (ptr, size);
#else
new_ptr = realloc (ptr, size);
#endif
new_ptr = BOUND_REALLOC (ptr, size);
dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
__FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
@ -1108,11 +1244,7 @@ void *__bound_calloc(size_t nmemb, size_t size)
}
}
#endif
#if MALLOC_REDIR
ptr = malloc_redir(size + 1);
#else
ptr = malloc(size + 1);
#endif
ptr = BOUND_MALLOC(size + 1);
dprintf (stderr, "%s, %s(): %p, 0x%lx\n",
__FILE__, __FUNCTION__, ptr, (unsigned long)size);
@ -1377,11 +1509,7 @@ char *__bound_strdup(const char *s)
INCR_COUNT(bound_strdup_count);
while (*p++);
__bound_check(s, p - s, "strdup");
#if MALLOC_REDIR
new = malloc_redir ((p - s) + 1);
#else
new = malloc ((p - s) + 1);
#endif
new = BOUND_MALLOC ((p - s) + 1);
dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
__FILE__, __FUNCTION__, new, (unsigned long)(p -s));
if (new) {
@ -1574,11 +1702,7 @@ static Tree * splay_insert(size_t addr, size_t size, Tree * t)
else
#endif
{
#if MALLOC_REDIR
new = (Tree *) malloc_redir (sizeof (Tree));
#else
new = (Tree *) malloc (sizeof (Tree));
#endif
new = (Tree *) BOUND_MALLOC (sizeof (Tree));
}
if (new == NULL) {
bound_alloc_error("not enough memory for bound checking code");
@ -1626,11 +1750,7 @@ static Tree * splay_delete(size_t addr, Tree *t)
t->left = tree_free_list;
tree_free_list = t;
#else
#if MALLOC_REDIR
free_redir(t);
#else
free(t);
#endif
BOUND_FREE(t);
#endif
return x;
} else {

View File

@ -909,6 +909,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
case TOK_alloca:
case TOK_mmap:
case TOK_munmap:
case TOK_longjmp:
strcpy(buf, "__bound_");
strcat(buf, name);
name = buf;
@ -6010,6 +6011,19 @@ special_math_val:
if (sa)
tcc_error("too few arguments to function");
skip(')');
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check &&
(nb_args == 1 || nb_args == 2) &&
(vtop[-nb_args].r & VT_SYM) &&
(vtop[-nb_args].sym->v == TOK_setjmp ||
vtop[-nb_args].sym->v == TOK__setjmp)) {
vpush_global_sym(&func_old_type, TOK___bound_setjmp);
vpushv(vtop - nb_args);
if (nb_args == 2)
vpushv(vtop - nb_args);
gfunc_call(nb_args);
}
#endif
gfunc_call(nb_args);
if (ret_nregs < 0) {

View File

@ -305,6 +305,7 @@
DEF(TOK___bound_main_arg, "__bound_main_arg")
DEF(TOK___bound_local_new, "__bound_local_new")
DEF(TOK___bound_local_delete, "__bound_local_delete")
DEF(TOK___bound_setjmp, "__bound_setjmp")
# ifdef TCC_TARGET_PE
# ifdef TCC_TARGET_X86_64
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
@ -326,6 +327,9 @@
DEF(TOK_strcat, "strcat")
DEF(TOK_strchr, "strchr")
DEF(TOK_strdup, "strdup")
DEF(TOK_setjmp, "setjmp")
DEF(TOK__setjmp, "_setjmp")
DEF(TOK_longjmp, "longjmp")
#endif
/* Tiny Assembler */

View File

@ -0,0 +1,169 @@
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#define TST int i, a[2], b[2]; \
for (i = 0; i < 2; i++) a[i] = 0; \
for (i = 0; i < 2; i++) b[i] = 0
static jmp_buf jmp;
static void tst1 (void)
{
TST;
longjmp(jmp, 1);
}
static void tst2(void)
{
jmp_buf jmp;
setjmp (jmp);
TST;
tst1();
}
static void tst3 (jmp_buf loc)
{
TST;
longjmp(loc, 1);
}
static void tst4(jmp_buf loc)
{
jmp_buf jmp;
setjmp (jmp);
TST;
tst3(loc);
}
static void tst (void)
{
jmp_buf loc;
static int cnt;
cnt = 0;
if (setjmp (jmp) == 0) {
TST;
tst2();
}
else {
cnt++;
}
if (setjmp (loc) == 0) {
TST;
tst4(loc);
}
else {
cnt++;
}
if (cnt != 2)
printf ("incorrect cnt %d\n", cnt);
}
static jmp_buf buf1;
static jmp_buf buf2;
static int *p;
static int n_x = 6;
static int g_counter;
static void stack (void)
{
static int counter;
static int way_point1;
static int way_point2;
counter = 0;
way_point1 = 3;
way_point2 = 2;
g_counter = 0;
if (setjmp (buf1) != 101) {
int a[n_x];
g_counter++;
p = &a[0];
if (g_counter < 5)
longjmp (buf1, 2);
else if (g_counter == 5)
longjmp (buf1, 101);
else {
setjmp (buf2);
longjmp (buf1, 101);
}
}
way_point1--;
if (counter == 0) {
counter++;
{
int a[n_x];
g_counter++;
p = &a[0];
if (g_counter < 5)
longjmp (buf1, 2);
else if (g_counter == 5)
longjmp (buf1, 101);
else {
setjmp (buf2);
longjmp (buf1, 101);
}
}
}
way_point2--;
if (counter == 1) {
counter++;
longjmp (buf2, 2);
}
if (!(way_point1 == 0 && way_point2 == 0 &&
g_counter == 6 && counter == 2))
printf ("Failed %d %d %d %d\n",
way_point1, way_point2, g_counter, counter);
}
static jmp_buf env;
static int last_value;
static void jump (int val)
{
longjmp (env, val);
}
static void check (void)
{
int value;
last_value = -1;
value = setjmp (env);
if (value != last_value + 1) {
printf ("incorrect value %d %d\n",
value, last_value + 1);
return;
}
last_value = value;
switch (value) {
case 0:
jump (0);
default:
if (value < 10)
jump (value + 1);
}
}
int
main (void)
{
int i;
for (i = 0; i < 10; i++) {
tst();
stack();
check();
}
return 0;
}

View File

View File

@ -0,0 +1,84 @@
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#if !defined(_WIN32)
#include <pthread.h>
#else
#include <windows.h>
#endif
#define SIZE 10
#define COUNT 10
#define TST int i, a[2], b[2]; \
for (i = 0; i < 2; i++) a[i] = 0; \
for (i = 0; i < 2; i++) b[i] = 0
static int count[SIZE];
static void tst1 (jmp_buf loc)
{
TST;
longjmp(loc, 1);
}
static void tst2(jmp_buf loc)
{
jmp_buf jmp;
setjmp (jmp);
TST;
tst1(loc);
}
static void *tst (void * index)
{
jmp_buf loc;
int i = *(int *) index;
static int v[SIZE];
for (v[i] = 0; v[i] < COUNT; v[i]++) {
if (setjmp (loc) == 0) {
TST;
tst2(loc);
}
else {
count[i]++;
}
i = *(int *) index;
}
return NULL;
}
int
main (void)
{
int i;
#if !defined(_WIN32)
pthread_t id[SIZE];
#else
HANDLE id[SIZE];
#endif
int index[SIZE];
for (i = 0; i < SIZE; i++) {
index[i] = i;
#if !defined(_WIN32)
pthread_create (&id[i], NULL, tst, (void *) &index[i]);
#else
id[i] = CreateThread(NULL, 8192, (LPTHREAD_START_ROUTINE) tst, (void *) &index[i], 0, NULL);
#endif
}
for (i = 0; i < SIZE; i++) {
#if !defined(_WIN32)
pthread_join (id[i], NULL);
#else
WaitForSingleObject(id[i], INFINITE);
#endif
}
for (i = 0; i < SIZE; i++) {
if (count[i] != COUNT)
printf ("error: %d %d\n", i, count[i]);
}
return 0;
}

View File

View File

@ -26,6 +26,8 @@ ifeq (,$(filter i386 x86_64,$(ARCH)))
SKIP += 85_asm-outside-function.test
SKIP += 112_backtrace.test 113_btdll.test
SKIP += 114_bound_signal.test
SKIP += 115_bound_setjmp.test
SKIP += 116_bound_setjmp2.test
endif
ifeq (-$(CONFIG_musl)-,-yes-)
SKIP += 112_backtrace.test
@ -91,6 +93,8 @@ GEN-ALWAYS =
-bt a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=.
114_bound_signal.test: FLAGS += -b
115_bound_setjmp.test: FLAGS += -b
116_bound_setjmp2.test: FLAGS += -b
# Filter source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'

View File

@ -149,7 +149,7 @@ static int func_ret_sub;
#if defined(CONFIG_TCC_BCHECK)
static addr_t func_bound_offset;
static unsigned long func_bound_ind;
static int func_bound_alloca_used;
static int func_bound_add_epilog;
#endif
#ifdef TCC_TARGET_PE
@ -637,8 +637,11 @@ static void gcall_or_jmp(int is_jmp)
#endif
oad(0xe8 + is_jmp, 0); /* call/jmp im */
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check && vtop->sym->v == TOK_alloca)
func_bound_alloca_used = 1;
if (tcc_state->do_bounds_check &&
(vtop->sym->v == TOK_alloca ||
vtop->sym->v == TOK_setjmp ||
vtop->sym->v == TOK__setjmp))
func_bound_add_epilog = 1;
#endif
} else {
/* otherwise, indirect call */
@ -725,7 +728,7 @@ static void gen_bounds_prolog(void)
/* leave some room for bound checking code */
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
func_bound_alloca_used = 0;
func_bound_add_epilog = 0;
o(0xb848 + TREG_FASTCALL_1 * 0x100); /*lbound section pointer */
gen_le64 (0);
oad(0xb8, 0); /* call to function */
@ -737,7 +740,7 @@ static void gen_bounds_epilog(void)
addr_t *bounds_ptr;
Sym *sym_data;
if (func_bound_offset == lbounds_section->data_offset && !func_bound_alloca_used)
if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)
return;
/* add end of table info */