Boost logo

Boost :

Subject: Re: [boost] [cfe-users] Boost.GIL test failing with clang 5.x while pass with 15 gcc/clang versions
From: Mateusz Loskot (mateusz_at_[hidden])
Date: 2018-05-21 19:15:24


FYI, cause of the problem has been identified: UB due to signed integer overflow

clang++ -fsanitize=signed-integer-overflow overflow.cpp
./a.out
-2147483648
overflow.cpp:24:52: runtime error: signed integer overflow: 2147483647
- -2147483648 cannot be represented in type 'int'

Thanks and credits to Jan Korous (and the awesome
UndefinedBehaviorSanitizer :-))

Mateusz

On 20 May 2018 at 11:47, Mateusz Loskot <mateusz_at_[hidden]> wrote:
> Hi,
>
> I posted this to clang mailing list a
> http://lists.llvm.org/pipermail/cfe-users/2018-May/001335.html
> but since it is related to Boost.GIL bugs I'm investigating,
> I'd like to reach for feedback here too.
>
> I'll appreciate any comments regarding the issue explained below.
>
> ML
>
> ---------- Forwarded message ----------
> From: Mateusz Loskot <mateusz_at_[hidden]>
> Date: 19 May 2018 at 21:38
> Subject: Boost.GIL test failing with clang 5.x while pass with 15
> gcc/clang versions
> To: cfe-users_at_[hidden]
>
> Hi,
>
> While testing Boost.GIL library [1] with gcc and clang, I noticed a
> peculiar issue.
> One particular test is failing with lang 5.x while passing with total of 15-17
> other versions of clang and GCC (total workflow of CircleCI with at [2]).
>
> Below is extracted minimal program equivalent to Boost.GIL
> channel_invert algorithm. It includes two variants: plain expression
> and the same expression wrapped with a function template:
>
> #include <limits>
> #include <iostream>
> #include <typeinfo>
>
> template <typename C>
> inline C channel_invert1(C x)
> {
> return std::numeric_limits<C>::max() - x + std::numeric_limits<C>::min();
> }
>
> template <typename C>
> inline C channel_invert2(C x)
> {
> return (x - std::numeric_limits<C>::max()) * (-1) +
> std::numeric_limits<C>::min();
> }
>
> int main()
> {
> int x = std::numeric_limits<int>::min();
> std::cout << x << std::endl;
>
> // plain expressions
> int x_invert1 = std::numeric_limits<int>::max() - x +
> std::numeric_limits<int>::min();
> int x_invert2 = (x - std::numeric_limits<int>::max()) * (-1) +
> std::numeric_limits<int>::min();
> std::cout << x_invert1 << std::endl;
> std::cout << x_invert2 << std::endl;
>
> // the same expressions wrapped in function template
> std::cout << channel_invert1<int>(x) << std::endl;
> std::cout << channel_invert2<int>(x) << std::endl;
> }
>
> If compiled as optimised variant (-O2 or -O3) with clang 5.x outputs
> the following:
>
> -2147483648
> 2147483647
> 2147483647
> -1
> -1
>
> The last two negative one is not expected.
>
> If compiled with clang 3.9, 4.0 or gcc from 5.1 to 7.3 it outputs
>
> -2147483648
> 2147483647
> 2147483647
> 2147483647
> 2147483647
>
> Could anyone help me to understand what is going on in the clang 5 case?
> Or, what UB is this hitting?
>
> [1] https://github.com/boostorg/gil/issues/89
> [2] https://circleci.com/workflow-run/3a14dd64-6c38-46b2-a6da-678c0075ca27
>
> Best regards,
> --
> Mateusz Loskot, http://mateusz.loskot.net

-- 
Mateusz Loskot, http://mateusz.loskot.net

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk