diff options
author | Jakub Jelinek <jakub@redhat.com> | 2020-12-31 10:20:39 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2020-12-31 10:20:39 +0100 |
commit | a9ec9902d7f1a9bf7a2778c3fb8fc75bc2df2cef (patch) | |
tree | 35dfacac654745f872232ce25e0897db144a2793 | |
parent | d96b8556e569a1ccce36ef990e167031d07a661a (diff) | |
download | gcc-a9ec9902d7f1a9bf7a2778c3fb8fc75bc2df2cef.zip gcc-a9ec9902d7f1a9bf7a2778c3fb8fc75bc2df2cef.tar.gz gcc-a9ec9902d7f1a9bf7a2778c3fb8fc75bc2df2cef.tar.bz2 |
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.
-rw-r--r-- | gcc/fold-const.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ubsan/align-4.C | 31 |
2 files changed, 43 insertions, 2 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 3a0f39a..0d7113a 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 0000000..42c091b --- /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 (); +} |