From fd36adc71d2ad1eb5187c560e825043db8ca1831 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 27 Mar 2019 16:26:31 -0400
Subject: [PATCH 158/217] FIXME: split malloc-ipa-8.c into two cases

---
 .../gcc.dg/analyzer/malloc-ipa-8-double-free.c     | 163 ++++++++++++++++
 .../gcc.dg/analyzer/malloc-ipa-8-unchecked.c       |  65 +++++++
 gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c       | 205 ---------------------
 3 files changed, 228 insertions(+), 205 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
 delete mode 100644 gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c

diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c
new file mode 100644
index 0000000..62e7302
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c
@@ -0,0 +1,163 @@
+/* Example of a multilevel wrapper around malloc/free, with a double-free.  */
+
+/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdump-analyzer-summaries -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes" } */
+
+#include <stdlib.h>
+
+void *wrapped_malloc (size_t size) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'unchecked'" } */
+{
+  return malloc (size);
+}
+
+void wrapped_free (void *ptr) /* { dg-warning "summary: add: 'ptr': 'start' -> 'free'" } */
+/* { dg-warning "summary: transition: 'ptr': 'nonnull' -> 'free'" "" { target *-*-* } .-1 } */
+/* { dg-warning "summary: transition: 'ptr': 'free' -> 'stop'" "" { target *-*-* } .-2 } */
+{
+  free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\\]" } */
+  /* FIXME: unchecked -> free is correct, but start -> free should be pruned
+     from the path.  */
+}
+
+typedef struct boxed_int
+{
+  int i;
+} boxed_int;
+
+boxed_int *
+make_boxed_int (int i) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'nonnull'" } */
+{
+  boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+  if (!result)
+    abort ();
+  result->i = i;
+  return result;
+}
+
+void
+free_boxed_int (boxed_int *bi) /* { dg-warning "summary: add: 'bi': 'start' -> 'free'" } */
+/* { dg-warning "summary: add: 'bi': 'start' -> 'stop'" "" { target *-*-* } .-1 } */
+{
+  wrapped_free (bi);
+  /* FIXME: events here are wrong; they refer to ptr, not bi.
+     (was "state of 'ptr': 'start' -> 'free'")
+     Also, they should be just start->free, or be skipped.  */
+}
+
+void test (int i)
+{
+  boxed_int *obj = make_boxed_int (i);
+
+  free_boxed_int (obj);
+
+  free_boxed_int (obj);
+}
+
+/* TODO: various strange entries in the path.  */
+
+/* Double-free.  */
+/* { dg-begin-multiline-output "" }
+  'test': events 1-2
+     |
+     |   NN | void test (int i)
+     |      |      ^~~~
+     |      |      |
+     |      |      (1) entry to 'test'
+     |   NN | {
+     |   NN |   boxed_int *obj = make_boxed_int (i);
+     |      |                    ~~~~~~~~~~~~~~~~~~
+     |      |                    |
+     |      |                    (2) calling 'make_boxed_int' from 'test'
+     |
+     +--> 'make_boxed_int': event 3
+                  |
+                  |   NN | make_boxed_int (int i)
+                  |      | ^~~~~~~~~~~~~~
+                  |      | |
+                  |      | (3) entry to 'make_boxed_int'
+                  |
+          'wrapped_malloc': event 4
+                  |
+                  |   NN | void *wrapped_malloc (size_t size)
+                  |      |       ^~~~~~~~~~~~~~
+                  |      |       |
+                  |      |       (4) entry to 'wrapped_malloc'
+                  |
+     <------------+
+     |
+  'test': events 5-6
+     |
+     |   NN |   boxed_int *obj = make_boxed_int (i);
+     |      |                    ^~~~~~~~~~~~~~~~~~
+     |      |                    |
+     |      |                    (5) returning to 'test' from 'make_boxed_int'
+     |   NN | 
+     |   NN |   free_boxed_int (obj);
+     |      |   ~~~~~~~~~~~~~~~~~~~~
+     |      |   |
+     |      |   (6) calling 'free_boxed_int' from 'test'
+     |
+     +--> 'free_boxed_int': events 7-9
+                  |
+                  |   NN | free_boxed_int (boxed_int *bi)
+                  |      | ^~~~~~~~~~~~~~
+                  |      | |
+                  |      | (7) entry to 'free_boxed_int'
+                  |......
+                  |   NN |   wrapped_free (bi);
+                  |      |   ~~~~~~~~~~~~~~~~~
+                  |      |   |
+                  |      |   (8) state of 'ptr': 'start' -> 'nonnull' (origin: NULL)
+                  |      |   (9) first 'free' here (state of 'ptr': 'start' -> 'free', origin: NULL)
+                  |
+          'wrapped_free': events 10-12
+                 |
+                 |   NN | void wrapped_free (void *ptr)
+                 |      |      ^~~~~~~~~~~~
+                 |      |      |
+                 |      |      (10) entry to 'wrapped_free'
+                 |......
+                 |   NN |   free (ptr);
+                 |      |   ~~~~~~~~~~
+                 |      |   |
+                 |      |   (11) first 'free' here (state of 'ptr': 'start' -> 'free', origin: NULL)
+                 |      |   (12) first 'free' here (state of 'ptr': 'nonnull' -> 'free', origin: NULL)
+                 |
+     <-----------+
+     |
+  'test': events 13-14
+     |
+     |   NN |   free_boxed_int (obj);
+     |      |   ^~~~~~~~~~~~~~~~~~~~
+     |      |   |
+     |      |   (13) returning to 'test' from 'free_boxed_int'
+     |   NN | 
+     |   NN |   free_boxed_int (obj);
+     |      |   ~~~~~~~~~~~~~~~~~~~~
+     |      |   |
+     |      |   (14) calling 'free_boxed_int' from 'test'
+     |
+     +--> 'free_boxed_int': events 15-16
+                  |
+                  |   NN | free_boxed_int (boxed_int *bi)
+                  |      | ^~~~~~~~~~~~~~
+                  |      | |
+                  |      | (15) entry to 'free_boxed_int'
+                  |......
+                  |   NN |   wrapped_free (bi);
+                  |      |   ~~~~~~~~~~~~~~~~~
+                  |      |   |
+                  |      |   (16) calling 'wrapped_free' from 'free_boxed_int'
+                  |
+                  +--> 'wrapped_free': events 17-18
+                              |
+                              |   NN | void wrapped_free (void *ptr)
+                              |      |      ^~~~~~~~~~~~
+                              |      |      |
+                              |      |      (17) entry to 'wrapped_free'
+                              |......
+                              |   NN |   free (ptr);
+                              |      |   ~~~~~~~~~~
+                              |      |   |
+                              |      |   (18) second 'free' here ('ptr' is in state 'free')
+                              |
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
new file mode 100644
index 0000000..48680e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
@@ -0,0 +1,65 @@
+/* Example of an  multilevel wrapper around malloc, with an unchecked write.  */
+
+/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdump-analyzer-summaries -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes" } */
+
+#include <stdlib.h>
+
+void *wrapped_malloc (size_t size) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'unchecked'" } */
+{
+  return malloc (size); /* { dg-message "this call could return NULL" } */
+}
+
+typedef struct boxed_int
+{
+  int i;
+} boxed_int;
+
+boxed_int *
+make_boxed_int (int i) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'nonnull'" } */
+{
+  boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+  result->i = i; /* { dg-warning "use of possibly-NULL 'result'" } */
+  /* { dg-message "\\(.*\\) 'result' could be NULL" "" { target *-*-* } .-1 } */
+  return result;
+}
+
+/* "use of possibly-NULL 'result' [CWE-690]".  */
+/* { dg-begin-multiline-output "" }
+  'make_boxed_int': events 1-2
+          |
+          |   NN | make_boxed_int (int i)
+          |      | ^~~~~~~~~~~~~~
+          |      | |
+          |      | (1) entry to 'make_boxed_int'
+          |   NN | {
+          |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+          |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+          |      |                                    |
+          |      |                                    (2) calling 'wrapped_malloc' from 'make_boxed_int'
+          |
+          +--> 'wrapped_malloc': events 3-4
+                       |
+                       |   NN | void *wrapped_malloc (size_t size)
+                       |      |       ^~~~~~~~~~~~~~
+                       |      |       |
+                       |      |       (3) entry to 'wrapped_malloc'
+                       |   NN | {
+                       |   NN |   return malloc (size);
+                       |      |          ~~~~~~~~~~~~~
+                       |      |          |
+                       |      |          (4) this call could return NULL (state of '<return-value>': 'start' -> 'unchecked', origin: NULL)
+                       |
+          <------------+
+          |
+  'make_boxed_int': events 5-6
+          |
+          |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+          |      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+          |      |                                    |
+          |      |                                    (5) returning to 'make_boxed_int' from 'wrapped_malloc'
+          |   NN |   result->i = i;
+          |      |   ~~~~~~~~~~~~~                     
+          |      |             |
+          |      |             (6) 'result' could be NULL ('result' is in state 'unchecked')
+          |
+  { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c
deleted file mode 100644
index 8cec3e9..0000000
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* Example of a multilevel wrapper around malloc/free, with a double-free.  */
-/* TODO: split into two test cases?
-   (one for the unchecked malloc, the other for the double-free).  */
-
-/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdump-analyzer-summaries -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes" } */
-
-#include <stdlib.h>
-
-void *wrapped_malloc (size_t size) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'unchecked'" } */
-{
-  return malloc (size); /* { dg-message "this call could return NULL" } */
-}
-
-void wrapped_free (void *ptr) /* { dg-warning "summary: add: 'ptr': 'start' -> 'free'" } */
-/* { dg-warning "summary: transition: 'ptr': 'nonnull' -> 'free'" "" { target *-*-* } .-1 } */
-/* { dg-warning "summary: transition: 'ptr': 'free' -> 'stop'" "" { target *-*-* } .-2 } */
-{
-  free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\\]" } */
-  /* FIXME: unchecked -> free is correct, but start -> free should be pruned
-     from the path.  */
-}
-
-typedef struct boxed_int
-{
-  int i;
-} boxed_int;
-
-boxed_int *
-make_boxed_int (int i) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'nonnull'" } */
-{
-  boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-  result->i = i; /* { dg-warning "use of possibly-NULL 'result'" } */
-  /* { dg-message "\\(.*\\) 'result' could be NULL" "" { target *-*-* } .-1 } */
-  return result;
-}
-
-void
-free_boxed_int (boxed_int *bi) /* { dg-warning "summary: add: 'bi': 'start' -> 'free'" } */
-/* { dg-warning "summary: add: 'bi': 'start' -> 'stop'" "" { target *-*-* } .-1 } */
-{
-  wrapped_free (bi);
-  /* FIXME: events here are wrong; they refer to ptr, not bi.
-     (was "state of 'ptr': 'start' -> 'free'")
-     Also, they should be just start->free, or be skipped.  */
-}
-
-void test (int i)
-{
-  boxed_int *obj = make_boxed_int (i);
-
-  free_boxed_int (obj);
-
-  free_boxed_int (obj);
-}
-
-/* TODO: various strange entries in the path.  */
-
-/* "use of possibly-NULL 'result' [CWE-690]".  */
-/* { dg-begin-multiline-output "" }
-  'make_boxed_int': events 1-2
-          |
-          |   NN | make_boxed_int (int i)
-          |      | ^~~~~~~~~~~~~~
-          |      | |
-          |      | (1) entry to 'make_boxed_int'
-          |   NN | {
-          |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-          |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-          |      |                                    |
-          |      |                                    (2) calling 'wrapped_malloc' from 'make_boxed_int'
-          |
-          +--> 'wrapped_malloc': events 3-4
-                       |
-                       |   NN | void *wrapped_malloc (size_t size)
-                       |      |       ^~~~~~~~~~~~~~
-                       |      |       |
-                       |      |       (3) entry to 'wrapped_malloc'
-                       |   NN | {
-                       |   NN |   return malloc (size);
-                       |      |          ~~~~~~~~~~~~~
-                       |      |          |
-                       |      |          (4) this call could return NULL (state of '<return-value>': 'start' -> 'unchecked', origin: NULL)
-                       |
-          <------------+
-          |
-  'make_boxed_int': events 5-6
-          |
-          |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-          |      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-          |      |                                    |
-          |      |                                    (5) returning to 'make_boxed_int' from 'wrapped_malloc'
-          |   NN |   result->i = i;
-          |      |   ~~~~~~~~~~~~~                     
-          |      |             |
-          |      |             (6) 'result' could be NULL ('result' is in state 'unchecked')
-          |
-  { dg-end-multiline-output "" } */
-
-/* Double-free.  */
-/* { dg-begin-multiline-output "" }
-  'test': events 1-2
-     |
-     |   NN | void test (int i)
-     |      |      ^~~~
-     |      |      |
-     |      |      (1) entry to 'test'
-     |   NN | {
-     |   NN |   boxed_int *obj = make_boxed_int (i);
-     |      |                    ~~~~~~~~~~~~~~~~~~
-     |      |                    |
-     |      |                    (2) calling 'make_boxed_int' from 'test'
-     |
-     +--> 'make_boxed_int': event 3
-                  |
-                  |   NN | make_boxed_int (int i)
-                  |      | ^~~~~~~~~~~~~~
-                  |      | |
-                  |      | (3) entry to 'make_boxed_int'
-                  |
-          'wrapped_malloc': event 4
-                  |
-                  |   NN | void *wrapped_malloc (size_t size)
-                  |      |       ^~~~~~~~~~~~~~
-                  |      |       |
-                  |      |       (4) entry to 'wrapped_malloc'
-                  |
-     <------------+
-     |
-  'test': events 5-6
-     |
-     |   NN |   boxed_int *obj = make_boxed_int (i);
-     |      |                    ^~~~~~~~~~~~~~~~~~
-     |      |                    |
-     |      |                    (5) returning to 'test' from 'make_boxed_int'
-     |   NN | 
-     |   NN |   free_boxed_int (obj);
-     |      |   ~~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (6) calling 'free_boxed_int' from 'test'
-     |
-     +--> 'free_boxed_int': events 7-9
-                  |
-                  |   NN | free_boxed_int (boxed_int *bi)
-                  |      | ^~~~~~~~~~~~~~
-                  |      | |
-                  |      | (7) entry to 'free_boxed_int'
-                  |......
-                  |   NN |   wrapped_free (bi);
-                  |      |   ~~~~~~~~~~~~~~~~~
-                  |      |   |
-                  |      |   (8) state of 'ptr': 'start' -> 'nonnull' (origin: NULL)
-                  |      |   (9) first 'free' here (state of 'ptr': 'start' -> 'free', origin: NULL)
-                  |
-          'wrapped_free': events 10-12
-                 |
-                 |   NN | void wrapped_free (void *ptr)
-                 |      |      ^~~~~~~~~~~~
-                 |      |      |
-                 |      |      (10) entry to 'wrapped_free'
-                 |......
-                 |   NN |   free (ptr);
-                 |      |   ~~~~~~~~~~
-                 |      |   |
-                 |      |   (11) first 'free' here (state of 'ptr': 'start' -> 'free', origin: NULL)
-                 |      |   (12) first 'free' here (state of 'ptr': 'nonnull' -> 'free', origin: NULL)
-                 |
-     <-----------+
-     |
-  'test': events 13-14
-     |
-     |   NN |   free_boxed_int (obj);
-     |      |   ^~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (13) returning to 'test' from 'free_boxed_int'
-     |   NN | 
-     |   NN |   free_boxed_int (obj);
-     |      |   ~~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (14) calling 'free_boxed_int' from 'test'
-     |
-     +--> 'free_boxed_int': events 15-16
-                  |
-                  |   NN | free_boxed_int (boxed_int *bi)
-                  |      | ^~~~~~~~~~~~~~
-                  |      | |
-                  |      | (15) entry to 'free_boxed_int'
-                  |......
-                  |   NN |   wrapped_free (bi);
-                  |      |   ~~~~~~~~~~~~~~~~~
-                  |      |   |
-                  |      |   (16) calling 'wrapped_free' from 'free_boxed_int'
-                  |
-                  +--> 'wrapped_free': events 17-18
-                              |
-                              |   NN | void wrapped_free (void *ptr)
-                              |      |      ^~~~~~~~~~~~
-                              |      |      |
-                              |      |      (17) entry to 'wrapped_free'
-                              |......
-                              |   NN |   free (ptr);
-                              |      |   ~~~~~~~~~~
-                              |      |   |
-                              |      |   (18) second 'free' here ('ptr' is in state 'free')
-                              |
-   { dg-end-multiline-output "" } */
-- 
1.8.5.3

