diff options
author | Stefan Metzmacher <metze@samba.org> | 2011-04-04 11:47:57 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2011-04-08 09:28:10 +0200 |
commit | 4895f55f0604a1851d45c24a8a584a10170d5917 (patch) | |
tree | e79f7a22ee681ec6f19b10052851db7392217939 | |
parent | efbb35824e3845c3cdefea328dd1bf67d0f9087d (diff) | |
download | samba-4895f55f0604a1851d45c24a8a584a10170d5917.tar.gz samba-4895f55f0604a1851d45c24a8a584a10170d5917.tar.bz2 samba-4895f55f0604a1851d45c24a8a584a10170d5917.zip |
talloc: add TC_INVALIDATE_FULL_CHUNK() macro
This makes it easier to mark a talloc pointer as
invalid.
metze
Signed-off-By: Andrew Tridgell <tridge@samba.org>
-rw-r--r-- | lib/talloc/talloc.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 8dec01fd41..522d60ff8f 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -115,6 +115,34 @@ static struct { #define TALLOC_FILL_ENV "TALLOC_FREE_FILL" +/* + * do not wipe the header, to allow the + * double-free logic to still work + */ +#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size; \ + char *_fptr = TC_PTR_FROM_CHUNK(_tc); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) +/* Mark the whole chunk as not accessable */ +#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \ + size_t _flen = TC_HDR_SIZE + (_tc)->size; \ + char *_fptr = (char *)(_tc); \ + VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ +} while(0) +#else +#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0) +#endif + +#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \ + TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \ + TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \ +} while (0) + struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; void *ptr; @@ -592,7 +620,7 @@ static inline int _talloc_free_internal(void *ptr, const char *location) } /* possibly initialised the talloc fill value */ - if (!talloc_fill.initialised) { + if (unlikely(!talloc_fill.initialised)) { const char *fill = getenv(TALLOC_FILL_ENV); if (fill != NULL) { talloc_fill.enabled = true; @@ -704,6 +732,8 @@ static inline int _talloc_free_internal(void *ptr, const char *location) } else { pool = (struct talloc_chunk *)tc->pool; next_tc = TC_POOLMEM_NEXT_CHUNK(tc); + + TC_INVALIDATE_FULL_CHUNK(tc); } pool_object_count = talloc_pool_objectcount(pool); @@ -724,9 +754,7 @@ static inline int _talloc_free_internal(void *ptr, const char *location) */ pool->pool = TC_POOL_FIRST_CHUNK(pool); } else if (unlikely(*pool_object_count == 0)) { - if (talloc_fill.enabled) { - memset(TC_PTR_FROM_CHUNK(pool), talloc_fill.fill_value, pool->size); - } + TC_INVALIDATE_FULL_CHUNK(pool); free(pool); } else if (pool->pool == next_tc) { /* @@ -736,14 +764,8 @@ static inline int _talloc_free_internal(void *ptr, const char *location) */ pool->pool = tc; } - } - else { - if (talloc_fill.enabled) { - /* don't wipe the header, to allow the - double-free logic to still work - */ - memset(TC_PTR_FROM_CHUNK(tc), talloc_fill.fill_value, tc->size); - } + } else { + TC_INVALIDATE_FULL_CHUNK(tc); free(tc); } return 0; @@ -1294,6 +1316,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons if (new_ptr) { memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + TC_INVALIDATE_FULL_CHUNK(tc); } } else { new_ptr = malloc(size + TC_HDR_SIZE); @@ -1375,6 +1398,7 @@ _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, cons if (new_ptr) { memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + TC_INVALIDATE_FULL_CHUNK(tc); if (*talloc_pool_objectcount(pool_tc) == 1) { /* |