brintos

brintos / llvm-project-archived public Read only

0
0
Text · 33.3 KiB · 0ca7b07 Raw
1130 lines · cpp
1// RUN: %clang_analyze_cc1 \2// RUN:   -analyzer-checker=core,debug.ExprInspection \3// RUN:   -verify %s \4// RUN:   -Wno-undefined-bool-conversion5// RUN: %clang_analyze_cc1 \6// RUN:   -analyzer-checker=core,debug.ExprInspection,unix.Malloc \7// RUN:   -verify %s \8// RUN:   -Wno-undefined-bool-conversion9// unix.Malloc is necessary to model __builtin_alloca,10// which could trigger an "unexpected region" bug in StackAddrEscapeChecker.11 12typedef __INTPTR_TYPE__ intptr_t;13 14template <typename T>15void clang_analyzer_dump(T x);16 17using size_t = decltype(sizeof(int));18void * malloc(size_t size);19void free(void*);20 21const int& g() {22  int s;23  return s; // expected-warning{{Address of stack memory associated with local variable 's' returned}} expected-warning{{reference to stack memory associated with local variable 's' returned}}24}25 26const int& g2() {27  int s1;28  int &s2 = s1; // expected-note {{binding reference variable 's2' here}}29  return s2; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}}30}31 32const int& g3() {33  int s1;34  int &s2 = s1; // expected-note {{binding reference variable 's2' here}}35  int &s3 = s2; // expected-note {{binding reference variable 's3' here}}36  return s3; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{reference to stack memory associated with local variable 's1' returned}}37}38 39void g4() {40  static const int &x = 3; // no warning41}42 43int get_value();44 45const int &get_reference1() { return get_value(); } // expected-warning{{Address of stack memory associated with temporary object of type 'int' returned}} expected-warning {{returning reference to local temporary}}46 47const int &get_reference2() {48  const int &x = get_value(); // expected-note {{binding reference variable 'x' here}}49  return x; // expected-warning{{Address of stack memory associated with temporary object of type 'int' lifetime extended by local variable 'x' returned to caller}} expected-warning {{returning reference to local temporary}} 50}51 52const int &get_reference3() {53  const int &x1 = get_value(); // expected-note {{binding reference variable 'x1' here}}54  const int &x2 = x1; // expected-note {{binding reference variable 'x2' here}}55  return x2; // expected-warning{{Address of stack memory associated with temporary object of type 'int' lifetime extended by local variable 'x1' returned to caller}} expected-warning {{returning reference to local temporary}}56}57 58int global_var;59int *f1() {60  int &y = global_var;61  return &y;62}63 64int *f2() {65  int x1;66  int &x2 = x1; // expected-note {{binding reference variable 'x2' here}}67  return &x2; // expected-warning{{Address of stack memory associated with local variable 'x1' returned}} expected-warning {{address of stack memory associated with local variable 'x1' returned}}68}69 70int *f3() {71  int x1;72  int *const &x2 = &x1; // expected-note {{binding reference variable 'x2' here}}73  return x2; // expected-warning {{address of stack memory associated with local variable 'x1' returned}} expected-warning {{Address of stack memory associated with local variable 'x1' returned to caller}}74}75 76const int *f4() {77  const int &x1 = get_value(); // expected-note {{binding reference variable 'x1' here}}78  const int &x2 = x1; // expected-note {{binding reference variable 'x2' here}}79  return &x2; // expected-warning{{Address of stack memory associated with temporary object of type 'int' lifetime extended by local variable 'x1' returned to caller}} expected-warning {{returning address of local temporary}}80}81 82struct S {83  int x;84};85 86int *mf() {87  S s1;88  S &s2 = s1; // expected-note {{binding reference variable 's2' here}}89  int &x = s2.x; // expected-note {{binding reference variable 'x' here}}90  return &x; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{address of stack memory associated with local variable 's1' returned}}91}92 93int *return_assign_expr_leak() {94  int x = 1;95  int *y;96  return y = &x; // expected-warning{{Address of stack memory associated with local variable 'x' returned}}97}98 99// Additional diagnostic from -Wreturn-stack-address in the simple case?100int *return_comma_separated_expressions_leak() {101  int x = 1;102  return (x=14), &x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning{{address of stack memory associated with local variable 'x' returned}}103}104 105void *lf() {106    label:107    void *const &x = &&label; // expected-note {{binding reference variable 'x' here}}108    return x; // expected-warning {{returning address of label, which is local}}109}110 111template <typename T>112struct TS {113  int *get();114  int *m() {115    int *&x = get();116    return x;117  }118};119 120int* f5() {121  int& i = i; // expected-warning {{Assigned value is uninitialized}} expected-warning{{reference 'i' is not yet bound to a value when used within its own initialization}}122  return &i;123}124 125void *radar13226577() {126    void *p = &p;127    return p; // expected-warning {{stack memory associated with local variable 'p' returned to caller}}128}129 130namespace rdar13296133 {131  class ConvertsToBool {132  public:133    operator bool() const { return this; }134  };135 136  class ConvertsToIntptr {137  public:138    operator intptr_t() const { return reinterpret_cast<intptr_t>(this); }139  };140 141  class ConvertsToPointer {142  public:143    operator const void *() const { return this; }144  };145 146  intptr_t returnAsNonLoc() {147    ConvertsToIntptr obj;148    return obj; // expected-warning{{Address of stack memory associated with local variable 'obj' returned to caller}}149  }150 151  bool returnAsBool() {152    ConvertsToBool obj;153    return obj; // no-warning154  }155 156  intptr_t returnAsNonLocViaPointer() {157    ConvertsToPointer obj;158    return reinterpret_cast<intptr_t>(static_cast<const void *>(obj)); // expected-warning{{Address of stack memory associated with local variable 'obj' returned to caller}}159  }160 161  bool returnAsBoolViaPointer() {162    ConvertsToPointer obj;163    return obj; // no-warning164  }165} // namespace rdar13296133166 167void* ret_cpp_static_cast(short x) {168  return static_cast<void*>(&x); // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory}}169}170 171int* ret_cpp_reinterpret_cast(double x) {172  return reinterpret_cast<int*>(&x); // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack me}}173}174 175int* ret_cpp_const_cast(const int x) {176  return const_cast<int*>(&x);  // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory}}177}178 179void write_stack_address_to(char **q) {180  char local;181  *q = &local;182  // expected-warning@-1 {{Address of stack memory associated with local \183variable 'local' is still referred to by the caller variable 'p' upon \184returning to the caller}}185}186 187void test_stack() {188  char *p;189  write_stack_address_to(&p);190}191 192struct C {193  ~C() {} // non-trivial class194};195 196C make1() {197  C c;198  return c; // no-warning199}200 201void test_copy_elision() {202  C c1 = make1();203}204 205C&& return_bind_rvalue_reference_to_temporary() {206  return C(); // expected-warning{{Address of stack memory associated with temporary object of type 'C' returned to caller}}207  // expected-warning@-1{{returning reference to local temporary object}} -Wreturn-stack-address208}209 210namespace leaking_via_direct_pointer {211void* returned_direct_pointer_top() {212  int local = 42;213  int* p = &local;214  return p; // expected-warning{{associated with local variable 'local' returned}}215}216 217int* returned_direct_pointer_callee() {218  int local = 42;219  int* p = &local;220  return p; // expected-warning{{associated with local variable 'local' returned}}221}222 223void returned_direct_pointer_caller() {224  int* loc_ptr = nullptr;225  loc_ptr = returned_direct_pointer_callee();226  (void)loc_ptr;227}228 229void* global_ptr;230 231void global_direct_pointer() {232  int local = 42;233  global_ptr = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_ptr'}}234}235 236void static_direct_pointer_top() {237  int local = 42;238  static int* p = &local;239  (void)p; // expected-warning{{local variable 'local' is still referred to by the static variable 'p'}}240}241 242void static_direct_pointer_callee() {243  int local = 42;244  static int* p = &local;245  (void)p; // expected-warning{{local variable 'local' is still referred to by the static variable 'p'}}246}247 248void static_direct_pointer_caller() {249  static_direct_pointer_callee();250}251 252void lambda_to_global_direct_pointer() {253  auto lambda = [&] {254    int local = 42;255    global_ptr = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_ptr'}}256  };257  lambda();258}259 260void lambda_to_context_direct_pointer() {261  int *p = nullptr;262  auto lambda = [&] {263    int local = 42;264    p = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}265  };266  lambda();267  (void)p;268}269 270template<typename Callable>271class MyFunction {272  Callable* fptr;273  public:274  MyFunction(Callable* callable) :fptr(callable) {}275};276 277void* lambda_to_context_direct_pointer_uncalled() {278  int *p = nullptr;279  auto lambda = [&] {280    int local = 42;281    p = &local; // no-warning: analyzed only as top-level, ignored explicitly by the checker282  };283  return new MyFunction(&lambda); // expected-warning{{Address of stack memory associated with local variable 'lambda' returned to caller}}284}285 286void lambda_to_context_direct_pointer_lifetime_extended() {287  int *p = nullptr;288  auto lambda = [&] {289    int&& local = 42;290    p = &local; // expected-warning{{'int' lifetime extended by local variable 'local' is still referred to by the caller variable 'p'}}291  };292  lambda();293  (void)p;294}295 296template<typename Callback>297void lambda_param_capture_direct_pointer_callee(Callback& callee) {298  int local = 42;299  callee(local); // expected-warning{{'local' is still referred to by the caller variable 'p'}}300}301 302void lambda_param_capture_direct_pointer_caller() {303  int* p = nullptr;304  auto capt = [&p](int& param) {305    p = &param;306  };307  lambda_param_capture_direct_pointer_callee(capt);308}309} // namespace leaking_via_direct_pointer310 311namespace leaking_via_ptr_to_ptr {312void** returned_ptr_to_ptr_top() {313  int local = 42;314  int* p = &local;315  void** pp = (void**)&p;316  return pp; // expected-warning{{associated with local variable 'p' returned}}317}318 319void** global_pp;320 321void global_ptr_local_to_ptr() {322  int local = 42;323  int* p = &local;324  global_pp = (void**)&p; // expected-warning{{local variable 'p' is still referred to by the global variable 'global_pp'}}325}326 327void global_ptr_to_ptr() {328  int local = 42;329  *global_pp = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_pp'}}330}331 332void *** global_ppp;333 334void global_ptr_to_ptr_to_ptr() {335  int local = 42;336  **global_ppp = &local; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_ppp'}}337}338 339void** get_some_pp();340 341void static_ptr_to_ptr() {342  int local = 42;343  static void** pp = get_some_pp();344  *pp = &local;345} // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.346 347void param_ptr_to_ptr_top(void** pp) {348  int local = 42;349  *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'pp'}}350}351 352void param_ptr_to_ptr_callee(void** pp) {353  int local = 42;354  *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}355}356 357void param_ptr_to_ptr_caller() {358  void* p = nullptr;359  param_ptr_to_ptr_callee((void**)&p);360}361 362void param_ptr_to_ptr_to_ptr_top(void*** ppp) {363  int local = 42;364  **ppp = &local; // expected-warning {{local variable 'local' is still referred to by the caller variable 'ppp'}}365}366 367void param_ptr_to_ptr_to_ptr_callee(void*** ppp) {368  int local = 42;369  **ppp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'pp'}}370}371 372void ***param_ptr_to_ptr_to_ptr_return(void ***ppp) {373  int local = 0;374  **ppp = &local;375  return ppp;376  // expected-warning@-1 {{Address of stack memory associated with local variable 'local' is still referred to by the caller variable 'ppp' upon returning to the caller.  This will be a dangling reference}}377}378 379void param_ptr_to_ptr_to_ptr_caller(void** pp) {380  param_ptr_to_ptr_to_ptr_callee(&pp);381}382 383void lambda_to_context_ptr_to_ptr(int **pp) {384  auto lambda = [&] {385    int local = 42;386    *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'pp'}}387  };388  lambda();389  (void)*pp;390}391 392void param_ptr_to_ptr_fptr(int **pp) {393  int local = 42;394  *pp = &local; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}395}396 397void param_ptr_to_ptr_fptr_caller(void (*fptr)(int**)) {398  int* p = nullptr;399  fptr(&p);400}401 402void param_ptr_to_ptr_caller_caller() {403  void (*fptr)(int**) = param_ptr_to_ptr_fptr;404  param_ptr_to_ptr_fptr_caller(fptr);405}406} // namespace leaking_via_ptr_to_ptr407 408namespace leaking_via_ref_to_ptr {409void** make_ptr_to_ptr();410void*& global_rtp = *make_ptr_to_ptr();411 412void global_ref_to_ptr() {413  int local = 42;414  int* p = &local;415  global_rtp = p; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_rtp'}}416}417 418void static_ref_to_ptr() {419  int local = 42;420  static void*& p = *make_ptr_to_ptr();421  p = &local;422  (void)p;423} // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.424 425void param_ref_to_ptr_top(void*& rp) {426  int local = 42;427  int* p = &local;428  rp = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'rp'}}429}430 431void param_ref_to_ptr_callee(void*& rp) {432  int local = 42;433  int* p = &local;434  rp = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'p'}}435}436 437void param_ref_to_ptr_caller() {438  void* p = nullptr;439  param_ref_to_ptr_callee(p);440}441} // namespace leaking_via_ref_to_ptr442 443namespace leaking_via_arr_of_ptr_static_idx {444void** returned_arr_of_ptr_top() {445  int local = 42;446  int* p = &local;447  void** arr = new void*[2];448  arr[1] = p;449  return arr; // expected-warning{{Address of stack memory associated with local variable 'local' returned to caller}}450}451 452void** returned_arr_of_ptr_callee() {453  int local = 42;454  int* p = &local;455  void** arr = new void*[2];456  arr[1] = p;457  return arr; // expected-warning{{Address of stack memory associated with local variable 'local' returned to caller}}458}459 460void returned_arr_of_ptr_caller() {461  void** arr = returned_arr_of_ptr_callee();462  (void)arr[1];463}464 465void* global_aop[2];466 467void global_arr_of_ptr() {468  int local = 42;469  int* p = &local;470  global_aop[1] = p; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_aop'}}471}472 473void static_arr_of_ptr() {474  int local = 42;475  static void* arr[2];476  arr[1] = &local;477  (void)arr[1]; // expected-warning{{local variable 'local' is still referred to by the static variable 'arr'}}478}479 480void param_arr_of_ptr_top(void* arr[2]) {481  int local = 42;482  int* p = &local;483  arr[1] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arr'}}484}485 486void param_arr_of_ptr_callee(void* arr[2]) {487  int local = 42;488  int* p = &local;489  arr[1] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arrStack'}}490}491 492void param_arr_of_ptr_caller() {493  void* arrStack[2];494  param_arr_of_ptr_callee(arrStack);495  (void)arrStack[1];496}497} // namespace leaking_via_arr_of_ptr_static_idx498 499namespace leaking_via_arr_of_ptr_dynamic_idx {500void** returned_arr_of_ptr_top(int idx) {501  int local = 42;502  int* p = &local;503  void** arr = new void*[2];504  arr[idx] = p;505  return arr; // expected-warning{{Address of stack memory associated with local variable 'local' returned to caller}}506}507 508void** returned_arr_of_ptr_callee(int idx) {509  int local = 42;510  int* p = &local;511  void** arr = new void*[2];512  arr[idx] = p;513  return arr; // expected-warning{{Address of stack memory associated with local variable 'local' returned to caller}}514}515 516void returned_arr_of_ptr_caller(int idx) {517  void** arr = returned_arr_of_ptr_callee(idx);518  (void)arr[idx];519}520 521void* global_aop[2];522 523void global_arr_of_ptr(int idx) {524  int local = 42;525  int* p = &local;526  global_aop[idx] = p; // expected-warning{{local variable 'local' is still referred to by the global variable 'global_aop'}}527}528 529void static_arr_of_ptr(int idx) {530  int local = 42;531  static void* arr[2];532  arr[idx] = &local;533  (void)arr[idx]; // expected-warning{{local variable 'local' is still referred to by the static variable 'arr'}}534}535 536void param_arr_of_ptr_top(void* arr[2], int idx) {537  int local = 42;538  int* p = &local;539  arr[idx] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arr'}}540}541 542void param_arr_of_ptr_callee(void* arr[2], int idx) {543  int local = 42;544  int* p = &local;545  arr[idx] = p; // expected-warning{{local variable 'local' is still referred to by the caller variable 'arrStack'}}546}547 548void param_arr_of_ptr_caller(int idx) {549  void* arrStack[2];550  param_arr_of_ptr_callee(arrStack, idx);551  (void)arrStack[idx];552}553} // namespace leaking_via_arr_of_ptr_dynamic_idx554 555namespace leaking_via_struct_with_ptr {556struct S {557  int* p;558};559 560S returned_struct_with_ptr_top() {561  int local = 42;562  S s;563  s.p = &local;564  return s; // expected-warning{{Address of stack memory associated with local variable 'local' returned to caller}}565}566 567S returned_struct_with_ptr_callee() {568  int local = 42;569  S s;570  s.p = &local;571  return s; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}} expected-warning{{Address of stack memory associated with local variable 'local' is still referred to by the caller variable 's' upon returning to the caller.  This will be a dangling reference}}572}573 574S leak_through_field_of_returned_object() {575  int local = 14;576  S s{&local};577  return s; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}578}579 580S leak_through_compound_literal() {581  int local = 0;582  return (S) { &local }; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}583}584 585void returned_struct_with_ptr_caller() {586  S s = returned_struct_with_ptr_callee();587  (void)s.p;588}589 590S global_s;591 592void global_struct_with_ptr() {593  int local = 42;594  global_s.p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}595}596 597void static_struct_with_ptr() {598  int local = 42;599  static S s;600  s.p = &local;601  (void)s.p; // expected-warning{{'local' is still referred to by the static variable 's'}}602}603} // namespace leaking_via_struct_with_ptr604 605namespace leaking_via_nested_structs_with_ptr {606struct Inner {607  int *ptr;608};609 610struct Outer {611  Inner I;612};613 614struct Deriving : public Outer {};615 616Outer leaks_through_nested_objects() {617  int local = 0;618  Outer O{&local};619  return O; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}620}621 622Deriving leaks_through_base_objects() {623  int local = 0;624  Deriving D{&local};625  return D; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}626}627} // namespace leaking_via_nested_structs_with_ptr628 629namespace leaking_via_ref_to_struct_with_ptr {630struct S {631  int* p;632};633 634S &global_s = *(new S);635 636void global_ref_to_struct_with_ptr() {637  int local = 42;638  global_s.p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}639}640 641void static_ref_to_struct_with_ptr() {642  int local = 42;643  static S &s = *(new S);644  s.p = &local;645  (void)s.p;646} // no-warning False Negative, requires relating multiple bindings to cross a heap region.647 648void param_ref_to_struct_with_ptr_top(S &s) {649  int local = 42;650  s.p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}651}652 653void param_ref_to_struct_with_ptr_callee(S &s) {654  int local = 42;655  s.p = &local; // expected-warning{{'local' is still referred to by the caller variable 'sStack'}}656}657 658void param_ref_to_struct_with_ptr_caller() {659  S sStack;660  param_ref_to_struct_with_ptr_callee(sStack);661}662 663template<typename Callable>664void lambda_param_capture_callee(Callable& callee) {665  int local = 42;666  callee(local); // expected-warning{{'local' is still referred to by the caller variable 'p'}}667}668 669void lambda_param_capture_caller() {670  int* p = nullptr;671  auto capt = [&p](int& param) {672    p = &param;673  };674  lambda_param_capture_callee(capt);675}676} // namespace leaking_via_ref_to_struct_with_ptr677 678namespace leaking_via_ptr_to_struct_with_ptr {679struct S {680  int* p;681};682 683S* returned_ptr_to_struct_with_ptr_top() {684  int local = 42;685  S* s = new S;686  s->p = &local;687  return s; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}688}689 690S* returned_ptr_to_struct_with_ptr_callee() {691  int local = 42;692  S* s = new S;693  s->p = &local;694  return s; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}695}696 697void returned_ptr_to_struct_with_ptr_caller() {698  S* s = returned_ptr_to_struct_with_ptr_callee();699  (void)s->p;700}701 702S* global_s;703 704void global_ptr_to_struct_with_ptr() {705  int local = 42;706  global_s->p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}707}708 709void static_ptr_to_struct_with_ptr_new() {710  int local = 42;711  static S* s = new S;712  s->p = &local;713  (void)s->p;714} // no-warning  False Negative, requires relating multiple bindings to cross a heap region.715 716S* get_some_s();717 718void static_ptr_to_struct_with_ptr_generated() {719  int local = 42;720  static S* s = get_some_s();721  s->p = &local;722} // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.723 724void param_ptr_to_struct_with_ptr_top(S* s) {725  int local = 42;726  s->p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}727}728 729void param_ptr_to_struct_with_ptr_callee(S* s) {730  int local = 42;731  s->p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}732}733 734void param_ptr_to_struct_with_ptr_caller() {735  S s;736  param_ptr_to_struct_with_ptr_callee(&s);737  (void)s.p;738}739} // namespace leaking_via_ptr_to_struct_with_ptr740 741namespace leaking_via_arr_of_struct_with_ptr {742struct S {743  int* p;744};745 746S* returned_ptr_to_struct_with_ptr_top() {747  int local = 42;748  S* s = new S[2];749  s[1].p = &local;750  return s; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}751}752 753S* returned_ptr_to_struct_with_ptr_callee() {754  int local = 42;755  S* s = new S[2];756  s[1].p = &local;757  return s; // expected-warning {{Address of stack memory associated with local variable 'local' returned to caller}}758}759 760void returned_ptr_to_struct_with_ptr_caller() {761  S* s = returned_ptr_to_struct_with_ptr_callee();762  (void)s[1].p;763}764 765S global_s[2];766 767void global_ptr_to_struct_with_ptr() {768  int local = 42;769  global_s[1].p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_s'}}770}771 772void static_ptr_to_struct_with_ptr_new() {773  int local = 42;774  static S* s = new S[2];775  s[1].p = &local;776  (void)s[1].p;777}778 779S* get_some_s();780 781void static_ptr_to_struct_with_ptr_generated() {782  int local = 42;783  static S* s = get_some_s();784  s[1].p = &local;785} // no-warning False Negative, requires relating multiple bindings to cross the invented pointer.786 787void param_ptr_to_struct_with_ptr_top(S s[2]) {788  int local = 42;789  s[1].p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}790}791 792void param_ptr_to_struct_with_ptr_callee(S s[2]) {793  int local = 42;794  s[1].p = &local; // expected-warning{{'local' is still referred to by the caller variable 's'}}795}796 797void param_ptr_to_struct_with_ptr_caller() {798  S s[2];799  param_ptr_to_struct_with_ptr_callee(s);800  (void)s[1].p;801}802} // namespace leaking_via_arr_of_struct_with_ptr803 804namespace leaking_via_nested_and_indirect {805struct NestedAndTransitive {806  int** p;807  NestedAndTransitive* next[3];808};809 810NestedAndTransitive global_nat;811 812void global_nested_and_transitive() {813  int local = 42;814  *global_nat.next[2]->next[1]->p = &local; // expected-warning{{'local' is still referred to by the global variable 'global_nat'}}815}816 817void param_nested_and_transitive_top(NestedAndTransitive* nat) {818  int local = 42;819  *nat->next[2]->next[1]->p = &local; // expected-warning{{'local' is still referred to by the caller variable 'nat'}}820}821 822void param_nested_and_transitive_callee(NestedAndTransitive* nat) {823  int local = 42;824  *nat->next[2]->next[1]->p = &local; // expected-warning{{'local' is still referred to by the caller variable 'natCaller'}}825}826 827void param_nested_and_transitive_caller(NestedAndTransitive natCaller) {828  param_nested_and_transitive_callee(&natCaller);829}830 831} // namespace leaking_via_nested_and_indirect832 833namespace leaking_as_member {834class CRef {835  int& ref; // expected-note{{reference member declared here}}836  CRef(int x) : ref(x) {}837  // expected-warning@-1 {{binding reference member 'ref' to stack allocated parameter 'x'}}838};839 840class CPtr {841  int* ptr;842  void memFun(int x) {843    ptr = &x;844  }845};846} // namespace leaking_as_member847 848namespace origin_region_limitation {849void leaker(int ***leakerArg) {850    int local;851    clang_analyzer_dump(*leakerArg); // expected-warning{{&SymRegion{reg_$0<int ** arg>}}}852    // Incorrect message: 'arg', after it is reinitialized with value returned by 'tweak'853    // is no longer relevant.854    // The message must refer to 'original_arg' instead, but there is no easy way to855    // connect the SymRegion stored in 'original_arg' and 'original_arg' as variable.856    **leakerArg = &local; // expected-warning{{ 'local' is still referred to by the caller variable 'arg'}}857}858 859int **tweak();860 861void foo(int **arg) {862    int **original_arg = arg;863    arg = tweak();864    leaker(&original_arg);865}866} // namespace origin_region_limitation867 868namespace leaking_via_indirect_global_invalidated {869void** global_pp;870void opaque();871void global_ptr_to_ptr() {872  int local = 42;873  *global_pp = &local;874  opaque();875  *global_pp = nullptr;876}877} // namespace leaking_via_indirect_global_invalidated878 879namespace not_leaking_via_simple_ptr {880void simple_ptr(const char *p) {881  char tmp;882  p = &tmp; // no-warning883}884 885void ref_ptr(const char *&p) {886  char tmp;887  p = &tmp; // expected-warning{{variable 'tmp' is still referred to by the caller variable 'p'}}888}889 890struct S {891  const char *p;892};893 894void struct_ptr(S s) {895  char tmp;896  s.p = &tmp; // no-warning897}898 899void array(const char arr[2]) {900  char tmp;901  arr = &tmp; // no-warning902}903 904extern void copy(char *output, const char *input, unsigned size);905extern bool foo(const char *input);906extern void bar(char *output, unsigned count);907extern bool baz(char *output, const char *input);908 909void repo(const char *input, char *output) {910  char temp[64];911  copy(temp, input, sizeof(temp));912 913  char result[64];914  input = temp;915  if (foo(temp)) {916    bar(result, sizeof(result));917    input = result;918  }919  if (!baz(output, input)) {920    copy(output, input, sizeof(result));921  }922}923} // namespace not_leaking_via_simple_ptr924 925namespace early_reclaim_dead_limitation {926void foo();927void top(char **p) {928  char local;929  *p = &local;930  foo(); // no-warning FIXME: p binding is reclaimed before the function end931}932} // namespace early_reclaim_dead_limitation933 934namespace alloca_region_pointer {935void callee(char **pptr) {936  char local;937  *pptr = &local;938} // no crash939 940void top_alloca_no_crash_fn() {941  char **pptr = (char**)__builtin_alloca(sizeof(char*));942  callee(pptr);943}944 945void top_malloc_no_crash_fn() {946  char **pptr = (char**)malloc(sizeof(char*));947  callee(pptr);948  free(pptr);949}950} // namespace alloca_region_pointer951 952// These all warn with -Wreturn-stack-address also953namespace return_address_of_true_positives {954int* ret_local_addrOf() {955  int x = 1;956  return &*&x; // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory associated with local variable 'x' returned}}957}958 959int* ret_local_addrOf_paren() {960  int x = 1;961  return (&(*(&x))); // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory associated with local variable 'x' returned}}962}963 964int* ret_local_addrOf_ptr_arith() {965  int x = 1;966  return &*(&x+1); // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory associated with local variable 'x' returned}}967}968 969int* ret_local_addrOf_ptr_arith2() {970  int x = 1;971  return &*(&x+1); // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory associated with local variable 'x' returned}}972}973 974int* ret_local_field() {975  struct { int x; } a;976  return &a.x; // expected-warning {{Address of stack memory associated with local variable 'a' returned to caller}} expected-warning {{address of stack memory associated with local variable 'a' returned}}977}978 979int& ret_local_field_ref() {980  struct { int x; } a;981  return a.x; // expected-warning {{Address of stack memory associated with local variable 'a' returned to caller}} expected-warning {{reference to stack memory associated with local variable 'a' returned}}982}983} //namespace return_address_of_true_positives984 985namespace return_from_child_block_scope {986struct S {987  int *p;988};989 990S return_child_stack_context() {991  S s;992  {993    int a = 1;994    s = (S){ &a };995  }996  return s; // expected-warning {{Address of stack memory associated with local variable 'a' returned to caller}}997}998 999S return_child_stack_context_field() {1000  S s;1001  {1002    int a = 1;1003    s.p = &a;1004  }1005  return s; // expected-warning {{Address of stack memory associated with local variable 'a' returned to caller}}1006}1007 1008// The below are reproducers from Issue #1234591009template <typename V>1010struct T {1011    V* q{};1012    T() = default;1013    T(T&& rhs) { q = rhs.q; rhs.q = nullptr;}1014    T& operator=(T&& rhs) { q = rhs.q; rhs.q = nullptr;}1015    void push_back(const V& v) { if (q == nullptr) q = new V(v); }1016    ~T() { delete q; }1017};1018 1019T<S> f() {1020    T<S> t;1021    {1022        int a = 1;1023        t.push_back({ &a });1024    }1025    return t; // expected-warning {{Address of stack memory associated with local variable 'a' returned to caller}}1026}1027 1028} // namespace return_from_child_block_scope1029 1030namespace true_negatives_return_expressions {1031struct Container { int *x; };1032 1033int test2() {1034  int x = 14;1035  return x; // no-warning1036}1037 1038void return_void() {1039  return void(); // no-warning1040}1041 1042int return_assign_expr_safe() {1043  int y, x = 14;1044  return y = x; // no-warning1045}1046 1047int return_comma_separated_expressions_safe() {1048  int x = 1;1049  int *y;1050  return (y=&x), (x=15); // no-warning1051}1052 1053int return_comma_separated_expressions_container_safe() {1054  int x = 1;1055  Container Other;1056  return Other = Container{&x}, x = 14; // no-warning1057}1058 1059int make_x();1060int return_symbol_safe() {1061  int x = make_x();1062  clang_analyzer_dump(x); // expected-warning-re {{conj_$2{int, {{.+}}}}}1063  return x; // no-warning1064}1065 1066int *return_symbolic_region_safe(int **ptr) {1067  return *ptr; // no-warning1068}1069 1070int *return_arg_ptr(int *arg) {1071  return arg; // no-warning1072}1073 1074// This has a false positive with -Wreturn-stack-address, but CSA should not1075// warn on this1076int *return_conditional_never_false(int *arg) {1077  int x = 14;1078  return true ? arg : &x; // expected-warning {{address of stack memory associated with local variable 'x' returned}}1079}1080 1081// This has a false positive with -Wreturn-stack-address, but CSA should not1082// warn on this1083int *return_conditional_never_true(int *arg) {1084  int x = 14;1085  return false ? &x : arg; // expected-warning {{address of stack memory associated with local variable 'x' returned}}1086}1087 1088int *return_conditional_path_split(int *arg, bool b) {1089  int x = 14;1090  return b ? arg : &x; // expected-warning {{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning {{address of stack memory associated with local variable 'x' returned}} -Wreturn-stack-address1091}1092 1093// compare of two symbolic regions1094// maybe in some implementation, make_ptr returns interior pointers that are comparable1095int *make_ptr();1096bool return_symbolic_exxpression() {1097  int *a = make_ptr();1098  int *b = make_ptr();1099  return a < b; // no-warning1100}1101 1102int *return_static() {1103  static int x = 0;1104  return &x; // no-warning1105}1106 1107int* return_cpp_reinterpret_cast_no_warning(long x) {1108  return reinterpret_cast<int*>(x); // no-warning1109}1110}1111 1112// TODO: The tail call expression tree must not hold a reference to an arg or stack local:1113// "The lifetimes of all local variables and function parameters end immediately before the 1114// [tail] call to the function. This means that it is undefined behaviour to pass a pointer or 1115// reference to a local variable to the called function, which is not the case without the 1116// attribute."1117// These only warn from -Wreturn-stack-address for now1118namespace with_attr_musttail {1119void TakesIntAndPtr(int, int *);1120void PassAddressOfLocal(int a, int *b) {1121  int c;1122  [[clang::musttail]] return TakesIntAndPtr(0, &c); // expected-warning {{address of stack memory associated with local variable 'c' pass\1123ed to musttail function}} False-negative on CSA1124}1125void PassAddressOfParam(int a, int *b) {1126  [[clang::musttail]] return TakesIntAndPtr(0, &a); // expected-warning {{address of stack memory associated with parameter 'a' passed to\1127 musttail function}} False-negative on CSA1128}1129} // namespace with_attr_musttail1130