https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116841
Bug ID: 116841 Summary: [regression gcc 13 -> 14] spurious -Warray-bounds=1 warning when resizing + memcpy-ing into vector Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: jakob.heher at iaik dot tugraz.at Target Milestone: --- possibly related to 114945 and the issues mentioned therein. I've tried to distil the minimal reproducible example as much as possible: https://godbolt.org/z/Kc1bY1e5d struct StreamWriter { private: std::vector<uint8_t> _buf; public: void putBytes(void const* buf, size_t n) { size_t const pos = _buf.size(); _buf.resize(pos+n); memcpy(_buf.data()+pos, buf, n); } void putByte(uint8_t v) { _buf.push_back(v); } void putVarint(uint32_t v) { if (v <= 0x7f) { putByte(v); } else { putByte((v >> 8) | 0x80); putByte(v & 0xff); } } std::vector<uint8_t> done() { return std::move(_buf); } }; struct Packet { uint32_t packetNumber = 0; std::array<uint8_t, 160> destinationConnectionId = {}; std::array<uint8_t, 160> sourceConnectionId = {}; }; std::vector<uint8_t> encode(Packet const& packet) { StreamWriter output; output.putVarint(packet.packetNumber); output.putBytes(packet.destinationConnectionId.data(), packet.destinationConnectionId.size()); output.putBytes(packet.sourceConnectionId.data(), packet.sourceConnectionId.size()); return output.done(); } int main(int, char const**) { encode(Packet()); } Compiling on gcc 14.2.0 using -std=c++20 -g -Wall -Wextra -Werror -fno-strict-aliasing -fwrapv -O2. Things that make the bug disappear: * Switching to -O3. However, the bug can be made to appear at -O3 using a slightly more complex variant: https://godbolt.org/z/Mr46xTo56 * Removing putVarint, or changing putVarint to always insert a fixed number of bytes (such as one byte on both branches) * Removing the second putBytes call * Manually inlining the function * Replacing the input to any of the putVarint calls with a predictable value Compiler output: In file included from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/array:43, from <source>:1: In function 'constexpr typename __gnu_cxx::__enable_if<std::__is_byte<_Tp>::__value, void>::__type std::__fill_a1(_Tp*, _Tp*, const _Tp&) [with _Tp = unsigned char]', inlined from 'constexpr void std::__fill_a(_FIte, _FIte, const _Tp&) [with _FIte = unsigned char*; _Tp = unsigned char]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_algobase.h:998:21, inlined from 'constexpr _OutputIterator std::__fill_n_a(_OutputIterator, _Size, const _Tp&, random_access_iterator_tag) [with _OutputIterator = unsigned char*; _Size = long unsigned int; _Tp = unsigned char]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_algobase.h:1151:20, inlined from 'constexpr _OI std::fill_n(_OI, _Size, const _Tp&) [with _OI = unsigned char*; _Size = long unsigned int; _Tp = unsigned char]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_algobase.h:1180:29, inlined from 'static constexpr _ForwardIterator std::__uninitialized_default_n_1<true>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = unsigned char*; _Size = long unsigned int]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_uninitialized.h:668:29, inlined from 'static constexpr _ForwardIterator std::__uninitialized_default_n_1<true>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = unsigned char*; _Size = long unsigned int]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_uninitialized.h:660:9, inlined from 'constexpr _ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = unsigned char*; _Size = long unsigned int]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_uninitialized.h:712:20, inlined from 'constexpr _ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, allocator<_Tp>&) [with _ForwardIterator = unsigned char*; _Size = long unsigned int; _Tp = unsigned char]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_uninitialized.h:779:44, inlined from 'constexpr void std::vector<_Tp, _Alloc>::_M_default_append(size_type) [with _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/vector.tcc:821:35, inlined from 'constexpr void std::vector<_Tp, _Alloc>::resize(size_type) [with _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]' at /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_vector.h:1016:21, inlined from 'void StreamWriter::putBytes(const void*, size_t)' at <source>:13:24, inlined from 'std::vector<unsigned char> encode(const Packet&)' at <source>:34:20: /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_algobase.h:972:25: error: 'void* __builtin_memset(void*, int, long unsigned int)' offset [162, 320] is out of the bounds [0, 162] [-Werror=array-bounds=] 972 | __builtin_memset(__first, static_cast<unsigned char>(__tmp), __len); | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1plus: all warnings being treated as errors The bug also occurs in gcc 15.0.0 20240925. The bug does not occur in gcc 13.3.0.