talloc: added TALLOC_FREE_FILL environment variable
authorAndrew Tridgell <tridge@samba.org>
Fri, 19 Nov 2010 00:04:33 +0000 (11:04 +1100)
committerAndrew Tridgell <tridge@samba.org>
Fri, 19 Nov 2010 04:17:42 +0000 (15:17 +1100)
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

lib/talloc/talloc.c

index 84947a77b00a153a7a3e5c2385d013615630c562..ec67a463abc43a5e0c92940f552c2e2ef52e8be0 100644 (file)
 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;