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],
../rlp, ../trie/[trie_defs, db]
from stew/objects
import checkedEnumAssign
export
stint, read, append, KeccakHash, rlp, options
@ -454,14 +457,21 @@ proc readTxTyped(rlp: var Rlp, tx: var Transaction) {.inline.} =
let txType = rlp.getByteValue
rlp.position += 1
case TxType(txType):
var txVal: TxType
if checkedEnumAssign(txVal, txType):
case txVal:
of TxEip2930:
rlp.readTxEip2930(tx)
return
of TxEip1559:
rlp.readTxEip1559(tx)
return
else:
raise newException(UnsupportedRlpError,
"TypedTransaction type must be 1 or 2 in this version, got " & $txType)
discard
raise newException(UnsupportedRlpError,
"TypedTransaction type must be 1 or 2 in this version, got " & $txType)
proc read*(rlp: var Rlp, T: type Transaction): T =
# Individual transactions are encoded and stored as either `RLP([fields..])`

View File

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