-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recent build break in fmt master with gcc10 #1810
Comments
I don't see anything wrong with the buffer access and wasn't able to repro the issue in godbolt (https://godbolt.org/z/nodo79). What is the value passed to |
Near as I can tell, it's a call to
I'll see if I can reproduce it in a simple way that's not in the middle of my software system. Maybe this just reveals that there's something important I never realized about godbolt, but how does that example know which version of fmt to use? |
Ah, I see where fmt comes from. Did not know Compiler Explorer has all those libraries pre-installed. Cool. On my laptop (OSX) running g++-10, as well as on GH CI, I can easily make this fail:
But it does not on Compiler Explorer. No explanation for you at the moment. The only thing I can think of is... Are you confident that the fmt "trunk" on Compiler Explorer is really the current master? The -O3 is required for the failure, but as it turns out, the -Wall is not. Here is my command line:
And here is the error I get:
Any suggestions about the next experiment I can run to help track this down? |
I did a clean build of
[ 96%] Linking CXX executable ../bin/chrono-test
[ 96%] Built target chrono-test
In file included from /tmp/fmt/include/fmt/color.h:11,
from /tmp/fmt/test/format-test.cc:27:
In function ‘fmt::v7::detail::format_decimal_result<Char*> fmt::v7::detail::format_decimal(Char*, UInt, int) [with Char = char; UInt = unsigned int]’,
inlined from ‘OutputIt fmt::v7::detail::write(OutputIt, T) [with Char = char; OutputIt = char*; T = int; typename std::enable_if<((fmt::v7::detail::is_integral<T>::value && (! std::is_same<T, bool>::value)) && (! std::is_same<T, Char>::value)), int>::type <anonymous> = 0]’ at /tmp/fmt/include/fmt/format.h:1802:28,
inlined from ‘std::string fmt::v7::to_string(T) [with T = int; typename std::enable_if<std::is_integral<_Tp>::value, int>::type <anonymous> = 0]’ at /tmp/fmt/include/fmt/format.h:3477:62,
inlined from ‘virtual void FormatTest_ToString_Test::TestBody()’ at /tmp/fmt/test/format-test.cc:1930:3:
/tmp/fmt/include/fmt/format.h:918:55: warning: writing 2 bytes into a region of size 0 [-Wstringop-overflow=]
918 | inline void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
| ~~~~~~^~~~~~~~~~~~~
/tmp/fmt/include/fmt/format.h: In member function ‘virtual void FormatTest_ToString_Test::TestBody()’:
/tmp/fmt/include/fmt/format.h:3475:8: note: at offset -2 to object ‘buffer’ with size 11 declared here
3475 | char buffer[max_size > 5 ? max_size : 5];
| ^~~~~~
[ 98%] Linking CXX executable ../bin/printf-test
[ 98%] Built target printf-test
[100%] Linking CXX executable ../bin/format-test
[100%] Built target format-test Tests ran successfully But compiling an FMT_HEADER_ONLY program doesn't produce any warnings #define FMT_HEADER_ONLY
#include <fmt/format.h>
#include <fmt/ranges.h>
int main()
{
fmt::print("Hello There!\n{}\n", "General Kenobi!");
fmt::print("Woah: {}\n", 42);
const std::string num = fmt::to_string(96);
fmt::print("Reversed: {}\n", fmt::join(num.crbegin(), num.crend(), ""));
return 0;
} $ # Using gcc 10.2.1 20200807, compiled with the following flags
$ g++ -o a a.cpp -std=c++2a -O3 -Wall -Wextra -Werror -Wshadow -Wpedantic -Wconversion -Wstringop-overflow=4 -Wshift-overflow=2 -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wdisabled-optimization -Wno-format-nonliteral |
And the following from an FMT_PEDANTIC build [ 94%] Linking CXX executable ../bin/chrono-test
[ 94%] Built target chrono-test
[ 96%] Linking CXX executable ../bin/compile-test
[ 96%] Built target compile-test
In file included from /tmp/fmt/include/fmt/color.h:11,
from /tmp/fmt/test/format-test.cc:27:
In function ‘fmt::v7::detail::format_decimal_result<Char*> fmt::v7::detail::format_decimal(Char*, UInt, int) [with Char = char; UInt = unsigned int]’,
inlined from ‘OutputIt fmt::v7::detail::write(OutputIt, T) [with Char = char; OutputIt = char*; T = int; typename std::enable_if<((fmt::v7::detail::is_integral<T>::value && (! std::is_same<T, bool>::value)) && (! std::is_same<T, Char>::value)), int>::type <anonymous> = 0]’ at /tmp/fmt/include/fmt/format.h:1802:28,
inlined from ‘std::string fmt::v7::to_string(T) [with T = int; typename std::enable_if<std::is_integral<_Tp>::value, int>::type <anonymous> = 0]’ at /tmp/fmt/include/fmt/format.h:3477:62,
inlined from ‘virtual void FormatTest_ToString_Test::TestBody()’ at /tmp/fmt/test/format-test.cc:1930:3:
/tmp/fmt/include/fmt/format.h:918:55: warning: writing 2 bytes into a region of size 0 [-Wstringop-overflow=]
918 | inline void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
| ~~~~~~^~~~~~~~~~~~~
/tmp/fmt/include/fmt/format.h: In member function ‘virtual void FormatTest_ToString_Test::TestBody()’:
/tmp/fmt/include/fmt/format.h:3475:8: note: at offset -2 to object ‘buffer’ with size 11 declared here
3475 | char buffer[max_size > 5 ? max_size : 5];
| ^~~~~~
[ 98%] Linking CXX executable ../bin/format-test
[ 98%] Built target format-test
[100%] Linking CXX executable ../bin/printf-test
[100%] Built target printf-test |
It's clearly a gcc bug: https://godbolt.org/z/fdE1jo |
Worked around in 6fb7c6f, thanks for reporting. |
Is this really a bug in GCC 10? Has anyone reported it to them? |
Yes, please see https://godbolt.org/z/fdE1jo. GCC incorrectly assumes that
I haven't, please do if you have time. |
Wow. Thanks for tracking this down and the workaround. |
I'm going to take a look at this today. Was there a GCC version in which this problem didn't show up? |
Yes, GCC 9.3: https://godbolt.org/z/Wvch7T |
Great, that should help me, thanks. |
OK, so this is https://gcc.gnu.org/PR95353 which has already been fixed in GCC mainline. I'm not sure if the fix will be backported to GCC 10. |
@mpolacek, thanks! |
Recent change in master, commit with SHA 2082912 ("Optimize count_digits") breaks the build on my project with -Wall, but the immediately preceding commit, SHA 8d9ab96 ("Cut a few cycles from count_digits") succeeds.
That doesn't guarantee the the bug is the contents of that commit per se, but maybe it put all the pieces in place for it to be symptomatic.
I'm 90% sure that it's building cleanly in gcc <= 9 and with clang. So it may just be a new warning in gcc10 it's hitting. I'm not seeing incorrect results, so maybe it's a spurious warning that I should be suppressing? Please advise if you think that's what I should do. But the "out of bounds" nature of the error message is worrying, I don't want to suppress it if it's really a buffer overflow problem.
I'm sorry I don't have a small repro case, it's in the middle of a large software project, but maybe this big block of error messages will ring a bell?
The text was updated successfully, but these errors were encountered: