1 // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s
2 struct [[gsl::Owner(int)]] MyIntOwner {
3   MyIntOwner();
4   int &operator*();
5 };
6 
7 struct [[gsl::Pointer(int)]] MyIntPointer {
8   MyIntPointer(int *p = nullptr);
9   // Conversion operator and constructor conversion will result in two
10   // different ASTs. The former is tested with another owner and
11   // pointer type.
12   MyIntPointer(const MyIntOwner &);
13   int &operator*();
14   MyIntOwner toOwner();
15 };
16 
17 struct MySpecialIntPointer : MyIntPointer {
18 };
19 
20 // We did see examples in the wild when a derived class changes
21 // the ownership model. So we have a test for it.
22 struct [[gsl::Owner(int)]] MyOwnerIntPointer : MyIntPointer {
23 };
24 
25 struct [[gsl::Pointer(long)]] MyLongPointerFromConversion {
26   MyLongPointerFromConversion(long *p = nullptr);
27   long &operator*();
28 };
29 
30 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion {
31   MyLongOwnerWithConversion();
32   operator MyLongPointerFromConversion();
33   long &operator*();
34   MyIntPointer releaseAsMyPointer();
35   long *releaseAsRawPointer();
36 };
37 
danglingHeapObject()38 void danglingHeapObject() {
39   new MyLongPointerFromConversion(MyLongOwnerWithConversion{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
40   new MyIntPointer(MyIntOwner{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
41 }
42 
intentionalFalseNegative()43 void intentionalFalseNegative() {
44   int i;
45   MyIntPointer p{&i};
46   // In this case we do not have enough information in a statement local
47   // analysis to detect the problem.
48   new MyIntPointer(p);
49   new MyIntPointer(MyIntPointer{p});
50 }
51 
ownershipTransferToMyPointer()52 MyIntPointer ownershipTransferToMyPointer() {
53   MyLongOwnerWithConversion t;
54   return t.releaseAsMyPointer(); // ok
55 }
56 
ownershipTransferToRawPointer()57 long *ownershipTransferToRawPointer() {
58   MyLongOwnerWithConversion t;
59   return t.releaseAsRawPointer(); // ok
60 }
61 
62 struct Y {
63   int a[4];
64 };
65 
dangligGslPtrFromTemporary()66 void dangligGslPtrFromTemporary() {
67   MyIntPointer p = Y{}.a; // TODO
68   (void)p;
69 }
70 
71 struct DanglingGslPtrField {
72   MyIntPointer p; // expected-note {{pointer member declared here}}
73   MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}}
DanglingGslPtrFieldDanglingGslPtrField74   DanglingGslPtrField(int i) : p(&i) {} // TODO
DanglingGslPtrFieldDanglingGslPtrField75   DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {} // expected-warning {{initializing pointer member 'p2' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}}
DanglingGslPtrFieldDanglingGslPtrField76   DanglingGslPtrField(double) : p(MyIntOwner{}) {} // expected-warning {{initializing pointer member 'p' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}}
77 };
78 
danglingGslPtrFromLocal()79 MyIntPointer danglingGslPtrFromLocal() {
80   int j;
81   return &j; // TODO
82 }
83 
returningLocalPointer()84 MyIntPointer returningLocalPointer() {
85   MyIntPointer localPointer;
86   return localPointer; // ok
87 }
88 
daglingGslPtrFromLocalOwner()89 MyIntPointer daglingGslPtrFromLocalOwner() {
90   MyIntOwner localOwner;
91   return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
92 }
93 
daglingGslPtrFromLocalOwnerConv()94 MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {
95   MyLongOwnerWithConversion localOwner;
96   return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
97 }
98 
danglingGslPtrFromTemporary()99 MyIntPointer danglingGslPtrFromTemporary() {
100   return MyIntOwner{}; // expected-warning {{returning address of local temporary object}}
101 }
102 
103 MyIntOwner makeTempOwner();
104 
danglingGslPtrFromTemporary2()105 MyIntPointer danglingGslPtrFromTemporary2() {
106   return makeTempOwner(); // expected-warning {{returning address of local temporary object}}
107 }
108 
danglingGslPtrFromTemporaryConv()109 MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {
110   return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}}
111 }
112 
noFalsePositive(MyIntOwner & o)113 int *noFalsePositive(MyIntOwner &o) {
114   MyIntPointer p = o;
115   return &*p; // ok
116 }
117 
118 MyIntPointer global;
119 MyLongPointerFromConversion global2;
120 
initLocalGslPtrWithTempOwner()121 void initLocalGslPtrWithTempOwner() {
122   MyIntPointer p = MyIntOwner{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
123   p = MyIntOwner{}; // TODO ?
124   global = MyIntOwner{}; // TODO ?
125   MyLongPointerFromConversion p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
126   p2 = MyLongOwnerWithConversion{}; // TODO ?
127   global2 = MyLongOwnerWithConversion{}; // TODO ?
128 }
129 
130 namespace __gnu_cxx {
131 template <typename T>
132 struct basic_iterator {
133   basic_iterator operator++();
134   T& operator*() const;
135   T* operator->() const;
136 };
137 
138 template<typename T>
139 bool operator!=(basic_iterator<T>, basic_iterator<T>);
140 }
141 
142 namespace std {
143 template<typename T> struct remove_reference       { typedef T type; };
144 template<typename T> struct remove_reference<T &>  { typedef T type; };
145 template<typename T> struct remove_reference<T &&> { typedef T type; };
146 
147 template<typename T>
148 typename remove_reference<T>::type &&move(T &&t) noexcept;
149 
150 template <typename C>
151 auto data(const C &c) -> decltype(c.data());
152 
153 template <typename C>
154 auto begin(C &c) -> decltype(c.begin());
155 
156 template<typename T, int N>
157 T *begin(T (&array)[N]);
158 
159 template <typename T>
160 struct vector {
161   typedef __gnu_cxx::basic_iterator<T> iterator;
162   iterator begin();
163   iterator end();
164   const T *data() const;
165   T &at(int n);
166 };
167 
168 template<typename T>
169 struct basic_string_view {
170   basic_string_view(const T *);
171   const T *begin() const;
172 };
173 
174 template<typename T>
175 struct basic_string {
176   basic_string();
177   basic_string(const T *);
178   const T *c_str() const;
179   operator basic_string_view<T> () const;
180 };
181 
182 
183 template<typename T>
184 struct unique_ptr {
185   T &operator*();
186   T *get() const;
187 };
188 
189 template<typename T>
190 struct optional {
191   optional();
192   optional(const T&);
193   T &operator*() &;
194   T &&operator*() &&;
195   T &value() &;
196   T &&value() &&;
197 };
198 
199 template<typename T>
200 struct stack {
201   T &top();
202 };
203 
204 struct any {};
205 
206 template<typename T>
207 T any_cast(const any& operand);
208 
209 template<typename T>
210 struct reference_wrapper {
211   template<typename U>
212   reference_wrapper(U &&);
213 };
214 
215 template<typename T>
216 reference_wrapper<T> ref(T& t) noexcept;
217 }
218 
219 struct Unannotated {
220   typedef std::vector<int>::iterator iterator;
221   iterator begin();
222   operator iterator() const;
223 };
224 
modelIterators()225 void modelIterators() {
226   std::vector<int>::iterator it = std::vector<int>().begin(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
227   (void)it;
228 }
229 
modelIteratorReturn()230 std::vector<int>::iterator modelIteratorReturn() {
231   return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}
232 }
233 
modelFreeFunctions()234 const int *modelFreeFunctions() {
235   return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}
236 }
237 
modelAnyCast()238 int &modelAnyCast() {
239   return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}
240 }
241 
modelAnyCast2()242 int modelAnyCast2() {
243   return std::any_cast<int>(std::any{}); // ok
244 }
245 
modelAnyCast3()246 int modelAnyCast3() {
247   return std::any_cast<int&>(std::any{}); // ok
248 }
249 
danglingRawPtrFromLocal()250 const char *danglingRawPtrFromLocal() {
251   std::basic_string<char> s;
252   return s.c_str(); // expected-warning {{address of stack memory associated with local variable 's' returned}}
253 }
254 
danglingRawPtrFromLocal2()255 int &danglingRawPtrFromLocal2() {
256   std::optional<int> o;
257   return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
258 }
259 
danglingRawPtrFromLocal3()260 int &danglingRawPtrFromLocal3() {
261   std::optional<int> o;
262   return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
263 }
264 
danglingRawPtrFromTemp()265 const char *danglingRawPtrFromTemp() {
266   return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}
267 }
268 
269 std::unique_ptr<int> getUniquePtr();
270 
danglingUniquePtrFromTemp()271 int *danglingUniquePtrFromTemp() {
272   return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}}
273 }
274 
danglingUniquePtrFromTemp2()275 int *danglingUniquePtrFromTemp2() {
276   return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}
277 }
278 
danglingReferenceFromTempOwner()279 void danglingReferenceFromTempOwner() {
280   int &&r = *std::optional<int>();          // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
281   int &&r2 = *std::optional<int>(5);        // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
282   int &&r3 = std::optional<int>(5).value(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
283   int &r4 = std::vector<int>().at(3);       // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
284 }
285 
286 std::vector<int> getTempVec();
287 std::optional<std::vector<int>> getTempOptVec();
288 
testLoops()289 void testLoops() {
290   for (auto i : getTempVec()) // ok
291     ;
292   for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
293     ;
294 }
295 
usedToBeFalsePositive(std::vector<int> & v)296 int &usedToBeFalsePositive(std::vector<int> &v) {
297   std::vector<int>::iterator it = v.begin();
298   int& value = *it;
299   return value; // ok
300 }
301 
doNotFollowReferencesForLocalOwner()302 int &doNotFollowReferencesForLocalOwner() {
303   std::unique_ptr<int> localOwner;
304   int &p = *localOwner.get();
305   // In real world code localOwner is usually moved here.
306   return p; // ok
307 }
308 
trackThroughMultiplePointer()309 const char *trackThroughMultiplePointer() {
310   return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}
311 }
312 
313 struct X {
XX314   X(std::unique_ptr<int> up) :
315     pointee(*up), pointee2(up.get()), pointer(std::move(up)) {}
316   int &pointee;
317   int *pointee2;
318   std::unique_ptr<int> pointer;
319 };
320 
321 std::vector<int>::iterator getIt();
322 std::vector<int> getVec();
323 
handleGslPtrInitsThroughReference()324 const int &handleGslPtrInitsThroughReference() {
325   const auto &it = getIt(); // Ok, it is lifetime extended.
326   return *it;
327 }
328 
handleGslPtrInitsThroughReference2()329 void handleGslPtrInitsThroughReference2() {
330   const std::vector<int> &v = getVec();
331   const int *val = v.data(); // Ok, it is lifetime extended.
332 }
333 
handleTernaryOperator(bool cond)334 void handleTernaryOperator(bool cond) {
335     std::basic_string<char> def;
336     std::basic_string_view<char> v = cond ? def : ""; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
337 }
338 
danglingPtrFromNonOwnerLocal()339 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() {
340   int i = 5;
341   return i; // TODO
342 }
343 
danglingPtrFromNonOwnerLocal2()344 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() {
345   int i = 5;
346   return std::ref(i); // TODO
347 }
348 
danglingPtrFromNonOwnerLocal3()349 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() {
350   int i = 5;
351   return std::reference_wrapper<int>(i); // TODO
352 }
353 
danglingPtrFromNonOwnerLocal4()354 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() {
355   Unannotated i;
356   return std::reference_wrapper<Unannotated>(i); // TODO
357 }
358 
danglingPtrFromNonOwnerLocal5()359 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() {
360   Unannotated i;
361   return std::ref(i); // TODO
362 }
363 
returnPtrToLocalArray()364 int *returnPtrToLocalArray() {
365   int a[5];
366   return std::begin(a); // TODO
367 }
368 
369 struct ptr_wrapper {
370   std::vector<int>::iterator member;
371 };
372 
373 ptr_wrapper getPtrWrapper();
374 
returnPtrFromWrapper()375 std::vector<int>::iterator returnPtrFromWrapper() {
376   ptr_wrapper local = getPtrWrapper();
377   return local.member;
378 }
379 
returnPtrFromWrapperThroughRef()380 std::vector<int>::iterator returnPtrFromWrapperThroughRef() {
381   ptr_wrapper local = getPtrWrapper();
382   ptr_wrapper &local2 = local;
383   return local2.member;
384 }
385 
returnPtrFromWrapperThroughRef2()386 std::vector<int>::iterator returnPtrFromWrapperThroughRef2() {
387   ptr_wrapper local = getPtrWrapper();
388   std::vector<int>::iterator &local2 = local.member;
389   return local2;
390 }
391 
checkPtrMemberFromAggregate()392 void checkPtrMemberFromAggregate() {
393   std::vector<int>::iterator local = getPtrWrapper().member; // OK.
394 }
395 
doNotInterferWithUnannotated()396 std::vector<int>::iterator doNotInterferWithUnannotated() {
397   Unannotated value;
398   // Conservative choice for now. Probably not ok, but we do not warn.
399   return std::begin(value);
400 }
401 
doNotInterferWithUnannotated2()402 std::vector<int>::iterator doNotInterferWithUnannotated2() {
403   Unannotated value;
404   return value;
405 }
406 
supportDerefAddrofChain(int a,std::vector<int>::iterator value)407 std::vector<int>::iterator supportDerefAddrofChain(int a, std::vector<int>::iterator value) {
408   switch (a)  {
409     default:
410       return value;
411     case 1:
412       return *&value;
413     case 2:
414       return *&*&value;
415     case 3:
416       return *&*&*&value;
417   }
418 }
419 
supportDerefAddrofChain2(int a,std::vector<int>::iterator value)420 int &supportDerefAddrofChain2(int a, std::vector<int>::iterator value) {
421   switch (a)  {
422     default:
423       return *value;
424     case 1:
425       return **&value;
426     case 2:
427       return **&*&value;
428     case 3:
429       return **&*&*&value;
430   }
431 }
432 
supportDerefAddrofChain3(int a,std::vector<int>::iterator value)433 int *supportDerefAddrofChain3(int a, std::vector<int>::iterator value) {
434   switch (a)  {
435     default:
436       return &*value;
437     case 1:
438       return &*&*value;
439     case 2:
440       return &*&**&value;
441     case 3:
442       return &*&**&*&value;
443   }
444 }
445 
handleDerivedToBaseCast1(MySpecialIntPointer ptr)446 MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {
447   return ptr;
448 }
449 
handleDerivedToBaseCast2(MyOwnerIntPointer ptr)450 MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {
451   return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}
452 }
453 
noFalsePositiveWithVectorOfPointers()454 std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {
455   std::vector<std::vector<int>::iterator> iters;
456   return iters.at(0);
457 }
458