Hi!

Bernd E. mentioned in the PR the problem that if some subobject ctor throws,
if for -fsanitize=vptr we clear again the vtable pointers even for virtual
bases then they won't be properly destructed.

So, here is an incremental patch to the earlier patch, which will clear
the virtual base vtbl pointers only in the in-charge ctor.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Though, this brings a non-sanitizer issue, for -flifetime-dse=2
we emit a clobber of the whole subobject even in a ctor with _vtt_parm
argument, and the virtual bases at that point might live inside of the
area that is clobbered by the ctor {CLOBBER}
(both data and vtable pointers).  I'm afraid that e.g. with inlining this
could result into wrong code, e.g. DSE removing the earlier stores from the
virtual base ctor stores, because we {CLOBBER} them later on.
Shouldn't we conditionalize the -flifetime-dse=2 clobbers on __in_chrg
(if that parm is present)?

2016-03-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/70147
        * cp-ubsan.c (cp_ubsan_dfs_initialize_vtbl_ptrs): Conditionalize
        BINFO_VIRTUAL_P vtable clearing on current_in_charge_parm.

        * g++.dg/ubsan/pr70147-2.C (C::C): Initialize A base with invalid
        method call to i () as argument.  Adjust expected output.

--- gcc/cp/cp-ubsan.c.jj        2016-03-15 09:25:19.000000000 +0100
+++ gcc/cp/cp-ubsan.c   2016-03-15 09:40:51.209005916 +0100
@@ -299,8 +299,14 @@ cp_ubsan_dfs_initialize_vtbl_ptrs (tree
 
       /* Assign NULL to the vptr.  */
       tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr));
-      finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl,
-                                             tf_warning_or_error));
+      tree stmt = cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl,
+                                       tf_warning_or_error);
+      if (BINFO_VIRTUAL_P (binfo))
+       stmt = build3 (COND_EXPR, void_type_node,
+                      build2 (NE_EXPR, boolean_type_node,
+                              current_in_charge_parm, integer_zero_node),
+                      stmt, void_node);
+      finish_expr_stmt (stmt);
     }
 
   return NULL_TREE;
--- gcc/testsuite/g++.dg/ubsan/pr70147-2.C.jj   2016-03-15 09:46:24.000000000 
+0100
+++ gcc/testsuite/g++.dg/ubsan/pr70147-2.C      2016-03-15 09:48:04.622051166 
+0100
@@ -46,7 +46,7 @@ struct B : virtual A, public E, public F
 };
 struct C : B, virtual A
 {
-  C () {}
+  C () : A (i ()) {}
 };
 
 int
@@ -55,28 +55,22 @@ main ()
   C c;
 }
 
-// { dg-output "\[^\n\r]*pr70147-2.C:33:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'E'(\n|\r\n|\r)" }
-// { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
-// { dg-output "  ?.. .. .. ..  ?.. .. .. ..  ?.. .. .. .. 
\[^\n\r]*(\n|\r\n|\r)" }
-// { dg-output "              ?\\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
-// { dg-output "              ?invalid vptr(\n|\r\n|\r)" }
-// { dg-output "\[^\n\r]*pr70147-2.C:34:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'F'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*pr70147-2.C:49:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'A'(\n|\r\n|\r)" }
 // { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
 // { dg-output "  ?.. .. .. ..  ?.. .. .. ..  ?.. .. .. .. 
\[^\n\r]*(\n|\r\n|\r)" }
 // { dg-output "              ?\\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
 // { dg-output "              ?invalid vptr\[^\n\r]*(\n|\r\n|\r)" }
-// { dg-output "\[^\n\r]*pr70147-2.C:35:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'A'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*pr70147-2.C:33:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'E'(\n|\r\n|\r)" }
 // { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
 // { dg-output "  ?.. .. .. ..  ?.. .. .. ..  ?.. .. .. .. 
\[^\n\r]*(\n|\r\n|\r)" }
 // { dg-output "              ?\\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
-// { dg-output "              ?invalid vptr\[^\n\r]*(\n|\r\n|\r)" }
-// Note we don't catch the UB of calling g () on line 36.
-// { dg-output "\[^\n\r]*pr70147-2.C:38:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'F'(\n|\r\n|\r)" }
+// { dg-output "              ?invalid vptr(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*pr70147-2.C:34:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'F'(\n|\r\n|\r)" }
 // { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
 // { dg-output "  ?.. .. .. ..  ?.. .. .. ..  ?.. .. .. .. 
\[^\n\r]*(\n|\r\n|\r)" }
 // { dg-output "              ?\\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
 // { dg-output "              ?invalid vptr\[^\n\r]*(\n|\r\n|\r)" }
-// { dg-output "\[^\n\r]*pr70147-2.C:39:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'A'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*pr70147-2.C:38:\[0-9]*: runtime error: member call on 
address 0x\[0-9a-fA-F]* which does not point to an object of type 
'F'(\n|\r\n|\r)" }
 // { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
 // { dg-output "  ?.. .. .. ..  ?.. .. .. ..  ?.. .. .. .. 
\[^\n\r]*(\n|\r\n|\r)" }
 // { dg-output "              ?\\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }


        Jakub

Reply via email to