On December 30, 2020 10:30:33 AM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>The following testcase is diagnosed by UBSan as invalid, even when it
>is
>valid.
>We have a derived type Base2 at offset 1 with alignment 1 and do:
>(const Derived &) ((const Base2 *) this + -1)
>but the folder before ubsan in the FE gets a chance to instrument it
>optimizes that into:
>(const Derived &) this + -1
>and so we require that this has 8-byte alignment which Derived class
>needs.
>
>Fixed by avoiding such an optimization when -fsanitize=alignment is in
>effect if it would affect the alignments (and guarded with
>!in_gimple_form
>because we don't really care during GIMPLE, though pointer conversions
>are
>useless then and so such folding isn't needed very much during GIMPLE).
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok. 

Richard. 

>2020-12-30  Jakub Jelinek  <ja...@redhat.com>
>
>       PR c++/98206
>       * fold-const.c: Include asan.h.
>       (fold_unary_loc): Don't optimize (ptr_type) (((ptr_type2) x) p+ y)
>       into ((ptr_type) x) p+ y if sanitizing alignment in GENERIC and
>       ptr_type points to type with higher alignment than ptr_type2.
>
>       * g++.dg/ubsan/align-4.C: New test.
>
>--- gcc/fold-const.c.jj        2020-12-21 10:14:39.409173804 +0100
>+++ gcc/fold-const.c   2020-12-29 15:40:34.283148245 +0100
>@@ -82,6 +82,7 @@ along with GCC; see the file COPYING3.
> #include "attribs.h"
> #include "tree-vector-builder.h"
> #include "vec-perm-indices.h"
>+#include "asan.h"
> 
> /* Nonzero if we are folding constants inside an initializer; zero
>    otherwise.  */
>@@ -9392,8 +9393,17 @@ fold_unary_loc (location_t loc, enum tre
>         tree arg00 = TREE_OPERAND (arg0, 0);
>         tree arg01 = TREE_OPERAND (arg0, 1);
> 
>-        return fold_build_pointer_plus_loc
>-                 (loc, fold_convert_loc (loc, type, arg00), arg01);
>+        /* If -fsanitize=alignment, avoid this optimization in GENERIC
>+           when the pointed type needs higher alignment than
>+           the p+ first operand's pointed type.  */
>+        if (!in_gimple_form
>+            && sanitize_flags_p (SANITIZE_ALIGNMENT)
>+            && (min_align_of_type (TREE_TYPE (type))
>+                > min_align_of_type (TREE_TYPE (TREE_TYPE (arg00)))))
>+          return NULL_TREE;
>+
>+        arg00 = fold_convert_loc (loc, type, arg00);
>+        return fold_build_pointer_plus_loc (loc, arg00, arg01);
>       }
> 
>    /* Convert (T1)(~(T2)X) into ~(T1)X if T1 and T2 are integral types
>--- gcc/testsuite/g++.dg/ubsan/align-4.C.jj    2020-12-29
>15:28:11.811501092 +0100
>+++ gcc/testsuite/g++.dg/ubsan/align-4.C       2020-12-29 15:29:54.198348346
>+0100
>@@ -0,0 +1,31 @@
>+// PR c++/98206
>+// { dg-do run }
>+// { dg-options "-fsanitize=alignment -std=c++11
>-fno-sanitize-recover=alignment" }
>+
>+template <typename Derived>
>+struct Base1
>+{
>+  char c1;
>+};
>+
>+template <typename Derived>
>+struct Base2
>+{
>+  char c2;
>+  const Derived &get2 () const { return static_cast<const Derived &>
>(*this); }
>+};
>+
>+struct X : public Base1<X>, public Base2<X>
>+{
>+  X (const char *d) : data{d} {}
>+  const char *data;
>+};
>+
>+int
>+main ()
>+{
>+  X x = X{"cheesecake"};
>+  const char *p = x.get2 ().data;
>+  if (p[0] != 'c')
>+    __builtin_abort ();
>+}
>
>       Jakub

Reply via email to