summaryrefslogtreecommitdiff
path: root/libc/malloc
diff options
context:
space:
mode:
Diffstat (limited to 'libc/malloc')
-rw-r--r--libc/malloc/Makefile4
-rw-r--r--libc/malloc/arena.c11
-rw-r--r--libc/malloc/hooks.c11
-rw-r--r--libc/malloc/malloc.c77
-rw-r--r--libc/malloc/tst-memalign.c99
-rw-r--r--libc/malloc/tst-posix_memalign.c108
-rw-r--r--libc/malloc/tst-pvalloc.c99
-rw-r--r--libc/malloc/tst-realloc.c146
-rw-r--r--libc/malloc/tst-valloc.c108
9 files changed, 627 insertions, 36 deletions
diff --git a/libc/malloc/Makefile b/libc/malloc/Makefile
index be81dd3b8..9ca8edf67 100644
--- a/libc/malloc/Makefile
+++ b/libc/malloc/Makefile
@@ -27,7 +27,9 @@ all:
dist-headers := malloc.h
headers := $(dist-headers) obstack.h mcheck.h
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
- tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 tst-malloc-usable
+ tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
+ tst-malloc-usable tst-realloc tst-posix_memalign \
+ tst-pvalloc tst-memalign
test-srcs = tst-mtrace
routines = malloc morecore mcheck mtrace obstack
diff --git a/libc/malloc/arena.c b/libc/malloc/arena.c
index 12a48ad7b..d81ed0d68 100644
--- a/libc/malloc/arena.c
+++ b/libc/malloc/arena.c
@@ -581,6 +581,7 @@ new_heap(size_t size, size_t top_pad)
h->size = size;
h->mprotect_size = size;
THREAD_STAT(stat_n_heaps++);
+ LIBC_PROBE (memory_heap_new, 2, h, h->size);
return h;
}
@@ -606,6 +607,7 @@ grow_heap(heap_info *h, long diff)
}
h->size = new_size;
+ LIBC_PROBE (memory_heap_more, 2, h, h->size);
return 0;
}
@@ -633,6 +635,7 @@ shrink_heap(heap_info *h, long diff)
/*fprintf(stderr, "shrink %p %08lx\n", h, new_size);*/
h->size = new_size;
+ LIBC_PROBE (memory_heap_less, 2, h, h->size);
return 0;
}
@@ -674,6 +677,7 @@ heap_trim(heap_info *heap, size_t pad)
break;
ar_ptr->system_mem -= heap->size;
arena_mem -= heap->size;
+ LIBC_PROBE (memory_heap_free, 2, heap, heap->size);
delete_heap(heap);
heap = prev_heap;
if(!prev_inuse(p)) { /* consolidate backward */
@@ -736,6 +740,7 @@ _int_new_arena(size_t size)
top(a) = (mchunkptr)ptr;
set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE);
+ LIBC_PROBE (memory_arena_new, 2, a, size);
tsd_setspecific(arena_key, (void *)a);
mutex_init(&a->mutex);
(void)mutex_lock(&a->mutex);
@@ -774,6 +779,7 @@ get_free_list (void)
if (result != NULL)
{
+ LIBC_PROBE (memory_arena_reuse_free_list, 1, result);
(void)mutex_lock(&result->mutex);
tsd_setspecific(arena_key, (void *)result);
THREAD_STAT(++(result->stat_lock_loop));
@@ -810,9 +816,11 @@ reused_arena (mstate avoid_arena)
result = result->next;
/* No arena available. Wait for the next in line. */
+ LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
(void)mutex_lock(&result->mutex);
out:
+ LIBC_PROBE (memory_arena_reuse, 2, result, avoid_arena);
tsd_setspecific(arena_key, (void *)result);
THREAD_STAT(++(result->stat_lock_loop));
next_to_use = result->next;
@@ -891,6 +899,7 @@ arena_get2(mstate a_tsd, size_t size, mstate avoid_arena)
if (retried)
(void)mutex_unlock(&list_lock);
THREAD_STAT(++(a->stat_lock_loop));
+ LIBC_PROBE (memory_arena_reuse, 2, a, a_tsd);
tsd_setspecific(arena_key, (void *)a);
return a;
}
@@ -903,6 +912,7 @@ arena_get2(mstate a_tsd, size_t size, mstate avoid_arena)
locks. */
if(!retried && mutex_trylock(&list_lock)) {
/* We will block to not run in a busy loop. */
+ LIBC_PROBE (memory_arena_reuse_wait, 3, &list_lock, NULL, a_tsd);
(void)mutex_lock(&list_lock);
/* Since we blocked there might be an arena available now. */
@@ -926,6 +936,7 @@ arena_get2(mstate a_tsd, size_t size, mstate avoid_arena)
static mstate
arena_get_retry (mstate ar_ptr, size_t bytes)
{
+ LIBC_PROBE (memory_arena_retry, 2, bytes, ar_ptr);
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
diff --git a/libc/malloc/hooks.c b/libc/malloc/hooks.c
index 8c2584633..3f663bb6b 100644
--- a/libc/malloc/hooks.c
+++ b/libc/malloc/hooks.c
@@ -361,10 +361,13 @@ memalign_check(size_t alignment, size_t bytes, const void *caller)
if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
if (alignment < MINSIZE) alignment = MINSIZE;
- if (bytes+1 == 0) {
- __set_errno (ENOMEM);
- return NULL;
- }
+ /* Check for overflow. */
+ if (bytes > SIZE_MAX - alignment - MINSIZE)
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
(void)mutex_lock(&main_arena.mutex);
mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) :
NULL;
diff --git a/libc/malloc/malloc.c b/libc/malloc/malloc.c
index dd295f522..1a18c3f5f 100644
--- a/libc/malloc/malloc.c
+++ b/libc/malloc/malloc.c
@@ -1878,6 +1878,8 @@ static int perturb_byte;
#define free_perturb(p, n) memset (p, perturb_byte & 0xff, n)
+#include <stap-probe.h>
+
/* ------------------- Support for multiple arenas -------------------- */
#include "arena.c"
@@ -2214,15 +2216,6 @@ static void do_check_malloc_state(mstate av)
/* top chunk is OK */
check_chunk(av, av->top);
- /* sanity checks for statistics */
-
- assert(mp_.n_mmaps <= mp_.max_n_mmaps);
-
- assert((unsigned long)(av->system_mem) <=
- (unsigned long)(av->max_system_mem));
-
- assert((unsigned long)(mp_.mmapped_mem) <=
- (unsigned long)(mp_.max_mmapped_mem));
}
#endif
@@ -2446,8 +2439,10 @@ static void* sysmalloc(INTERNAL_SIZE_T nb, mstate av)
below even if we cannot call MORECORE.
*/
- if (size > 0)
+ if (size > 0) {
brk = (char*)(MORECORE(size));
+ LIBC_PROBE (memory_sbrk_more, 2, brk, size);
+ }
if (brk != (char*)(MORECORE_FAILURE)) {
/* Call the `morecore' hook if necessary. */
@@ -2745,6 +2740,8 @@ static int systrim(size_t pad, mstate av)
(*hook) ();
new_brk = (char*)(MORECORE(0));
+ LIBC_PROBE (memory_sbrk_less, 2, new_brk, extra);
+
if (new_brk != (char*)MORECORE_FAILURE) {
released = (long)(current_brk - new_brk);
@@ -2854,6 +2851,7 @@ __libc_malloc(size_t bytes)
return 0;
victim = _int_malloc(ar_ptr, bytes);
if(!victim) {
+ LIBC_PROBE (memory_malloc_retry, 1, bytes);
ar_ptr = arena_get_retry(ar_ptr, bytes);
if (__builtin_expect(ar_ptr != NULL, 1)) {
victim = _int_malloc(ar_ptr, bytes);
@@ -2894,6 +2892,8 @@ __libc_free(void* mem)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
+ LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
+ mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk(p);
return;
@@ -2973,6 +2973,7 @@ __libc_realloc(void* oldmem, size_t bytes)
#endif
#if !defined PER_THREAD
+ LIBC_PROBE (memory_arena_reuse_realloc, 1, ar_ptr);
/* As in malloc(), remember this arena for the next allocation. */
tsd_setspecific(arena_key, (void *)ar_ptr);
#endif
@@ -2986,6 +2987,7 @@ __libc_realloc(void* oldmem, size_t bytes)
if (newp == NULL)
{
/* Try harder to allocate memory in other arenas. */
+ LIBC_PROBE (memory_realloc_retry, 2, bytes, oldmem);
newp = __libc_malloc(bytes);
if (newp != NULL)
{
@@ -3015,11 +3017,19 @@ __libc_memalign(size_t alignment, size_t bytes)
/* Otherwise, ensure that it is at least a minimum chunk size */
if (alignment < MINSIZE) alignment = MINSIZE;
+ /* Check for overflow. */
+ if (bytes > SIZE_MAX - alignment - MINSIZE)
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
arena_get(ar_ptr, bytes + alignment + MINSIZE);
if(!ar_ptr)
return 0;
p = _int_memalign(ar_ptr, alignment, bytes);
if(!p) {
+ LIBC_PROBE (memory_memalign_retry, 2, bytes, alignment);
ar_ptr = arena_get_retry (ar_ptr, bytes);
if (__builtin_expect(ar_ptr != NULL, 1)) {
p = _int_memalign(ar_ptr, alignment, bytes);
@@ -3046,6 +3056,13 @@ __libc_valloc(size_t bytes)
size_t pagesz = GLRO(dl_pagesize);
+ /* Check for overflow. */
+ if (bytes > SIZE_MAX - pagesz - MINSIZE)
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
void *(*hook) (size_t, size_t, const void *) =
force_reg (__memalign_hook);
if (__builtin_expect (hook != NULL, 0))
@@ -3056,6 +3073,7 @@ __libc_valloc(size_t bytes)
return 0;
p = _int_valloc(ar_ptr, bytes);
if(!p) {
+ LIBC_PROBE (memory_valloc_retry, 1, bytes);
ar_ptr = arena_get_retry (ar_ptr, bytes);
if (__builtin_expect(ar_ptr != NULL, 1)) {
p = _int_memalign(ar_ptr, pagesz, bytes);
@@ -3082,6 +3100,13 @@ __libc_pvalloc(size_t bytes)
size_t page_mask = GLRO(dl_pagesize) - 1;
size_t rounded_bytes = (bytes + page_mask) & ~(page_mask);
+ /* Check for overflow. */
+ if (bytes > SIZE_MAX - 2*pagesz - MINSIZE)
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
void *(*hook) (size_t, size_t, const void *) =
force_reg (__memalign_hook);
if (__builtin_expect (hook != NULL, 0))
@@ -3090,6 +3115,7 @@ __libc_pvalloc(size_t bytes)
arena_get(ar_ptr, bytes + 2*pagesz + MINSIZE);
p = _int_pvalloc(ar_ptr, bytes);
if(!p) {
+ LIBC_PROBE (memory_pvalloc_retry, 1, bytes);
ar_ptr = arena_get_retry (ar_ptr, bytes + 2*pagesz + MINSIZE);
if (__builtin_expect(ar_ptr != NULL, 1)) {
p = _int_memalign(ar_ptr, pagesz, rounded_bytes);
@@ -3166,6 +3192,7 @@ __libc_calloc(size_t n, size_t elem_size)
av == arena_for_chunk(mem2chunk(mem)));
if (mem == 0) {
+ LIBC_PROBE (memory_calloc_retry, 1, sz);
av = arena_get_retry (av, sz);
if (__builtin_expect(av != NULL, 1)) {
mem = _int_malloc(av, sz);
@@ -4674,21 +4701,29 @@ int __libc_mallopt(int param_number, int value)
/* Ensure initialization/consolidation */
malloc_consolidate(av);
+ LIBC_PROBE (memory_mallopt, 2, param_number, value);
+
switch(param_number) {
case M_MXFAST:
- if (value >= 0 && value <= MAX_FAST_SIZE) {
- set_max_fast(value);
- }
+ if (value >= 0 && value <= MAX_FAST_SIZE)
+ {
+ LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ());
+ set_max_fast(value);
+ }
else
res = 0;
break;
case M_TRIM_THRESHOLD:
+ LIBC_PROBE (memory_mallopt_trim_threshold, 3, value,
+ mp_.trim_threshold, mp_.no_dyn_threshold);
mp_.trim_threshold = value;
mp_.no_dyn_threshold = 1;
break;
case M_TOP_PAD:
+ LIBC_PROBE (memory_mallopt_top_pad, 3, value,
+ mp_.top_pad, mp_.no_dyn_threshold);
mp_.top_pad = value;
mp_.no_dyn_threshold = 1;
break;
@@ -4699,33 +4734,45 @@ int __libc_mallopt(int param_number, int value)
res = 0;
else
{
+ LIBC_PROBE (memory_mallopt_mmap_threshold, 3, value,
+ mp_.mmap_threshold, mp_.no_dyn_threshold);
mp_.mmap_threshold = value;
mp_.no_dyn_threshold = 1;
}
break;
case M_MMAP_MAX:
+ LIBC_PROBE (memory_mallopt_mmap_max, 3, value,
+ mp_.n_mmaps_max, mp_.no_dyn_threshold);
mp_.n_mmaps_max = value;
mp_.no_dyn_threshold = 1;
break;
case M_CHECK_ACTION:
+ LIBC_PROBE (memory_mallopt_check_action, 2, value, check_action);
check_action = value;
break;
case M_PERTURB:
+ LIBC_PROBE (memory_mallopt_perturb, 2, value, perturb_byte);
perturb_byte = value;
break;
#ifdef PER_THREAD
case M_ARENA_TEST:
if (value > 0)
- mp_.arena_test = value;
+ {
+ LIBC_PROBE (memory_mallopt_arena_test, 2, value, mp_.arena_test);
+ mp_.arena_test = value;
+ }
break;
case M_ARENA_MAX:
if (value > 0)
- mp_.arena_max = value;
+ {
+ LIBC_PROBE (memory_mallopt_arena_max, 2, value, mp_.arena_max);
+ mp_.arena_max = value;
+ }
break;
#endif
}
diff --git a/libc/malloc/tst-memalign.c b/libc/malloc/tst-memalign.c
new file mode 100644
index 000000000..1c5975248
--- /dev/null
+++ b/libc/malloc/tst-memalign.c
@@ -0,0 +1,99 @@
+/* Test for memalign.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+ ++errors;
+ printf ("Error: %s\n", msg);
+}
+
+static int
+do_test (void)
+{
+ void *p;
+ unsigned long pagesize = getpagesize ();
+ unsigned long ptrval;
+ int save;
+
+ errno = 0;
+
+ /* An attempt to allocate a huge value should return NULL and set
+ errno to ENOMEM. */
+ p = memalign (sizeof (void *), -1);
+
+ save = errno;
+
+ if (p != NULL)
+ merror ("memalign (sizeof (void *), -1) succeeded.");
+
+ if (p == NULL && save != ENOMEM)
+ merror ("memalign (sizeof (void *), -1) errno is not set correctly");
+
+ free (p);
+
+ errno = 0;
+
+ /* Test to expose integer overflow in malloc internals from BZ #15857. */
+ p = memalign (pagesize, -pagesize);
+
+ save = errno;
+
+ if (p != NULL)
+ merror ("memalign (pagesize, -pagesize) succeeded.");
+
+ if (p == NULL && save != ENOMEM)
+ merror ("memalign (pagesize, -pagesize) errno is not set correctly");
+
+ free (p);
+
+ /* A zero-sized allocation should succeed with glibc, returning a
+ non-NULL value. */
+ p = memalign (sizeof (void *), 0);
+
+ if (p == NULL)
+ merror ("memalign (sizeof (void *), 0) failed.");
+
+ free (p);
+
+ /* Check the alignment of the returned pointer is correct. */
+ p = memalign (0x100, 10);
+
+ if (p == NULL)
+ merror ("memalign (0x100, 10) failed.");
+
+ ptrval = (unsigned long) p;
+
+ if ((ptrval & 0xff) != 0)
+ merror ("pointer is not aligned to 0x100");
+
+ free (p);
+
+ return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libc/malloc/tst-posix_memalign.c b/libc/malloc/tst-posix_memalign.c
new file mode 100644
index 000000000..27c0dd2bd
--- /dev/null
+++ b/libc/malloc/tst-posix_memalign.c
@@ -0,0 +1,108 @@
+/* Test for posix_memalign.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+ ++errors;
+ printf ("Error: %s\n", msg);
+}
+
+static int
+do_test (void)
+{
+ void *p;
+ int ret;
+ unsigned long pagesize = getpagesize ();
+ unsigned long ptrval;
+
+ p = NULL;
+
+ /* An attempt to allocate a huge value should return ENOMEM and
+ p should remain NULL. */
+ ret = posix_memalign (&p, sizeof (void *), -1);
+
+ if (ret != ENOMEM)
+ merror ("posix_memalign (&p, sizeof (void *), -1) succeeded.");
+
+ if (ret == ENOMEM && p != NULL)
+ merror ("returned an error but pointer was modified");
+
+ free (p);
+
+ p = NULL;
+
+ /* Test to expose integer overflow in malloc internals from BZ #15857. */
+ ret = posix_memalign (&p, pagesize, -pagesize);
+
+ if (ret != ENOMEM)
+ merror ("posix_memalign (&p, pagesize, -pagesize) succeeded.");
+
+ free (p);
+
+ p = NULL;
+
+ /* A zero-sized allocation should succeed with glibc, returning zero
+ and setting p to a non-NULL value. */
+ ret = posix_memalign (&p, sizeof (void *), 0);
+
+ if (ret != 0 || p == NULL)
+ merror ("posix_memalign (&p, sizeof (void *), 0) failed.");
+
+ free (p);
+
+ ret = posix_memalign (&p, 0x300, 10);
+
+ if (ret != EINVAL)
+ merror ("posix_memalign (&p, 0x300, 10) succeeded.");
+
+ ret = posix_memalign (&p, 0, 10);
+
+ if (ret != EINVAL)
+ merror ("posix_memalign (&p, 0, 10) succeeded.");
+
+ p = NULL;
+
+ ret = posix_memalign (&p, 0x100, 10);
+
+ if (ret != 0)
+ merror ("posix_memalign (&p, 0x100, 10) failed.");
+
+ if (ret == 0 && p == NULL)
+ merror ("returned success but pointer is NULL");
+
+ ptrval = (unsigned long) p;
+
+ if (ret == 0 && (ptrval & 0xff) != 0)
+ merror ("pointer is not aligned to 0x100");
+
+ free (p);
+
+ return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libc/malloc/tst-pvalloc.c b/libc/malloc/tst-pvalloc.c
new file mode 100644
index 000000000..1c8129492
--- /dev/null
+++ b/libc/malloc/tst-pvalloc.c
@@ -0,0 +1,99 @@
+/* Test for pvalloc.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+ ++errors;
+ printf ("Error: %s\n", msg);
+}
+
+static int
+do_test (void)
+{
+ void *p;
+ unsigned long pagesize = getpagesize ();
+ unsigned long ptrval;
+ int save;
+
+ errno = 0;
+
+ /* An attempt to allocate a huge value should return NULL and set
+ errno to ENOMEM. */
+ p = pvalloc (-1);
+
+ save = errno;
+
+ if (p != NULL)
+ merror ("pvalloc (-1) succeeded.");
+
+ if (p == NULL && save != ENOMEM)
+ merror ("pvalloc (-1) errno is not set correctly");
+
+ free (p);
+
+ errno = 0;
+
+ /* Test to expose integer overflow in malloc internals from BZ #15855. */
+ p = pvalloc (-pagesize);
+
+ save = errno;
+
+ if (p != NULL)
+ merror ("pvalloc (-pagesize) succeeded.");
+
+ if (p == NULL && save != ENOMEM)
+ merror ("pvalloc (-pagesize) errno is not set correctly");
+
+ free (p);
+
+ /* A zero-sized allocation should succeed with glibc, returning a
+ non-NULL value. */
+ p = pvalloc (0);
+
+ if (p == NULL)
+ merror ("pvalloc (0) failed.");
+
+ free (p);
+
+ /* Check the alignment of the returned pointer is correct. */
+ p = pvalloc (32);
+
+ if (p == NULL)
+ merror ("pvalloc (32) failed.");
+
+ ptrval = (unsigned long) p;
+
+ if ((ptrval & (pagesize - 1)) != 0)
+ merror ("returned pointer is not page aligned.");
+
+ free (p);
+
+ return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libc/malloc/tst-realloc.c b/libc/malloc/tst-realloc.c
new file mode 100644
index 000000000..9d290d24c
--- /dev/null
+++ b/libc/malloc/tst-realloc.c
@@ -0,0 +1,146 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+ ++errors;
+ printf ("Error: %s\n", msg);
+}
+
+static int
+do_test (void)
+{
+ void *p;
+ unsigned char *c;
+ int save, i, ok;
+
+ errno = 0;
+
+ /* realloc (NULL, ...) behaves similarly to malloc (C89). */
+ p = realloc (NULL, -1);
+ save = errno;
+
+ if (p != NULL)
+ merror ("realloc (NULL, -1) succeeded.");
+
+ /* errno should be set to ENOMEM on failure (POSIX). */
+ if (p == NULL && save != ENOMEM)
+ merror ("errno is not set correctly");
+
+ errno = 0;
+
+ /* realloc (NULL, ...) behaves similarly to malloc (C89). */
+ p = realloc (NULL, 10);
+ save = errno;
+
+ if (p == NULL)
+ merror ("realloc (NULL, 10) failed.");
+
+ /* errno should be clear on success (POSIX). */
+ if (p != NULL && save != 0)
+ merror ("errno is set but should not be");
+
+ free (p);
+
+ p = calloc (20, 1);
+ if (p == NULL)
+ merror ("calloc (20, 1) failed.");
+
+ /* Check increasing size preserves contents (C89). */
+ p = realloc (p, 200);
+ if (p == NULL)
+ merror ("realloc (p, 200) failed.");
+
+ c = p;
+ ok = 1;
+
+ for (i = 0; i < 20; i++)
+ {
+ if (c[i] != 0)
+ ok = 0;
+ }
+
+ if (ok == 0)
+ merror ("first 20 bytes were not cleared");
+
+ free (p);
+
+ p = realloc (NULL, 100);
+ if (p == NULL)
+ merror ("realloc (NULL, 100) failed.");
+
+ memset (p, 0xff, 100);
+
+ /* Check decreasing size preserves contents (C89). */
+ p = realloc (p, 16);
+ if (p == NULL)
+ merror ("realloc (p, 16) failed.");
+
+ c = p;
+ ok = 1;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (c[i] != 0xff)
+ ok = 0;
+ }
+
+ if (ok == 0)
+ merror ("first 16 bytes were not correct");
+
+ /* Check failed realloc leaves original untouched (C89). */
+ c = realloc (p, -1);
+ if (c != NULL)
+ merror ("realloc (p, -1) succeeded.");
+
+ c = p;
+ ok = 1;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (c[i] != 0xff)
+ ok = 0;
+ }
+
+ if (ok == 0)
+ merror ("first 16 bytes were not correct after failed realloc");
+
+ /* realloc (p, 0) frees p (C89) and returns NULL (glibc). */
+ p = realloc (p, 0);
+ if (p != NULL)
+ merror ("realloc (p, 0) returned non-NULL.");
+
+ /* realloc (NULL, 0) acts like malloc (0) (glibc). */
+ p = realloc (NULL, 0);
+ if (p == NULL)
+ merror ("realloc (NULL, 0) returned NULL.");
+
+ free (p);
+
+ return errors != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libc/malloc/tst-valloc.c b/libc/malloc/tst-valloc.c
index 643a0dda4..4fd0dbb96 100644
--- a/libc/malloc/tst-valloc.c
+++ b/libc/malloc/tst-valloc.c
@@ -1,23 +1,99 @@
-/* Test case by Stephen Tweedie <sct@redhat.com>. */
-#include <unistd.h>
-#include <stdio.h>
+/* Test for valloc.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
-int
-main (void)
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+ ++errors;
+ printf ("Error: %s\n", msg);
+}
+
+static int
+do_test (void)
{
- char *p;
- int pagesize = getpagesize ();
- int i;
+ void *p;
+ unsigned long pagesize = getpagesize ();
+ unsigned long ptrval;
+ int save;
+
+ errno = 0;
+
+ /* An attempt to allocate a huge value should return NULL and set
+ errno to ENOMEM. */
+ p = valloc (-1);
+
+ save = errno;
+
+ if (p != NULL)
+ merror ("valloc (-1) succeeded.");
- p = valloc (pagesize);
- i = (long int) p;
+ if (p == NULL && save != ENOMEM)
+ merror ("valloc (-1) errno is not set correctly");
- if ((i & (pagesize-1)) != 0)
- {
- fprintf (stderr, "Alignment problem: valloc returns %p\n", p);
- exit (1);
- }
+ free (p);
- return 0;
+ errno = 0;
+
+ /* Test to expose integer overflow in malloc internals from BZ #15856. */
+ p = valloc (-pagesize);
+
+ save = errno;
+
+ if (p != NULL)
+ merror ("valloc (-pagesize) succeeded.");
+
+ if (p == NULL && save != ENOMEM)
+ merror ("valloc (-pagesize) errno is not set correctly");
+
+ free (p);
+
+ /* A zero-sized allocation should succeed with glibc, returning a
+ non-NULL value. */
+ p = valloc (0);
+
+ if (p == NULL)
+ merror ("valloc (0) failed.");
+
+ free (p);
+
+ /* Check the alignment of the returned pointer is correct. */
+ p = valloc (32);
+
+ if (p == NULL)
+ merror ("valloc (32) failed.");
+
+ ptrval = (unsigned long) p;
+
+ if ((ptrval & (pagesize - 1)) != 0)
+ merror ("returned pointer is not page aligned.");
+
+ free (p);
+
+ return errors != 0;
}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"