aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-12-31 10:20:39 +0100
committerJakub Jelinek <jakub@redhat.com>2020-12-31 10:20:39 +0100
commita9ec9902d7f1a9bf7a2778c3fb8fc75bc2df2cef (patch)
tree35dfacac654745f872232ce25e0897db144a2793 /gcc
parentd96b8556e569a1ccce36ef990e167031d07a661a (diff)
fold-const: Avoid (cast) ((cast2) x p+ y) folding for -fsanitize=alignment [PR98206]
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). 2020-12-31 Jakub Jelinek <jakub@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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fold-const.c14
-rw-r--r--gcc/testsuite/g++.dg/ubsan/align-4.C31
2 files changed, 43 insertions, 2 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3a0f39a85b8..0d7113a8025 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -82,6 +82,7 @@ along with GCC; see the file COPYING3. If not see
#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 tree_code code, tree type, tree op0)
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
diff --git a/gcc/testsuite/g++.dg/ubsan/align-4.C b/gcc/testsuite/g++.dg/ubsan/align-4.C
new file mode 100644
index 00000000000..42c091b92cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/align-4.C
@@ -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 ();
+}