added warnings in everything that broke, minor additions

This commit is contained in:
Antonis Geralis 2022-08-26 08:15:17 +03:00
parent 020f294416
commit 870c7f06ae
11 changed files with 103 additions and 27 deletions

View File

@ -1,4 +1,7 @@
# Compile with: nim c -d:danger -d:fuzzerStandalone bench_graph.nim
# WARNING: This benchmark does not run a complete fuzzing iteration, just the mutator.
# TODO: Doesn't work after adding the cache.
# As such it doesn't account for LibFuzzer's overhead or the efficiency of the cache.
# Compile with: nim c -d:danger bench_graph.nim
# Then run: perf record -e cycles:pp --call-graph dwarf ./bench_graph
include examples/fuzz_graph

View File

@ -2,10 +2,10 @@ mode = ScriptMode.Verbose
version = "0.1.0"
author = "Dr. Chaos Team"
description = "Library for structured fuzzing for Nim"
description = "A powerful and easy-to-use fuzzing framework in Nim for C/C++/Obj-C targets"
license = "MIT"
srcDir = "."
skipDirs = @["tests", "benchmarks", "examples"]
skipDirs = @["tests", "benchmarks", "examples", "experiments"]
requires "nim >= 1.4.0"
@ -23,29 +23,29 @@ proc buildBinary(name: string, srcDir = "./", params = "", lang = "c") =
exec "nim " & lang & " --out:build/" & name & " " & extra_params & " " & srcDir & name & ".nim"
proc test(name: string, srcDir = "tests/", lang = "c") =
proc test(name: string, srcDir = "tests/", params = "", lang = "c") =
buildBinary name, srcDir, "--mm:arc -d:danger"
withDir("build/"):
exec name & " -error_exitcode=0 -max_total_time=5 -runs=10000"
exec name & " -max_total_time=3 -runs=10000" & params
task testDrChaosExamples, "Build & run Dr. Chaos examples":
let examples = @["fuzz_graph", "fuzz_tree"]
let examples = @["fuzz_graph"]
for ex in examples:
test ex, "examples/"
task testDrChaos, "Build & run Dr. Chaos tests":
for filePath in listFiles("tests/"):
if filePath[^4..^1] == ".nim":
test filePath[len("tests/")..^5]
test filePath[len("tests/")..^5], " -error_exitcode=0"
task testDrChaosTimed, "Build & run Dr. Chaos time limited tests":
for filePath in listFiles("tests/time_limited/"):
task testDrChaosNoCrash, "Build & run Dr. Chaos tests that should not crash":
for filePath in listFiles("tests/no_crash/"):
if filePath[^4..^1] == ".nim":
test filePath[len("tests/time_limited/")..^5], "tests/time_limited/"
test filePath[len("tests/no_crash/")..^5], "tests/no_crash/"
#task test, "Run basic tests":
#testDrChaosTask()
task test, "Run basic tests":
testDrChaosTask()
task testAll, "Run all tests":
testDrChaosTask()
testDrChaosTimedTask()
testDrChaosNoCrash()

View File

@ -2,7 +2,7 @@ import std/[random, macros, setutils, enumutils, typetraits, options]
import common, private/[sampler, utf8fix]
when not defined(fuzzerStandalone):
proc initialize(): cint {.exportc: "LLVMFuzzerInitialize".} =
proc LLVMFuzzerInitialize(): cint {.exportc.} =
{.emit: "N_CDECL(void, NimMain)(void); NimMain();".}
proc mutate(data: ptr UncheckedArray[byte], len, maxLen: int): int {.

View File

@ -1,4 +1,4 @@
# Good seed to try out without the postProcess proc. -seed=4013847822
# Good seed to try out: -seed=4013847822
when defined(runFuzzTests):
const
MaxNodes = 8 # User defined, statically limits number of nodes.
@ -60,17 +60,16 @@ when defined(runFuzzTests) and isMainModule:
proc mutate(value: var seq[NodeIdx]; sizeIncreaseHint: int; enforceChanges: bool; r: var Rand) =
repeatMutateInplace(mutateSeq(value, tmp, MaxEdges, sizeIncreaseHint, r))
# We run it as a test, so cheat a little.
proc postProcess[T: SomeNumber](x: var seq[Node[T]]; r: var Rand) =
if x.len >= 8:
x[0].data = 63
x[1].data = 3
x[2].data = -56
x[3].data = 100
x[4].data = -100
x[5].data = -78
x[6].data = 46
x[7].data = 120
#proc postProcess[T: SomeNumber](x: var seq[Node[T]]; r: var Rand) =
#if x.len >= 8:
#x[0].data = 63
#x[1].data = 3
#x[2].data = -56
#x[3].data = 100
#x[4].data = -100
#x[5].data = -78
#x[6].data = 46
#x[7].data = 120
func fuzzTarget(x: Graph[int8]) =
when defined(dumpFuzzInput): debugEcho(x)

View File

@ -0,0 +1,75 @@
# WARNING: This mutator crashes for OrderedTable and it's too slow with Table.
# TODO: split into files and make it compile again.
import random
include std/tables
proc firstPositionHidden*[A, B](t: OrderedTable[A, B]): int =
## Undocumented API for iteration.
if t.counter > 0:
result = t.first
while result >= 0 and not isFilled(t.data[result].hcode):
result = t.data[result].next
else:
result = -1
proc nextPositionHidden*[A, B](t: OrderedTable[A, B]; current: int): int =
## Undocumented API for iteration.
result = t.data[current].next
while result >= 0 and not isFilled(t.data[result].hcode):
result = t.data[result].next
proc nextPositionHidden*[A, B](t: Table[A, B]; current: int): int =
## Undocumented API for iteration.
result = current
while result >= 0 and not isFilled(t.data[result].hcode):
inc result
if result > t.data.high: result = -1
proc positionOfHidden*[A, B](t: OrderedTable[A, B]; index: int): int =
var index = index
result = firstPositionHidden(t)
while result >= 0 and index > 0:
result = t.nextPositionHidden(result)
dec index
proc positionOfHidden*[A, B](t: Table[A, B]; index: int): int =
var index = index
result = if t.counter > 0: 0 else: -1
while result >= 0 and index > 0:
result = t.nextPositionHidden(result)
dec index
proc keyAtHidden*[A, B](t: (Table[A, B]|OrderedTable[A, B]); current: int): lent A {.inline.} =
## Undocumented API for iteration.
result = t.data[current].key
proc keyAtHidden*[A, B](t: var (Table[A, B]|OrderedTable[A, B]); current: int): var A {.inline.} =
## Undocumented API for iteration.
result = t.data[current].key
proc newInput*[T](sizeIncreaseHint: int; r: var Rand): T = discard
proc runMutator*[T](x: var T; sizeIncreaseHint: int; enforceChanges: bool; r: var Rand) = discard
proc mutateTab*[A, B](value: var (Table[A, B]|OrderedTable[A, B]); previous: OrderedTable[A, B];
userMax, sizeIncreaseHint: int; r: var Rand): bool =
let previousSize = previous.byteSize
while value.len > 0 and r.rand(bool):
let pos = positionOfHidden(value, rand(r, value.len-1))
assert pos >= 0
value.del(value.keyAtHidden(pos))
var currentSize = value.byteSize
template remainingSize: untyped = sizeIncreaseHint-currentSize+previousSize
while value.len < userMax and remainingSize > 0 and r.rand(bool):
let key = newInput[A](remainingSize, r)
value[key] = newInput[B](remainingSize-key.byteSize, r)
currentSize = value.byteSize
if value != previous:
return true
elif value.len == 0:
let key = newInput[A](remainingSize, r)
value[key] = newInput[B](remainingSize-key.byteSize, r)
else:
let pos = positionOfHidden(value, rand(r, value.len-1))
assert pos >= 0
runMutator(value.keyAtHidden(pos), remainingSize, true, r)
result = value != previous

View File

@ -17,7 +17,6 @@ func `==`(a, b: ContentNode): bool =
of Text: return a.textStr == b.textStr
func fuzzTarget(x: ContentNode) =
when defined(dumpFuzzInput): debugEcho(x)
let data = ContentNode(kind: P, pChildren: @[
ContentNode(kind: Text, textStr: "mychild"),
ContentNode(kind: Br)