mirror of https://github.com/status-im/nim-eth.git
Add rlp_decode fuzz test + some corpus generate code
This commit is contained in:
parent
4e4836a0fe
commit
f0638eb3f1
|
@ -19,10 +19,10 @@ const
|
||||||
type
|
type
|
||||||
PacketTag* = array[tagSize, byte]
|
PacketTag* = array[tagSize, byte]
|
||||||
|
|
||||||
AuthResponse = object
|
AuthResponse* = object
|
||||||
version: int
|
version*: int
|
||||||
signature: array[64, byte]
|
signature*: array[64, byte]
|
||||||
record: Option[enr.Record]
|
record*: Option[enr.Record]
|
||||||
|
|
||||||
Codec* = object
|
Codec* = object
|
||||||
localNode*: Node
|
localNode*: Node
|
||||||
|
|
|
@ -230,7 +230,7 @@ proc `xor`[N: static[int], T](a, b: array[N, T]): array[N, T] =
|
||||||
for i in 0 .. a.high:
|
for i in 0 .. a.high:
|
||||||
result[i] = a[i] xor b[i]
|
result[i] = a[i] xor b[i]
|
||||||
|
|
||||||
proc whoareyouMagic(toNode: NodeId): array[magicSize, byte] =
|
proc whoareyouMagic*(toNode: NodeId): array[magicSize, byte] =
|
||||||
const prefix = "WHOAREYOU"
|
const prefix = "WHOAREYOU"
|
||||||
var data: array[prefix.len + sizeof(toNode), byte]
|
var data: array[prefix.len + sizeof(toNode), byte]
|
||||||
data[0 .. sizeof(toNode) - 1] = toNode.toByteArrayBE()
|
data[0 .. sizeof(toNode) - 1] = toNode.toByteArrayBE()
|
||||||
|
|
|
@ -8,7 +8,8 @@ var targetNode: protocol.Protocol
|
||||||
init:
|
init:
|
||||||
let
|
let
|
||||||
rng = newRng()
|
rng = newRng()
|
||||||
privKey = PrivateKey.random(rng[])
|
privKey = PrivateKey.fromHex(
|
||||||
|
"5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d")[]
|
||||||
ip = some(ValidIpAddress.init("127.0.0.1"))
|
ip = some(ValidIpAddress.init("127.0.0.1"))
|
||||||
port = Port(20301)
|
port = Port(20301)
|
||||||
dbb = DiscoveryDB.init(newMemoryDB())
|
dbb = DiscoveryDB.init(newMemoryDB())
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import
|
||||||
|
std/[os, strutils],
|
||||||
|
stew/shims/net,
|
||||||
|
eth/[rlp, keys], eth/p2p/discoveryv5/[encoding, enr, types],
|
||||||
|
../fuzzing_helpers
|
||||||
|
|
||||||
|
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||||
|
const inputsDir = sourceDir / "corpus" & DirSep
|
||||||
|
|
||||||
|
proc generate() =
|
||||||
|
let
|
||||||
|
rng = keys.newRng()
|
||||||
|
privKey = PrivateKey.random(rng[])
|
||||||
|
pubKey = PrivateKey.random(rng[]).toPublicKey()
|
||||||
|
var idNonce: IdNonce
|
||||||
|
brHmacDrbgGenerate(rng[], idNonce)
|
||||||
|
|
||||||
|
let
|
||||||
|
ephKeys = KeyPair.random(rng[])
|
||||||
|
signature = signIDNonce(privKey, idNonce, ephKeys.pubkey.toRaw)
|
||||||
|
record = enr.Record.init(1, privKey, none(ValidIpAddress), Port(9000),
|
||||||
|
Port(9000))[]
|
||||||
|
authResponse =
|
||||||
|
AuthResponse(version: 5, signature: signature.toRaw, record: some(record))
|
||||||
|
authResponseNoRecord =
|
||||||
|
AuthResponse(version: 5, signature: signature.toRaw, record: none(enr.Record))
|
||||||
|
|
||||||
|
rlp.encode(authResponse).toFile(inputsDir & "auth-response")
|
||||||
|
rlp.encode(authResponseNoRecord).toFile(inputsDir & "auth-response-no-enr")
|
||||||
|
|
||||||
|
discard existsOrCreateDir(inputsDir)
|
||||||
|
generate()
|
|
@ -0,0 +1,51 @@
|
||||||
|
import
|
||||||
|
std/[os, strutils],
|
||||||
|
stew/shims/net,
|
||||||
|
eth/[keys, rlp, trie/db],
|
||||||
|
eth/p2p/discoveryv5/[protocol, discovery_db, enr, node, types, encoding],
|
||||||
|
../fuzzing_helpers
|
||||||
|
|
||||||
|
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||||
|
const inputsDir = sourceDir / "corpus" & DirSep
|
||||||
|
|
||||||
|
proc generate() =
|
||||||
|
let
|
||||||
|
rng = keys.newRng()
|
||||||
|
privKey = PrivateKey.random(rng[])
|
||||||
|
ip = some(ValidIpAddress.init("127.0.0.1"))
|
||||||
|
port = Port(20301)
|
||||||
|
dbb = DiscoveryDB.init(newMemoryDB())
|
||||||
|
d = newProtocol(privKey, dbb, ip, port, port, rng = rng)
|
||||||
|
|
||||||
|
# Same as the on in the fuzz test to have at least one working packet for
|
||||||
|
# the whoareyou-packet.
|
||||||
|
toPrivKey = PrivateKey.fromHex(
|
||||||
|
"5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d")[]
|
||||||
|
toRecord = enr.Record.init(1, toPrivKey,
|
||||||
|
some(ValidIpAddress.init("127.0.0.1")), Port(9000), Port(9000))[]
|
||||||
|
toNode = newNode(toRecord)[]
|
||||||
|
|
||||||
|
block: # random packet
|
||||||
|
# No handshake done obviously so a new packet will be a random packet.
|
||||||
|
let
|
||||||
|
reqId = RequestId.init(d.rng[])
|
||||||
|
message = encodeMessage(PingMessage(enrSeq: d.localNode.record.seqNum), reqId)
|
||||||
|
(data, _) = encodePacket(d.rng[], d.codec, toNode.id, toNode.address.get(),
|
||||||
|
message, challenge = nil)
|
||||||
|
|
||||||
|
data.toFile(inputsDir & "random-packet")
|
||||||
|
|
||||||
|
block: # whoareyou packet
|
||||||
|
var authTag: AuthTag
|
||||||
|
var idNonce: IdNonce
|
||||||
|
brHmacDrbgGenerate(d.rng[], authTag)
|
||||||
|
brHmacDrbgGenerate(d.rng[], idNonce)
|
||||||
|
|
||||||
|
let challenge = Whoareyou(authTag: authTag, idNonce: idNonce, recordSeq: 0)
|
||||||
|
var data = @(whoareyouMagic(toNode.id))
|
||||||
|
data.add(rlp.encode(challenge[]))
|
||||||
|
|
||||||
|
data.toFile(inputsDir & "whoareyou-packet")
|
||||||
|
|
||||||
|
discard existsOrCreateDir(inputsDir)
|
||||||
|
generate()
|
|
@ -1,17 +1,12 @@
|
||||||
import
|
import
|
||||||
streams, os, strutils, options,
|
std/[os, strutils, options],
|
||||||
stew/shims/net,
|
stew/shims/net,
|
||||||
eth/keys, eth/p2p/discoveryv5/enr
|
eth/keys, eth/p2p/discoveryv5/enr,
|
||||||
|
../fuzzing_helpers
|
||||||
|
|
||||||
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||||
const inputsDir = sourceDir / "corpus"
|
const inputsDir = sourceDir / "corpus"
|
||||||
|
|
||||||
proc toFile(data: seq[byte], fn: string) =
|
|
||||||
var s = newFileStream(fn, fmWrite)
|
|
||||||
for x in data:
|
|
||||||
s.write(x)
|
|
||||||
s.close()
|
|
||||||
|
|
||||||
proc generate() =
|
proc generate() =
|
||||||
let
|
let
|
||||||
rng = newRng()
|
rng = newRng()
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import
|
||||||
|
std/streams
|
||||||
|
|
||||||
|
proc toFile*(data: seq[byte], fn: string) =
|
||||||
|
var s = newFileStream(fn, fmWrite)
|
||||||
|
for x in data:
|
||||||
|
s.write(x)
|
||||||
|
s.close()
|
|
@ -0,0 +1,32 @@
|
||||||
|
import
|
||||||
|
testutils/fuzzing, chronicles,
|
||||||
|
eth/rlp
|
||||||
|
|
||||||
|
type
|
||||||
|
TestEnum = enum
|
||||||
|
one = 1
|
||||||
|
two = 2
|
||||||
|
TestObject* = object
|
||||||
|
test1: uint32
|
||||||
|
test2: string
|
||||||
|
|
||||||
|
template testDecode(payload: openarray, T: type) =
|
||||||
|
try:
|
||||||
|
discard rlp.decode(payload, T)
|
||||||
|
except RlpError as e:
|
||||||
|
debug "Decode failed", err = e.msg
|
||||||
|
|
||||||
|
test:
|
||||||
|
testDecode(payload, string)
|
||||||
|
testDecode(payload, uint)
|
||||||
|
testDecode(payload, uint8)
|
||||||
|
testDecode(payload, uint16)
|
||||||
|
testDecode(payload, uint32)
|
||||||
|
testDecode(payload, uint64)
|
||||||
|
testDecode(payload, int)
|
||||||
|
testDecode(payload, bool)
|
||||||
|
testDecode(payload, float64)
|
||||||
|
testDecode(payload, seq[byte])
|
||||||
|
testDecode(payload, (string, int32))
|
||||||
|
testDecode(payload, TestEnum)
|
||||||
|
testDecode(payload, TestObject)
|
Loading…
Reference in New Issue