1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright © 2020 Keith Packard
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above
14  *    copyright notice, this list of conditions and the following
15  *    disclaimer in the documentation and/or other materials provided
16  *    with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #define _DEFAULT_SOURCE
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <malloc.h>
42 #include <stdlib.h>
43 #include <stdint.h>
44 
45 #ifndef __clang__
46 #pragma GCC diagnostic ignored "-Walloc-size-larger-than="
47 #endif
48 
49 int
main(void)50 main(void)
51 {
52 	void *r;
53 	int result = 0;
54 	int pow;
55 
56 	errno = 0;
57 	r = malloc(0);
58         printf("malloc(0): %p\n", r);
59 	if (errno != 0) {
60 		printf("malloc(0) failed: %s. got %p\n", strerror(errno), r);
61 		result++;
62 	}
63 	free(r);
64 
65 	r = memalign(128, 237);
66         printf("memalign(128, 237): %p\n", r);
67 	if ((uintptr_t) r & 127) {
68 		printf("memalign(128, 237) unaligned (%p)\n", r);
69 		result++;
70 	}
71 	free(r);
72 
73 	errno = 0;
74 	r = malloc(PTRDIFF_MAX);
75         printf("malloc(PTRDIFF_MAX): %p\n", r);
76 	if (r || errno != ENOMEM) {
77                 printf("malloc(PTRDIFF_MAX) should have failed. got %p error %s\n", r, strerror(errno));
78 		result++;
79 	}
80 
81 	errno = 0;
82 	r = malloc(SIZE_MAX);
83         printf("malloc(SIZE_MAX): %p\n", r);
84 	if (r || errno != ENOMEM) {
85 		printf("malloc(SIZE_MAX) should have failed. got %p error %s\n", r, strerror(errno));
86 		result++;
87 	}
88 
89 	errno = 0;
90 	r = calloc(1, SIZE_MAX);
91         printf("calloc(1, SIZE_MAX): %p\n", r);
92 	if (r || errno != ENOMEM) {
93 		printf("calloc(1, SIZE_MAX) should have failed. got %p error %s\n", r, strerror(errno));
94 		result++;
95 	}
96 
97 	errno = 0;
98 	r = reallocarray(NULL, 1, SIZE_MAX);
99         printf("reallocarray(NULL, 1, SIZE_MAX): %p\n", r);
100 	if (r || errno != ENOMEM) {
101 		printf("reallocarray(NULL, 1, SIZE_MAX) should have failed. got %p error %s\n", r, strerror(errno));
102 		result++;
103 	}
104 
105 	for (pow = 0; pow < 4; pow++) {
106 		errno = 0;
107 		r = calloc(SIZE_MAX >> pow, SIZE_MAX >> pow);
108                 printf("calloc(SIZE_MAX >> %d, SIZE_MAX >> %d): %p\n", pow, pow, r);
109 		if (r || errno != ENOMEM) {
110 			printf("calloc(SIZE_MAX >> %d, SIZE_MAX >> %d) should have failed. got %p error %s\n", pow, pow, r, strerror(errno));
111 			result++;
112 		}
113 		r = reallocarray(NULL, SIZE_MAX >> pow, SIZE_MAX >> pow);
114                 printf("reallocarray(SIZE_MAX >> %d, SIZE_MAX >> %d): %p\n", pow, pow, r);
115 		if (r || errno != ENOMEM) {
116 			printf("reallocarray(NULL, SIZE_MAX >> %d, SIZE_MAX >> %d) should have failed. got %p error %s\n", pow, pow, r, strerror(errno));
117 			result++;
118 		}
119 	}
120 
121 	/* make sure realloc doesn't read past the source */
122 
123 	void *big = malloc(1024);
124 	memset(big, '1', 1024);
125         printf("big %p\n", big);
126 	if (big) {
127 		void *small = malloc(128);
128 		memset(small, '2', 128);
129                 printf("small %p\n", small);
130 		if (small) {
131                         (void) atoi(small);
132 			free(big);
133 			char *med = realloc(small, 1024);
134 			if (med) {
135                                 printf("med %p\n", med);
136 #ifdef _NANO_MALLOC
137 				int i;
138 				for (i = 128; i < 1024; i++)
139 					if (med[i] != 0) {
140 						printf("looks like realloc read past old at %d (saw %d)\n", i, med[i]);
141 						++result;
142 					}
143 #endif
144 				free(med);
145 				small = NULL;
146 			}
147 			free (small);
148 		}
149 	}
150 
151 	malloc_stats();
152 
153 	return result;
154 }
155