10BC0 Add nullptr-check to CChain::Contains(), tests by optout21 · Pull Request #34416 · bitcoin/bitcoin · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@optout21
Copy link
Contributor

Add unit tests to the CChain class, and add a nullptr-check to CChain::Contains() to avoid potential memory access violation by nullptr dereference.

The CChain::Contains() method (in src/chain.h) dereferences its input without checking. The Next() method also calls into this with a nullptr if invoked with nullptr. While most call sites have indirect guarantee that the input is not nullptr, it's not easy to establish this to all call sites with high confidence. These methods are publicly available. There is no known high-level use case to trigger this error, but the fix is easy, and makes the code safer.

Also, unit tests were added to the CChain class, filling a gap.

Changes:

  • Add basic unit tests for CChain class methods
  • Add a nullptr-check to CChain::Contains()
  • Add unit tests for CChain::FindFork(). These are lengthier, and not closely related to the topic of the PR, could be removed, but kept for extra test coverage.

Alternative. I have considered changing Contains() to take a reference instead of pointer, to better express that it cannot take a nullptr input. It's a viable solution, requires update to only a handful of call sites (solution available on branch cchain-contains1). However, since most CChain logic operates with pointers and pointer comparison, it would break the style, so I dropped this solution.

This change is remotely related to and partly triggered by #32875 .

Add basic unit tests to the `CChain` class, filling a gap.
Add (lengthier) unit tests for `CChain::FindFork()`.
The `CChain::Contains()` method dereferences its input without checking,
potentially resulting in nullptr-dereference if invoked with `nullptr`.
The `Next()` method can also trigger this. Avoid the memory access
violation by adding an extra check for the `pindex` input.
The result is `false` for `nullptr` input.
@DrahtBot
Copy link
Contributor
DrahtBot commented Jan 27, 2026

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/34416.

Reviews

See the guideline for information on the review process.
A summary of reviews will appear here.

@optout21 optout21 marked this pull request as ready for review January 27, 2026 07:31
Comment on lines 1923 to +1926
bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
{
AssertLockHeld(cs_main);
if (!pindex) return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this goes in the wrong direction. All call sites have checked against nullptr, and there should never be a reason to call this with nullptr, so this seems it should be a reference. Just like BlockRequested and FetchBlock take a reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following this feedback, I will reconsider the switch to pass-by-reference. As mentioned in the description, I started in that direction, but was concerned about consistency.
For consistency, it makes sense to also change the other methods (e.g. Next()), increasing the scope. Const input pointer parameters are relatively easy to change to pass-by-reference; but return values where nullptr is a valid option should be changed to std::option<&...>. These end up in a larger changeset (arguably not adding much value).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, i haven't looked into the lower level chain util methods. For some methods, it could make sense to accept a pointer. My comment was mostly about BlockRequestAllowed, and other similar high level functions that only work on blocks that exist and whose presence has been previously confirmed

@optout21 optout21 marked this pull request as draft January 27, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

0