-
Notifications
You must be signed in to change notification settings - Fork 37.7k
fuzz: a new target for the coins database #28216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/28216. 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. |
…in the `coins_view` target e417c98 fuzz: coins_view: remove an incorrect assertion (Antoine Poinsot) c5f6b1d fuzz: coins_view: correct an incorrect assertion (Antoine Poinsot) Pull request description: The `coins_view` fuzz target would assert in two places that the cache is consistent with the backend. But it's never the case (that's the whole point of using a cache). The only reason this didn't result in a crash was that we would never actually hit these assertions. I ran into this while introducing a new target with an in-memory `CCoinsViewDB` as the backend view (see bitcoin/bitcoin#28216) which made the code paths with those assertions actually reachable. ACKs for top commit: dergoegge: Code review ACK e417c98 Tree-SHA512: 5847bb2744a2f2831dace62d32b79cc491bf54e2af4ce425411d245d566622d9aff816d9be5ec8e830d10851c13f2500bf4f0c004d88b4d7cca1d483ef8960a6
Want rebase this now that #28215 is merged (also update PR description). |
43a766b
to
d776491
Compare
Rebased. |
…coins_view` target e417c98 fuzz: coins_view: remove an incorrect assertion (Antoine Poinsot) c5f6b1d fuzz: coins_view: correct an incorrect assertion (Antoine Poinsot) Pull request description: The `coins_view` fuzz target would assert in two places that the cache is consistent with the backend. But it's never the case (that's the whole point of using a cache). The only reason this didn't result in a crash was that we would never actually hit these assertions. I ran into this while introducing a new target with an in-memory `CCoinsViewDB` as the backend view (see bitcoin#28216) which made the code paths with those assertions actually reachable. ACKs for top commit: dergoegge: Code review ACK e417c98 Tree-SHA512: 5847bb2744a2f2831dace62d32b79cc491bf54e2af4ce425411d245d566622d9aff816d9be5ec8e830d10851c13f2500bf4f0c004d88b4d7cca1d483ef8960a6
d776491
to
ad9cfb5
Compare
Rebased on master to fix the macOS CI. |
While rebasing this i found another crash in the bitcoin/src/test/fuzz/coins_view.cpp Lines 67 to 75 in 4b1196a
Lines 76 to 100 in 4b1196a
|
ad9cfb5
to
a77c29a
Compare
Rebased on top of #29164 to fix the above. |
Alright, i can't reproduce the non-determinism he observed. |
@dergoegge could you have a look here when you have a sec? |
How did you try to reproduce it? Because I'm still seeing only ~70% stability when running with afl++. @marcofleon this could also be a target to test your "stability debugging" script on. |
…coins_view` target e417c98 fuzz: coins_view: remove an incorrect assertion (Antoine Poinsot) c5f6b1d fuzz: coins_view: correct an incorrect assertion (Antoine Poinsot) Pull request description: The `coins_view` fuzz target would assert in two places that the cache is consistent with the backend. But it's never the case (that's the whole point of using a cache). The only reason this didn't result in a crash was that we would never actually hit these assertions. I ran into this while introducing a new target with an in-memory `CCoinsViewDB` as the backend view (see bitcoin#28216) which made the code paths with those assertions actually reachable. ACKs for top commit: dergoegge: Code review ACK e417c98 Tree-SHA512: 5847bb2744a2f2831dace62d32b79cc491bf54e2af4ce425411d245d566622d9aff816d9be5ec8e830d10851c13f2500bf4f0c004d88b4d7cca1d483ef8960a6
…coins_view` target e417c98 fuzz: coins_view: remove an incorrect assertion (Antoine Poinsot) c5f6b1d fuzz: coins_view: correct an incorrect assertion (Antoine Poinsot) Pull request description: The `coins_view` fuzz target would assert in two places that the cache is consistent with the backend. But it's never the case (that's the whole point of using a cache). The only reason this didn't result in a crash was that we would never actually hit these assertions. I ran into this while introducing a new target with an in-memory `CCoinsViewDB` as the backend view (see bitcoin#28216) which made the code paths with those assertions actually reachable. ACKs for top commit: dergoegge: Code review ACK e417c98 Tree-SHA512: 5847bb2744a2f2831dace62d32b79cc491bf54e2af4ce425411d245d566622d9aff816d9be5ec8e830d10851c13f2500bf4f0c004d88b4d7cca1d483ef8960a6
…coins_view` target e417c98 fuzz: coins_view: remove an incorrect assertion (Antoine Poinsot) c5f6b1d fuzz: coins_view: correct an incorrect assertion (Antoine Poinsot) Pull request description: The `coins_view` fuzz target would assert in two places that the cache is consistent with the backend. But it's never the case (that's the whole point of using a cache). The only reason this didn't result in a crash was that we would never actually hit these assertions. I ran into this while introducing a new target with an in-memory `CCoinsViewDB` as the backend view (see bitcoin#28216) which made the code paths with those assertions actually reachable. ACKs for top commit: dergoegge: Code review ACK e417c98 Tree-SHA512: 5847bb2744a2f2831dace62d32b79cc491bf54e2af4ce425411d245d566622d9aff816d9be5ec8e830d10851c13f2500bf4f0c004d88b4d7cca1d483ef8960a6
…coins_view` target e417c98 fuzz: coins_view: remove an incorrect assertion (Antoine Poinsot) c5f6b1d fuzz: coins_view: correct an incorrect assertion (Antoine Poinsot) Pull request description: The `coins_view` fuzz target would assert in two places that the cache is consistent with the backend. But it's never the case (that's the whole point of using a cache). The only reason this didn't result in a crash was that we would never actually hit these assertions. I ran into this while introducing a new target with an in-memory `CCoinsViewDB` as the backend view (see bitcoin#28216) which made the code paths with those assertions actually reachable. ACKs for top commit: dergoegge: Code review ACK e417c98 Tree-SHA512: 5847bb2744a2f2831dace62d32b79cc491bf54e2af4ce425411d245d566622d9aff816d9be5ec8e830d10851c13f2500bf4f0c004d88b4d7cca1d483ef8960a6
I think fixing stability would be nice, but not a blocker |
Also, if you rebase, you get a free check from the newly added "fuzz stability checkers" |
We'll reuse it for a target where the coins view is a DB.
e79784e
to
4dafb32
Compare
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
It reuses the logic from the `coins_view` target, except it uses an in-memory CCoinsViewDB as the backend. Note `CCoinsViewDB` will assert the best block hash is never null, so we slightly modify the coins_view fuzz logic to take care of this.
4dafb32
to
ea0bcbc
Compare
@@ -207,7 +213,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend | |||
|
|||
{ | |||
std::unique_ptr<CCoinsViewCursor> coins_view_cursor = backend_coins_view.Cursor(); | |||
assert(!coins_view_cursor); | |||
assert(is_db ? !!coins_view_cursor : !coins_view_cursor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why explicit conversion with !!
? Doesn't assert cause contextual conversion to bool of the expression, or is this implementation specific?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be shorter and clearer to write assert(!!coins_view_cursor == is_db);
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I commented on this already, but seems I forgot to submit:
👍 for
assert(is_db ? !!coins_view_cursor : !coins_view_cursor); | |
assert(is_db == !!coins_view_cursor); |
or maybe even
assert(is_db ? !!coins_view_cursor : !coins_view_cursor); | |
assert(is_db != !coins_view_cursor); |
Reviewed the added fuzz test and it looks good. I let the fuzz binary run with And, I generated some corpora (https://github.com/davidgumberg/qa-assets/tree/coins_db_corpora) for ~20 minutes by doing $ ./build_fuzz/test/fuzz/test_runner.py -g qa-assets/fuzz_corpora/ coins_db and used the deterministic fuzz coverage tool from #31836 but it found instability: $ RUST_BACKTRACE=1 cargo run --manifest-path ./contrib/devtools/deterministic-fuzz-coverage/Cargo.toml -- $PWD/build_fuzz $PWD/qa-assets/fuzz_corpora/ coins_db deterministic-fuzz-coverage output
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still can't run any fuzzing on my Mac (for the past ~5 months), so I only added code review comments based on what I found.
Concept ACK
@@ -207,7 +213,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend | |||
|
|||
{ | |||
std::unique_ptr<CCoinsViewCursor> coins_view_cursor = backend_coins_view.Cursor(); | |||
assert(!coins_view_cursor); | |||
assert(is_db ? !!coins_view_cursor : !coins_view_cursor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I commented on this already, but seems I forgot to submit:
👍 for
assert(is_db ? !!coins_view_cursor : !coins_view_cursor); | |
assert(is_db == !!coins_view_cursor); |
or maybe even
assert(is_db ? !!coins_view_cursor : !coins_view_cursor); | |
assert(is_db != !coins_view_cursor); |
.memory_only = true, | ||
}; | ||
CCoinsViewDB coins_db{std::move(db_params), CoinsViewOptions{}}; | ||
TestCoinsView(fuzzed_data_provider, coins_db, /* is_db = */ true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The boolean parameter basically decides if the second parameter is a database view or not.
We could reduce this duplication by deducing it inside the TestCoinsView
method instead:
void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend_coins_view)
{
const bool is_db{!!dynamic_cast<CCoinsViewDB*>(&backend_coins_view)};
or if you prefer:
void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend_coins_view)
{
const bool is_db{typeid(backend_coins_view) == typeid(CCoinsViewDB)};
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; | ||
auto db_params = DBParams{ | ||
.path = "", // Memory only. | ||
.cache_bytes = 1 << 20, // 1MB. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I know this was just copied over, but technically this is
.cache_bytes = 1 << 20, // 1MB. | |
.cache_bytes = 1 << 20, // 1MiB. |
TestCoinsView(fuzzed_data_provider, backend_coins_view); | ||
} | ||
|
||
FUZZ_TARGET(coins_db, .init = initialize_coins_view) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file name previously coincided with the only fuzz target - now a coins_view
contains a coins_db
target as well.
Given that the type is CCoinsViewDB
, we could rename this to:
FUZZ_TARGET(coins_db, .init = initialize_coins_view) | |
FUZZ_TARGET(coins_view_db, .init = initialize_coins_view) |
{ | ||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; | ||
auto db_params = DBParams{ | ||
.path = "", // Memory only. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already obvious from two lines below:
.path = "", // Memory only. | |
.path = "", |
// of cachedCoinsUsage would have been incorrectly decreased, leading to an underflow later on. | ||
// To avoid this, use Flush() to reset the value of cachedCoinsUsage in sync with the cacheCoins | ||
// mapping. | ||
(void)coins_view_cache.Flush(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of the comment?
Why not add that to the commit message only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment seems to me to document relevant and lasting context for what is otherwise a non-sequitur, anyone touching this line in the future should know what motivated putting it here.
I explored the instablilty of the I generated two coverage reports: one with a corpus of inputs that were all stable (afl++ showing 99.3%) and then one with that same corpus but just a single added unstable input (afl++ showing ~75%). You can see that basically all of the differences in coverage are in LevelDB. If you look at the coverage for Anyway, all this to say that I don't think the instability should be a blocker for this harness. Unless we want to start changing LevelDB... |
Closing my old open PRs. I have intended to come back to it for a while but as a matter of fact i did not. Anyone interested feel free to pick it up. |
Picked up in #32602. |
cfc42ae fuzz: add a target for the coins database (Antoine Poinsot) 46e1463 fuzz: move the coins_view target's body into a standalone function (Antoine Poinsot) 56d878c fuzz: avoid underflow in coins_view target (Antoine Poinsot) Pull request description: This reopens #28216. The current `coins_view` target only tests `CCoinsViewCache` using a basic `CCoinsView` instance. The addition of the `coins_view_db` target enables testing with an actual `CCoinsViewDB` as the backend. ACKs for top commit: maflcko: lgtm ACK cfc42ae l0rinc: code review ACK cfc42ae TheCharlatan: ACK cfc42ae Tree-SHA512: d3a92f122629f075767453a1abd9819a1c9716db53b997418993fef62d27683324740d0a8f84df76d8a7a45e508ccadeb69553b6f69e29a1238cd7c0be5276ca
Similarly to #28209, this introduces a fuzz target for
CCoinsViewDb
by using an in-memory LevelDB. We reuse the body of the existing fuzz target forcoins_view
.