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;
36    }
37 
38    p = hp + RZ;
39    hp += size2;
40 
41    VALGRIND_MALLOCLIKE_BLOCK( p, size, RZ, /*is_zeroed*/1 );
42    return (void*)p;
43 }
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 __attribute__((unused)) = 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.
88 
89    // leak from make_leak()
90 }
91