Add copy constructor and copy operator= to CScript to remove ubsan suppression#17510
Add copy constructor and copy operator= to CScript to remove ubsan suppression#17510achow101 wants to merge 1 commit intobitcoin:masterfrom
Conversation
| CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { } | ||
| CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { } | ||
|
|
||
| // Define a copy constructor so that operator= is a copy instead of a move to avoid undefined behavior |
There was a problem hiding this comment.
If this is needed, there is another problem. Why does a move cause UB? And why is a move being invoked in the first place with operator=?
There was a problem hiding this comment.
No idea. Maybe @practicalswift can shed some light here?
|
For reference, one tb is this: |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Agree. This is kind of scary, and working around it like this seems a bad idea if we don't understand why it happens. |
|
Could this pragma in prevector.h be causing alignment issues? (doesn't it mean something like "ignore all padding requirements within the struct") |
|
Smaller code to reproduce: struct Test {
uint8_t a : 8;
CScript script;
};
{
const std::array<unsigned char, 5> D{1, 2, 3, 4, 5};
Test t{0x0f, {}};
t.script = CScript{D.begin(), D.end()};
}Result: |
|
Does it go away if you remove the pragma? |
|
Yes, with this diff it goes away: diff --git a/src/prevector.h b/src/prevector.h
index d307495fbe..a55bcb50fe 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -14,7 +14,6 @@
#include <cstddef>
#include <type_traits>
-#pragma pack(push, 1)
/** Implements a drop-in replacement for std::vector<T> which stores up to N
* elements directly (without heap allocation). The types Size and Diff are
* used to store element counts, and can be any unsigned + signed type.
@@ -522,6 +521,5 @@ public:
return item_ptr(0);
}
};
-#pragma pack(pop)
#endif // BITCOIN_PREVECTOR_H |
|
I would prefer that solution, then. I'm not sure in how far unaligned integers are really UB in C++ (versus architecture/implementation defined), but it'd be better to avoid that for architectures that don't support (or have slow fallback paths for) unaligned reads/writes. (E.g. SiFive U540 traps into the kernel/bootloader to handle unaligned reads and writes, with a function, in software. Wouldn't be surprised if it's 1000 times slower) |
|
@laanwj John Regehr and Pascal Cuoq's excellent post "Undefined Behavior in 2017" has a nice section on Alignment Violations. Highly recommended reading! |
`#pragma pack(1)` prevents aligning the struct and its members to their required alignment. This can result in code that performs non-aligned reads and writes to integers and pointers, which is problematic on some architectures. It also triggers UBsan — see bitcoin#17156 (comment) and bitcoin#17510.
`#pragma pack(1)` prevents aligning the struct and its members to their required alignment. This can result in code that performs non-aligned reads and writes to integers and pointers, which is problematic on some architectures. It also triggers UBsan — see bitcoin#17156 (comment) and bitcoin#17510.
`#pragma pack(1)` prevents aligning the struct and its members to their required alignment. This can result in code that performs non-aligned reads and writes to integers and pointers, which is problematic on some architectures. It also triggers UBsan — see bitcoin#17156 (comment) and bitcoin#17510.
`#pragma pack(1)` prevents aligning the struct and its members to their required alignment. This can result in code that performs non-aligned reads and writes to integers and pointers, which is problematic on some architectures. It also triggers UBsan — see bitcoin/bitcoin#17156 (comment) and #17510.
As noted in #17156 (comment), the PSBT fuzzer is triggering a UBSan condition which is fixed by this PR. Additionally, by fixing this, some UBSan suppressions can be removed.
Split from #17156