From 448ae4c5496213eee2cd57012d50c6e7bebf858f Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 25 Mar 2019 17:42:11 -0400
Subject: [PATCH 146/161] FIXME: handle deref via COMPONENT_REF

---
 gcc/analyzer/hardcoded-state-machine-malloc.cc     |  3 ++
 .../multiple-errors/deref-of-null/input.c          | 41 -------------------
 .../multiple-errors/deref-of-null/script.py        | 46 ----------------------
 .../multiple-errors/deref-of-null/stderr.txt       |  4 --
 .../multiple-errors/deref-of-null/stdout.txt       |  0
 gcc/testsuite/gcc.dg/analyzer/malloc-1.c           | 27 +++++++++++++
 gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c       |  8 ++--
 7 files changed, 34 insertions(+), 95 deletions(-)
 delete mode 100644 gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/input.c
 delete mode 100644 gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/script.py
 delete mode 100644 gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stderr.txt
 delete mode 100644 gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stdout.txt

diff --git a/gcc/analyzer/hardcoded-state-machine-malloc.cc b/gcc/analyzer/hardcoded-state-machine-malloc.cc
index 6b67845..8445448 100644
--- a/gcc/analyzer/hardcoded-state-machine-malloc.cc
+++ b/gcc/analyzer/hardcoded-state-machine-malloc.cc
@@ -368,6 +368,9 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt,
 #endif
       if (!op)
 	continue;
+      if (TREE_CODE (op) == COMPONENT_REF)
+	op = TREE_OPERAND (op, 0);
+
       if (TREE_CODE (op) == MEM_REF)
 	{
 	  tree arg = TREE_OPERAND (op, 0);
diff --git a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/input.c b/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/input.c
deleted file mode 100644
index 7db1b58..0000000
--- a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/input.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-   Copyright 2013 David Malcolm <dmalcolm@redhat.com>
-   Copyright 2013 Red Hat, Inc.
-
-   This is free software: you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see
-   <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-struct foo {
-  int i;
-  int j;
-  int k;
-};
-
-struct foo *test(void)
-{
-  struct foo *p = NULL;
-
-  /* BUG: dereference of NULL ptr: */
-  p->i = 1;
-
-  /* Only the first such usage should be reported: */
-  p->j = 2;
-  p->k = 3;
-
-  return p;
-}
diff --git a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/script.py b/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/script.py
deleted file mode 100644
index 71617ba..0000000
--- a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/script.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- coding: utf-8 -*-
-#   Copyright 2013 David Malcolm <dmalcolm@redhat.com>
-#   Copyright 2013 Red Hat, Inc.
-#
-#   This is free software: you can redistribute it and/or modify it
-#   under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-#
-#   This program is distributed in the hope that it will be useful, but
-#   WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#   General Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see
-#   <http://www.gnu.org/licenses/>.
-
-from sm import main
-from sm.parser import parse_file
-
-def selftest(ctxt, solution):
-    if 0:
-        import sys
-        solution.dump(sys.stderr)
-
-    node_write_to_p = ctxt.get_nodes().assigning_constant(0).one()
-    ssaname = node_write_to_p.stmt.lhs
-
-    p = ctxt.find_var(node_write_to_p, 'p')
-    node_write_to_p_i = ctxt.get_nodes().assigning_constant(1).one()
-    ctxt.assert_statenames_for_expr(node_write_to_p_i, p,
-                                    frozenset(['ptr.null']))
-
-    # It should now have given up, with the p in the "ptr.stop" state:
-    node_write_to_p_j = ctxt.get_nodes().assigning_constant(2).one()
-    ctxt.assert_statenames_for_expr(node_write_to_p_j, p,
-                                    frozenset(['ptr.stop']))
-
-    node_write_to_p_k = ctxt.get_nodes().assigning_constant(3).one()
-    ctxt.assert_statenames_for_expr(node_write_to_p_k, p,
-                                    frozenset(['ptr.stop']))
-
-
-checker = parse_file('sm/checkers/malloc_checker.sm')
-main([checker], selftest=selftest)
diff --git a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stderr.txt b/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stderr.txt
deleted file mode 100644
index c1d6d40..0000000
--- a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-tests/sm/checkers/malloc-checker/multiple-errors/deref-of-null/input.c: In function 'test':
-tests/sm/checkers/malloc-checker/multiple-errors/deref-of-null/input.c:34:nn: error: dereference of NULL pointer p [CWE-690]
-tests/sm/checkers/malloc-checker/multiple-errors/deref-of-null/input.c:31:nn: note: p assigned to 0
-tests/sm/checkers/malloc-checker/multiple-errors/deref-of-null/input.c:34:nn: note: dereference of NULL pointer p
diff --git a/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stdout.txt b/gcc/testsuite/gcc.dg/TODO-analyzer/checkers/malloc-checker/multiple-errors/deref-of-null/stdout.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
index 24235b1..5914d65 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
@@ -274,3 +274,30 @@ int test_26 (void)
   free (p); /* { dg-warning "free of 'p' which points to memory not on the heap \\\[CWE-590\\\]" } */
   /* TODO: more precise messages here.  */
 }
+
+struct coord {
+  float x;
+  float y;
+};
+
+struct coord *test_27 (void)
+{
+  struct coord *p = (struct coord *) malloc (sizeof (struct coord)); /* { dg-message "this call could return NULL" } */
+  p->x = 0.f;  /* { dg-warning "use of possibly-NULL 'p'" } */
+
+  /* Only the first such usage should be reported: */
+  p->y = 0.f;
+
+  return p;
+}
+
+struct coord *test_28 (void)
+{
+  struct coord *p = NULL;
+  p->x = 0.f; /* { dg-warning "use of NULL 'p'" } */
+
+  /* Only the first such usage should be reported: */
+  p->y = 0.f;
+
+  return p;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c
index 2b7364c..c9034f1 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8.c
@@ -11,7 +11,7 @@ void *wrapped_malloc (size_t size) /* { dg-warning "summary: add: '<return-value
 }
 
 void wrapped_free (void *ptr) /* { dg-warning "summary: add: 'ptr': 'start' -> 'free'" } */
-/* { dg-warning "summary: transition: 'ptr': 'unchecked' -> 'free'" "" { target *-*-* } .-1 } */
+/* { dg-warning "summary: transition: 'ptr': 'nonnull' -> 'free'" "" { target *-*-* } .-1 } */
 /* { dg-warning "summary: transition: 'ptr': 'free' -> 'stop'" "" { target *-*-* } .-2 } */
 /* { dg-message "\\(10\\) entry to 'wrapped_free'" "" { target *-*-* } .-3 } */
 /* { dg-message "\\(17\\) entry to 'wrapped_free'" "" { target *-*-* } .-4 } */
@@ -31,11 +31,11 @@ typedef struct boxed_int
 } boxed_int;
 
 boxed_int *
-make_boxed_int (int i) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'unchecked'" } */
+make_boxed_int (int i) /* { dg-warning "summary: add: '<return-value>': 'start' -> 'nonnull'" } */
 /* { dg-message "\\(3\\) entry to 'make_boxed_int'" "" { target *-*-* } .-1 } */
 {
   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-  result->i = i;
+  result->i = i; /* { dg-warning "use of possibly-NULL 'result'" } */
   return result;
 }
 
@@ -45,7 +45,7 @@ free_boxed_int (boxed_int *bi) /* { dg-warning "summary: add: 'bi': 'start' -> '
 /* { dg-message "\\(7\\) entry to 'free_boxed_int'" "" { target *-*-* } .-2 } */
 /* { dg-message "\\(15\\) entry to 'free_boxed_int'" "" { target *-*-* } .-3 } */
 {
-  wrapped_free (bi); /* { dg-message "\\(8\\) state of 'ptr': 'start' -> 'unchecked'" } */
+  wrapped_free (bi); /* { dg-message "\\(8\\) state of 'ptr': 'start' -> 'nonnull'" } */
   /* { dg-message "\\(9\\) first 'free' here" "" { target *-*-* } .-1 } */
   /* FIXME: these are wrong; they refer to ptr, not bi.
      (was "state of 'ptr': 'start' -> 'free'")
-- 
1.8.5.3

