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 # Then run: perf record -e cycles:pp --call-graph dwarf ./bench_graph
include examples/fuzz_graph include examples/fuzz_graph

View File

@ -2,10 +2,10 @@ mode = ScriptMode.Verbose
version = "0.1.0" version = "0.1.0"
author = "Dr. Chaos Team" 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" license = "MIT"
srcDir = "." srcDir = "."
skipDirs = @["tests", "benchmarks", "examples"] skipDirs = @["tests", "benchmarks", "examples", "experiments"]
requires "nim >= 1.4.0" 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" 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" buildBinary name, srcDir, "--mm:arc -d:danger"
withDir("build/"): 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": task testDrChaosExamples, "Build & run Dr. Chaos examples":
let examples = @["fuzz_graph", "fuzz_tree"] let examples = @["fuzz_graph"]
for ex in examples: for ex in examples:
test ex, "examples/" test ex, "examples/"
task testDrChaos, "Build & run Dr. Chaos tests": task testDrChaos, "Build & run Dr. Chaos tests":
for filePath in listFiles("tests/"): for filePath in listFiles("tests/"):
if filePath[^4..^1] == ".nim": 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": task testDrChaosNoCrash, "Build & run Dr. Chaos tests that should not crash":
for filePath in listFiles("tests/time_limited/"): for filePath in listFiles("tests/no_crash/"):
if filePath[^4..^1] == ".nim": 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": task test, "Run basic tests":
#testDrChaosTask() testDrChaosTask()
task testAll, "Run all tests": task testAll, "Run all tests":
testDrChaosTask() testDrChaosTask()
testDrChaosTimedTask() testDrChaosNoCrash()

View File

@ -2,7 +2,7 @@ import std/[random, macros, setutils, enumutils, typetraits, options]
import common, private/[sampler, utf8fix] import common, private/[sampler, utf8fix]
when not defined(fuzzerStandalone): when not defined(fuzzerStandalone):
proc initialize(): cint {.exportc: "LLVMFuzzerInitialize".} = proc LLVMFuzzerInitialize(): cint {.exportc.} =
{.emit: "N_CDECL(void, NimMain)(void); NimMain();".} {.emit: "N_CDECL(void, NimMain)(void); NimMain();".}
proc mutate(data: ptr UncheckedArray[byte], len, maxLen: int): int {. 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): when defined(runFuzzTests):
const const
MaxNodes = 8 # User defined, statically limits number of nodes. 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) = proc mutate(value: var seq[NodeIdx]; sizeIncreaseHint: int; enforceChanges: bool; r: var Rand) =
repeatMutateInplace(mutateSeq(value, tmp, MaxEdges, sizeIncreaseHint, r)) 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) =
proc postProcess[T: SomeNumber](x: var seq[Node[T]]; r: var Rand) = #if x.len >= 8:
if x.len >= 8: #x[0].data = 63
x[0].data = 63 #x[1].data = 3
x[1].data = 3 #x[2].data = -56
x[2].data = -56 #x[3].data = 100
x[3].data = 100 #x[4].data = -100
x[4].data = -100 #x[5].data = -78
x[5].data = -78 #x[6].data = 46
x[6].data = 46 #x[7].data = 120
x[7].data = 120
func fuzzTarget(x: Graph[int8]) = func fuzzTarget(x: Graph[int8]) =
when defined(dumpFuzzInput): debugEcho(x) 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 of Text: return a.textStr == b.textStr
func fuzzTarget(x: ContentNode) = func fuzzTarget(x: ContentNode) =
when defined(dumpFuzzInput): debugEcho(x)
let data = ContentNode(kind: P, pChildren: @[ let data = ContentNode(kind: P, pChildren: @[
ContentNode(kind: Text, textStr: "mychild"), ContentNode(kind: Text, textStr: "mychild"),
ContentNode(kind: Br) ContentNode(kind: Br)