diff --git a/stateless/invalidInput/crash-6081fe3734250348623b03c1d3acb35d90d2ecfc b/stateless/invalidInput/crash-6081fe3734250348623b03c1d3acb35d90d2ecfc new file mode 100644 index 000000000..1bf239ad0 Binary files /dev/null and b/stateless/invalidInput/crash-6081fe3734250348623b03c1d3acb35d90d2ecfc differ diff --git a/stateless/invalidInput/crash-a865d42d79ebbfd42b86d11e2e068643cf0fd503 b/stateless/invalidInput/crash-a865d42d79ebbfd42b86d11e2e068643cf0fd503 new file mode 100644 index 000000000..09e441efd Binary files /dev/null and b/stateless/invalidInput/crash-a865d42d79ebbfd42b86d11e2e068643cf0fd503 differ diff --git a/stateless/invalidInput/crash-a8a8b9592a31539c0318ae6a1cd416d5644cb74a b/stateless/invalidInput/crash-a8a8b9592a31539c0318ae6a1cd416d5644cb74a new file mode 100644 index 000000000..d5d64275b Binary files /dev/null and b/stateless/invalidInput/crash-a8a8b9592a31539c0318ae6a1cd416d5644cb74a differ diff --git a/stateless/invalidInput/crash-d755f044304f53abf28a735763865a449a198235 b/stateless/invalidInput/crash-d755f044304f53abf28a735763865a449a198235 new file mode 100644 index 000000000..bece4c4b9 Binary files /dev/null and b/stateless/invalidInput/crash-d755f044304f53abf28a735763865a449a198235 differ diff --git a/stateless/invalidInput/crash-eb262bbb7d5a0b11e1a8112ea592eb67cc618c9b b/stateless/invalidInput/crash-eb262bbb7d5a0b11e1a8112ea592eb67cc618c9b new file mode 100644 index 000000000..5d6b306eb Binary files /dev/null and b/stateless/invalidInput/crash-eb262bbb7d5a0b11e1a8112ea592eb67cc618c9b differ diff --git a/stateless/invalidInput/crash-f9a002e389b120714a2324487a6e473b0fedc12e b/stateless/invalidInput/crash-f9a002e389b120714a2324487a6e473b0fedc12e new file mode 100644 index 000000000..83050f8a5 Binary files /dev/null and b/stateless/invalidInput/crash-f9a002e389b120714a2324487a6e473b0fedc12e differ diff --git a/stateless/test_witness_keys.nim b/stateless/test_witness_keys.nim index 93e160916..95904c0ac 100644 --- a/stateless/test_witness_keys.nim +++ b/stateless/test_witness_keys.nim @@ -1,5 +1,5 @@ import - randutils, random, unittest2, stew/byteutils, + randutils, random, unittest2, stew/byteutils, os, eth/[common, rlp], eth/trie/[hexary, db, trie_defs, nibbles], faststreams/inputs, nimcrypto/sysrand, ../stateless/[witness_from_tree, tree_from_witness], @@ -124,6 +124,14 @@ proc initMultiKeys(keys: openArray[string]): MultikeysRef = hash: hexToByteArray[32](x) ) +proc parseInvalidInput(payload: openArray[byte]): bool = + var db = newMemoryDB() + try: + var tb = initTreeBuilder(payload, db, {wfEIP170}) + discard tb.buildTree() + except ParsingError, ContractCodeError: + result = true + proc witnessKeysMain*() = suite "random keys block witness roundtrip test": randomize() @@ -223,5 +231,10 @@ proc witnessKeysMain*() = mg.group.first == 2 mg.group.last == 3 + test "parse invalid input": + for x in walkDirRec("stateless" / "invalidInput"): + let z = readFile(x) + check parseInvalidInput(z.toOpenArrayByte(0, z.len-1)) + when isMainModule: witnessKeysMain() diff --git a/stateless/tree_from_witness.nim b/stateless/tree_from_witness.nim index d0ba39070..cc75c2bd5 100644 --- a/stateless/tree_from_witness.nim +++ b/stateless/tree_from_witness.nim @@ -218,7 +218,9 @@ proc buildForest*(t: var TreeBuilder): seq[KeccakHash] result.add KeccakHash(data: res.data) proc treeNode(t: var TreeBuilder, depth: int, storageMode = false): NodeKey = - assert(depth < 64) + if depth >= 64: + raise newException(ParsingError, "invalid trie structure") + let nodeType = safeReadEnum(t, TrieNodeType) case nodeType of BranchNodeType: result = t.branchNode(depth, storageMode) @@ -235,7 +237,9 @@ proc treeNode(t: var TreeBuilder, depth: int, storageMode = false): NodeKey = result = t.forceSmallNodeKeyToHash(result) proc branchNode(t: var TreeBuilder, depth: int, storageMode: bool): NodeKey = - assert(depth < 64) + if depth >= 64: + raise newException(ParsingError, "invalid trie structure") + let mask = constructBranchMask(t.safeReadByte, t.safeReadByte) when defined(debugDepth): @@ -305,9 +309,13 @@ func hexPrefixLeaf(r: var RlpWriter, x: openArray[byte], depth: int) = r.append toOpenArray(bytes, 0, nibblesLen div 2) proc extensionNode(t: var TreeBuilder, depth: int, storageMode: bool): NodeKey = - assert(depth < 63) + if depth >= 63: + raise newException(ParsingError, "invalid trie structure") + let nibblesLen = t.safeReadByte().int - assert(nibblesLen < 65) + if nibblesLen > 64 or nibblesLen < 1: + raise newException(ParsingError, "nibblesLen should between 1..64") + var r = initRlpList(2) let pathLen = nibblesLen div 2 + nibblesLen mod 2 safeReadBytes(t, pathLen): @@ -321,7 +329,9 @@ proc extensionNode(t: var TreeBuilder, depth: int, storageMode: bool): NodeKey = var hash: NodeKey toKeccak(hash, t.read(32)) - assert(depth + nibblesLen < 65) + if nibblesLen + depth > 64 or nibblesLen + depth < 1: + raise newException(ParsingError, "depth should between 1..64") + let nodeType = safeReadEnum(t, TrieNodeType) case nodeType of BranchNodeType: r.append t.branchNode(depth + nibblesLen, storageMode) @@ -375,7 +385,8 @@ proc readByteCode(t: var TreeBuilder, acc: var Account) = acc.codeHash.data = codeHash.data proc accountNode(t: var TreeBuilder, depth: int): NodeKey = - assert(depth < 65) + if depth >= 65: + raise newException(ParsingError, "invalid trie structure") when defined(debugHash): let len = t.safeReadU32().int @@ -443,7 +454,8 @@ proc readStorageSlot(t: var TreeBuilder): Hash256 = t.keys[^1].slots.add slot proc accountStorageLeafNode(t: var TreeBuilder, depth: int): NodeKey = - assert(depth < 65) + if depth >= 65: + raise newException(ParsingError, "invalid trie structure") when defined(debugHash): let len = t.safeReadU32().int