nim-eth/tests/fuzzing/fuzz_helpers.nim

59 lines
1.6 KiB
Nim
Raw Normal View History

import streams, posix, strutils, chronicles, macros
2019-09-03 13:45:26 +00:00
template fuzz(body) =
2019-09-03 13:45:26 +00:00
# For code we want to fuzz, SIGSEGV is needed on unwanted exceptions.
# However, this is only needed when fuzzing with afl.
when defined(afl):
try:
body
except Exception as e:
error "Fuzzer input created exception", exception=e.name, trace=e.repr, msg=e.msg
discard kill(getpid(), SIGSEGV)
else:
body
proc readStdin*(): seq[byte] =
# Read input from stdin (fastest for AFL)
let s = newFileStream(stdin)
if s.isNil:
error "Error opening stdin"
discard kill(getpid(), SIGSEGV)
# We use binary files as with hex we can get lots of "not hex" failures
var input = s.readAll()
s.close()
# Remove newline if it is there
input.removeSuffix
result = cast[seq[byte]](input)
proc NimMain() {.importc: "NimMain".}
template `+`*[T](p: ptr T, off: int): ptr T =
cast[ptr type(p[])](cast[ByteAddress](p) +% off * sizeof(p[]))
2019-09-25 15:16:35 +00:00
template test*(body: untyped): untyped =
when defined(afl):
2019-09-25 15:16:35 +00:00
var payload {.inject.} = readStdin()
2019-09-25 15:16:35 +00:00
fuzz: `body`
else:
2019-09-25 15:16:35 +00:00
proc fuzzerCall(data: ptr byte, len: csize):
cint {.exportc: "LLVMFuzzerTestOneInput".} =
var payload {.inject.} : seq[byte]
if len > 0:
# TODO: something better to get this data in the seq?
newSeq(payload, len)
for i in 0..<len:
payload[i] = (data + i)[]
`body`
template init*(body: untyped): untyped =
when defined(afl):
2019-09-25 15:16:35 +00:00
fuzz: `body`
else:
2019-09-25 15:16:35 +00:00
proc fuzzerInit(): cint {.exportc: "LLVMFuzzerInitialize".} =
NimMain()
2019-09-25 15:16:35 +00:00
`body`
2019-09-25 15:16:35 +00:00
return 0