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.