This incremental patch brings the implementation of reference binding
instrumentation, that is, it detects cases like

int *p = NULL;
int &r = *p;
or 
auto &&rr = *p;
and similarly.  It does so by adding a COMPOUND_EXPR to the decl.
As standard says, "A reference shall be initialized to refer to a
valid object or function.".

Jason, is that tiny C++ part ok with you?

Regtested/bootstrapped on x86_64-linux, ran bootstrap-ubsan, ok for
trunk?

2013-11-18  Marek Polacek  <pola...@redhat.com>

c-family/
        * c-ubsan.h (ubsan_instrument_reference): Declare.
        * c-ubsan.c (ubsan_instrument_reference): New function.
cp/
        * decl.c (cp_finish_decl): Instrument reference binding.
testsuite/
        * g++.dg/ubsan/null-1.C: New test.

--- gcc/c-family/c-ubsan.h.mp2  2013-11-18 12:52:00.572671736 +0100
+++ gcc/c-family/c-ubsan.h      2013-11-18 12:52:25.751761970 +0100
@@ -24,5 +24,6 @@ along with GCC; see the file COPYING3.
 extern tree ubsan_instrument_division (location_t, tree, tree);
 extern tree ubsan_instrument_shift (location_t, enum tree_code, tree, tree);
 extern tree ubsan_instrument_vla (location_t, tree);
+extern tree ubsan_instrument_reference (location_t, tree);
 
 #endif  /* GCC_C_UBSAN_H  */
--- gcc/c-family/c-ubsan.c.mp2  2013-11-18 12:49:00.553025438 +0100
+++ gcc/c-family/c-ubsan.c      2013-11-18 15:26:53.835120271 +0100
@@ -179,3 +179,30 @@ ubsan_instrument_vla (location_t loc, tr
 
   return t;
 }
+
+/* Instrument reference binding, that is, ensure that the reference
+   declaration doesn't bind the reference to a NULL pointer.  */
+
+tree
+ubsan_instrument_reference (location_t loc, tree init)
+{
+  if (!INDIRECT_REF_P (init))
+    /* This may happen, e.g. int &&r4 = p;, so don't put an assert here.  */
+    return init;
+
+  init = TREE_OPERAND (init, 0);
+  tree eq_expr = fold_build2 (EQ_EXPR, boolean_type_node, init,
+                             build_zero_cst (TREE_TYPE (init)));
+  const struct ubsan_mismatch_data m
+    = { build_zero_cst (pointer_sized_int_node),
+       build_int_cst (unsigned_char_type_node, UBSAN_REF_BINDING)};
+  tree data = ubsan_create_data ("__ubsan_null_data",
+                                loc, &m,
+                                ubsan_type_descriptor (TREE_TYPE (init),
+                                                       true), NULL_TREE);
+  data = build_fold_addr_expr_loc (loc, data);
+  tree fn = builtin_decl_implicit (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH);
+  fn = build_call_expr_loc (loc, fn, 2, data,
+                           build_zero_cst (pointer_sized_int_node));
+  return fold_build3 (COND_EXPR, void_type_node, eq_expr, fn, void_zero_node);
+}
--- gcc/cp/decl.c.mp2   2013-11-15 17:14:24.887512640 +0100
+++ gcc/cp/decl.c       2013-11-18 13:38:15.356077696 +0100
@@ -6216,6 +6217,11 @@ cp_finish_decl (tree decl, tree init, bo
          if (decl_maybe_constant_var_p (decl))
            TREE_CONSTANT (decl) = 1;
        }
+      if (flag_sanitize & SANITIZE_NULL
+         && TREE_CODE (type) == REFERENCE_TYPE)
+       init = fold_build2 (COMPOUND_EXPR, TREE_TYPE (init),
+                           ubsan_instrument_reference (input_location, init),
+                           init);
     }
 
   if (processing_template_decl)
--- gcc/testsuite/g++.dg/ubsan/null-1.C.mp2     2013-11-18 15:29:44.722831910 
+0100
+++ gcc/testsuite/g++.dg/ubsan/null-1.C 2013-11-18 15:29:54.744874505 +0100
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w -std=c++11" } */
+
+typedef const long int L;
+
+int
+main (void)
+{
+  int *p = 0;
+  L *l = 0;
+
+  int &r = *p;
+  auto &r2 = *p;
+  L &lr = *l;
+
+  /* Try an rvalue reference.  */
+  auto &&r3 = *p;
+}
+
+/* { dg-output "reference binding to null pointer of type 'int'(\n|\r\n|\r)" } 
*/
+/* { dg-output "\[^\n\r]*reference binding to null pointer of type 
'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*reference binding to null pointer of type 'const 
L'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*reference binding to null pointer of type 
'int'(\n|\r\n|\r)" } */

        Marek

Reply via email to