summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-04-04 11:47:57 +0200
committerStefan Metzmacher <metze@samba.org>2011-04-08 09:28:10 +0200
commit4895f55f0604a1851d45c24a8a584a10170d5917 (patch)
treee79f7a22ee681ec6f19b10052851db7392217939
parentefbb35824e3845c3cdefea328dd1bf67d0f9087d (diff)
downloadsamba-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.c48
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) {
/*