Fix stability issues (#512)

* Fix stability issues

why:
  Handling malformed messages typically raises `RangeError` exceptions
  when de-serialising RLP, or decoding message data. This is an
  (incomplete) attempt to weed out some out it driven by real live
  tests.

remark:
  Employing the new `snap` protocol there might be different views on what
  the messages really contain (currently specs are more a hint.)

* Update RLP exception handling

* Undo effect-less patch

why:
  problem occurred somewhere above the try/catch handler

* Using `checkedEnumAssign()` for RLP enum
This commit is contained in:
Jordan Hrycaj 2022-06-16 16:23:07 +01:00 committed by GitHub
parent dacf827a86
commit 8761ea3222
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 11 deletions

View File

@ -3,6 +3,9 @@ import
stew/[endians2, byteutils], chronicles, stint, nimcrypto/[keccak, hash], stew/[endians2, byteutils], chronicles, stint, nimcrypto/[keccak, hash],
../rlp, ../trie/[trie_defs, db] ../rlp, ../trie/[trie_defs, db]
from stew/objects
import checkedEnumAssign
export export
stint, read, append, KeccakHash, rlp, options stint, read, append, KeccakHash, rlp, options
@ -454,15 +457,22 @@ proc readTxTyped(rlp: var Rlp, tx: var Transaction) {.inline.} =
let txType = rlp.getByteValue let txType = rlp.getByteValue
rlp.position += 1 rlp.position += 1
case TxType(txType): var txVal: TxType
if checkedEnumAssign(txVal, txType):
case txVal:
of TxEip2930: of TxEip2930:
rlp.readTxEip2930(tx) rlp.readTxEip2930(tx)
return
of TxEip1559: of TxEip1559:
rlp.readTxEip1559(tx) rlp.readTxEip1559(tx)
return
else: else:
discard
raise newException(UnsupportedRlpError, raise newException(UnsupportedRlpError,
"TypedTransaction type must be 1 or 2 in this version, got " & $txType) "TypedTransaction type must be 1 or 2 in this version, got " & $txType)
proc read*(rlp: var Rlp, T: type Transaction): T = proc read*(rlp: var Rlp, T: type Transaction): T =
# Individual transactions are encoded and stored as either `RLP([fields..])` # Individual transactions are encoded and stored as either `RLP([fields..])`
# for legacy transactions, or `Type || RLP([fields..])`. Both of these # for legacy transactions, or `Type || RLP([fields..])`. Both of these

View File

@ -62,17 +62,20 @@ proc read(rlp: var Rlp; T: type DisconnectionReasonList): T
# Be strict here: The expression `rlp.read(DisconnectionReasonList)` # Be strict here: The expression `rlp.read(DisconnectionReasonList)`
# accepts lists with at least one item. The array expression wants # accepts lists with at least one item. The array expression wants
# exactly one item. # exactly one item.
if rlp.rawData.len < 3:
# avoids looping through all items when parsing for an overlarge array
return DisconnectionReasonList( return DisconnectionReasonList(
value: rlp.read(array[1,DisconnectionReason])[0]) value: rlp.read(array[1,DisconnectionReason])[0])
# Also accepted: a single byte reason code. Is is typically used # Also accepted: a single byte reason code. Is is typically used
# by variants of the reference implementation `Geth` # by variants of the reference implementation `Geth`
if rlp.blobLen <= 1: elif rlp.blobLen <= 1:
return DisconnectionReasonList( return DisconnectionReasonList(
value: rlp.read(DisconnectionReason)) value: rlp.read(DisconnectionReason))
# Also accepted: a blob of a list (aka object) of reason code. It is # Also accepted: a blob of a list (aka object) of reason code. It is
# used by `bor`, a `geth` fork # used by `bor`, a `geth` fork
elif rlp.blobLen < 4:
var subList = rlp.toBytes.rlpFromBytes var subList = rlp.toBytes.rlpFromBytes
if subList.isList: if subList.isList:
# Ditto, see above. # Ditto, see above.