This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug sanitizer/81281] [6/7/8 Regression] UBSAN: false positive, dropped promotion to long type.
- From: "jakub at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Mon, 04 Dec 2017 16:59:39 +0000
- Subject: [Bug sanitizer/81281] [6/7/8 Regression] UBSAN: false positive, dropped promotion to long type.
- Auto-submitted: auto-generated
- References: <bug-81281-4@http.gcc.gnu.org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81281
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So it is indeed the
/* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
(for add (plus pointer_plus)
(simplify
(minus (convert (add @@0 @1))
(convert (add @0 @2)))
(if (element_precision (type) <= element_precision (TREE_TYPE (@1))
/* For integer types, if A has a smaller type
than T the result depends on the possible
overflow in P + A.
E.g. T=size_t, A=(unsigned)429497295, P>0.
However, if an overflow in P + A would cause
undefined behavior, we can assume that there
is no overflow. */
|| (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
/* For pointer types, if the conversion of A to the
final type requires a sign- or zero-extension,
then we have to punt - it is not defined which
one is correct. */
|| (POINTER_TYPE_P (TREE_TYPE (@0))
&& TREE_CODE (@1) == INTEGER_CST
&& tree_int_cst_sign_bit (@1) == 0
&& TREE_CODE (@2) == INTEGER_CST
&& tree_int_cst_sign_bit (@2) == 0))
(minus (convert @1) (convert @2)))))))
case, where we have:
op0 (int) ((((unsigned int) ll - (unsigned int) ci) - (unsigned int) i) +
2270794745)
op1 (int) ((((unsigned int) ll - (unsigned int) ci) - (unsigned int) i) +
(unsigned int) ci);
type here is int, @0/@1/@2 all have unsigned type.
The (T)(P + A) - (T)(P + B) to (T)A - (T)B transformation is incorrect if
TYPE_OVERFLOW_UNDEFINED (type) (or its element type)
and either !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) (or its element type), or
TREE_TYPE (@1) has larger element precision.
Say if T is int, and TREE_TYPE (P) is unsigned, then e.g. random example of A =
0U+INT_MIN, B = 1U, P = -1U overflows only in the (int) INT_MIN - (int) 1 case,
but doesn't overflow in the (int)(-1U+INT_MIN) - (int)(1U + -1U) case (many
other examples).
We need to do the subtraction in an unsigned_type_for (type) instead and only
cast to type at the end.
For the POINTER_PLUS_EXPR case, the explicitly enabled case is only if both @1
and @2 are INTEGER_CSTs with MSB clear which is fine for the widening
conversion to type, but for equal or narrowing one not really sure.