Skip to content

Conversation

@maflcko
Copy link
Member

@maflcko maflcko commented Sep 29, 2020

No description provided.

@maflcko
Copy link
Member Author

maflcko commented Sep 29, 2020

Too sad that teaching the compiler to warn about this would make the code massively verbose, but maybe it is worth a shot now that this is the second time this year?

@theStack
Copy link
Contributor

Concept ACK

The parameters BIP16Exception and BIP34Hash are also not initialized for Signet?

@maflcko
Copy link
Member Author

maflcko commented Sep 29, 2020

unit256 are default initialized to all-zeros

@theStack
Copy link
Contributor

unit256 are default initialized to all-zeros

Right, in those case there is no uninitialized read.

Still, looking at mainnet, testnet and regtest, without exception all parameters (i.e. all 22 fields of struct Params) are explicitely initialized -- hence I think for signet and all future *nets the same should be done. Both for consistency and do avoid such uninitialized read errors in the feature. The following params are not set for signet, i.e. uninitialized or default initialized:

  • MinBIP9WarningHeight (fixed in this PR)
  • nMinimumChainWork
  • defaultAssumeValid
  • BIP16Exception
  • BIP34Hash

@practicalswift
Copy link
Contributor

practicalswift commented Sep 29, 2020

@MarcoFalke Nice catch! How did you find this one?

It's always a bit sad to see unitialized reads enter our code base without being caught automatically at CI stage by either dynamic analysis (MSAN or Valgrind) or static analysis :(

@practicalswift
Copy link
Contributor

The UUM takes place in WarningBitsConditionChecker::Condition which is executed in the message handler thread:

$ valgrind --exit-on-first-error=yes --track-origins=yes --suppressions=contrib/valgrind.supp src/bitcoind -signet
…
==9443== Thread 23 b-msghand:
==9443== Conditional jump or move depends on uninitialised value(s)
==9443==    at 0x6F3E65: WarningBitsConditionChecker::Condition(CBlockIndex const*, Consensus::Params const&) const (validation.cpp:1862)
==9443==    by 0x744269: AbstractThresholdConditionChecker::GetStateFor(CBlockIndex const*, Consensus::Params const&, std::map<CBlockIndex const*, ThresholdState, std::less<CBlockIndex const*>, std::allocator<std::pair<CBlockIndex const* const, ThresholdState> > >&) const (versionbits.cpp:70)
==9443==    by 0x6D77FA: UpdateTip(CTxMemPool&, CBlockIndex const*, CChainParams const&) (validation.cpp:2458)
==9443==    by 0x6D8B64: CChainState::ConnectTip(BlockValidationState&, CChainParams const&, CBlockIndex*, std::shared_ptr<CBlock const> const&, ConnectTrace&, DisconnectedBlockTransactions&) (validation.cpp:2649)
==9443==    by 0x6D9712: CChainState::ActivateBestChainStep(BlockValidationState&, CChainParams const&, CBlockIndex*, std::shared_ptr<CBlock const> const&, bool&, ConnectTrace&) (validation.cpp:2781)
==9443==    by 0x6D9E8F: CChainState::ActivateBestChain(BlockValidationState&, CChainParams const&, std::shared_ptr<CBlock const>) (validation.cpp:2908)
==9443==    by 0x6E089E: ChainstateManager::ProcessNewBlock(CChainParams const&, std::shared_ptr<CBlock const>, bool, bool*) (validation.cpp:3864)
==9443==    by 0x3FADD3: PeerManager::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, CDataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&) (net_processing.cpp:3506)
==9443==    by 0x3FDA75: PeerManager::ProcessMessages(CNode*, std::atomic<bool>&) (net_processing.cpp:3864)
==9443==    by 0x390065: CConnman::ThreadMessageHandler() (net.cpp:2155)
==9443==    by 0x3E018D: void std::__invoke_impl<void, void (CConnman::*&)(), CConnman*&>(std::__invoke_memfun_deref, void (CConnman::*&)(), CConnman*&) (invoke.h:73)
==9443==    by 0x3DB61C: std::__invoke_result<void (CConnman::*&)(), CConnman*&>::type std::__invoke<void (CConnman::*&)(), CConnman*&>(void (CConnman::*&)(), CConnman*&) (invoke.h:95)
==9443==  Uninitialised value was created by a heap allocation
==9443==    at 0x4C3052A: operator new(unsigned long) (vg_replace_malloc.c:342)
==9443==    by 0xA1C134: CreateChainParams(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (chainparams.cpp:495)
==9443==    by 0xA1C31B: SelectParams(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (chainparams.cpp:505)
==9443==    by 0x30ABB6: AppInit(int, char**) (bitcoind.cpp:82)
==9443==    by 0x30B53E: main (bitcoind.cpp:172)

@practicalswift
Copy link
Contributor

practicalswift commented Sep 30, 2020

Unfortunately it seems like this UUM is not triggered by the code paths exercised by feature_signet.py. Covering the triggering code path in the functional test would be nice as part of this fix :)

$ test/functional/test_runner.py --valgrind --timeout-factor=0 feature_signet

TEST              | STATUS    | DURATION

feature_signet.py | ✓ Passed  | 151 s

ALL               | ✓ Passed  | 151 s (accumulated) 
Runtime: 151 s

Copy link
Contributor

@kallewoof kallewoof left a comment

Choose a reason for hiding this comment

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

utACK

@maflcko maflcko force-pushed the 2009-signetUninitRead branch from faff676 to fa82143 Compare September 30, 2020 12:52
@maflcko
Copy link
Member Author

maflcko commented Sep 30, 2020

Pushed some non-bugfix changes

@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 30, 2020

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

Conflicts

No conflicts as of last run.

Copy link
Contributor

@kallewoof kallewoof left a comment

Choose a reason for hiding this comment

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

re-ACK. Agree with moving chain work / assume valid comments.

@practicalswift
Copy link
Contributor

@kallewoof @MarcoFalke Have someone investigated why this UUM appear not to be exercised in the functional tests?

@kallewoof
Copy link
Contributor

kallewoof commented Oct 1, 2020

@practicalswift @MarcoFalke I made a minimal test that fails on master: https://github.com/kallewoof/bitcoin/tree/202010-signet-uuv-min9-test

test/validation_block_tests.cpp:379: error: in "validation_block_tests/chainparameters": check chain->GetConsensus().MinBIP9WarningHeight == 0 has failed [809056355 != 0]
2020-10-01T06:51:08.729020Z [scheduler] scheduler thread exit
test/validation_block_tests.cpp:376: Leaving test case "chainparameters"; testing time: 79044us
test/validation_block_tests.cpp:33: Leaving test suite "validation_block_tests"; testing time: 13338900us
test/validation_chainstate_tests.cpp:16: Test suite "validation_chainstate_tests" is skipped because disabled
[...]
wallet/test/scriptpubkeyman_tests.cpp:13: Test suite "scriptpubkeyman_tests" is skipped because disabled
Leaving test module "Bitcoin Core Test Suite"; testing time: 13340245us

*** 1 failure is detected in the test module "Bitcoin Core Test Suite"

The test succeeds on top of this PR.

@maflcko
Copy link
Member Author

maflcko commented Oct 1, 2020

The versionbits condition isn't evaluated for the first retarget period after the genesis block, so no test hits it.

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

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

ACK fa82143e41c067e7d16d612c775701be94974d54 🩹

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

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

fa82143e maybe also change

--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -365,7 +365,7 @@ public:
         consensus.nSubsidyHalvingInterval = 150;
         consensus.BIP16Exception = uint256();
         consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests)
-        consensus.BIP34Hash = uint256();
+        consensus.BIP34Hash = uint256{};

@jonatack
Copy link
Member

jonatack commented Oct 1, 2020

Great find -- LGTM modulo the two comments

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

Code review ACK fa82143e41c067e7d16d612c775701be94974d54.

@jonatack
Copy link
Member

jonatack commented Oct 1, 2020

Code review ACK fa82143e41c067e7d16d612c775701be94974d54

@practicalswift
Copy link
Contributor

practicalswift commented Oct 1, 2020

@MarcoFalke

Want to share how you found this one (great find!)? :) Was it found by static analysis or dynamic analysis? Automatic testing or manual testing?

I'm thinking about what we can learn from this UUM case. More specifically I'm thinking about potential ways to improve manual and/or automated processes to catch UUM:s pre-merge (in the spirit of #18288, #17633, #18159, #18166 and similar attempts to kill this bug class for good) :)


FWIW, some previous UUM cases if someone wants to analyse specific instances of this bug class more in-depth:

@maflcko
Copy link
Member Author

maflcko commented Oct 1, 2020

It was found by reading/reviewing the code

@michaelfolkson
Copy link

Concept ACK, Approach ACK

Haven't looked into @kallewoof test but presumably that will be in a follow up PR.

Thanks for sharing resources too @practicalswift. Added to a StackExchange post.

@practicalswift
Copy link
Contributor

ACK fa82143e41c067e7d16d612c775701be94974d54: diff looks correct

@maflcko maflcko added this to the 0.21.0 milestone Oct 9, 2020
@laanwj
Copy link
Member

laanwj commented Oct 15, 2020

Sorry, needs rebase (probably with taproot changes)

@maflcko maflcko force-pushed the 2009-signetUninitRead branch from fa82143 to fa60f0d Compare October 15, 2020 09:30
@maflcko
Copy link
Member Author

maflcko commented Oct 15, 2020

Rebased

Copy link
Contributor

@kallewoof kallewoof left a comment

Choose a reason for hiding this comment

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

Typo in 3rd commit message (unit256).

@maflcko maflcko force-pushed the 2009-signetUninitRead branch from fa60f0d to fa723e3 Compare October 16, 2020 04:32
@maflcko
Copy link
Member Author

maflcko commented Oct 16, 2020

Fixed typo in commit msg

@practicalswift
Copy link
Contributor

re-ACK fa723e3: patch still looks correct

Copy link
Contributor

@kallewoof kallewoof left a comment

Choose a reason for hiding this comment

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

ReACK fa723e3

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

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

re-ACK fa723e3 🍐

@laanwj laanwj merged commit 2947ae6 into bitcoin:master Oct 16, 2020
@maflcko maflcko deleted the 2009-signetUninitRead branch October 16, 2020 10:39
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Oct 16, 2020
fa723e3 Initialize default-initialized uint256 consensus params to zero explicitly (MarcoFalke)
fa729cd doc: Move assumed-values doxygen comments to header (MarcoFalke)
fa64892 signet: Fix uninitialized read in validation (MarcoFalke)

Pull request description:

ACKs for top commit:
  practicalswift:
    re-ACK fa723e3: patch still looks correct
  kallewoof:
    ReACK fa723e3
  theStack:
    re-ACK fa723e3 🍐

Tree-SHA512: db562bcc15af23bbcbf485f0bbf7564c64c144a4368230fd7682e8861d9500f6f5240351e31c560140df43b2e8456eafd9d27d1e8dd682b20afcc279a39dc329
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants