aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/analyzer/store.cc17
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/explode-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr94851-2.c54
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr98575-1.c46
4 files changed, 115 insertions, 4 deletions
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index abdb336..da5b5ad 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -1820,9 +1820,20 @@ store::set_value (store_manager *mgr, const region *lhs_reg,
const region *lhs_base_reg = lhs_reg->get_base_region ();
binding_cluster *lhs_cluster;
if (lhs_base_reg->symbolic_for_unknown_ptr_p ())
- /* Reject attempting to bind values into a symbolic region
- for an unknown ptr; merely invalidate values below. */
- lhs_cluster = NULL;
+ {
+ /* Reject attempting to bind values into a symbolic region
+ for an unknown ptr; merely invalidate values below. */
+ lhs_cluster = NULL;
+
+ /* The LHS of the write is *UNKNOWN. If the RHS is a pointer,
+ then treat the region being pointed to as having escaped. */
+ if (const region_svalue *ptr_sval = rhs_sval->dyn_cast_region_svalue ())
+ {
+ const region *ptr_dst = ptr_sval->get_pointee ();
+ const region *ptr_base_reg = ptr_dst->get_base_region ();
+ mark_as_escaped (ptr_base_reg);
+ }
+ }
else
{
lhs_cluster = get_or_create_cluster (lhs_base_reg);
diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-1.c b/gcc/testsuite/gcc.dg/analyzer/explode-1.c
index 9b95afd..6b62e8e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/explode-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/explode-1.c
@@ -47,7 +47,7 @@ void test (void)
{
default:
case 0:
- *pp = malloc (16); /* { dg-warning "leak" } */
+ *pp = malloc (16);
break;
case 1:
free (*pp);
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c
new file mode 100644
index 0000000..6094721
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c
@@ -0,0 +1,54 @@
+/* As pr94851-1.c, but verify that we don't get confused by a call to
+ an unknown function (PR analyzer/98575). */
+
+/* { dg-additional-options "-O2" } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct AMARK {
+ struct AMARK *m_next;
+ char m_name;
+} AMARK;
+
+struct buf {
+ AMARK *b_amark;
+};
+
+struct buf *curbp;
+
+extern void unknown_fn (void);
+
+int pamark(void) {
+ int c;
+
+ AMARK *p = curbp->b_amark;
+ AMARK *last = curbp->b_amark;
+
+ unknown_fn ();
+
+ c = getchar ();
+
+ while (p != (AMARK *)NULL && p->m_name != (char)c) {
+ last = p;
+ p = p->m_next;
+ }
+
+ if (p != (AMARK *)NULL) {
+ printf("over writing mark %c\n", c);
+ } else {
+ if ((p = (AMARK *)malloc(sizeof(AMARK))) == (AMARK *)NULL)
+ return 0;
+
+ p->m_next = (AMARK *)NULL;
+
+ if (curbp->b_amark == (AMARK *)NULL)
+ curbp->b_amark = p;
+ else
+ last->m_next = p;
+ }
+
+ p->m_name = (char)c; /* { dg-bogus "leak of 'p'" "bogus leak" } */
+
+ return 1;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr98575-1.c b/gcc/testsuite/gcc.dg/analyzer/pr98575-1.c
new file mode 100644
index 0000000..6472e76
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr98575-1.c
@@ -0,0 +1,46 @@
+/* A malloced pointer that's written to a global pointer shouldn't be
+ reported as leaking, even if an unknown function has been called
+ (PR analyzer/98575). */
+
+void **g;
+
+extern void unknown_fn (void);
+
+/* Without a call to unknown_fn. */
+
+int test_1 (void)
+{
+ void *p;
+ p = __builtin_malloc(1024);
+ *g = p;
+ return 0;
+}
+
+/* With a call to unknown_fn in various places. */
+
+int test_2 (void)
+{
+ void *p;
+ unknown_fn ();
+ p = __builtin_malloc(1024);
+ *g = p;
+ return 0;
+}
+
+int test_3 (void)
+{
+ void *p;
+ p = __builtin_malloc(1024);
+ unknown_fn ();
+ *g = p;
+ return 0;
+}
+
+int test_4 (void)
+{
+ void *p;
+ p = __builtin_malloc(1024);
+ *g = p;
+ unknown_fn ();
+ return 0;
+}