mirror of
https://github.com/status-im/nim-drchaos.git
synced 2025-02-19 22:28:15 +00:00
fixes #7, minor cleanups
This commit is contained in:
parent
539b60661e
commit
449162b1b8
@ -1,5 +1,4 @@
|
||||
# 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
|
||||
@ -116,5 +115,6 @@ proc benchFuzzTarget =
|
||||
buf.setLen(x.len)
|
||||
copyMem(cstring(buf), cstring(x), x.len)
|
||||
discard LLVMFuzzerCustomMutator(cast[ptr UncheckedArray[byte]](cstring(buf)), buf.len, 4096, 1600568261)
|
||||
#discard LLVMFuzzerTestOneInput(cast[ptr UncheckedArray[byte]](cstring(buf)), buf.len)
|
||||
|
||||
benchFuzzTarget()
|
||||
|
@ -1 +1,2 @@
|
||||
--define: runFuzzTests
|
||||
--define: fuzzerStandalone
|
||||
|
@ -1,11 +1,5 @@
|
||||
--cc: clang
|
||||
--define: useMalloc
|
||||
@if not fuzzerStandalone:
|
||||
--noMain: on
|
||||
--define: noSignalHandler
|
||||
--passC: "-fsanitize=fuzzer"
|
||||
--passL: "-fsanitize=fuzzer"
|
||||
@end
|
||||
--passC: "-fsanitize=address,undefined"
|
||||
--passL: "-fsanitize=address,undefined"
|
||||
#--define: release
|
||||
|
@ -24,9 +24,9 @@ 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/", args = "", lang = "c") =
|
||||
buildBinary name, srcDir, "-d:release"
|
||||
# Should ideally run inside build/ because of the artifacts, but cd doesn't work!
|
||||
exec "build/" & name & " -max_total_time=3 -runs=10000" & args
|
||||
buildBinary name, srcDir, "--mm:arc -d:release"
|
||||
withDir("build/"):
|
||||
exec "./" & name & " -max_total_time=3 -runs=10000" & args
|
||||
|
||||
task testDrChaosExamples, "Build & run Dr. Chaos examples":
|
||||
let examples = @["fuzz_graph"]
|
||||
|
@ -40,17 +40,17 @@ proc runMutator*[T: tuple|object](x: var T; sizeIncreaseHint: int; enforceChange
|
||||
proc runMutator*[T](x: var ref T; sizeIncreaseHint: int; enforceChanges: bool; r: var Rand)
|
||||
proc runMutator*[S, T](x: var array[S, T]; sizeIncreaseHint: int; enforceChanges: bool; r: var Rand)
|
||||
|
||||
proc flipBit*(bytes: ptr UncheckedArray[byte]; len: int; r: var Rand) =
|
||||
## Flips random bit in the buffer.
|
||||
let bit = rand(r, len * 8 - 1)
|
||||
bytes[bit div 8] = bytes[bit div 8] xor (1'u8 shl (bit mod 8))
|
||||
|
||||
proc flipBit*[T](value: T; r: var Rand): T =
|
||||
## Flips random bit in the value.
|
||||
result = value
|
||||
flipBit(cast[ptr UncheckedArray[byte]](addr result), sizeof(T), r)
|
||||
|
||||
when defined(fuzzerStandalone):
|
||||
proc flipBit*(bytes: ptr UncheckedArray[byte]; len: int; r: var Rand) =
|
||||
## Flips random bit in the buffer.
|
||||
let bit = rand(r, len * 8 - 1)
|
||||
bytes[bit div 8] = bytes[bit div 8] xor (1'u8 shl (bit mod 8))
|
||||
|
||||
proc flipBit*[T](value: T; r: var Rand): T =
|
||||
## Flips random bit in the value.
|
||||
result = value
|
||||
flipBit(cast[ptr UncheckedArray[byte]](addr result), sizeof(T), r)
|
||||
|
||||
proc mutateValue*[T](value: T; r: var Rand): T =
|
||||
flipBit(value, r)
|
||||
else:
|
||||
@ -88,29 +88,80 @@ proc mutateSeq*[T](value: var seq[T]; previous: seq[T]; userMax, sizeIncreaseHin
|
||||
runMutator(value[index], remainingSize, true, r)
|
||||
result = value != previous # runMutator item may still fail to generate a new mutation.
|
||||
|
||||
proc mutateByteSizedSeq*[T: ByteSized and not range](value: sink seq[T]; userMax, sizeIncreaseHint: int;
|
||||
r: var Rand): seq[T] =
|
||||
if r.rand(0..20) == 0:
|
||||
result = @[]
|
||||
else:
|
||||
let oldSize = value.len
|
||||
result = value
|
||||
result.setLen(max(1, oldSize + r.rand(sizeIncreaseHint)))
|
||||
result.setLen(mutate(cast[ptr UncheckedArray[byte]](addr result[0]), oldSize, result.len))
|
||||
when T is bool:
|
||||
# Fix bool values so UBSan stops complaining.
|
||||
for i in 0..<result.len: result[i] = cast[seq[byte]](result)[i] != 0.byte
|
||||
elif T is range:
|
||||
for i in 0..<result.len: result[i] = clamp(result[i], low(T), high(T))
|
||||
when defined(fuzzerStandalone):
|
||||
proc delete(x: var string, i: Natural) {.noSideEffect.} =
|
||||
let xl = x.len
|
||||
for j in i.int..xl-2: x[j] = x[j+1]
|
||||
setLen(x, xl-1)
|
||||
|
||||
proc mutateString*(value: sink string; userMax, sizeIncreaseHint: int; r: var Rand): string =
|
||||
if r.rand(0..20) == 0:
|
||||
result = ""
|
||||
else:
|
||||
let oldSize = value.len
|
||||
proc insert(x: var string, item: char, i = 0.Natural) {.noSideEffect.} =
|
||||
let xl = x.len
|
||||
setLen(x, xl+1)
|
||||
var j = xl-1
|
||||
while j >= i:
|
||||
x[j+1] = x[j]
|
||||
dec(j)
|
||||
x[i] = item
|
||||
|
||||
proc mutateString(value: sink string; userMax, sizeIncreaseHint: int; r: var Rand): string =
|
||||
result = value
|
||||
result.setLen(max(1, oldSize + r.rand(sizeIncreaseHint)))
|
||||
result.setLen(mutate(cast[ptr UncheckedArray[byte]](addr result[0]), oldSize, result.len))
|
||||
while result.len != 0 and r.rand(bool):
|
||||
result.delete(rand(r, result.high))
|
||||
while sizeIncreaseHint > 0 and result.len < sizeIncreaseHint and r.rand(bool):
|
||||
let index = rand(r, result.len)
|
||||
result.insert(r.rand(char), index)
|
||||
if result != value:
|
||||
return result
|
||||
if result.len == 0:
|
||||
result.add(r.rand(char))
|
||||
return result
|
||||
else:
|
||||
flipBit(cast[ptr UncheckedArray[uint8]](addr result[0]), result.len, r)
|
||||
|
||||
proc mutateByteSizedSeq*[T: ByteSized and not range](value: sink seq[T]; userMax, sizeIncreaseHint: int;
|
||||
r: var Rand): seq[T] =
|
||||
result = value
|
||||
while result.len != 0 and r.rand(bool):
|
||||
result.delete(rand(r, result.high))
|
||||
while sizeIncreaseHint > 0 and result.len < sizeIncreaseHint and r.rand(bool):
|
||||
let index = rand(r, result.len)
|
||||
result.insert(r.rand(T), index)
|
||||
if result != value:
|
||||
return result
|
||||
if result.len == 0:
|
||||
result.add(r.rand(T))
|
||||
return result
|
||||
else:
|
||||
flipBit(cast[ptr UncheckedArray[uint8]](addr result[0]), result.len, r)
|
||||
when T is bool:
|
||||
# Fix bool values so UBSan stops complaining.
|
||||
for i in 0..<result.len: result[i] = cast[seq[byte]](result)[i] != 0.byte
|
||||
elif T is range:
|
||||
for i in 0..<result.len: result[i] = clamp(result[i], low(T), high(T))
|
||||
else:
|
||||
proc mutateByteSizedSeq*[T: ByteSized and not range](value: sink seq[T]; userMax, sizeIncreaseHint: int;
|
||||
r: var Rand): seq[T] =
|
||||
if r.rand(0..20) == 0:
|
||||
result = @[]
|
||||
else:
|
||||
let oldSize = value.len
|
||||
result = value
|
||||
result.setLen(max(1, oldSize + r.rand(sizeIncreaseHint)))
|
||||
result.setLen(mutate(cast[ptr UncheckedArray[byte]](addr result[0]), oldSize, result.len))
|
||||
when T is bool:
|
||||
# Fix bool values so UBSan stops complaining.
|
||||
for i in 0..<result.len: result[i] = cast[seq[byte]](result)[i] != 0.byte
|
||||
elif T is range:
|
||||
for i in 0..<result.len: result[i] = clamp(result[i], low(T), high(T))
|
||||
|
||||
proc mutateString*(value: sink string; userMax, sizeIncreaseHint: int; r: var Rand): string =
|
||||
if r.rand(0..20) == 0:
|
||||
result = ""
|
||||
else:
|
||||
let oldSize = value.len
|
||||
result = value
|
||||
result.setLen(max(1, oldSize + r.rand(sizeIncreaseHint)))
|
||||
result.setLen(mutate(cast[ptr UncheckedArray[byte]](addr result[0]), oldSize, result.len))
|
||||
|
||||
proc mutateUtf8String*(value: sink string; userMax, sizeIncreaseHint: int; r: var Rand): string {.inline.} =
|
||||
result = mutateString(value, userMax, sizeIncreaseHint, r)
|
||||
|
Loading…
x
Reference in New Issue
Block a user