Skip to content

Commit bb687b0

Browse files
author
Craig Ringer
committed
Demonstrate how to trick llvm scan-build's core.StackAddressEscape
1 parent 64e5d52 commit bb687b0

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

c/clang_return_stack_checks/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ sigjmp_escape_noinner
77
sigjmp_escape_noinner_fake*
88
sigjmp_escape_hdr
99
sigjmp_escape_inner_pop
10+
mask_local_escape
1011
scan-build-*/

c/clang_return_stack_checks/Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ sigjmp_escape_hdr: sigjmp_escape_hdr.c sigjmp_escape_hdr_try.c | tmpdir
4747
$(CC) $(CFLAGS) -DUSE_FINALLY -c sigjmp_escape_hdr.c -o sigjmp_escape_hdr.o
4848
$(CC) $(CFLAGS_LINK) sigjmp_escape_hdr.o sigjmp_escape_hdr_try.o -o $@
4949

50+
mask_local_escape: mask_local_escape.c | tmpdir
51+
$(CC) $(CFLAGS) $< -o $@
52+
5053
clean:
51-
rm -f *.o guard.so return_stack_escape sigjmp_escape sigjmp_escape_fake* sigjmp_escape_guard sigjmp_escape_guard_fake* sigjmp_escape_guard_inner_pop sigjmp_escape_hdr
54+
rm -f *.o guard.so return_stack_escape sigjmp_escape sigjmp_escape_fake* sigjmp_escape_guard sigjmp_escape_guard_fake* sigjmp_escape_guard_inner_pop sigjmp_escape_hdr mask_local_escape
5255
rm -rf scan-build-*
5356

5457
run_return_stack_escape: return_stack_escape
@@ -67,6 +70,9 @@ run_sigjmp_escape_hdr: sigjmp_escape_hdr
6770
if ./sigjmp_escape_hdr 0 1; then exit 1; fi
6871
./sigjmp_escape_hdr 1 1
6972

70-
run: run_return_stack_escape run_sigjmp_escape run_sigjmp_escape_hdr
73+
run_mask_local_escape: mask_local_escape
74+
./mask_local_escape
75+
76+
run: run_return_stack_escape run_sigjmp_escape run_sigjmp_escape_hdr run_mask_local_escape
7177

7278
check: run
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Demonstrate how to trick llvm scan-build's core.StackAddressEscape checker
3+
* via simple indirection.
4+
*/
5+
6+
#include <stdio.h>
7+
#include <assert.h>
8+
9+
struct chain_container {
10+
int * leaky_member;
11+
struct chain_container * previous;
12+
};
13+
14+
struct chain_container * sneaky_chain_container = 0;
15+
void
16+
escape_via_sneaky_chain_assignment_1(void)
17+
{
18+
struct chain_container new_entry = {0,0};
19+
int g = 1;
20+
fprintf(stderr, "&g = %p\n", &g);
21+
/* g escapes into global scope */
22+
sneaky_chain_container->leaky_member = &g;
23+
/* Pointer to container is replaced with indirect pointer via chain */
24+
new_entry.previous = sneaky_chain_container;
25+
sneaky_chain_container = &new_entry;
26+
27+
/*
28+
* Restore container pointer from caller.
29+
*
30+
* scan-build has lost track of &g in its leaky_member now.
31+
*/
32+
sneaky_chain_container = sneaky_chain_container->previous;
33+
34+
/* even though we definitely leak it */
35+
assert(sneaky_chain_container->leaky_member == &g);
36+
}
37+
38+
void
39+
escape_via_sneaky_chain_assignment(void)
40+
{
41+
struct chain_container parent_sneaky = {0,0};
42+
sneaky_chain_container = &parent_sneaky;
43+
escape_via_sneaky_chain_assignment_1();
44+
/*
45+
* pointer to auto variable from escape_via_sneaky_chain_assignment_1
46+
* has escaped. Dereferencing it would be a memory error.
47+
*/
48+
fprintf(stderr, "&g has escaped: %p\n",
49+
sneaky_chain_container->leaky_member);
50+
51+
/*
52+
* Ensure we don't complain about &parent_sneaky escaping.
53+
*/
54+
sneaky_chain_container = 0;
55+
}
56+
57+
int
58+
main(void)
59+
{
60+
escape_via_sneaky_chain_assignment();
61+
return 0;
62+
}

0 commit comments

Comments
 (0)