Bug 95334 - GCC detect missing signed-integer-overflow when add "const"
Summary: GCC detect missing signed-integer-overflow when add "const"
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2020-05-26 12:53 UTC by Haoxin Tu
Modified: 2023-01-06 12:22 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Haoxin Tu 2020-05-26 12:53:43 UTC
This code test1.cc

#include <iostream>
#include <climits>

wchar_t g_wchar = 0;
int g_int = -1975564288;
int l_int = -1227761344;

int main () {
    g_wchar = l_int + g_int;
    std::cout << g_wchar << std::endl;
    std::cout << "WCHAR_MIN = " << WCHAR_MIN << std::endl;
    std::cout << "WCHAR_MAX = " << WCHAR_MAX << std::endl;
    return 0;
}

GCC can detect UB correctly

$g++ -w -fsanitize=signed-integer-overflow ; ./a.out
test1.cc:9:21: runtime error: signed integer overflow: -1227761344 + -1975564288 cannot be represented in type 'int'
1091641664
WCHAR_MIN = -2147483648
WCHAR_MAX = 2147483647

But in this case test2.cc add "const" for int
#include <iostream>
#include <climits>

wchar_t g_wchar = 0;
const int g_int = -1975564288;
const int l_int = -1227761344;

int main () {
    g_wchar = l_int + g_int;
    std::cout << g_wchar << std::endl;
    std::cout << "WCHAR_MIN = " << WCHAR_MIN << std::endl;
    std::cout << "WCHAR_MAX = " << WCHAR_MAX << std::endl;
    return 0;
}

GCC detect nothing.

$g++ -w -fsanitize=signed-integer-overflow test2.cc; ./a.out
1091641664
WCHAR_MIN = -2147483648
WCHAR_MAX = 2147483647

My g++ version

$g++ --version
g++ (GCC) 11.0.0 20200526 (experimental)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I have tested them in recent GCC versions including GCC-8, GCC-9, GCC-10, they have the same symptom as well.

I also test them in clang-trunk, above two testcases can be detected as "signed integer overflow".
Comment 1 Jonathan Wakely 2020-05-26 13:08:57 UTC
My guess is that G++ folds the constants early and the overflow happens at compile time, so is never seen by UBsan.
Comment 2 Haoxin Tu 2020-05-27 01:26:13 UTC
I also find these cases

test1.cc
#include <iostream>

bool g_bool = 0;
long g_long = -4075183478711827874L;
const long l_long = 7122990940771016367L;
int main () {
    g_bool = g_long * l_long;
    std::cout << g_bool << std::endl;
    return 0;
}

GCC detects nothing.

$g++ -w -fsanitize=signed-integer-overflow test1.cc
1

But when remove "const"
test2.cc
#include <iostream>

bool g_bool = 0;
long g_long = -4075183478711827874L;
const long l_long = 7122990940771016367L;
int main () {
    g_bool = g_long * l_long;
    std::cout << g_bool << std::endl;
    return 0;
}

GCC can dectect the signed-integer-overflow.

$g++ -w -fsanitize=signed-integer-overflow test2.cc
test2.cc:7:21: runtime error: signed integer overflow: -4075183478711827874 * 7122990940771016367 cannot be represented in type 'long int'
1