[
https://issues.apache.org/jira/browse/THRIFT-6076?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Jens Geyer reassigned THRIFT-6076:
----------------------------------
Assignee: Justin Caratzas
> Compiler build fails with GCC 14 LTO
> ------------------------------------
>
> Key: THRIFT-6076
> URL: https://issues.apache.org/jira/browse/THRIFT-6076
> Project: Thrift
> Issue Type: Bug
> Components: Compiler (General)
> Reporter: Justin Caratzas
> Assignee: Justin Caratzas
> Priority: Major
> Time Spent: 0.5h
> Remaining Estimate: 0h
>
> Summary
> Building the Thrift compiler (`compiler/cpp`) with GCC 14 and link-time
> optimisation enabled (`-flto=auto -ffat-lto-objects`) fails at the final link
> step with false-positive `-Werror=stringop-overflow` /
> `-Werror=stringop-overread` diagnostics in ten generator source files. The
> code is correct; GCC 14's LTO inter-procedural analysis incorrectly estimates
> intermediate buffer sizes when chained `std::string() + "literal"`
> expressions are inlined.
> Environment
> - *{*}GCC{*}*: 14.3.1 (Red Hat 14.3.1-4), also reproducible with upstream
> GCC 14.x
> - *{*}Build flags{*}*: `-flto=auto -ffat-lto-objects` (default RPM/distro
> hardened flags on RHEL 10 / Fedora 40+)
> - *{*}Thrift{*}*: `master` branch and 0.24.0 release
> Affected files
> |File|Function|Line (master)|
> |------|----------|--------------|
> |`compiler/cpp/src/thrift/generate/t_javame_generator.cc`|`java_type_imports()`|292|
> |`compiler/cpp/src/thrift/generate/t_javame_generator.cc`|`java_thrift_imports()`|302|
> |`compiler/cpp/src/thrift/generate/t_haxe_generator.cc`|`haxe_type_imports()`|321|
> |`compiler/cpp/src/thrift/generate/t_haxe_generator.cc`|`haxe_thrift_imports()`|341|
> |`compiler/cpp/src/thrift/generate/t_js_generator.cc`|`autogen_comment()`|272|
> |`compiler/cpp/src/thrift/generate/t_ocaml_generator.cc`|`ocaml_autogen_comment()`|252|
> |`compiler/cpp/src/thrift/generate/t_perl_generator.cc`|`autogen_comment()`|155|
> |`compiler/cpp/src/thrift/generate/t_erl_generator.cc`|`erl_autogen_comment()`|396|
> |`compiler/cpp/src/thrift/generate/t_go_generator.cc`|`go_autogen_comment()`|695|
> |`compiler/cpp/src/thrift/generate/t_delphi_generator.cc`|`autogen_comment()`|345|
> |`compiler/cpp/src/thrift/generate/t_rb_generator.cc`|`rb_autogen_comment()`|345|
> |`compiler/cpp/src/thrift/generate/t_xsd_generator.cc`|`xml_autogen_comment()`|97|
> Error output
> ```
> /usr/include/c++/14/bits/char_traits.h:427:56: error: '__builtin_memcpy'
> writing 41 bytes into a region of size 16 overflows the destination
> [-Werror=stringop-overflow=]
> 427 | return static_cast<char_type*>(_{_}builtin_memcpy({_}_s1, __s2, __n));
> src/thrift/generate/t_javame_generator.cc: In member function
> 'java_type_imports':
> src/thrift/generate/t_javame_generator.cc:292:21: note: at offset 16 into
> destination object '<anonymous>' of size 32
> src/thrift/generate/t_haxe_generator.cc: In member function
> 'haxe_thrift_imports':
> /usr/include/c++/14/bits/char_traits.h:427:56: error: '__builtin_memcpy'
> writing 67 bytes into a region of size 16 overflows the destination
> [-Werror=stringop-overflow=]
> src/thrift/generate/t_js_generator.cc: In member function 'autogen_comment':
> /usr/include/c++/14/bits/char_traits.h:427:56: error: '__builtin_memcpy'
> writing 47 bytes into a region of size 16 overflows the destination
> [-Werror=stringop-overflow=]
> lto1: all warnings being treated as errors
> lto-wrapper: fatal error: make returned 2 exit status
> collect2: error: ld returned 1 exit status
> ```
> Root cause
> All affected sites use one of these patterns where chained `operator+` calls
> on temporary `std::string` objects trigger GCC 14's LTO false positive:
> ```cpp
> // Pattern 1 — empty string() seed
> return string() + "import java.util.Hashtable;\n" + "import
> java.util.Vector;\n"
> + "import java.util.Enumeration;\n\n";
> // Pattern 2 — non-empty literal seed + THRIFT_VERSION variable
> return std::string("//\n") + "// Autogenerated by Thrift Compiler (" +
> THRIFT_VERSION + ")\n"
> + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE
> DOING\n"
> + "//\n";
> ```
> Proposed fix
> *{*}For pure-literal returns{*}* (no `THRIFT_VERSION`): replace with adjacent
> string literal concatenation, which is resolved at compile time and produces
> no temporary objects:
> ```cpp
> // t_javame_generator.cc java_type_imports() — before
> return string() + "import java.util.Hashtable;\n" + "import
> java.util.Vector;\n"
> + "import java.util.Enumeration;\n\n";
> // after
> return "import java.util.Hashtable;\n"
> "import java.util.Vector;\n"
> "import java.util.Enumeration;\n\n";
> ```
> *{*}For returns that embed `THRIFT_VERSION`{*}*: use adjacent literals up to
> the variable insertion point, so that only one `operator+` call with a
> correctly-sized left operand remains:
> ```cpp
> // t_js_generator.cc autogen_comment() — before
> return std::string("//\n") + "// Autogenerated by Thrift Compiler (" +
> THRIFT_VERSION + ")\n"
> + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE
> DOING\n"
> + "//\n";
> // after
> return "//\n"
> "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
> "//\n"
> "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
> "//\n";
> ```
> This pattern is safe: adjacent string literals are concatenated by the
> compiler before `operator+` is evaluated, so the left operand of the first
> `+` is always a correctly-sized compile-time constant.
> A workaround for downstream packagers is to add `-Wno-stringop-overflow
> -Wno-stringop-overread` to `CXXFLAGS` at build time, but fixing the source is
> the correct long-term solution.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)