- 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
Unified · Split
| @@ -80,6 +80,10 @@ void __bound_init(void); · 79 unmodified lines | |||
| 80 | void __bound_new_region(void *p, size_t size); | 80 | void __bound_new_region(void *p, size_t size); |
| 81 | int __bound_delete_region(void *p); | 81 | int __bound_delete_region(void *p); |
| 82 | 82 | ||
| 83 | #ifdef __attribute__ | ||
| 84 | /* __attribute__ is redifened in system headers */ | ||
| 85 | #undef __attribute__ | ||
| 86 | #endif | ||
| 83 | #define FASTCALL __attribute__((regparm(3))) | 87 | #define FASTCALL __attribute__((regparm(3))) |
| 84 | 88 | ||
| 85 | void *__bound_malloc(size_t size, const void *caller); | 89 | void *__bound_malloc(size_t size, const void *caller); |
| @@ -161,7 +165,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) · 75 unmodified lines | |||
| 161 | size_t addr = (size_t)p; | 165 | size_t addr = (size_t)p; |
| 162 | BoundEntry *e; | 166 | BoundEntry *e; |
| 163 | #if defined(BOUND_DEBUG) | 167 | #if defined(BOUND_DEBUG) |
| 164 | printf("add: 0x%x %d\n", (int)p, offset); | 168 | printf("%s %s: 0x%x %d\n", __FILE__, __FUNCTION__, (int)p, offset); |
| 165 | #endif | 169 | #endif |
| 166 | 170 | ||
| 167 | e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; | 171 | e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; |
| @@ -174,15 +178,19 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) · 6 unmodified lines | |||
| 174 | addr = (size_t)p - e->start; | 178 | addr = (size_t)p - e->start; |
| 175 | } | 179 | } |
| 176 | addr += offset; | 180 | addr += offset; |
| 177 | if (addr > e->size) | 181 | if (addr >= e->size) { |
| 182 | #if defined(BOUND_DEBUG) | ||
| 183 | printf("%s %s: 0x%zx is outside of the region\n", __FILE__, __FUNCTION__, p + offset); | ||
| 184 | #endif | ||
| 178 | return INVALID_POINTER; /* return an invalid pointer */ | 185 | return INVALID_POINTER; /* return an invalid pointer */ |
| 186 | } | ||
| 179 | return p + offset; | 187 | return p + offset; |
| 180 | } | 188 | } |
| 181 | 189 | ||
| 182 | /* return '(p + offset)' for pointer indirection (the resulting must | 190 | /* return '(p + offset)' for pointer indirection (the resulting must |
| 183 | be strictly inside the region */ | 191 | be strictly inside the region */ |
| 184 | #define BOUND_PTR_INDIR(dsize) \ | 192 | #define BOUND_PTR_INDIR(dsize) \ |
| 185 | void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \ | 193 | void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ |
| 186 | { \ | 194 | { \ |
| 187 | size_t addr = (size_t)p; \ | 195 | size_t addr = (size_t)p; \ |
| 188 | BoundEntry *e; \ | 196 | BoundEntry *e; \ |
| @@ -197,7 +205,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \ · 8 unmodified lines | |||
| 197 | addr = (size_t)p - e->start; \ | 205 | addr = (size_t)p - e->start; \ |
| 198 | } \ | 206 | } \ |
| 199 | addr += offset + dsize; \ | 207 | addr += offset + dsize; \ |
| 200 | if (addr > e->size) \ | 208 | if (addr >= e->size) \ |
| 201 | return INVALID_POINTER; /* return an invalid pointer */ \ | 209 | return INVALID_POINTER; /* return an invalid pointer */ \ |
| 202 | return p + offset; \ | 210 | return p + offset; \ |
| 203 | } | 211 | } |
| @@ -219,6 +227,9 @@ BOUND_PTR_INDIR(16) · 15 unmodified lines | |||
| 219 | void FASTCALL __bound_local_new(void *p1) | 227 | void FASTCALL __bound_local_new(void *p1) |
| 220 | { | 228 | { |
| 221 | size_t addr, size, fp, *p = p1; | 229 | size_t addr, size, fp, *p = p1; |
| 230 | #ifdef BOUND_DEBUG | ||
| 231 | fprintf(stderr, "%s, %s start p1=%zx *p1=%zx\n", __FILE__, __FUNCTION__, p, *p); | ||
| 232 | #endif | ||
| 222 | GET_CALLER_FP(fp); | 233 | GET_CALLER_FP(fp); |
| 223 | for(;;) { | 234 | for(;;) { |
| 224 | addr = p[0]; | 235 | addr = p[0]; |
| @@ -229,6 +240,9 @@ void FASTCALL __bound_local_new(void *p1) · 4 unmodified lines | |||
| 229 | p += 2; | 240 | p += 2; |
| 230 | __bound_new_region((void *)addr, size); | 241 | __bound_new_region((void *)addr, size); |
| 231 | } | 242 | } |
| 243 | #ifdef BOUND_DEBUG | ||
| 244 | fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); | ||
| 245 | #endif | ||
| 232 | } | 246 | } |
| 233 | 247 | ||
| 234 | /* called when leaving a function to delete all the local regions */ | 248 | /* called when leaving a function to delete all the local regions */ |
| @@ -348,9 +362,11 @@ void __bound_init(void) · 113 unmodified lines | |||
| 348 | int i; | 362 | int i; |
| 349 | BoundEntry *page; | 363 | BoundEntry *page; |
| 350 | size_t start, size; | 364 | size_t start, size; |
| 365 | size_t *p; | ||
| 351 | 366 | ||
| 352 | /* int *p; */ | 367 | #ifdef BOUND_DEBUG |
| 353 | __PTRDIFF_TYPE__ *p; /* 32 or 64 bit integer */ | 368 | fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); |
| 369 | #endif | ||
| 354 | 370 | ||
| 355 | /* save malloc hooks and install bound check hooks */ | 371 | /* save malloc hooks and install bound check hooks */ |
| 356 | install_malloc_hooks(); | 372 | install_malloc_hooks(); |
| @@ -413,17 +429,24 @@ void __bound_init(void) · 56 unmodified lines | |||
| 413 | #endif | 429 | #endif |
| 414 | 430 | ||
| 415 | /* add all static bound check values */ | 431 | /* add all static bound check values */ |
| 416 | p = (__PTRDIFF_TYPE__ *)&__bounds_start; | 432 | p = (size_t *)&__bounds_start; |
| 417 | while (p[0] != 0) { | 433 | while (p[0] != 0) { |
| 418 | __bound_new_region((void *)p[0], p[1]); | 434 | __bound_new_region((void *)p[0], p[1]); |
| 419 | p += 2; | 435 | p += 2; |
| 420 | } | 436 | } |
| 437 | #ifdef BOUND_DEBUG | ||
| 438 | fprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); | ||
| 439 | #endif | ||
| 421 | } | 440 | } |
| 422 | 441 | ||
| 423 | void __bound_main_arg(void **p) | 442 | void __bound_main_arg(void **p) |
| 424 | { | 443 | { |
| 425 | void *start = p; | 444 | void *start = p; |
| 426 | while (*p++); | 445 | while (*p++); |
| 446 | #ifdef BOUND_DEBUG | ||
| 447 | fprintf(stderr, "%s, %s calling __bound_new_region(%p, %llx)\n", | ||
| 448 | __FILE__, __FUNCTION__, (void *) p - start); | ||
| 449 | #endif | ||
| 427 | __bound_new_region(start, (void *) p - start); | 450 | __bound_new_region(start, (void *) p - start); |
| 428 | } | 451 | } |
| 429 | 452 | ||
| @@ -459,6 +482,11 @@ void __bound_new_region(void *p, size_t size) · 29 unmodified lines | |||
| 459 | BoundEntry *page, *e, *e2; | 482 | BoundEntry *page, *e, *e2; |
| 460 | size_t t1_start, t1_end, i, t2_start, t2_end; | 483 | size_t t1_start, t1_end, i, t2_start, t2_end; |
| 461 | 484 | ||
| 485 | #ifdef BOUND_DEBUG | ||
| 486 | fprintf(stderr, "%s, %s(%p, %zx) start\n", | ||
| 487 | __FILE__, __FUNCTION__, p, size); | ||
| 488 | #endif | ||
| 489 | |||
| 462 | start = (size_t)p; | 490 | start = (size_t)p; |
| 463 | end = start + size; | 491 | end = start + size; |
| 464 | t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); | 492 | t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); |
| @@ -470,10 +498,7 @@ void __bound_new_region(void *p, size_t size) · 5 unmodified lines | |||
| 470 | ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); | 498 | ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
| 471 | t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & | 499 | t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
| 472 | ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); | 500 | ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
| 473 | #ifdef BOUND_DEBUG | 501 | |
| 474 | printf("new %lx %lx %x %x %x %x\n", | ||
| 475 | start, end, t1_start, t1_end, t2_start, t2_end); | ||
| 476 | #endif | ||
| 477 | 502 | ||
| 478 | e = (BoundEntry *)((char *)page + t2_start); | 503 | e = (BoundEntry *)((char *)page + t2_start); |
| 479 | add_region(e, start, size); | 504 | add_region(e, start, size); |
| @@ -515,6 +540,9 @@ void __bound_new_region(void *p, size_t size) · 35 unmodified lines | |||
| 515 | } | 540 | } |
| 516 | add_region(e, start, size); | 541 | add_region(e, start, size); |
| 517 | } | 542 | } |
| 543 | #ifdef BOUND_DEBUG | ||
| 544 | fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); | ||
| 545 | #endif | ||
| 518 | } | 546 | } |
| 519 | 547 | ||
| 520 | /* delete a region */ | 548 | /* delete a region */ |
| @@ -567,6 +595,10 @@ int __bound_delete_region(void *p) · 46 unmodified lines | |||
| 567 | BoundEntry *page, *e, *e2; | 595 | BoundEntry *page, *e, *e2; |
| 568 | size_t t1_start, t1_end, t2_start, t2_end, i; | 596 | size_t t1_start, t1_end, t2_start, t2_end, i; |
| 569 | 597 | ||
| 598 | #ifdef BOUND_DEBUG | ||
| 599 | fprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); | ||
| 600 | #endif | ||
| 601 | |||
| 570 | start = (size_t)p; | 602 | start = (size_t)p; |
| 571 | t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); | 603 | t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); |
| 572 | t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & | 604 | t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
| @@ -633,6 +665,11 @@ int __bound_delete_region(void *p) · 60 unmodified lines | |||
| 633 | } | 665 | } |
| 634 | delete_region(e, p, empty_size); | 666 | delete_region(e, p, empty_size); |
| 635 | } | 667 | } |
| 668 | |||
| 669 | #ifdef BOUND_DEBUG | ||
| 670 | fprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); | ||
| 671 | #endif | ||
| 672 | |||
| 636 | return 0; | 673 | return 0; |
| 637 | } | 674 | } |
| 638 | 675 | ||
| @@ -718,6 +755,11 @@ void *__bound_malloc(size_t size, const void *caller) · 79 unmodified lines | |||
| 718 | 755 | ||
| 719 | if (!ptr) | 756 | if (!ptr) |
| 720 | return NULL; | 757 | return NULL; |
| 758 | |||
| 759 | #ifdef BOUND_DEBUG | ||
| 760 | fprintf(stderr, "%s, %s calling __bound_new_region(%p, %llx)\n", | ||
| 761 | __FILE__, __FUNCTION__, ptr, size); | ||
| 762 | #endif | ||
| 721 | __bound_new_region(ptr, size); | 763 | __bound_new_region(ptr, size); |
| 722 | return ptr; | 764 | return ptr; |
| 723 | } | 765 | } |
| @@ -747,6 +789,11 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 23 unmodified lines | |||
| 747 | 789 | ||
| 748 | if (!ptr) | 790 | if (!ptr) |
| 749 | return NULL; | 791 | return NULL; |
| 792 | |||
| 793 | #ifdef BOUND_DEBUG | ||
| 794 | fprintf(stderr, "%s, %s calling __bound_new_region(%p, %llx)\n", | ||
| 795 | __FILE__, __FUNCTION__, ptr, size); | ||
| 796 | #endif | ||
| 750 | __bound_new_region(ptr, size); | 797 | __bound_new_region(ptr, size); |
| 751 | return ptr; | 798 | return ptr; |
| 752 | } | 799 | } |
| @@ -861,7 +908,7 @@ void *__bound_memset(void *dst, int c, size_t size) · 108 unmodified lines | |||
| 861 | int __bound_strlen(const char *s) | 908 | int __bound_strlen(const char *s) |
| 862 | { | 909 | { |
| 863 | const char *p; | 910 | const char *p; |
| 864 | int len; | 911 | size_t len; |
| 865 | 912 | ||
| 866 | len = 0; | 913 | len = 0; |
| 867 | for(;;) { | 914 | for(;;) { |
| @@ -881,4 +928,3 @@ char *__bound_strcpy(char *dst, const char *src) · 13 unmodified lines | |||
| 881 | len = __bound_strlen(src); | 928 | len = __bound_strlen(src); |
| 882 | return __bound_memcpy(dst, src, len + 1); | 929 | return __bound_memcpy(dst, src, len + 1); |
| 883 | } | 930 | } |
| 884 | |||
| @@ -1577,7 +1577,7 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) · 1576 unmodified lines | |||
| 1577 | return; | 1577 | return; |
| 1578 | 1578 | ||
| 1579 | /* XXX: add an object file to do that */ | 1579 | /* XXX: add an object file to do that */ |
| 1580 | ptr = section_ptr_add(bounds_section, sizeof(unsigned long)); | 1580 | ptr = section_ptr_add(bounds_section, sizeof(*ptr)); |
| 1581 | *ptr = 0; | 1581 | *ptr = 0; |
| 1582 | add_elf_sym(symtab_section, 0, 0, | 1582 | add_elf_sym(symtab_section, 0, 0, |
| 1583 | ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, | 1583 | ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, |