(without mangling it this time...)
diff --git a/stdlib/malloc.c b/stdlib/malloc.c
index 424dd77..c408594 100644
--- a/stdlib/malloc.c
+++ b/stdlib/malloc.c
@@ -182,6 +182,7 @@ struct malloc_readonly {
int malloc_freeunmap; /* mprotect free pages PROT_NONE? */
int malloc_hint; /* call madvice on free pages? */
int malloc_junk; /* junk fill? */
+ int malloc_validate; /* validate junk */
int malloc_move; /* move allocations to end of page? */
int malloc_realloc; /* always realloc? */
int malloc_xmalloc; /* xmalloc behaviour? */
@@ -218,6 +219,8 @@ static void malloc_exit(void);
#define CALLER NULL
#endif
+static void validate_delayed_chunks(void);
+
/* low bits of r->p determine size: 0 means >= page size and p->size holding
* real size, otherwise r->size is a shift count, or 1 for malloc(0)
*/
@@ -560,6 +563,12 @@ omalloc_init(struct dir_info **dp)
case 'J':
mopts.malloc_junk = 2;
break;
+ case 'v':
+ mopts.malloc_validate = 0;
+ break;
+ case 'V':
+ mopts.malloc_validate = 1;
+ break;
case 'n':
case 'N':
break;
@@ -608,6 +617,9 @@ omalloc_init(struct dir_info **dp)
}
}
+ if (!mopts.malloc_junk)
+ mopts.malloc_validate = 0;
+
#ifdef MALLOC_STATS
if (mopts.malloc_stats && (atexit(malloc_exit) == -1)) {
static const char q[] = "malloc() warning: atexit(2) failed."
@@ -616,6 +628,12 @@ omalloc_init(struct dir_info **dp)
}
#endif /* MALLOC_STATS */
+ if (mopts.malloc_validate && (atexit(validate_delayed_chunks) == -1)) {
+ static const char q[] = "malloc() warning: atexit(2) failed."
+ " Will not be able to check for use after free\n";
+ write(STDERR_FILENO, q, sizeof(q) - 1);
+ }
+
while ((mopts.malloc_canary = arc4random()) == 0)
;
@@ -1190,6 +1208,35 @@ malloc(size_t size)
/*DEF_STRONG(malloc);*/
static void
+validate_junk(void *p) {
+ struct region_info *r;
+ struct dir_info *pool = getpool();
+ size_t byte, sz;
+ if (p == NULL)
+ return;
+ r = find(pool, p);
+ if (r == NULL)
+ wrterror("bogus pointer in validate_junk", p);
+ REALSIZE(sz, r);
+ for (byte = 0; byte < sz; byte++) {
+ if (((char *)p)[byte] != SOME_FREEJUNK) {
+ wrterror("use after free", p);
+ return;
+ }
+ }
+}
+
+static void
+validate_delayed_chunks(void) {
+ struct dir_info *pool = getpool();
+ int i;
+ if (pool == NULL)
+ return;
+ for (i = 0; i < MALLOC_DELAYED_CHUNK_MASK + 1; i++)
+ validate_junk(pool->delayed_chunks[i]);
+}
+
+static void
ofree(void *p)
{
struct dir_info *pool = getpool();
@@ -1253,6 +1300,8 @@ ofree(void *p)
wrterror("double free", p);
return;
}
+ if (mopts.malloc_validate)
+ validate_junk(p);
pool->delayed_chunks[i] = tmp;
}
if (p != NULL) {