1 | /* Test that malloc uses mmap when sbrk or brk fails. |
2 | Copyright (C) 2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | /* This test sets up an obstruction to ensure that brk/sbrk fails to |
20 | grow the heap, then verifies that malloc uses mmap for allocations |
21 | instead. */ |
22 | |
23 | #include <unistd.h> |
24 | #include <sys/mman.h> |
25 | #include <stdlib.h> |
26 | #include <libc-pointer-arith.h> |
27 | #include <support/check.h> |
28 | #include <stddef.h> |
29 | #include <stdalign.h> |
30 | |
31 | #define LARGE_SIZE (10 * (1 << 20)) // 10 MB |
32 | static long page_size; |
33 | |
34 | static int |
35 | do_test (void) |
36 | { |
37 | /* Get current program break. */ |
38 | void *current_brk = sbrk (delta: 0); |
39 | |
40 | page_size = sysconf (_SC_PAGESIZE); |
41 | |
42 | /* Round up to the next page boundary. */ |
43 | void *next_page_boundary = PTR_ALIGN_UP (current_brk, page_size); |
44 | |
45 | /* Place a mapping using mmap at the next page boundary. */ |
46 | void *obstruction_addr |
47 | = mmap (addr: next_page_boundary, len: page_size, PROT_READ, |
48 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, fd: -1, offset: 0); |
49 | |
50 | /* Check if memory obstruction is set up correctly. */ |
51 | TEST_VERIFY_EXIT (obstruction_addr == next_page_boundary); |
52 | |
53 | /* Try to extend the heap beyond the obstruction using sbrk */ |
54 | int *ptr = sbrk (delta: page_size); |
55 | TEST_VERIFY_EXIT (ptr == (void *) -1); |
56 | |
57 | /* Attempt multiple small allocations using malloc. */ |
58 | for (size_t i = 0; i < page_size / alignof (max_align_t); i++) |
59 | { |
60 | TEST_VERIFY (malloc (alignof (max_align_t))); |
61 | } |
62 | |
63 | /* Attempt to allocate a large block of memory using malloc. */ |
64 | TEST_VERIFY_EXIT (malloc (LARGE_SIZE) != NULL); |
65 | |
66 | /* Check if malloc changed current program break. */ |
67 | TEST_VERIFY_EXIT (current_brk == sbrk (0)); |
68 | |
69 | return 0; |
70 | } |
71 | |
72 | #include <support/test-driver.c> |
73 | |