From: Nicholas Nethercote Date: Wed, 15 Jul 2009 02:31:45 +0000 (+0000) Subject: Ignore MALLOCLIKE_BLOCK/FREELIKE_BLOCK if addr==0. Fixes bug 137073. DRD X-Git-Tag: svn/VALGRIND_3_5_0~392 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2a7a73345f786086afae489200c629687afda376;p=thirdparty%2Fvalgrind.git Ignore MALLOCLIKE_BLOCK/FREELIKE_BLOCK if addr==0. Fixes bug 137073. DRD now has its own copy of custom_alloc.c which is a little different to Memcheck's; making them both work with the same version was too difficult. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10455 --- diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 59f59686be..91bb20cd81 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -1465,7 +1465,18 @@ void do_client_request ( ThreadId tid ) SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ break; + case VG_USERREQ__MALLOCLIKE_BLOCK: + case VG_USERREQ__FREELIKE_BLOCK: + // Ignore them if the addr is NULL; otherwise pass onto the tool. + if (!arg[1]) { + SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ + break; + } else { + goto my_default; + } + default: + my_default: if (os_client_request(tid, arg)) { // do nothing, os_client_request() handled it } else if (VG_(needs).client_requests) { diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am index e4abf7b2c4..f59180ee54 100644 --- a/drd/tests/Makefile.am +++ b/drd/tests/Makefile.am @@ -222,6 +222,7 @@ EXTRA_DIST = \ check_PROGRAMS = \ + custom_alloc \ fp_race \ hold_lock \ linuxthreads_det \ diff --git a/drd/tests/custom_alloc.c b/drd/tests/custom_alloc.c new file mode 100644 index 0000000000..8032ba2f20 --- /dev/null +++ b/drd/tests/custom_alloc.c @@ -0,0 +1,90 @@ +#include +#include "tests/sys_mman.h" +#include +#include + +#include "../drd.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_ANONYMOUS, -1, 0 ); + + assert(p != ((void*)(-1))); + + 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) + // (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() +} diff --git a/drd/tests/custom_alloc.vgtest b/drd/tests/custom_alloc.vgtest index 705903af0f..2b8a141542 100644 --- a/drd/tests/custom_alloc.vgtest +++ b/drd/tests/custom_alloc.vgtest @@ -1 +1 @@ -prog: ../../memcheck/tests/custom_alloc +prog: custom_alloc diff --git a/include/valgrind.h b/include/valgrind.h index 44c97391af..bdb037c2de 100644 --- a/include/valgrind.h +++ b/include/valgrind.h @@ -3886,6 +3886,8 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) superblocks, rather than mmap() or brk(), this will not work properly -- you'll likely get assertion failures during leak detection. This is because Valgrind doesn't like seeing overlapping heap blocks. Sorry. + + Ignored if addr == 0. */ #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ {unsigned int _qzz_res; \ @@ -3894,7 +3896,9 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) addr, sizeB, rzB, is_zeroed, 0); \ } -/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. */ +/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. + Ignored if addr == 0. +*/ #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ {unsigned int _qzz_res; \ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ diff --git a/memcheck/tests/custom_alloc.c b/memcheck/tests/custom_alloc.c index 5ad965c6f0..fb16979998 100644 --- a/memcheck/tests/custom_alloc.c +++ b/memcheck/tests/custom_alloc.c @@ -70,8 +70,8 @@ void make_leak(void) int main(void) { - int* array; - int* array3; + int *array, *array3; + int x; array = custom_alloc(sizeof(int) * 10); array[8] = 8; @@ -80,17 +80,24 @@ int main(void) custom_free(array); // ok - custom_free(NULL); // invalid free (ok without MALLOCLIKE) + custom_free((void*)0x1); // invalid free 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) + x = 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. + + // Bug 137073: passing 0 to MALLOCLIKE_BLOCK was causing an assertion + // failure. Test for this (and likewise for FREELIKE_BLOCK). + //VALGRIND_MALLOCLIKE_BLOCK(0,0,0,0); + //VALGRIND_FREELIKE_BLOCK(0,0); + return x; + // leak from make_leak() }