summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2010-11-19 11:04:33 +1100
committerAndrew Tridgell <tridge@samba.org>2010-11-19 15:17:42 +1100
commit999f3ed2ce656ecf97b95afa85823115939f9360 (patch)
tree3f131913280332b7ee8be0538a84548f39f26684
parent58c43f74b9bc2d660f58ccfe912bd3fff7cf672e (diff)
downloadsamba-999f3ed2ce656ecf97b95afa85823115939f9360.tar.gz
samba-999f3ed2ce656ecf97b95afa85823115939f9360.tar.bz2
samba-999f3ed2ce656ecf97b95afa85823115939f9360.zip
talloc: added TALLOC_FREE_FILL environment variable
when this environment variable is set, talloc will fill freed memory with the value from that environment variable. This can be used to help find use after free bugs when valgrind is too slow to be used
-rw-r--r--lib/talloc/talloc.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 84947a77b0..ec67a463ab 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -104,6 +104,17 @@
static void *null_context;
static void *autofree_context;
+/* used to enable fill of memory on free, which can be useful for
+ * catching use after free errors when valgrind is too slow
+ */
+static struct {
+ bool initialised;
+ bool enabled;
+ uint8_t fill_value;
+} talloc_fill;
+
+#define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
+
struct talloc_reference_handle {
struct talloc_reference_handle *next, *prev;
void *ptr;
@@ -567,6 +578,16 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
return -1;
}
+ /* possibly initialised the talloc fill value */
+ if (!talloc_fill.initialised) {
+ const char *fill = getenv(TALLOC_FILL_ENV);
+ if (fill != NULL) {
+ talloc_fill.enabled = true;
+ talloc_fill.fill_value = strtoul(fill, NULL, 0);
+ }
+ talloc_fill.initialised = true;
+ }
+
tc = talloc_chunk_from_ptr(ptr);
if (unlikely(tc->refs)) {
@@ -662,10 +683,19 @@ static inline int _talloc_free_internal(void *ptr, const char *location)
*pool_object_count -= 1;
if (*pool_object_count == 0) {
+ if (talloc_fill.enabled) {
+ memset(TC_PTR_FROM_CHUNK(pool), talloc_fill.fill_value, pool->size);
+ }
free(pool);
}
}
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);
+ }
free(tc);
}
return 0;