Fix mem access violation merkleblock #9980

Merged
merged 1 commit into from Jul 17, 2017

Conversation

Projects
None yet
9 participants
Contributor

Christewart commented Mar 12, 2017

Fixing a possible memory access violation in CPartialMerkleTree::CalcHash().

This can happen if we some how a merkle tree with zero txids. I don't think this can happen in practice as we only send merkle block messages on the p2p network as of now -- we cannot receive them.

This was found with #8469, specifically using this generator which will cause a memory access violation on this test case.

@laanwj laanwj added Bug Tests labels Mar 13, 2017

Contributor

dcousens commented Mar 13, 2017

If it shouldn't happen, maybe an assert is better?

Contributor

pstratem commented Mar 14, 2017

@TheBlueMatt what was the behavior before if the elements list was empty?

Contributor

pstratem commented Mar 14, 2017

wait no that's @sipa

Contributor

pstratem commented Mar 14, 2017

nvm it returned 0 so this maintains the original behavior

Contributor

TheBlueMatt commented Mar 17, 2017

Probably best to assert that vTxid has non-zero length, as that would represent generating a tree for an invalid block.

Contributor

Christewart commented Mar 26, 2017

Changed to what @dcousens and @TheBlueMatt suggested. I think that makes sense at the end of the day. Also, from what I can tell, that assert cannot be hit from the p2p code.

Member

NicolasDorier commented Mar 27, 2017 edited

I would have set fBad, so we don't risk later to reach a network reachable assert(0) by inadvertance. :)

Member

jnewbery commented Apr 6, 2017 edited

Looks good. Lightly tested ACK 51802cc

if you're adding an assert, can you put some commenting in explaining the assumptions that you're testing (either around the assert or the function declaration).

Also please remove the merge commits from this PR.

EDIT: cool that this was found using your property-based testing. I've been meaning to review #8469 for a while.

Contributor

Christewart commented Apr 7, 2017

@jnewbery Addressed the concerns you had.

If you want to chat about 8469 don't be afraid to ping me on irc. I think it will allow us to streamline testing AND exhaustively test invariants better than we are now.

Member

NicolasDorier commented Apr 7, 2017 edited

why no just setting fBad and returning ? I really don't like having an assert, this code might be reached from the network one day for some reason (maybe unsuspecting new feature). Putting an assert here is a tragedy waiting to happen.

Member

jnewbery commented Apr 7, 2017

@NicolasDorier - I had the same concerns as you, so I spent some time reading around the code to convince myself that this was ok. This code is only called from the CMerkleBlock constructor, which is only called from the gettxoutproof RPC or in response to a MSG_FILTERED_BLOCK getdata request. In both cases, we're constructing the Merkle Block from a block that's already in our mapBlockIndex. Therefore to hit this assert, we'd need there to be an invalid block in the mapBlockIndex, which would mean:

  • our internal data is corrupted; and
  • we've probably fallen pretty badly out of consensus

in which case, asserting is appropriate.

As for concerns about future code calling this without knowing about the assert - they'd have to be constructing a merkle block for a block that they hadn't already validated, which is a very bad idea! Just to make sure, Chris has now also added a comment above the assert to clarify assumptions.

Hope that allays your concerns!

Contributor

TheBlueMatt commented Jul 11, 2017

utACK bbdd771, though it would be nice to add a comment to CMerkleBlock noting that the block containing transactions will be asserted-on.

Contributor

Christewart commented Jul 12, 2017 edited

@TheBlueMatt Added the comment, is this ready for merge?

EDIT: Also rebased

src/merkleblock.h
@@ -121,6 +121,8 @@ class CPartialMerkleTree
/**
* Used to relay blocks as header + vector<merkle branch>
* to filtered nodes.
+ *
+ * NOTE: This is asserted on when building CPartialMerkleTree
@TheBlueMatt

TheBlueMatt Jul 12, 2017

Contributor

Wait, what is asserted? Also note extra space at EOL here.

@Christewart Christewart Adding assert to avoid a memory access violation inside of PartialMer…
…kleTree::CalcHash()

Adding comment to assert in PartialMerkleTree::CalcHash()

Adding comment on CMerkleBlock indicating it calls something that contains an assert

Removing EOL whitespace
8276e70
@gmaxwell

utACK.

Contributor

TheBlueMatt commented Jul 17, 2017

utACK 8276e70

Owner

sipa commented Jul 17, 2017

utACK 8276e70

@sipa sipa merged commit 8276e70 into bitcoin:master Jul 17, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@sipa sipa added a commit that referenced this pull request Jul 17, 2017

@sipa sipa Merge #9980: Fix mem access violation merkleblock
8276e70 Adding assert to avoid a memory access violation inside of PartialMerkleTree::CalcHash() (Chris Stewart)

Pull request description:

  Fixing a possible memory access violation in CPartialMerkleTree::CalcHash().

  This can happen if we some how a merkle tree with zero txids. I don't think this can happen in practice as we only send merkle block messages on the p2p network as of now -- we cannot receive them.

  This was found with #8469, specifically using this [generator](https://github.com/Christewart/bitcoin/blob/rapidcheck/src/test/gen/merkleblock_gen.h#L52-L77) which will cause a memory access violation on [this test case](https://github.com/Christewart/bitcoin/blob/rapidcheck/src/test/merkleblock_properties.cpp#L48).

Tree-SHA512: b95904ec45ea3f082c7722161d93ee06b24c706fbffa909a6e995ed14788aed2830f91b626da6f0347660c45874a0735dab61c9440b59c949c690af4165c83fb
fee0d80
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment