njn | 32f8d8c | 2009-07-15 02:31:45 +0000 | [diff] [blame] | 1 | #include <unistd.h> |
| 2 | #include "tests/sys_mman.h" |
| 3 | #include <assert.h> |
| 4 | #include <stdlib.h> |
| 5 | |
| 6 | #include "../drd.h" |
| 7 | |
| 8 | #define SUPERBLOCK_SIZE 100000 |
| 9 | |
| 10 | //------------------------------------------------------------------------- |
| 11 | // Allocator |
| 12 | //------------------------------------------------------------------------- |
| 13 | |
| 14 | void* get_superblock(void) |
| 15 | { |
| 16 | void* p = mmap( 0, SUPERBLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, |
| 17 | MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 ); |
| 18 | |
| 19 | assert(p != ((void*)(-1))); |
| 20 | |
| 21 | return p; |
| 22 | } |
| 23 | |
| 24 | // has a redzone |
| 25 | static void* custom_alloc(int size) |
| 26 | { |
| 27 | #define RZ 8 |
| 28 | static void* hp = 0; // current heap pointer |
| 29 | static void* hp_lim = 0; // maximum usable byte in current block |
| 30 | int size2 = size + RZ*2; |
| 31 | void* p; |
| 32 | |
| 33 | if (hp + size2 > hp_lim) { |
| 34 | hp = get_superblock(); |
| 35 | hp_lim = hp + SUPERBLOCK_SIZE - 1; |
bart | 31b983d | 2010-02-21 14:52:59 +0000 | [diff] [blame] | 36 | } |
njn | 32f8d8c | 2009-07-15 02:31:45 +0000 | [diff] [blame] | 37 | |
| 38 | p = hp + RZ; |
| 39 | hp += size2; |
| 40 | |
| 41 | VALGRIND_MALLOCLIKE_BLOCK( p, size, RZ, /*is_zeroed*/1 ); |
| 42 | return (void*)p; |
bart | 31b983d | 2010-02-21 14:52:59 +0000 | [diff] [blame] | 43 | } |
njn | 32f8d8c | 2009-07-15 02:31:45 +0000 | [diff] [blame] | 44 | |
| 45 | static void custom_free(void* p) |
| 46 | { |
| 47 | // don't actually free any memory... but mark it as freed |
| 48 | VALGRIND_FREELIKE_BLOCK( p, RZ ); |
| 49 | } |
| 50 | #undef RZ |
| 51 | |
| 52 | |
| 53 | |
| 54 | //------------------------------------------------------------------------- |
| 55 | // Rest |
| 56 | //------------------------------------------------------------------------- |
| 57 | |
| 58 | void make_leak(void) |
| 59 | { |
| 60 | int* array2 = custom_alloc(sizeof(int) * 10); |
| 61 | array2 = 0; // leak |
| 62 | return; |
| 63 | } |
| 64 | |
| 65 | int main(void) |
| 66 | { |
| 67 | int* array; |
| 68 | int* array3; |
| 69 | |
| 70 | array = custom_alloc(sizeof(int) * 10); |
| 71 | array[8] = 8; |
| 72 | array[9] = 8; |
| 73 | array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock) |
| 74 | |
| 75 | custom_free(array); // ok |
| 76 | |
| 77 | custom_free(NULL); // invalid free (ok without MALLOCLIKE) |
| 78 | |
| 79 | array3 = malloc(sizeof(int) * 10); |
| 80 | custom_free(array3); // mismatched free (ok without MALLOCLIKE) |
| 81 | |
| 82 | make_leak(); |
| 83 | return array[0]; // use after free (ok without MALLOCLIKE) |
| 84 | // (nb: initialised because is_zeroed==1 above) |
| 85 | // unfortunately not identified as being in a free'd |
| 86 | // block because the freeing of the block and shadow |
| 87 | // chunk isn't postponed. |
bart | 31b983d | 2010-02-21 14:52:59 +0000 | [diff] [blame] | 88 | |
njn | 32f8d8c | 2009-07-15 02:31:45 +0000 | [diff] [blame] | 89 | // leak from make_leak() |
| 90 | } |