mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
Add new bounds checking functions.
The following functions are now also bounds checked: memcmp, strncpy, strcmp, strncmp, strcat, strchr, strdup. Add statistics code for bounds checking functions. The statistics can be printed by settings environment variable "TCC_BOUNDS_PRINT_STATISTIC". Enabled more tests in test/Makefile.
This commit is contained in:
parent
35512be1ee
commit
39c0ff311d
@ -42,7 +42,7 @@ ifdef CONFIG_OSX
|
||||
XFLAGS += -D_ANSI_SOURCE
|
||||
endif
|
||||
|
||||
XFLAGS += -g -Wno-deprecated-declarations
|
||||
XFLAGS += -g
|
||||
|
||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o
|
||||
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
|
||||
|
218
lib/bcheck.c
218
lib/bcheck.c
@ -35,6 +35,7 @@
|
||||
#endif
|
||||
|
||||
#define BOUND_DEBUG
|
||||
#define BOUND_STATISTIC
|
||||
|
||||
#ifdef BOUND_DEBUG
|
||||
#define dprintf(a...) if (print_calls) fprintf(a)
|
||||
@ -50,8 +51,7 @@
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__dietlibc__) \
|
||||
|| defined(_WIN32)
|
||||
|| defined(__dietlibc__)
|
||||
#undef HAVE_MEMALIGN
|
||||
#define INIT_SEM()
|
||||
#define EXIT_SEM()
|
||||
@ -59,6 +59,16 @@
|
||||
#define POST_SEM()
|
||||
#define HAS_ENVIRON 0
|
||||
#define MALLOC_REDIR (0)
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#undef HAVE_MEMALIGN
|
||||
static CRITICAL_SECTION bounds_sem;
|
||||
#define INIT_SEM() InitializeCriticalSection(&bounds_sem)
|
||||
#define EXIT_SEM() DeleteCriticalSection(&bounds_sem)
|
||||
#define WAIT_SEM() EnterCriticalSection(&bounds_sem)
|
||||
#define POST_SEM() LeaveCriticalSection(&bounds_sem)
|
||||
#define HAS_ENVIRON 0
|
||||
#define MALLOC_REDIR (0)
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
@ -86,6 +96,7 @@ static unsigned char initial_pool[256];
|
||||
#define TCC_TYPE_CALLOC (2)
|
||||
#define TCC_TYPE_REALLOC (3)
|
||||
#define TCC_TYPE_MEMALIGN (4)
|
||||
#define TCC_TYPE_STRDUP (5)
|
||||
|
||||
/* this pointer is generated when bound check is incorrect */
|
||||
#define INVALID_POINTER ((void *)(-2))
|
||||
@ -149,9 +160,45 @@ static alloca_list_type *alloca_list = NULL;
|
||||
static int inited = 0;
|
||||
static int print_calls = 0;
|
||||
static int print_heap = 0;
|
||||
static int print_statistic = 0;
|
||||
static int never_fatal = 0;
|
||||
static int no_checking = 0;
|
||||
|
||||
#ifdef BOUND_STATISTIC
|
||||
static unsigned long bound_ptr_add_count;
|
||||
static unsigned long bound_ptr_indir1_count;
|
||||
static unsigned long bound_ptr_indir2_count;
|
||||
static unsigned long bound_ptr_indir4_count;
|
||||
static unsigned long bound_ptr_indir8_count;
|
||||
static unsigned long bound_ptr_indir12_count;
|
||||
static unsigned long bound_ptr_indir16_count;
|
||||
static unsigned long bound_local_new_count;
|
||||
static unsigned long bound_local_delete_count;
|
||||
static unsigned long bound_malloc_count;
|
||||
static unsigned long bound_calloc_count;
|
||||
static unsigned long bound_realloc_count;
|
||||
static unsigned long bound_free_count;
|
||||
static unsigned long bound_memalign_count;
|
||||
static unsigned long bound_mmap_count;
|
||||
static unsigned long bound_munmap_count;
|
||||
static unsigned long bound_alloca_count;
|
||||
static unsigned long bound_mempcy_count;
|
||||
static unsigned long bound_memcmp_count;
|
||||
static unsigned long bound_memmove_count;
|
||||
static unsigned long bound_memset_count;
|
||||
static unsigned long bound_strlen_count;
|
||||
static unsigned long bound_strcpy_count;
|
||||
static unsigned long bound_strncpy_count;
|
||||
static unsigned long bound_strcmp_count;
|
||||
static unsigned long bound_strncmp_count;
|
||||
static unsigned long bound_strcat_count;
|
||||
static unsigned long bound_strchr_count;
|
||||
static unsigned long bound_strdup_count;
|
||||
#define INCR_COUNT(x) x++
|
||||
#else
|
||||
#define INCR_COUNT(x)
|
||||
#endif
|
||||
|
||||
/* enable/disable checking. This can be used for signal handlers. */
|
||||
void __bound_checking (int no_check)
|
||||
{
|
||||
@ -186,6 +233,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset)
|
||||
__FILE__, __FUNCTION__, p, (unsigned)offset);
|
||||
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_ptr_add_count);
|
||||
if (tree) {
|
||||
tree = splay (addr, tree);
|
||||
addr -= tree->start;
|
||||
@ -223,6 +271,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \
|
||||
dprintf(stderr, "%s %s: %p 0x%x start\n", \
|
||||
__FILE__, __FUNCTION__, p, (unsigned)offset); \
|
||||
WAIT_SEM (); \
|
||||
INCR_COUNT(bound_ptr_indir ## dsize ## _count); \
|
||||
if (tree) { \
|
||||
tree = splay (addr, tree); \
|
||||
addr -= tree->start; \
|
||||
@ -284,6 +333,7 @@ void FASTCALL __bound_local_new(void *p1)
|
||||
addr = p[0];
|
||||
if (addr == 0)
|
||||
break;
|
||||
INCR_COUNT(bound_local_new_count);
|
||||
if (addr == 1) {
|
||||
dprintf(stderr, "%s, %s() alloca/vla used\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
@ -315,6 +365,7 @@ void FASTCALL __bound_local_delete(void *p1)
|
||||
addr = p[0];
|
||||
if (addr == 0)
|
||||
break;
|
||||
INCR_COUNT(bound_local_delete_count);
|
||||
if (addr == 1) {
|
||||
while (alloca_list && alloca_list->fp == fp) {
|
||||
alloca_list_type *next = alloca_list->next;
|
||||
@ -350,6 +401,7 @@ void __bound_init(void)
|
||||
|
||||
print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL;
|
||||
print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL;
|
||||
print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;
|
||||
never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;
|
||||
|
||||
dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
|
||||
@ -444,7 +496,7 @@ void __attribute__((destructor)) __bound_exit(void)
|
||||
{
|
||||
int i;
|
||||
static const char * const alloc_type[] = {
|
||||
"", "malloc", "calloc", "realloc", "memalign"
|
||||
"", "malloc", "calloc", "realloc", "memalign", "strdup"
|
||||
};
|
||||
|
||||
dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
|
||||
@ -488,6 +540,39 @@ void __attribute__((destructor)) __bound_exit(void)
|
||||
}
|
||||
EXIT_SEM ();
|
||||
inited = 0;
|
||||
#ifdef BOUND_STATISTIC
|
||||
if (print_statistic) {
|
||||
fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count);
|
||||
fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count);
|
||||
fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count);
|
||||
fprintf (stderr, "bound_ptr_indir4_count %llu\n", bound_ptr_indir4_count);
|
||||
fprintf (stderr, "bound_ptr_indir8_count %llu\n", bound_ptr_indir8_count);
|
||||
fprintf (stderr, "bound_ptr_indir12_count %llu\n", bound_ptr_indir12_count);
|
||||
fprintf (stderr, "bound_ptr_indir16_count %llu\n", bound_ptr_indir16_count);
|
||||
fprintf (stderr, "bound_local_new_count %llu\n", bound_local_new_count);
|
||||
fprintf (stderr, "bound_local_delete_count %llu\n", bound_local_delete_count);
|
||||
fprintf (stderr, "bound_malloc_count %llu\n", bound_malloc_count);
|
||||
fprintf (stderr, "bound_calloc_count %llu\n", bound_calloc_count);
|
||||
fprintf (stderr, "bound_realloc_count %llu\n", bound_realloc_count);
|
||||
fprintf (stderr, "bound_free_count %llu\n", bound_free_count);
|
||||
fprintf (stderr, "bound_memalign_count %llu\n", bound_memalign_count);
|
||||
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_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);
|
||||
fprintf (stderr, "bound_memset_count %llu\n", bound_memset_count);
|
||||
fprintf (stderr, "bound_strlen_count %llu\n", bound_strlen_count);
|
||||
fprintf (stderr, "bound_strcpy_count %llu\n", bound_strcpy_count);
|
||||
fprintf (stderr, "bound_strncpy_count %llu\n", bound_strncpy_count);
|
||||
fprintf (stderr, "bound_strcmp_count %llu\n", bound_strcmp_count);
|
||||
fprintf (stderr, "bound_strncmp_count %llu\n", bound_strncmp_count);
|
||||
fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count);
|
||||
fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count);
|
||||
fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,6 +601,7 @@ void *__bound_malloc(size_t size, const void *caller)
|
||||
separated by at least one byte. With the glibc malloc, it may
|
||||
be in fact not necessary */
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_malloc_count);
|
||||
#if MALLOC_REDIR
|
||||
ptr = malloc_redir (size);
|
||||
#else
|
||||
@ -544,6 +630,7 @@ void *__bound_memalign(size_t size, size_t align, const void *caller)
|
||||
void *ptr;
|
||||
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_memalign_count);
|
||||
|
||||
#ifndef HAVE_MEMALIGN
|
||||
if (align > 4) {
|
||||
@ -599,6 +686,7 @@ void __bound_free(void *ptr, const void *caller)
|
||||
dprintf(stderr, "%s, %s (%p)\n", __FILE__, __FUNCTION__, ptr);
|
||||
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_free_count);
|
||||
tree = splay (addr, tree);
|
||||
if (tree->start == addr) {
|
||||
if (tree->is_invalid) {
|
||||
@ -645,6 +733,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
|
||||
ptr = realloc (ptr, size);
|
||||
#endif
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_realloc_count);
|
||||
if (ptr) {
|
||||
tree = splay_insert ((size_t) ptr, size, tree);
|
||||
if (tree->start == (size_t) ptr) {
|
||||
@ -701,6 +790,7 @@ void *__bound_calloc(size_t nmemb, size_t size)
|
||||
if (ptr) {
|
||||
memset (ptr, 0, size);
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_calloc_count);
|
||||
tree = splay_insert ((size_t) ptr, size, tree);
|
||||
if (tree->start == (size_t) ptr) {
|
||||
tree->type = TCC_TYPE_CALLOC;
|
||||
@ -721,6 +811,7 @@ void *__bound_mmap (void *start, size_t size, int prot,
|
||||
result = mmap (start, size, prot, flags, fd, offset);
|
||||
if (result) {
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_mmap_count);
|
||||
tree = splay_insert((size_t)result, size, tree);
|
||||
POST_SEM ();
|
||||
}
|
||||
@ -734,6 +825,7 @@ int __bound_munmap (void *start, size_t size)
|
||||
dprintf(stderr, "%s, %s (%p, 0x%x)\n",
|
||||
__FILE__, __FUNCTION__, start, (unsigned)size);
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_munmap_count);
|
||||
tree = splay_delete ((size_t) start, tree);
|
||||
POST_SEM ();
|
||||
result = munmap (start, size);
|
||||
@ -751,6 +843,7 @@ void __bound_new_region(void *p, size_t size)
|
||||
dprintf(stderr, "%s, %s (%p, 0x%x)\n",
|
||||
__FILE__, __FUNCTION__, p, (unsigned)size);
|
||||
WAIT_SEM ();
|
||||
INCR_COUNT(bound_alloca_count);
|
||||
GET_CALLER_FP (fp);
|
||||
last = NULL;
|
||||
cur = alloca_list;
|
||||
@ -813,6 +906,7 @@ void *__bound_memcpy(void *dst, const void *src, size_t size)
|
||||
{
|
||||
void* p;
|
||||
|
||||
INCR_COUNT(bound_mempcy_count);
|
||||
__bound_check(dst, size);
|
||||
__bound_check(src, size);
|
||||
/* check also region overlap */
|
||||
@ -824,8 +918,17 @@ void *__bound_memcpy(void *dst, const void *src, size_t size)
|
||||
return p;
|
||||
}
|
||||
|
||||
int __bound_memcmp(const void *s1, const void *s2, size_t size)
|
||||
{
|
||||
INCR_COUNT(bound_memcmp_count);
|
||||
__bound_check(s1, size);
|
||||
__bound_check(s2, size);
|
||||
return memcmp(s1, s2, size);
|
||||
}
|
||||
|
||||
void *__bound_memmove(void *dst, const void *src, size_t size)
|
||||
{
|
||||
INCR_COUNT(bound_memmove_count);
|
||||
__bound_check(dst, size);
|
||||
__bound_check(src, size);
|
||||
return memmove(dst, src, size);
|
||||
@ -833,25 +936,22 @@ void *__bound_memmove(void *dst, const void *src, size_t size)
|
||||
|
||||
void *__bound_memset(void *dst, int c, size_t size)
|
||||
{
|
||||
INCR_COUNT(bound_memset_count);
|
||||
__bound_check(dst, size);
|
||||
return memset(dst, c, size);
|
||||
}
|
||||
|
||||
/* XXX: could be optimized */
|
||||
int __bound_strlen(const char *s)
|
||||
{
|
||||
const char *p;
|
||||
const char *p = s;
|
||||
size_t len;
|
||||
|
||||
len = 0;
|
||||
for(;;) {
|
||||
p = __bound_ptr_indir1((char *)s, len);
|
||||
if (p == INVALID_POINTER)
|
||||
bound_error("bad pointer in strlen()");
|
||||
if (*p == '\0')
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
INCR_COUNT(bound_strlen_count);
|
||||
while (*p++);
|
||||
len = (p - s) - 1;
|
||||
p = __bound_ptr_indir1((char *)s, len);
|
||||
if (p == INVALID_POINTER)
|
||||
bound_error("bad pointer in strlen()");
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -860,11 +960,101 @@ char *__bound_strcpy(char *dst, const char *src)
|
||||
size_t len;
|
||||
void *p;
|
||||
|
||||
INCR_COUNT(bound_strcpy_count);
|
||||
len = __bound_strlen(src);
|
||||
p = __bound_memcpy(dst, src, len + 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *__bound_strncpy(char *dst, const char *src, size_t n)
|
||||
{
|
||||
size_t len;
|
||||
void *p;
|
||||
|
||||
INCR_COUNT(bound_strncpy_count);
|
||||
__bound_check(dst, n);
|
||||
__bound_check(src, n);
|
||||
return strncpy (dst, src, n);
|
||||
}
|
||||
|
||||
int __bound_strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
const unsigned char *u1 = (const unsigned char *) s1;
|
||||
const unsigned char *u2 = (const unsigned char *) s2;
|
||||
|
||||
INCR_COUNT(bound_strcmp_count);
|
||||
while (*u1 && *u1 == *u2) {
|
||||
u1++;
|
||||
u2++;
|
||||
}
|
||||
__bound_check(s1, ((const char *)u1 - s1) + 1);
|
||||
__bound_check(s2, ((const char *)u2 - s2) + 1);
|
||||
return (*u1 - *u2);
|
||||
}
|
||||
|
||||
int __bound_strncmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
INCR_COUNT(bound_strncmp_count);
|
||||
__bound_check(s1, n);
|
||||
__bound_check(s2, n);
|
||||
return strncmp(s1, s2, n);
|
||||
}
|
||||
|
||||
char *__bound_strcat(char *dest, const char *src)
|
||||
{
|
||||
char *r = dest;
|
||||
const char *s = src;
|
||||
|
||||
INCR_COUNT(bound_strcat_count);
|
||||
while (*dest++);
|
||||
dest--;
|
||||
while ((*dest++ = *src++) != 0);
|
||||
__bound_check(r, dest - r);
|
||||
__bound_check(s, src - s);
|
||||
return r;
|
||||
}
|
||||
|
||||
char *__bound_strchr(const char *string, int ch)
|
||||
{
|
||||
const unsigned char *s = (const unsigned char *) string;
|
||||
unsigned char c = ch;
|
||||
|
||||
INCR_COUNT(bound_strchr_count);
|
||||
while (*s) {
|
||||
if (*s == c) {
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
__bound_check(string, ((const char *)s - string) + 1);
|
||||
return *s == c ? (char *) s : NULL;
|
||||
}
|
||||
|
||||
char *__bound_strdup(const char *s)
|
||||
{
|
||||
const char *p = s;
|
||||
char *new;
|
||||
|
||||
INCR_COUNT(bound_strdup_count);
|
||||
while (*p++);
|
||||
__bound_check(s, p - s);
|
||||
#if MALLOC_REDIR
|
||||
new = malloc_redir (p - s);
|
||||
#else
|
||||
new = malloc (p - s);
|
||||
#endif
|
||||
if (new) {
|
||||
WAIT_SEM ();
|
||||
tree = splay_insert((size_t)new, p - s, tree);
|
||||
if (tree->start == (size_t) new) {
|
||||
tree->type = TCC_TYPE_STRDUP;
|
||||
}
|
||||
memcpy (new, s, p - s);
|
||||
POST_SEM ();
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
An implementation of top-down splaying with sizes
|
||||
D. Sleator <sleator@cs.cmu.edu>, January 1994.
|
||||
|
@ -356,12 +356,14 @@ memory allocations and array/pointer bounds. @option{-g} is implied. Note
|
||||
that the generated code is slower and bigger in this case.
|
||||
The bound checking code is not included in shared libaries. The main executable should always be compiled with the @option{-b}.
|
||||
|
||||
There are three environment variables that can be used:
|
||||
There are four environment variables that can be used:
|
||||
@table @option
|
||||
@item TCC_BOUNDS_PRINT_CALLS
|
||||
Print bound checking calls. Can be used for debugging.
|
||||
@item TCC_BOUNDS_PRINT_HEAP
|
||||
Print heap objects that are not freed at exit of program.
|
||||
@item TCC_BOUNDS_PRINT_STATISTIC
|
||||
Print statistic information at exit of program.
|
||||
@item TCC_BOUNDS_NEVER_FATAL
|
||||
Try to continue in case of a bound checking error.
|
||||
@end table
|
||||
@ -915,7 +917,7 @@ Here are some examples of caught errors:
|
||||
int *tab;
|
||||
tab = malloc(20 * sizeof(int));
|
||||
for(i=0;i<21;i++) @{
|
||||
sum += tab4[i];
|
||||
sum += tab[i];
|
||||
@}
|
||||
free(tab);
|
||||
@}
|
||||
@ -928,7 +930,7 @@ Here are some examples of caught errors:
|
||||
tab = malloc(20 * sizeof(int));
|
||||
free(tab);
|
||||
for(i=0;i<20;i++) @{
|
||||
sum += tab4[i];
|
||||
sum += tab[i];
|
||||
@}
|
||||
@}
|
||||
@end example
|
||||
|
7
tccgen.c
7
tccgen.c
@ -432,8 +432,15 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||
case TOK_memcpy:
|
||||
case TOK_memmove:
|
||||
case TOK_memset:
|
||||
case TOK_memcmp:
|
||||
case TOK_strlen:
|
||||
case TOK_strcpy:
|
||||
case TOK_strncpy:
|
||||
case TOK_strcmp:
|
||||
case TOK_strncmp:
|
||||
case TOK_strcat:
|
||||
case TOK_strchr:
|
||||
case TOK_strdup:
|
||||
case TOK_alloca:
|
||||
case TOK_mmap:
|
||||
case TOK_munmap:
|
||||
|
7
tcctok.h
7
tcctok.h
@ -314,8 +314,15 @@
|
||||
# endif
|
||||
DEF(TOK_mmap, "mmap")
|
||||
DEF(TOK_munmap, "munmap")
|
||||
DEF(TOK_memcmp, "memcmp")
|
||||
DEF(TOK_strlen, "strlen")
|
||||
DEF(TOK_strcpy, "strcpy")
|
||||
DEF(TOK_strncpy, "strncpy")
|
||||
DEF(TOK_strcmp, "strcmp")
|
||||
DEF(TOK_strncmp, "strncmp")
|
||||
DEF(TOK_strcat, "strcat")
|
||||
DEF(TOK_strchr, "strchr")
|
||||
DEF(TOK_strdup, "strdup")
|
||||
#endif
|
||||
|
||||
/* Tiny Assembler */
|
||||
|
@ -23,13 +23,12 @@ TESTS = \
|
||||
tests2-dir \
|
||||
pp-dir
|
||||
|
||||
BTESTS = test1b test3b btest
|
||||
BTESTS = test1b test3b btest test4
|
||||
|
||||
# test4 -- problem with -static
|
||||
# test4_static -- Not all relocation types are implemented yet.
|
||||
# asmtest / asmtest2 -- minor differences with gcc
|
||||
# btest -- works on i386 (including win32)
|
||||
|
||||
# bounds-checking is supported only on i386
|
||||
# bounds-checking is supported on i386 and x86_64 on linux and windows
|
||||
ifeq ($(ARCH),i386)
|
||||
TESTS += $(BTESTS)
|
||||
endif
|
||||
@ -116,7 +115,7 @@ test3 test3b: tcctest.c test.ref
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3
|
||||
@diff -u test.ref test.out3 && echo "Auto Test3 OK"
|
||||
|
||||
test%b : TCCFLAGS += -b
|
||||
test%b : TCCFLAGS += -b -ba
|
||||
|
||||
# binary output test
|
||||
test4: tcctest.c test.ref
|
||||
@ -131,10 +130,12 @@ test4: tcctest.c test.ref
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
||||
# dynamic output + bound check
|
||||
$(TCC) -b -o tcctest4 $<
|
||||
$(TCC) -b -ba -o tcctest4 $<
|
||||
./tcctest4 > test4.out
|
||||
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
|
||||
# static output
|
||||
|
||||
test4_static: tcctest.c test.ref
|
||||
# static output.
|
||||
$(TCC) -static -o tcctest2 $<
|
||||
./tcctest2 > test2.out
|
||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
||||
@ -162,8 +163,7 @@ memtest:
|
||||
|
||||
|
||||
# memory and bound check auto test
|
||||
# 3 is profiling test
|
||||
BOUNDS_OK = 1 4 8 10 14 16
|
||||
BOUNDS_OK = 1 3 4 8 10 14 16
|
||||
BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17
|
||||
|
||||
btest: boundtest.c
|
||||
@ -171,7 +171,7 @@ btest: boundtest.c
|
||||
@ulimit -c 0; \
|
||||
for i in $(BOUNDS_OK); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run $< $$i ; then \
|
||||
if $(TCC) -b -ba -run $< $$i ; then \
|
||||
echo succeeded as expected; \
|
||||
else\
|
||||
echo Failed positive test $$i ; exit 1 ; \
|
||||
@ -179,7 +179,7 @@ btest: boundtest.c
|
||||
done ;\
|
||||
for i in $(BOUNDS_FAIL); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run $< $$i ; then \
|
||||
if $(TCC) -b -ba -run $< $$i ; then \
|
||||
echo Failed negative test $$i ; exit 1 ;\
|
||||
else\
|
||||
echo failed as expected; \
|
||||
|
Loading…
Reference in New Issue
Block a user