build: Fix linking for fuzz target when building with MSan#30778
build: Fix linking for fuzz target when building with MSan#30778fanquake merged 2 commits intobitcoin:masterfrom
fuzz target when building with MSan#30778Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. 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. |
786cf06 to
90f771a
Compare
|
🚧 At least one of the CI tasks failed. HintsMake sure to run all tests locally, according to the documentation. The failure may happen due to a number of reasons, for example:
Leave a comment here, if you need help tracking down a confusing failure. |
90f771a to
923f96e
Compare
24c65a1 to
331e976
Compare
|
review-only ACK 331e976 |
I'm still working on it. MSan fuzzing CI job still fails when running locally. |
Additionally, setting the "Debug" build configuration ensures that `linux_debug_CPPFLAGS` from depends are passed to the main build system.
331e976 to
787dfaf
Compare
-g -O1 set in MSAN_FLAGSfuzz target when building with MSan
The issue has been resolved. The PR description has been updated. Ready for review and testing. |
| test_fuzz | ||
| bitcoin_cli | ||
| bitcoin_common | ||
| bitcoin_util |
There was a problem hiding this comment.
Can you explain this a bit better? Why did it only fail on one CI config, and none of the others? Why was the error an msan runtime-error, as opposed to a link-time error?
There was a problem hiding this comment.
Can you explain this a bit better?
I'm afraid I can't (
Why did it only fail on one CI config, and none of the others? Why was the error an msan runtime-error, as opposed to a link-time error?
Those are the questions I asked myself :)
I'm not able to answer them at this moment. There are two reasons for that:
- The current set of internal libraries, including
test_fuzzandtest_util, has circular symbol dependencies, which is inherited from Autotools. - I'm not fully aware of how the linker works with
-fsanitize=fuzzer,memory.
There was a problem hiding this comment.
Ok, so I guess the reason is that this is required to mirror the autotools approach from
bitcoin/src/Makefile.test.include
Line 44 in 5abb9b1
There was a problem hiding this comment.
Autotools tends to overlink, while in CMake, I aimed to link only the necessary components.
Yes, this PR commit mirrors the line from bitcoin/src/Makefile.test.include that you mentioned. However, simply removing that line from 80f00ca results in a link-time error.
Is this not a bug? If depends is built (in any configuration/with any options/flags) then the expectation would be that everything is passed to CMake (regardless of the CMake build type). However it seems like your saying CMake will actually just ignore some flags depending on which build type has been set? If this was the intended behaviour, has this been documented somewhere? Otherwise how are builders meant to know that certains flags from depends might just be ignored, depending on which build type is selected in CMake? |
|
review-only ACK 787dfaf Only change since last review is linking with libbitcoin_util. It would be nice to better understand this change, but this can be done later and is not a blocker to for a test-only change. Also, the depends behavior can be documented better, or be changed, but this is probably best done in a separate issue or pull request, so that this test-only change stays focussed. |
No, it is not. Rather it is a design feature.
While both depends and CMake have configuration-specific flags, it seems unreasonable to expect from CMake configured for the "Release" build type pull in
Yes, it was intended. No, it has not been documented. FWIW, the fact that flags from depends override flags set in the main build system has also never been documented. Here are more details regarding that design decision (C++ flags are used as an example, but the same applies for other tool flags):
|
CMake shouldn't have a concept of "depends debug" flags (it shouldn't really even know about depends). It should just get flags/options passed to it in a toolchain file (which is the interface between the two), and it should use them. Having any special coupling/behaviour based on if things are a "depends" build or not, removes the ability for anyone else to bring a CMake toolchain file, and expect it to work properly. We should open an issue to follow up on this, as at a minimum, it needs better documentation around expections / how things are meant to work, or even reworking, as at the moment, the behaviour seems inconsistent/unexpected. |
fanquake
left a comment
There was a problem hiding this comment.
ACK 787dfaf - as a follow up it would be good to:
- Actually figure out why this fix works, and why the other msan build wasn't broken: #30778 (comment).
- Update oss-fuzz to match what is being done here? Now that they've diverged.
- Open an issue to figure out expectations around depends-with-cmake behaviour.
|
For reference, before (https://cirrus-ci.com/task/6668539271053312?logs=ci#L1064): After (https://api.cirrus-ci.com/v1/task/6661080322146304/logs/ci.log): |
The OSS-Fuzz script controls all flags explicitly, including https://github.com/google/oss-fuzz/blob/5403c34ff006baf410b94cad1112a6c385d1bade/projects/bitcoin-core/build.sh#L50: export CPPFLAGS="-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG -DBOOST_MULTI_INDEX_ENABLE_SAFE_MODE" |
Sure, but you changed the CMake build type here, so why not change it in oss-fuzz? Otherwise, it'd be good to explain somewhere why they (should) differ. |
Sure. Please consider google/oss-fuzz#12443. |
| # BDB generates false-positives and will be removed in future | ||
| export DEP_OPTS="DEBUG=1 NO_BDB=1 NO_QT=1 CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}'" | ||
| export GOAL="install" | ||
| # Setting CMAKE_{C,CXX}_FLAGS_DEBUG flags to an empty string ensures that the flags set in MSAN_FLAGS remain unaltered. |
There was a problem hiding this comment.
I think I understand why this needs to pass BUILD_TYPE=Debug so the debug flags from the depends system will be applied. But I don't understand why FLAGS_DEBUG variables need to be set to empty stings. How does setting those to empty strings cause MSAN_FLAGS to remain unaltered? What code is altering MSAN_FLAGS if FLAGS_DEBUG variables are unset?
There was a problem hiding this comment.
Perhaps I used the word 'unaltered' incorrectly. It would be more accurate to say that "flags set in MSAN_FLAGS won't be overridden". The CMAKE_CXX_FLAGS_DEBUG follow CMAKE_CXX_FLAGS in the compiler invocation string and competing flags may be overridden.
There was a problem hiding this comment.
Good point that "overridden" is probably more appropriate word, but I think I already understood that this meant overridden.
The thing I don't understand is what causes MSAN_FLAGS to be overridden when FLAGS_DEBUG variables are unset, but not overridden when they are empty? Appreciate the clarification. I'm not asking for any particular reason, just curious to understand this better.
There was a problem hiding this comment.
Sure. The logic is follows:
- The
MSAN_FLAGSvariable's value is... -g -O1 .... - This value is assigned to
CXXFLAGSfor building depends and become the value ofCMAKE_CXX_FLAGSin the toolchain file. - Being configured with
-DCMAKE_BUILD_TYPE=Debug, the build system may assign-O0 -ftrapv -g3toCMAKE_CXX_FLAGS_DEBUG. - When invoking a compier,
CMAKE_CXX_FLAGSandCMAKE_CXX_FLAGS_DEBUGare concatenated, resulting in.. -g -O1 ... -O0 ... -g3 .... This means that flags set inMSAN_FLAGSwill not have any effect.
There was a problem hiding this comment.
Very helpful, thanks. I think I would write comment as "Set CMAKE_{C,CXX}_FLAGS_DEBUG options to empty so CMake's default options for debug builds do not interfere with MSAN flags"
There was a problem hiding this comment.
Followup points:
-
I misunderstood "the build system may assign" to mean "cmake may assign" but actually it is referring to our own ProcessConfigurations.cmake file. So I think a more accurate comment than what I suggested would be "Set CMAKE_{C,CXX}_FLAGS_DEBUG to empty so the default options normally used for debug builds do not override MSAN options in CMAKE_{C,CXX}_FLAGS"
-
I'm probably missing something, but maybe a cleaner workaround instead of setting
Debugbuild type and then erasing all the debug flags is just to set a custom build type -DCMAKE_BUILD_TYPE=msan that doesn't have the flags to begin with? -
Probably not applicable to this case, but it does seem unfortunate that only having
FLAGSandFLAGS_<build_type>options forces a choice between specifying lower priority flags independent of build type, or higher priority flags tied to the build type. Ideally there would be a third option to specify high priority flags not depending on build type, maybe calledFLAGS_ALLthat would be applied to all build configurations. This seems like something that would not be too hard to support. Not important here, but maybe something to look into if there are more cases like this.
There was a problem hiding this comment.
- I'm probably missing something, but maybe a cleaner workaround instead of setting
Debugbuild type and then erasing all the debug flags is just to set a custom build type -DCMAKE_BUILD_TYPE=msan that doesn't have the flags to begin with?
I agree with you, and that was my initial preference when I worked on the CMake staging branch. However, using undefined build configurations is not documented. As a result, the rough consensus among the CMake staging branch contributors was to adhere to documented practices.
- Probably not applicable to this case, but it does seem unfortunate that only having
FLAGSandFLAGS_<build_type>options forces a choice between specifying lower priority flags independent of build type, or higher priority flags tied to the build type. Ideally there would be a third option to specify high priority flags not depending on build type, maybe calledFLAGS_ALLthat would be applied to all build configurations. This seems like something that would not be too hard to support. Not important here, but maybe something to look into if there are more cases like this.
Such an option is implemented in the APPEND_* variables, if I understood you correctly:
Lines 203 to 206 in 0e5cd60
| -DCMAKE_C_FLAGS_DEBUG='' \ | ||
| -DCMAKE_CXX_FLAGS_DEBUG='' \ | ||
| -DSANITIZERS=memory \ | ||
| -DAPPEND_CPPFLAGS='-U_FORTIFY_SOURCE' \ |
There was a problem hiding this comment.
So given the Build type change, this line, and the equivalent flag in the other CI config, are redundant and should have been removed. However I don't actually think they should be removed, because it's instead CMake that should be fixed, to remove the assumption that builds using the Debug build type, will always have no optimisations, as this isn't actually the case, for example, in oss-fuzz, or doing a depends build with DEBUG=1. See further discussion in google/oss-fuzz#12443.
…ld type 30803a3 cmake: decouple FORTIFY_SOURCE check from Debug build type (fanquake) Pull request description: `FORTIFY_SOURCE` should be used if `ENABLE_HARDENING=ON` and optimisations are being used. This should not be coupled to any particular build type, because even if the build type is `Debug`, optimisations might still be in use. Fixes: #30800. Also somewhat of a followup to #30778 (comment). ACKs for top commit: ryanofsky: Code review ACK 30803a3 TheCharlatan: ACK 30803a3 Tree-SHA512: 298f8805a5bb2f1ff54e51ea31324d712c2070cc3eba26561c31001ace4bfa37ae6d18531cbd45e2faf610a0a1b83b420fcde6e329e17f02b021d26563583913
The first commit fixes #30760.
The second commit:
-g -O1set inMSAN_FLAGS. Since configuration-specific flags override general flags, these are set to empty strings. A similar approach is used in the OSS-Fuzz repository.DEBUG=1, ensuring thatlinux_debug_CPPFLAGSfrom depends are passed to the main build system.