1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -fblocks -verify %s
5 return &x
; // expected-warning{{Address of stack memory associated with local variable 'x' returned}} expected-warning{{address of stack memory associated with local variable 'x' returned}}
9 return &y
; // expected-warning{{Address of stack memory associated with local variable 'y' returned}} expected-warning{{address of stack memory associated with parameter 'y' returned}}
12 int* f3(int x
, int *y
) {
18 return y
; // expected-warning{{Address of stack memory associated with local variable 'w' returned to caller}}
21 void* compound_literal(int x
, int y
) {
23 return &(unsigned short){((unsigned short)0x22EF)};
24 // expected-warning-re@-1{{Address of stack memory associated with a compound literal declared on line {{[0-9]+}} returned to caller [core.StackAddressEscape]}}
25 // expected-warning@-2{{address of stack memory}}
28 struct s
{ int z
; double y
; int w
; };
31 return &((struct s
){ 2, 0.4, 5 * 8 });
32 // expected-warning-re@-1{{Address of stack memory associated with a compound literal declared on line {{[0-9]+}} returned to caller [core.StackAddressEscape]}}
33 // expected-warning@-2{{address of stack memory}}
35 void* p
= &((struct s
){ 42, 0.4, x
? 42 : 0 });
37 // expected-warning-re@-1{{Address of stack memory associated with a compound literal declared on line {{[0-9]+}} returned to caller [core.StackAddressEscape]}}
40 void* alloca_test(void) {
41 void* p
= __builtin_alloca(10);
42 return p
; // expected-warning{{Address of stack memory}}
45 int array_test(int x
[2]) {
46 return x
[0]; // no-warning
54 int struct_test(struct baz byVal
, int flag
) {
56 return byVal
.x
; // no-warning
58 return byVal
.y
[0]; // no-warning
62 typedef int (^ComparatorBlock
)(int a
, int b
);
63 ComparatorBlock
test_return_block(void) {
64 // This block is a global since it has no captures.
65 ComparatorBlock b
= ^int(int a
, int b
){ return a
> b
; };
66 return b
; // no-warning
69 ComparatorBlock
test_return_block_with_capture(int x
) {
70 // This block is stack allocated because it has captures.
71 ComparatorBlock b
= ^int(int a
, int b
){ return a
> b
+ x
; };
72 return b
; // expected-warning{{Address of stack-allocated block}}
75 ComparatorBlock
test_return_block_neg_aux(void);
76 ComparatorBlock
test_return_block_neg(void) {
77 ComparatorBlock b
= test_return_block_neg_aux();
78 return b
; // no-warning
81 int *rdar_7523821_f2(void) {
83 return a
; // expected-warning 2 {{ddress of stack memory associated with local variable 'a' returned}}
86 // Handle blocks that have no captures or are otherwise declared 'static'.
87 typedef int (^RDar10348049
)(int value
);
88 RDar10348049
test_rdar10348049(void) {
89 static RDar10348049 b
= ^int(int x
) {
92 return b
; // no-warning
95 void testRegister(register const char *reg
) {
96 if (reg
) (void)reg
[0];
98 void callTestRegister(void) {
100 testRegister(buf
); // no-warning
103 void top_level_leaking(int **out
) {
105 *out
= &local
; // expected-warning{{Address of stack memory associated with local variable 'local' is still referred to by the caller variable 'out'}}
108 void callee_leaking_via_param(int **out
) {
111 // expected-warning@-1{{Address of stack memory associated with local variable 'local' is still referred to by the caller variable 'ptr'}}
114 void caller_for_leaking_callee() {
116 callee_leaking_via_param(&ptr
);
119 void callee_nested_leaking(int **out
) {
122 // expected-warning@-1{{Address of stack memory associated with local variable 'local' is still referred to by the caller variable 'ptr'}}
125 void caller_mid_for_nested_leaking(int **mid
) {
126 callee_nested_leaking(mid
);
129 void caller_for_nested_leaking() {
131 caller_mid_for_nested_leaking(&ptr
);
134 // This used to crash StackAddrEscapeChecker because
135 // it features a symbol conj_$1{struct c *, LC1, S763, #1}
136 // that has no origin region.
142 struct a
*nested_ptr
;
144 void opaque(struct c
*);
145 struct c
* get_c(void);
146 void no_crash_for_symbol_without_origin_region(void) {
147 struct c
*ptr
= get_c();
149 ptr
->nested_ptr
->member
++;
150 } // No crash at the end of the function