From 6f3af3562804db0ef656dcc02b1e192c8f7fc8cc Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Fri, 31 Mar 2017 20:39:25 +0200
Subject: [PATCH] re PR sanitizer/79572 (reference binding to null pointer not
 reported with -fsanitize=undefined)

	PR c++/79572
	* c-ubsan.h (ubsan_maybe_instrument_reference): Change argument to
	tree *.
	* c-ubsan.c (ubsan_maybe_instrument_reference): Likewise.  Handle
	not just NOP_EXPR to REFERENCE_TYPE, but also INTEGER_CST with
	REFERENCE_TYPE.

	* cp-gimplify.c (cp_genericize_r): Sanitize INTEGER_CSTs with
	REFERENCE_TYPE.  Adjust ubsan_maybe_instrument_reference caller
	for NOP_EXPR to REFERENCE_TYPE.

	* g++.dg/ubsan/null-8.C: New test.

From-SVN: r246621
---
 gcc/c-family/ChangeLog              |  9 +++++++++
 gcc/c-family/c-ubsan.c              | 17 +++++++++++++----
 gcc/c-family/c-ubsan.h              |  2 +-
 gcc/cp/ChangeLog                    |  5 +++++
 gcc/cp/cp-gimplify.c                | 15 ++++++++++++++-
 gcc/testsuite/ChangeLog             |  5 +++++
 gcc/testsuite/g++.dg/ubsan/null-8.C | 19 +++++++++++++++++++
 7 files changed, 66 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ubsan/null-8.C

diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 0f0bd49714a2..0d5a16f66091 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,12 @@
+2017-03-31  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/79572
+	* c-ubsan.h (ubsan_maybe_instrument_reference): Change argument to
+	tree *.
+	* c-ubsan.c (ubsan_maybe_instrument_reference): Likewise.  Handle
+	not just NOP_EXPR to REFERENCE_TYPE, but also INTEGER_CST with
+	REFERENCE_TYPE.
+
 2017-03-31  David Malcolm  <dmalcolm@redhat.com>
 
 	PR documentation/78732
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 36aa919a872f..91bdef883203 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -458,17 +458,26 @@ ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
   return fold_build2 (COMPOUND_EXPR, TREE_TYPE (op), call, op);
 }
 
-/* Instrument a NOP_EXPR to REFERENCE_TYPE if needed.  */
+/* Instrument a NOP_EXPR to REFERENCE_TYPE or INTEGER_CST with REFERENCE_TYPE
+   type if needed.  */
 
 void
-ubsan_maybe_instrument_reference (tree stmt)
+ubsan_maybe_instrument_reference (tree *stmt_p)
 {
-  tree op = TREE_OPERAND (stmt, 0);
+  tree stmt = *stmt_p;
+  tree op = stmt;
+  if (TREE_CODE (stmt) == NOP_EXPR)
+    op = TREE_OPERAND (stmt, 0);
   op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op,
 						 TREE_TYPE (stmt),
 						 UBSAN_REF_BINDING);
   if (op)
-    TREE_OPERAND (stmt, 0) = op;
+    {
+      if (TREE_CODE (stmt) == NOP_EXPR) 
+	TREE_OPERAND (stmt, 0) = op;
+      else
+	*stmt_p = op;
+    }
 }
 
 /* Instrument a CALL_EXPR to a method if needed.  */
diff --git a/gcc/c-family/c-ubsan.h b/gcc/c-family/c-ubsan.h
index dc0897d605f9..3c3ffc7f7a2c 100644
--- a/gcc/c-family/c-ubsan.h
+++ b/gcc/c-family/c-ubsan.h
@@ -28,7 +28,7 @@ extern tree ubsan_instrument_return (location_t);
 extern tree ubsan_instrument_bounds (location_t, tree, tree *, bool);
 extern bool ubsan_array_ref_instrumented_p (const_tree);
 extern void ubsan_maybe_instrument_array_ref (tree *, bool);
-extern void ubsan_maybe_instrument_reference (tree);
+extern void ubsan_maybe_instrument_reference (tree *);
 extern void ubsan_maybe_instrument_member_call (tree, bool);
 
 /* Declare this here as well as in ubsan.h. */
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 14eee1c33409..743847908d0c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2017-03-31  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c++/79572
+	* cp-gimplify.c (cp_genericize_r): Sanitize INTEGER_CSTs with
+	REFERENCE_TYPE.  Adjust ubsan_maybe_instrument_reference caller
+	for NOP_EXPR to REFERENCE_TYPE.
+
 	PR libstdc++/80251
 	* cp-tree.h (enum cp_trait_kind): Add CPTK_IS_AGGREGATE.
 	* cxx-pretty-print.c (pp_cxx_trait_expression): Handle
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 354ae1af8526..6e49daf84997 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1130,6 +1130,19 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 	}
     }
 
+  if (TREE_CODE (stmt) == INTEGER_CST
+      && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE
+      && (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
+      && !wtd->no_sanitize_p)
+    {
+      ubsan_maybe_instrument_reference (stmt_p);
+      if (*stmt_p != stmt)
+	{
+	  *walk_subtrees = 0;
+	  return NULL_TREE;
+	}
+    }
+
   /* Other than invisiref parms, don't walk the same tree twice.  */
   if (p_set->contains (stmt))
     {
@@ -1477,7 +1490,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       if ((flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
 	  && TREE_CODE (stmt) == NOP_EXPR
 	  && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE)
-	ubsan_maybe_instrument_reference (stmt);
+	ubsan_maybe_instrument_reference (stmt_p);
       else if (TREE_CODE (stmt) == CALL_EXPR)
 	{
 	  tree fn = CALL_EXPR_FN (stmt);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 02581a2ca65a..134fc2a309c0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-31  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/79572
+	* g++.dg/ubsan/null-8.C: New test.
+
 2017-03-31  Pat Haugen  <pthaugen@us.ibm.com>
 
 	PR target/80107
diff --git a/gcc/testsuite/g++.dg/ubsan/null-8.C b/gcc/testsuite/g++.dg/ubsan/null-8.C
new file mode 100644
index 000000000000..259a213183a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/null-8.C
@@ -0,0 +1,19 @@
+// PR c++/79572
+// { dg-do run }
+// { dg-options "-fsanitize=null -std=c++14" }
+// { dg-output "reference binding to null pointer of type 'const int'" }
+
+void
+foo (const int &iref)
+{
+  if (&iref)
+    __builtin_printf ("iref %d\n", iref);
+  else
+    __builtin_printf ("iref is NULL\n");
+}
+
+int
+main ()
+{
+  foo (*((int*) __null));
+}
-- 
GitLab