fix for the bcheck.o (bug #14958)

- care about __attribute__ redefinition in the system headers
    - an invalid pointer must be returned when (addr >= e->size),
      and not (addr > e->size)

    A test program:
    #include <stdio.h>
    #include <stdlib.h>
    int main ()
    {
	int v[10];
	fprintf(stderr, "&v[0]  = %p\n", &v[0]);
	fprintf(stderr, "&v[10] = %p\n", &v[10]);
	exit(1);
	return 0;
    }
    // tcc -b test.c

    The output before a patch:
    &v[0]  = 0xbf929d8c
    &v[10] = 0xbf929db4

    The output after a patch:
    &v[0]  = 0xbff6e33c
    &v[10] = 0xfffffffe
This commit is contained in:
seyko 2015-03-29 11:28:02 +03:00
parent f2cfc07554
commit d80593bc4d
2 changed files with 60 additions and 14 deletions

View File

@ -80,6 +80,10 @@ void __bound_init(void);
void __bound_new_region(void *p, size_t size); void __bound_new_region(void *p, size_t size);
int __bound_delete_region(void *p); int __bound_delete_region(void *p);
#ifdef __attribute__
/* __attribute__ is redifened in system headers */
#undef __attribute__
#endif
#define FASTCALL __attribute__((regparm(3))) #define FASTCALL __attribute__((regparm(3)))
void *__bound_malloc(size_t size, const void *caller); void *__bound_malloc(size_t size, const void *caller);
@ -161,7 +165,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset)
size_t addr = (size_t)p; size_t addr = (size_t)p;
BoundEntry *e; BoundEntry *e;
#if defined(BOUND_DEBUG) #if defined(BOUND_DEBUG)
printf("add: 0x%x %d\n", (int)p, offset); printf("%s %s: 0x%x %d\n", __FILE__, __FUNCTION__, (int)p, offset);
#endif #endif
e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)];
@ -174,15 +178,19 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset)
addr = (size_t)p - e->start; addr = (size_t)p - e->start;
} }
addr += offset; addr += offset;
if (addr > e->size) if (addr >= e->size) {
#if defined(BOUND_DEBUG)
printf("%s %s: 0x%zx is outside of the region\n", __FILE__, __FUNCTION__, p + offset);
#endif
return INVALID_POINTER; /* return an invalid pointer */ return INVALID_POINTER; /* return an invalid pointer */
}
return p + offset; return p + offset;
} }
/* return '(p + offset)' for pointer indirection (the resulting must /* return '(p + offset)' for pointer indirection (the resulting must
be strictly inside the region */ be strictly inside the region */
#define BOUND_PTR_INDIR(dsize) \ #define BOUND_PTR_INDIR(dsize) \
void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \
{ \ { \
size_t addr = (size_t)p; \ size_t addr = (size_t)p; \
BoundEntry *e; \ BoundEntry *e; \
@ -197,7 +205,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \
addr = (size_t)p - e->start; \ addr = (size_t)p - e->start; \
} \ } \
addr += offset + dsize; \ addr += offset + dsize; \
if (addr > e->size) \ if (addr >= e->size) \
return INVALID_POINTER; /* return an invalid pointer */ \ return INVALID_POINTER; /* return an invalid pointer */ \
return p + offset; \ return p + offset; \
} }
@ -219,6 +227,9 @@ BOUND_PTR_INDIR(16)
void FASTCALL __bound_local_new(void *p1) void FASTCALL __bound_local_new(void *p1)
{ {
size_t addr, size, fp, *p = p1; size_t addr, size, fp, *p = p1;
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s start p1=%zx *p1=%zx\n", __FILE__, __FUNCTION__, p, *p);
#endif
GET_CALLER_FP(fp); GET_CALLER_FP(fp);
for(;;) { for(;;) {
addr = p[0]; addr = p[0];
@ -229,6 +240,9 @@ void FASTCALL __bound_local_new(void *p1)
p += 2; p += 2;
__bound_new_region((void *)addr, size); __bound_new_region((void *)addr, size);
} }
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
#endif
} }
/* called when leaving a function to delete all the local regions */ /* called when leaving a function to delete all the local regions */
@ -348,9 +362,11 @@ void __bound_init(void)
int i; int i;
BoundEntry *page; BoundEntry *page;
size_t start, size; size_t start, size;
size_t *p;
/* int *p; */ #ifdef BOUND_DEBUG
__PTRDIFF_TYPE__ *p; /* 32 or 64 bit integer */ fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__);
#endif
/* save malloc hooks and install bound check hooks */ /* save malloc hooks and install bound check hooks */
install_malloc_hooks(); install_malloc_hooks();
@ -413,17 +429,24 @@ void __bound_init(void)
#endif #endif
/* add all static bound check values */ /* add all static bound check values */
p = (__PTRDIFF_TYPE__ *)&__bounds_start; p = (size_t *)&__bounds_start;
while (p[0] != 0) { while (p[0] != 0) {
__bound_new_region((void *)p[0], p[1]); __bound_new_region((void *)p[0], p[1]);
p += 2; p += 2;
} }
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__);
#endif
} }
void __bound_main_arg(void **p) void __bound_main_arg(void **p)
{ {
void *start = p; void *start = p;
while (*p++); while (*p++);
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s calling __bound_new_region(%p, %llx)\n",
__FILE__, __FUNCTION__, (void *) p - start);
#endif
__bound_new_region(start, (void *) p - start); __bound_new_region(start, (void *) p - start);
} }
@ -459,6 +482,11 @@ void __bound_new_region(void *p, size_t size)
BoundEntry *page, *e, *e2; BoundEntry *page, *e, *e2;
size_t t1_start, t1_end, i, t2_start, t2_end; size_t t1_start, t1_end, i, t2_start, t2_end;
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s(%p, %zx) start\n",
__FILE__, __FUNCTION__, p, size);
#endif
start = (size_t)p; start = (size_t)p;
end = start + size; end = start + size;
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
@ -470,10 +498,7 @@ void __bound_new_region(void *p, size_t size)
((BOUND_T2_SIZE - 1) << BOUND_E_BITS); ((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) &
((BOUND_T2_SIZE - 1) << BOUND_E_BITS); ((BOUND_T2_SIZE - 1) << BOUND_E_BITS);
#ifdef BOUND_DEBUG
printf("new %lx %lx %x %x %x %x\n",
start, end, t1_start, t1_end, t2_start, t2_end);
#endif
e = (BoundEntry *)((char *)page + t2_start); e = (BoundEntry *)((char *)page + t2_start);
add_region(e, start, size); add_region(e, start, size);
@ -515,6 +540,9 @@ void __bound_new_region(void *p, size_t size)
} }
add_region(e, start, size); add_region(e, start, size);
} }
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__);
#endif
} }
/* delete a region */ /* delete a region */
@ -567,6 +595,10 @@ int __bound_delete_region(void *p)
BoundEntry *page, *e, *e2; BoundEntry *page, *e, *e2;
size_t t1_start, t1_end, t2_start, t2_end, i; size_t t1_start, t1_end, t2_start, t2_end, i;
#ifdef BOUND_DEBUG
fprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__);
#endif
start = (size_t)p; start = (size_t)p;
t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS);
t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) &
@ -633,6 +665,11 @@ int __bound_delete_region(void *p)
} }
delete_region(e, p, empty_size); delete_region(e, p, empty_size);
} }
#ifdef BOUND_DEBUG
fprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__);
#endif
return 0; return 0;
} }
@ -718,6 +755,11 @@ void *__bound_malloc(size_t size, const void *caller)
if (!ptr) if (!ptr)
return NULL; return NULL;
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s calling __bound_new_region(%p, %llx)\n",
__FILE__, __FUNCTION__, ptr, size);
#endif
__bound_new_region(ptr, size); __bound_new_region(ptr, size);
return ptr; return ptr;
} }
@ -747,6 +789,11 @@ void *__bound_memalign(size_t size, size_t align, const void *caller)
if (!ptr) if (!ptr)
return NULL; return NULL;
#ifdef BOUND_DEBUG
fprintf(stderr, "%s, %s calling __bound_new_region(%p, %llx)\n",
__FILE__, __FUNCTION__, ptr, size);
#endif
__bound_new_region(ptr, size); __bound_new_region(ptr, size);
return ptr; return ptr;
} }
@ -861,7 +908,7 @@ void *__bound_memset(void *dst, int c, size_t size)
int __bound_strlen(const char *s) int __bound_strlen(const char *s)
{ {
const char *p; const char *p;
int len; size_t len;
len = 0; len = 0;
for(;;) { for(;;) {
@ -881,4 +928,3 @@ char *__bound_strcpy(char *dst, const char *src)
len = __bound_strlen(src); len = __bound_strlen(src);
return __bound_memcpy(dst, src, len + 1); return __bound_memcpy(dst, src, len + 1);
} }

View File

@ -1577,7 +1577,7 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1)
return; return;
/* XXX: add an object file to do that */ /* XXX: add an object file to do that */
ptr = section_ptr_add(bounds_section, sizeof(unsigned long)); ptr = section_ptr_add(bounds_section, sizeof(*ptr));
*ptr = 0; *ptr = 0;
add_elf_sym(symtab_section, 0, 0, add_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,