================
@@ -0,0 +1,151 @@
+// RUN: %clang_analyze_cc1 
-analyzer-checker=core,unix.Malloc,deadcode.DeadStores,debug.ExprInspection 
-verify %s
+
+// Test modeling of GCC's __attribute__((cleanup(f))): the implicit f(&var)
+// call at scope exit is evaluated as an implicit call, inlined when a
+// definition is available and conservatively evaluated otherwise.
+
+#include "Inputs/system-header-simulator-for-malloc.h"
+
+void clang_analyzer_dump_int(int);
+void clang_analyzer_dump_ptr(void *);
+void clang_analyzer_numTimesReached(void);
+void clang_analyzer_warnIfReached(void);
+
+//===----------------------------------------------------------------------===//
+// The analysis continues past a scope exit with a cleanup-attributed variable.
+//===----------------------------------------------------------------------===//
+
+static void noop_cleanup(int *p) { (void)p; }
+
+void path_continues_after_scope(void) {
+  {
+    int x __attribute__((cleanup(noop_cleanup)));
+    x = 42; // no dead-store warning: the value is read by the cleanup call.
+  }
+  clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+}
+
+//===----------------------------------------------------------------------===//
+// An inlined cleanup observes the address of the variable and the value last
+// stored to it.
+//===----------------------------------------------------------------------===//
+
+static void dump_cleanup(int *p) {
+  clang_analyzer_dump_ptr(p);  // expected-warning {{&x}}
+  clang_analyzer_dump_int(*p); // expected-warning {{42 S32b}}
+}
+
+void inlined_cleanup_observes_value(void) {
+  int x __attribute__((cleanup(dump_cleanup)));
+  x = 42;
+}
+
+//===----------------------------------------------------------------------===//
+// A declared-only cleanup is conservatively evaluated: the argument escapes
+// and no leak is reported for memory the unknown cleanup may have released.
+//===----------------------------------------------------------------------===//
+
+void declared_only_cleanup(void *p);
+
+void declared_only_cleanup_escapes(void) {
+  void *p __attribute__((cleanup(declared_only_cleanup)));
+  p = malloc(10);
+} // no leak: the pointer escapes into the conservatively evaluated call.
+
+//===----------------------------------------------------------------------===//
+// An inlined cleanup that frees the pointee: no leak.
+//===----------------------------------------------------------------------===//
+
+static void free_pointer_cleanup(char **p) {
+  free(*p);
+}
+
+void inlined_cleanup_frees(void) {
+  char *p __attribute__((cleanup(free_pointer_cleanup)));
+  p = malloc(10);
+} // no leak: free_pointer_cleanup(p) frees *p at the scope exit.
+
+//===----------------------------------------------------------------------===//
+// A non-releasing cleanup still leaks.
+//===----------------------------------------------------------------------===//
+
+static void non_releasing_cleanup(char **p) {
+  (void)p;
+}
+
+void non_releasing_cleanup_leaks(void) {
+  char *p __attribute__((cleanup(non_releasing_cleanup)));
+  p = malloc(10);
+} // expected-warning {{Potential leak of memory pointed to by 'p'}}
+
+//===----------------------------------------------------------------------===//
+// A double free through a cleanup function is anchored inside the cleanup
+// body.
+//===----------------------------------------------------------------------===//
+
+static void double_free_cleanup(char **p) {
+  free(*p);
+  free(*p); // expected-warning {{Attempt to release already released memory}}
+}
----------------
necto wrote:

In this configuration, it is believable that the double-free is reported based 
just on the `double_free_cleanup` function alone: `free(x)` called twice on the 
same pointer.
To make it specific to the `cleanup` attribute, you can either do the first 
free in the caller, or invoke second free on a global pointer, which is set in 
the caller.

https://github.com/llvm/llvm-project/pull/221110
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to