analyzer: round-trip pointer-equality through intptr_t
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 5 Feb 2020 17:09:23 +0000 (12:09 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 6 Feb 2020 19:44:23 +0000 (14:44 -0500)
When investigating how the analyzer handles malloc/free of Cray pointers
in gfortran I noticed that that analyzer was losing information on
pointers that were cast to an integer type, and then back to a pointer
type again.

The root cause is that region_model::maybe_cast_1 was only preserving
the region_svalue-ness of the result if both types were pointers,
instead returning an unknown_svalue for a pointer-to-int cast.

This patch updates the above code so that it attempts to use a
region_svalue if *either* type is a pointer

Doing so allows the analyzer to recognize that the same underlying
region is in use through various casts through integer types.

gcc/analyzer/ChangeLog:
* region-model.cc (region_model::maybe_cast_1): Attempt to provide
a region_svalue if either type is a pointer, rather than if both
types are pointers.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/torture/intptr_t.c: New test.

gcc/analyzer/ChangeLog
gcc/analyzer/region-model.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c [new file with mode: 0644]

index 0666d0028c6a9b3e4cf0aafb5d0a1dc3d1f9ac94..ba59131ce4bdb36b16c470294a28511cf3cd7585 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-06  David Malcolm  <dmalcolm@redhat.com>
+
+       * region-model.cc (region_model::maybe_cast_1): Attempt to provide
+       a region_svalue if either type is a pointer, rather than if both
+       types are pointers.
+
 2020-02-05  David Malcolm  <dmalcolm@redhat.com>
 
        * engine.cc (exploded_node::dump_dot): Show merger enodes.
index c837ec6ed3b8858fd1869bea98d3b7a40a88d837..60363c726d78e367fe7687262e1b8f2905ac5053 100644 (file)
@@ -4977,7 +4977,7 @@ region_model::maybe_cast_1 (tree dst_type, svalue_id sid)
     return sid;
 
   if (POINTER_TYPE_P (dst_type)
-      && POINTER_TYPE_P (src_type))
+      || POINTER_TYPE_P (src_type))
     {
       /* Pointer to region.  */
       if (region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
index fd80c8d0f324c2e5634e7c101704c35c7527856b..f6f12dd764c6e6dd8db4b1f9b2ca4d891f5f6754 100644 (file)
@@ -1,3 +1,7 @@
+2020-02-06  David Malcolm  <dmalcolm@redhat.com>
+
+       * gcc.dg/analyzer/torture/intptr_t.c: New test.
+
 2020-02-06  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * gcc.target/powerpc/pr93012.c: New.
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c b/gcc/testsuite/gcc.dg/analyzer/torture/intptr_t.c
new file mode 100644 (file)
index 0000000..847ba62
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+#include <stdlib.h>
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+void test_1 (void)
+{
+  intptr_t ip;
+  void *p = malloc (1024);
+  ip = (intptr_t)p;
+  free ((void *)ip);
+} /* { dg-bogus "leak" } */
+
+void test_2 (void)
+{
+  uintptr_t uip;
+  void *p = malloc (1024);
+  uip = (uintptr_t)p;
+  free ((void *)uip);
+} /* { dg-bogus "leak" } */
+
+void test_3 (intptr_t ip)
+{
+  free ((void *)ip); /* { dg-message "first 'free'" } */
+  free ((void *)ip); /* { dg-warning "double-'free'" } */
+}