mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-26 17:52:13 +01:00
prevector: avoid GCC bogus warnings in insert method
When compiling with GCC 12.2, both `-Warray-bounds` and `-Wstringop-overflow` warnings were triggered in the `prevector::insert` method during CScript prevector operations. GCC incorrectly assumed that operator new could modify the state of class members, leading to false positives during the memmove operation. Following the approach in https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=cca06f0d6d76b0, we introduced local copies for the destination pointer in memmove operations. This prevents GCC from misinterpreting memory manipulation as unsafe. A minimal reproducer triggering this issue in GCC 12.2 and passing in GCC 12.3 can be found at https://godbolt.org/z/8r9TKKoxv. ------- Full error (with changes from the next commit as well): ``` In file included from /ci_container_base/src/script/script.h:11, from /ci_container_base/src/primitives/transaction.h:11, from /ci_container_base/src/primitives/block.h:9, from /ci_container_base/src/kernel/chainparams.h:11, from /ci_container_base/src/kernel/chainparams.cpp:6: In member function ‘void prevector<N, T, Size, Diff>::fill(T*, InputIterator, InputIterator) [with InputIterator = const unsigned char*; unsigned int N = 28; T = unsigned char; Size = unsigned int; Diff = int]’, inlined from ‘void prevector<N, T, Size, Diff>::insert(iterator, InputIterator, InputIterator) [with InputIterator = const unsigned char*; unsigned int N = 28; T = unsigned char; Size = unsigned int; Diff = int]’ at /ci_container_base/src/prevector.h:395:13, inlined from ‘void CScript::AppendData(const prevector<28, unsigned char>::value_type*, size_t)’ at /ci_container_base/src/script/script.h:439:15, inlined from ‘CScript& CScript::operator<<(std::span<const std::byte>)’ at /ci_container_base/src/script/script.h:496:17, inlined from ‘CBlock CreateGenesisBlock(uint32_t, uint32_t, uint32_t, int32_t, const CAmount&)’ at /ci_container_base/src/kernel/chainparams.cpp:76:54: /ci_container_base/src/prevector.h:216:13: error: writing 65 bytes into a region of size 32 [-Werror=stringop-overflow=] 216 | new(static_cast<void*>(dst)) T(*first); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /ci_container_base/src/kernel/chainparams.cpp: In function ‘CBlock CreateGenesisBlock(uint32_t, uint32_t, uint32_t, int32_t, const CAmount&)’: /ci_container_base/src/kernel/chainparams.cpp:76:49: note: destination object ‘<anonymous>’ of size 32 76 | const CScript genesisOutputScript = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG; | ^ In file included from /usr/lib/gcc/x86_64-w64-mingw32/12-posix/include/c++/cstring:42, from /ci_container_base/src/crypto/common.h:11, from /ci_container_base/src/uint256.h:9, from /ci_container_base/src/consensus/params.h:9, from /ci_container_base/src/kernel/chainparams.h:9: In function ‘void* memmove(void*, const void*, size_t)’, inlined from ‘void prevector<N, T, Size, Diff>::insert(iterator, InputIterator, InputIterator) [with InputIterator = const unsigned char*; unsigned int N = 28; T = unsigned char; Size = unsigned int; Diff = int]’ at /ci_container_base/src/prevector.h:393:16, inlined from ‘void CScript::AppendData(const prevector<28, unsigned char>::value_type*, size_t)’ at /ci_container_base/src/script/script.h:439:15, inlined from ‘CScript& CScript::operator<<(std::span<const std::byte>)’ at /ci_container_base/src/script/script.h:496:17, inlined from ‘CBlock CreateGenesisBlock(uint32_t, uint32_t, uint32_t, int32_t, const CAmount&)’ at /ci_container_base/src/kernel/chainparams.cpp:76:54: /usr/share/mingw-w64/include/string.h:214:33: warning: ‘void* __builtin_memmove(void*, const void*, long long unsigned int)’ offset [65, 35] is out of the bounds [0, 32] of object ‘<anonymous>’ with type ‘CScript’ [-Warray-bounds] 214 | return __builtin___memmove_chk(__dst, __src, __n, __mingw_bos(__dst, 0)); | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /ci_container_base/src/kernel/chainparams.cpp: In function ‘CBlock CreateGenesisBlock(uint32_t, uint32_t, uint32_t, int32_t, const CAmount&)’: /ci_container_base/src/kernel/chainparams.cpp:76:49: note: ‘<anonymous>’ declared here 76 | const CScript genesisOutputScript = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG; | ^ ``` Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com> Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
parent
a7a4e11db8
commit
c78d8ff4cb
@ -363,7 +363,8 @@ public:
|
||||
change_capacity(new_size + (new_size >> 1));
|
||||
}
|
||||
T* ptr = item_ptr(p);
|
||||
memmove(ptr + 1, ptr, (size() - p) * sizeof(T));
|
||||
T* dst = ptr + 1;
|
||||
memmove(dst, ptr, (size() - p) * sizeof(T));
|
||||
_size++;
|
||||
new(static_cast<void*>(ptr)) T(value);
|
||||
return iterator(ptr);
|
||||
@ -376,7 +377,8 @@ public:
|
||||
change_capacity(new_size + (new_size >> 1));
|
||||
}
|
||||
T* ptr = item_ptr(p);
|
||||
memmove(ptr + count, ptr, (size() - p) * sizeof(T));
|
||||
T* dst = ptr + count;
|
||||
memmove(dst, ptr, (size() - p) * sizeof(T));
|
||||
_size += count;
|
||||
fill(item_ptr(p), count, value);
|
||||
}
|
||||
@ -390,7 +392,8 @@ public:
|
||||
change_capacity(new_size + (new_size >> 1));
|
||||
}
|
||||
T* ptr = item_ptr(p);
|
||||
memmove(ptr + count, ptr, (size() - p) * sizeof(T));
|
||||
T* dst = ptr + count;
|
||||
memmove(dst, ptr, (size() - p) * sizeof(T));
|
||||
_size += count;
|
||||
fill(ptr, first, last);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user