Skip to content

Commit 9ca3279

Browse files
committed
test: add tests for zero sized realloc(3)
C23 declared calling realloc(3) with a non-NULL pointer and zero size Undefined behavior. Check that hardened_malloc handles that case sanely by free'ing the old pointer and returning a special pointer, like `malloc(3)` called with size zero.
1 parent 1d7fc7f commit 9ca3279

File tree

6 files changed

+80
-1
lines changed

6 files changed

+80
-1
lines changed

test/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,7 @@ overflow_small_8_byte
4141
uninitialized_read_large
4242
uninitialized_read_small
4343
realloc_init
44+
realloc_c23_undefined_behaviour
45+
realloc_c23_undefined_behaviour_double_free
46+
realloc_c23_undefined_behaviour_use_after_free
4447
__pycache__/

test/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ EXECUTABLES := \
6767
invalid_malloc_object_size_small \
6868
invalid_malloc_object_size_small_quarantine \
6969
impossibly_large_malloc \
70-
realloc_init
70+
realloc_init \
71+
realloc_c23_undefined_behaviour \
72+
realloc_c23_undefined_behaviour_double_free \
73+
realloc_c23_undefined_behaviour_use_after_free
7174

7275
all: $(EXECUTABLES)
7376

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
#include "test_util.h"
5+
6+
OPTNONE int main(void) {
7+
char *p, *q, *r;
8+
9+
p = malloc(16);
10+
if (!p) {
11+
return 1;
12+
}
13+
14+
q = realloc(p, 0);
15+
16+
free(q);
17+
18+
return 0;
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
#include "test_util.h"
5+
6+
OPTNONE int main(void) {
7+
char *p, *q, *r;
8+
9+
p = malloc(16);
10+
if (!p) {
11+
return 1;
12+
}
13+
14+
q = realloc(p, 0);
15+
16+
free(p);
17+
18+
return 0;
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
#include "test_util.h"
5+
6+
OPTNONE int main(void) {
7+
char *p, *q, *r;
8+
9+
p = malloc(256 * 1024);
10+
if (!p) {
11+
return 1;
12+
}
13+
14+
q = realloc(p, 0);
15+
16+
printf("%c\n", *p);
17+
18+
free(q);
19+
20+
return 0;
21+
}

test/test_smc.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ def test_uninitialized_realloc(self):
169169
self.assertEqual(stderr.decode("utf-8"),
170170
"fatal allocator error: invalid realloc\n")
171171

172+
def test_realloc_c23_undefined_behaviour(self):
173+
_stdout, stderr, returncode = self.run_test("realloc_c23_undefined_behaviour")
174+
self.assertEqual(returncode, 0)
175+
176+
def test_realloc_c23_undefined_behaviour_double_free(self):
177+
_stdout, stderr, returncode = self.run_test("realloc_c23_undefined_behaviour_double_free")
178+
self.assertEqual(returncode, -6)
179+
self.assertEqual(stderr.decode("utf-8"),
180+
"fatal allocator error: double free (quarantine)\n")
181+
182+
def test_realloc_c23_undefined_behaviour_use_after_free(self):
183+
_stdout, stderr, returncode = self.run_test("realloc_c23_undefined_behaviour_use_after_free")
184+
self.assertEqual(returncode, -11)
185+
172186
def test_write_after_free_large_reuse(self):
173187
_stdout, _stderr, returncode = self.run_test(
174188
"write_after_free_large_reuse")

0 commit comments

Comments
 (0)