diff options
Diffstat (limited to 'src/compactblock.cpp')
| -rw-r--r-- | src/compactblock.cpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/compactblock.cpp b/src/compactblock.cpp index 3999ab7..1ca6118 100644 --- a/src/compactblock.cpp +++ b/src/compactblock.cpp | |||
| @@ -48,8 +48,16 @@ bool BuildCompactBlock(const CBlock& block, CCmpctBlock& out) | |||
| 48 | out.nBits = block.nBits; | 48 | out.nBits = block.nBits; |
| 49 | out.nNonce = block.nNonce; | 49 | out.nNonce = block.nNonce; |
| 50 | 50 | ||
| 51 | // Upstream ignored the RAND_bytes return value here. On failure nonceBytes | ||
| 52 | // is left uninitialised and an indeterminate shortIdNonce goes out on the | ||
| 53 | // wire -- which is precisely the value this file relies on being | ||
| 54 | // unpredictable to stop short IDs being precomputed or ground against. | ||
| 55 | // Fail closed instead, matching every other RAND_bytes call site in this | ||
| 56 | // tree (bip32.cpp, db.cpp): the caller falls back to full-block relay, | ||
| 57 | // which is always correct. | ||
| 51 | unsigned char nonceBytes[sizeof(uint64)]; | 58 | unsigned char nonceBytes[sizeof(uint64)]; |
| 52 | RAND_bytes(nonceBytes, sizeof(nonceBytes)); | 59 | if (RAND_bytes(nonceBytes, sizeof(nonceBytes)) != 1) |
| 60 | return false; | ||
| 53 | memcpy(&out.shortIdNonce, nonceBytes, sizeof(uint64)); | 61 | memcpy(&out.shortIdNonce, nonceBytes, sizeof(uint64)); |
| 54 | 62 | ||
| 55 | out.vPrefilledIndex.clear(); | 63 | out.vPrefilledIndex.clear(); |
| @@ -75,6 +83,18 @@ bool TryReconstructBlock(const CCmpctBlock& cmpct, CBlock& outBlock, std::vector | |||
| 75 | if (cmpct.vPrefilledIndex.size() != cmpct.vPrefilledTx.size() || nTotal == 0) | 83 | if (cmpct.vPrefilledIndex.size() != cmpct.vPrefilledTx.size() || nTotal == 0) |
| 76 | return false; // malformed | 84 | return false; // malformed |
| 77 | 85 | ||
| 86 | // nTotal comes straight off the wire once this is wired into the P2P | ||
| 87 | // layer, and serialize.h only bounds a vector length by MAX_SIZE | ||
| 88 | // (0x02000000), so an unbounded assign() below would let one 60-odd-byte | ||
| 89 | // message ask this node for ~33M default-constructed CTransactions. The | ||
| 90 | // smallest a transaction can serialise to is 10 bytes (nVersion, empty | ||
| 91 | // vin, empty vout, nLockTime), so no block within MAX_BLOCK_SIZE can hold | ||
| 92 | // more than MAX_BLOCK_SIZE/10 of them; anything above that is not a block | ||
| 93 | // we could ever accept. Rejecting here just falls back to full-block | ||
| 94 | // relay, which is always correct. | ||
| 95 | if (nTotal > MAX_BLOCK_SIZE / 10) | ||
| 96 | return false; // implausible tx count -- refuse to size a vector from it | ||
| 97 | |||
| 78 | outBlock.SetNull(); | 98 | outBlock.SetNull(); |
| 79 | outBlock.nVersion = cmpct.nVersion; | 99 | outBlock.nVersion = cmpct.nVersion; |
| 80 | outBlock.hashPrevBlock = cmpct.hashPrevBlock; | 100 | outBlock.hashPrevBlock = cmpct.hashPrevBlock; |