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) {
check_PROGRAMS = \
+ custom_alloc \
fp_race \
hold_lock \
linuxthreads_det \
--- /dev/null
+#include <unistd.h>
+#include "tests/sys_mman.h"
+#include <assert.h>
+#include <stdlib.h>
+
+#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()
+}
-prog: ../../memcheck/tests/custom_alloc
+prog: custom_alloc
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; \
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, \
int main(void)
{
- int* array;
- int* array3;
+ int *array, *array3;
+ int x;
array = custom_alloc(sizeof(int) * 10);
array[8] = 8;
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()
}