Skip to content

Commit

Permalink
Demonstrate how to trick llvm scan-build's core.StackAddressEscape
Browse files Browse the repository at this point in the history
  • Loading branch information
Craig Ringer committed Sep 9, 2020
1 parent 64e5d52 commit bb687b0
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
1 change: 1 addition & 0 deletions c/clang_return_stack_checks/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ sigjmp_escape_noinner
sigjmp_escape_noinner_fake*
sigjmp_escape_hdr
sigjmp_escape_inner_pop
mask_local_escape
scan-build-*/
10 changes: 8 additions & 2 deletions c/clang_return_stack_checks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ sigjmp_escape_hdr: sigjmp_escape_hdr.c sigjmp_escape_hdr_try.c | tmpdir
$(CC) $(CFLAGS) -DUSE_FINALLY -c sigjmp_escape_hdr.c -o sigjmp_escape_hdr.o
$(CC) $(CFLAGS_LINK) sigjmp_escape_hdr.o sigjmp_escape_hdr_try.o -o $@

mask_local_escape: mask_local_escape.c | tmpdir
$(CC) $(CFLAGS) $< -o $@

clean:
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
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
rm -rf scan-build-*

run_return_stack_escape: return_stack_escape
Expand All @@ -67,6 +70,9 @@ run_sigjmp_escape_hdr: sigjmp_escape_hdr
if ./sigjmp_escape_hdr 0 1; then exit 1; fi
./sigjmp_escape_hdr 1 1

run: run_return_stack_escape run_sigjmp_escape run_sigjmp_escape_hdr
run_mask_local_escape: mask_local_escape
./mask_local_escape

run: run_return_stack_escape run_sigjmp_escape run_sigjmp_escape_hdr run_mask_local_escape

check: run
62 changes: 62 additions & 0 deletions c/clang_return_stack_checks/mask_local_escape.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Demonstrate how to trick llvm scan-build's core.StackAddressEscape checker
* via simple indirection.
*/

#include <stdio.h>
#include <assert.h>

struct chain_container {
int * leaky_member;
struct chain_container * previous;
};

struct chain_container * sneaky_chain_container = 0;
void
escape_via_sneaky_chain_assignment_1(void)
{
struct chain_container new_entry = {0,0};
int g = 1;
fprintf(stderr, "&g = %p\n", &g);
/* g escapes into global scope */
sneaky_chain_container->leaky_member = &g;
/* Pointer to container is replaced with indirect pointer via chain */
new_entry.previous = sneaky_chain_container;
sneaky_chain_container = &new_entry;

/*
* Restore container pointer from caller.
*
* scan-build has lost track of &g in its leaky_member now.
*/
sneaky_chain_container = sneaky_chain_container->previous;

/* even though we definitely leak it */
assert(sneaky_chain_container->leaky_member == &g);
}

void
escape_via_sneaky_chain_assignment(void)
{
struct chain_container parent_sneaky = {0,0};
sneaky_chain_container = &parent_sneaky;
escape_via_sneaky_chain_assignment_1();
/*
* pointer to auto variable from escape_via_sneaky_chain_assignment_1
* has escaped. Dereferencing it would be a memory error.
*/
fprintf(stderr, "&g has escaped: %p\n",
sneaky_chain_container->leaky_member);

/*
* Ensure we don't complain about &parent_sneaky escaping.
*/
sneaky_chain_container = 0;
}

int
main(void)
{
escape_via_sneaky_chain_assignment();
return 0;
}

0 comments on commit bb687b0

Please sign in to comment.