mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 10:05:29 +00:00
noaccess, writable, readable, other
Now they are:
noaccess, undefined, defined, partdefined
As a result, the following names:
make_writable, make_readable,
check_writable, check_readable, check_defined
have become:
make_mem_undefined, make_mem_defined,
check_mem_is_addressable, check_mem_is_defined, check_value_is_defined
(and likewise for the upper-case versions for client request macros).
The old MAKE_* and CHECK_* macros still work for backwards compatibility.
This is much better, because the old names were subtly misleading. For
example:
- "readable" really meant "readable and writable".
- "writable" really meant "writable and maybe readable, depending on how
the read value is used".
- "check_writable" really meant "check writable or readable"
The new names avoid these problems.
The recently-added macro which was called MAKE_DEFINED is now
MAKE_MEM_DEFINED_IF_ADDRESSABLE.
I also corrected the spelling of "addressable" in numerous places in
memcheck.h.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5802
97 lines
2.4 KiB
C
97 lines
2.4 KiB
C
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "../memcheck.h"
|
|
|
|
#define SUPERBLOCK_SIZE 100000
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Allocator
|
|
//-------------------------------------------------------------------------
|
|
|
|
void* get_superblock(void)
|
|
{
|
|
void* p = mmap( 0, SUPERBLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC,
|
|
MAP_PRIVATE|MAP_ANON, -1, 0 );
|
|
|
|
assert(p != ((void*)(-1)));
|
|
|
|
// Mark it no access; although it's addressible we don't want the
|
|
// program to be using it unless its handed out by custom_alloc()
|
|
|
|
// with redzones, better not to have it
|
|
VALGRIND_MAKE_MEM_NOACCESS(p, SUPERBLOCK_SIZE);
|
|
|
|
return p;
|
|
}
|
|
|
|
// has a redzone
|
|
static void* custom_alloc(int size)
|
|
{
|
|
#define RZ 8
|
|
static void* hp = 0; // current heap pointer
|
|
static void* hp_lim = 0; // maximum usable byte in current block
|
|
int size2 = size + RZ*2;
|
|
void* p;
|
|
|
|
if (hp + size2 > hp_lim) {
|
|
hp = get_superblock();
|
|
hp_lim = hp + SUPERBLOCK_SIZE - 1;
|
|
}
|
|
|
|
p = hp + RZ;
|
|
hp += size2;
|
|
|
|
VALGRIND_MALLOCLIKE_BLOCK( p, size, RZ, /*is_zeroed*/1 );
|
|
return (void*)p;
|
|
}
|
|
|
|
static void custom_free(void* p)
|
|
{
|
|
// don't actually free any memory... but mark it as freed
|
|
VALGRIND_FREELIKE_BLOCK( p, RZ );
|
|
}
|
|
#undef RZ
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Rest
|
|
//-------------------------------------------------------------------------
|
|
|
|
void make_leak(void)
|
|
{
|
|
int* array2 = custom_alloc(sizeof(int) * 10);
|
|
array2 = 0; // leak
|
|
return;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int* array;
|
|
int* array3;
|
|
|
|
array = custom_alloc(sizeof(int) * 10);
|
|
array[8] = 8;
|
|
array[9] = 8;
|
|
array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock)
|
|
|
|
custom_free(array); // ok
|
|
|
|
custom_free(NULL); // invalid free (ok without MALLOCLIKE)
|
|
|
|
array3 = malloc(sizeof(int) * 10);
|
|
custom_free(array3); // mismatched free (ok without MALLOCLIKE)
|
|
|
|
make_leak();
|
|
return array[0]; // use after free (ok without MALLOCLIKE/MAKE_MEM_NOACCESS)
|
|
// (nb: initialised because is_zeroed==1 above)
|
|
// unfortunately not identified as being in a free'd
|
|
// block because the freeing of the block and shadow
|
|
// chunk isn't postponed.
|
|
|
|
// leak from make_leak()
|
|
}
|