.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $OpenBSD: malloc.3,v 1.132 2023/04/17 05:45:06 jmc Exp $
+.\" $OpenBSD: malloc.3,v 1.133 2023/06/04 06:58:33 otto Exp $
.\"
-.Dd $Mdocdate: April 17 2023 $
+.Dd $Mdocdate: June 4 2023 $
.Dt MALLOC 3
.Os
.Sh NAME
Decrease the junk level by one if it is larger than 0.
Junking writes some junk bytes into the area allocated.
Junk is bytes of 0xdb when allocating;
-freed chunks are filled with 0xdf.
+freed allocations are filled with 0xdf.
By default the junk level is 1: after free,
small chunks are completely junked;
for pages the first part is junked.
.Fn free
or
reallocate an unallocated pointer was made.
-.It Dq chunk is already free
-There was an attempt to free a chunk that had already been freed.
+.It Dq double free
+There was an attempt to free an allocation that had already been freed.
.It Dq write after free
-A chunk has been modified after it was freed.
+An allocation has been modified after it was freed.
.It Dq modified chunk-pointer
The pointer passed to
.Fn free
or a reallocation function has been modified.
-.It Dq chunk canary corrupted address offset@length
+.It Dq canary corrupted address offset@length
A byte after the requested size has been overwritten,
indicating a heap overflow.
The offset at which corruption was detected is printed before the @,
and the requested length of the allocation after the @.
-.It Dq recorded old size oldsize != size
+.It Dq recorded size oldsize inconsistent with size
.Fn recallocarray
-has detected that the given old size does not equal the recorded size in its
+or
+.Fn freezero
+has detected that the given old size does not match the recorded size in its
meta data.
Enabling option
.Cm C
-/* $OpenBSD: malloc.c,v 1.284 2023/05/27 04:33:00 otto Exp $ */
+/* $OpenBSD: malloc.c,v 1.285 2023/06/04 06:58:33 otto Exp $ */
/*
* Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
NULL))
goto err;
LIST_INSERT_HEAD(&d->chunk_dir[bucket][listnum], bp, entries);
+
+ if (bucket > 0 && d->malloc_junk != 0)
+ memset(pp, SOME_FREEJUNK, MALLOC_PAGESIZE);
+
return bp;
err:
p = (char *)bp->page + k;
if (bp->bucket > 0) {
- if (d->malloc_junk == 2)
- memset(p, SOME_JUNK, B2SIZE(bp->bucket));
- else if (mopts.chunk_canaries)
+ validate_junk(d, p, B2SIZE(bp->bucket));
+ if (mopts.chunk_canaries)
fill_canary(p, size, B2SIZE(bp->bucket));
}
return p;
while (p < q) {
if (*p != (u_char)mopts.chunk_canaries && *p != SOME_JUNK) {
- wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s",
+ wrterror(d, "canary corrupted %p %#tx@%#zx%s",
ptr, p - ptr, sz,
*p == SOME_FREEJUNK ? " (double free?)" : "");
}
wrterror(d, "modified chunk-pointer %p", ptr);
if (info->bits[chunknum / MALLOC_BITS] &
(1U << (chunknum % MALLOC_BITS)))
- wrterror(d, "chunk is already free %p", ptr);
+ wrterror(d, "double free %p", ptr);
if (check && info->bucket > 0) {
validate_canary(d, ptr, info->bits[info->offset + chunknum],
B2SIZE(info->bucket));
uint32_t chunknum = find_chunknum(pool, info, p, 0);
if (info->bits[info->offset + chunknum] != oldsize)
- wrterror(pool, "recorded old size %hu != %zu",
+ wrterror(pool, "recorded size %hu != %zu",
info->bits[info->offset + chunknum],
oldsize);
+ } else {
+ if (sz < oldsize)
+ wrterror(pool, "chunk size %zu < %zu",
+ sz, oldsize);
}
- } else if (oldsize < (sz - mopts.malloc_guard) / 2)
- wrterror(pool, "recorded old size %zu != %zu",
- sz - mopts.malloc_guard, oldsize);
+ } else {
+ if (sz - mopts.malloc_guard < oldsize)
+ wrterror(pool, "recorded size %zu < %zu",
+ sz - mopts.malloc_guard, oldsize);
+ if (oldsize < (sz - mopts.malloc_guard) / 2)
+ wrterror(pool, "recorded size %zu inconsistent with %zu",
+ sz - mopts.malloc_guard, oldsize);
+ }
newptr = omalloc(pool, newsize, 0, f);
if (newptr == NULL)
-/* $OpenBSD: malloc_errs.c,v 1.2 2023/05/09 19:07:37 otto Exp $ */
+/* $OpenBSD: malloc_errs.c,v 1.3 2023/06/04 06:58:33 otto Exp $ */
/*
* Copyright (c) 2023 Otto Moerbeek <otto@drijf.net>
*
void
t9(void)
{
- char *p;
-
- p = malloc(100);
+ char *p = malloc(100);
p[100] = 0;
free(p);
}
void
t16(void)
{
- abort(); /* not yet */
char *p = recallocarray(NULL, 0, 16, 1);
char *q = recallocarray(p, 2, 3, 16);
}
void
t18(void)
{
- abort(); /* not yet */
char *p = recallocarray(NULL, 0, 1, getpagesize());
char *q = recallocarray(p, 2, 3, getpagesize());
}
+/* recallocarray with wrong size, pages */
+void
+t19(void)
+{
+ char *p = recallocarray(NULL, 0, 1, 10 * getpagesize());
+ char *q = recallocarray(p, 1, 2, 4 * getpagesize());
+}
+
+/* canary check pages */
+void
+t20(void)
+{
+ char *p = malloc(2*getpagesize() - 100);
+ p[2*getpagesize() - 100] = 0;
+ free(p);
+}
+
struct test {
void (*test)(void);
const char *flags;
{ t16, "" },
{ t17, "C" },
{ t18, "" },
+ { t19, "" },
+ { t20, "C" },
};
int main(int argc, char *argv[])