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
14void* 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
25static 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
45static 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
58void make_leak(void)
59{
60   int* array2 __attribute__((unused)) = custom_alloc(sizeof(int) * 10);
61   array2 = 0;          // leak
62   return;
63}
64
65int 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