- 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 | 80 | void __bound_new_region(void *p, size_t size); |
| 81 | 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 | 87 | #define FASTCALL __attribute__((regparm(3))) |
| 84 | 88 | |
| 85 | 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 | 165 | size_t addr = (size_t)p; |
| 162 | 166 | BoundEntry *e; |
| 163 | 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 | 169 | #endif |
| 166 | 170 | |
| 167 | 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 | 178 | addr = (size_t)p - e->start; |
| 175 | 179 | } |
| 176 | 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 | 185 | return INVALID_POINTER; /* return an invalid pointer */ |
| 186 | + } | |
| 179 | 187 | return p + offset; |
| 180 | 188 | } |
| 181 | 189 | |
| 182 | 190 | /* return '(p + offset)' for pointer indirection (the resulting must |
| 183 | 191 | be strictly inside the region */ |
| 184 | 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 | 195 | size_t addr = (size_t)p; \ |
| 188 | 196 | BoundEntry *e; \ |
| @@ -197,7 +205,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset) \ · 8 unmodified lines | ||
| 197 | 205 | addr = (size_t)p - e->start; \ |
| 198 | 206 | } \ |
| 199 | 207 | addr += offset + dsize; \ |
| 200 | − if (addr > e->size) \ | |
| 208 | + if (addr >= e->size) \ | |
| 201 | 209 | return INVALID_POINTER; /* return an invalid pointer */ \ |
| 202 | 210 | return p + offset; \ |
| 203 | 211 | } |
| @@ -219,6 +227,9 @@ BOUND_PTR_INDIR(16) · 15 unmodified lines | ||
| 219 | 227 | void FASTCALL __bound_local_new(void *p1) |
| 220 | 228 | { |
| 221 | 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 | 233 | GET_CALLER_FP(fp); |
| 223 | 234 | for(;;) { |
| 224 | 235 | addr = p[0]; |
| @@ -229,6 +240,9 @@ void FASTCALL __bound_local_new(void *p1) · 4 unmodified lines | ||
| 229 | 240 | p += 2; |
| 230 | 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 | 248 | /* called when leaving a function to delete all the local regions */ |
| @@ -348,9 +362,11 @@ void __bound_init(void) · 113 unmodified lines | ||
| 348 | 362 | int i; |
| 349 | 363 | BoundEntry *page; |
| 350 | 364 | size_t start, size; |
| 365 | + size_t *p; | |
| 351 | 366 | |
| 352 | − /* int *p; */ | |
| 353 | − __PTRDIFF_TYPE__ *p; /* 32 or 64 bit integer */ | |
| 367 | +#ifdef BOUND_DEBUG | |
| 368 | + fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); | |
| 369 | +#endif | |
| 354 | 370 | |
| 355 | 371 | /* save malloc hooks and install bound check hooks */ |
| 356 | 372 | install_malloc_hooks(); |
| @@ -413,17 +429,24 @@ void __bound_init(void) · 56 unmodified lines | ||
| 413 | 429 | #endif |
| 414 | 430 | |
| 415 | 431 | /* add all static bound check values */ |
| 416 | − p = (__PTRDIFF_TYPE__ *)&__bounds_start; | |
| 432 | + p = (size_t *)&__bounds_start; | |
| 417 | 433 | while (p[0] != 0) { |
| 418 | 434 | __bound_new_region((void *)p[0], p[1]); |
| 419 | 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 | 442 | void __bound_main_arg(void **p) |
| 424 | 443 | { |
| 425 | 444 | void *start = p; |
| 426 | 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 | 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 | 482 | BoundEntry *page, *e, *e2; |
| 460 | 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 | 490 | start = (size_t)p; |
| 463 | 491 | end = start + size; |
| 464 | 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 | 498 | ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
| 471 | 499 | t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & |
| 472 | 500 | ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); |
| 473 | −#ifdef BOUND_DEBUG | |
| 474 | − printf("new %lx %lx %x %x %x %x\n", | |
| 475 | − start, end, t1_start, t1_end, t2_start, t2_end); | |
| 476 | −#endif | |
| 501 | + | |
| 477 | 502 | |
| 478 | 503 | e = (BoundEntry *)((char *)page + t2_start); |
| 479 | 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 | 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 | 548 | /* delete a region */ |
| @@ -567,6 +595,10 @@ int __bound_delete_region(void *p) · 46 unmodified lines | ||
| 567 | 595 | BoundEntry *page, *e, *e2; |
| 568 | 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 | 602 | start = (size_t)p; |
| 571 | 603 | t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); |
| 572 | 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 | 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 | 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 | 756 | if (!ptr) |
| 720 | 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 | 763 | __bound_new_region(ptr, size); |
| 722 | 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 | 790 | if (!ptr) |
| 749 | 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 | 797 | __bound_new_region(ptr, size); |
| 751 | 798 | return ptr; |
| 752 | 799 | } |
| @@ -861,7 +908,7 @@ void *__bound_memset(void *dst, int c, size_t size) · 108 unmodified lines | ||
| 861 | 908 | int __bound_strlen(const char *s) |
| 862 | 909 | { |
| 863 | 910 | const char *p; |
| 864 | − int len; | |
| 911 | + size_t len; | |
| 865 | 912 | |
| 866 | 913 | len = 0; |
| 867 | 914 | for(;;) { |
| @@ -881,4 +928,3 @@ char *__bound_strcpy(char *dst, const char *src) · 13 unmodified lines | ||
| 881 | 928 | len = __bound_strlen(src); |
| 882 | 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 | 1577 | return; |
| 1578 | 1578 | |
| 1579 | 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 | 1581 | *ptr = 0; |
| 1582 | 1582 | add_elf_sym(symtab_section, 0, 0, |
| 1583 | 1583 | ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, |