This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug sanitizer/81281] [6/7/8 Regression] UBSAN: false positive, dropped promotion to long type.


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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]