mirror of
https://github.com/status-im/nim-drchaos.git
synced 2025-02-21 07:08:14 +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.
|
# 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.
|
# 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
|
# 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
|
||||||
@ -116,5 +115,6 @@ proc benchFuzzTarget =
|
|||||||
buf.setLen(x.len)
|
buf.setLen(x.len)
|
||||||
copyMem(cstring(buf), cstring(x), x.len)
|
copyMem(cstring(buf), cstring(x), x.len)
|
||||||
discard LLVMFuzzerCustomMutator(cast[ptr UncheckedArray[byte]](cstring(buf)), buf.len, 4096, 1600568261)
|
discard LLVMFuzzerCustomMutator(cast[ptr UncheckedArray[byte]](cstring(buf)), buf.len, 4096, 1600568261)
|
||||||
|
#discard LLVMFuzzerTestOneInput(cast[ptr UncheckedArray[byte]](cstring(buf)), buf.len)
|
||||||
|
|
||||||
benchFuzzTarget()
|
benchFuzzTarget()
|
||||||
|
@ -1 +1,2 @@
|
|||||||
--define: runFuzzTests
|
--define: runFuzzTests
|
||||||
|
--define: fuzzerStandalone
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
--cc: clang
|
--cc: clang
|
||||||
--define: useMalloc
|
--define: useMalloc
|
||||||
@if not fuzzerStandalone:
|
|
||||||
--noMain: on
|
|
||||||
--define: noSignalHandler
|
|
||||||
--passC: "-fsanitize=fuzzer"
|
|
||||||
--passL: "-fsanitize=fuzzer"
|
|
||||||
@end
|
|
||||||
--passC: "-fsanitize=address,undefined"
|
--passC: "-fsanitize=address,undefined"
|
||||||
--passL: "-fsanitize=address,undefined"
|
--passL: "-fsanitize=address,undefined"
|
||||||
#--define: release
|
#--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"
|
exec "nim " & lang & " --out:build/" & name & " " & extra_params & " " & srcDir & name & ".nim"
|
||||||
|
|
||||||
proc test(name: string, srcDir = "tests/", args = "", lang = "c") =
|
proc test(name: string, srcDir = "tests/", args = "", lang = "c") =
|
||||||
buildBinary name, srcDir, "-d:release"
|
buildBinary name, srcDir, "--mm:arc -d:release"
|
||||||
# Should ideally run inside build/ because of the artifacts, but cd doesn't work!
|
withDir("build/"):
|
||||||
exec "build/" & name & " -max_total_time=3 -runs=10000" & args
|
exec "./" & name & " -max_total_time=3 -runs=10000" & args
|
||||||
|
|
||||||
task testDrChaosExamples, "Build & run Dr. Chaos examples":
|
task testDrChaosExamples, "Build & run Dr. Chaos examples":
|
||||||
let examples = @["fuzz_graph"]
|
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*[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 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):
|
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 =
|
proc mutateValue*[T](value: T; r: var Rand): T =
|
||||||
flipBit(value, r)
|
flipBit(value, r)
|
||||||
else:
|
else:
|
||||||
@ -88,29 +88,80 @@ proc mutateSeq*[T](value: var seq[T]; previous: seq[T]; userMax, sizeIncreaseHin
|
|||||||
runMutator(value[index], remainingSize, true, r)
|
runMutator(value[index], remainingSize, true, r)
|
||||||
result = value != previous # runMutator item may still fail to generate a new mutation.
|
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;
|
when defined(fuzzerStandalone):
|
||||||
r: var Rand): seq[T] =
|
proc delete(x: var string, i: Natural) {.noSideEffect.} =
|
||||||
if r.rand(0..20) == 0:
|
let xl = x.len
|
||||||
result = @[]
|
for j in i.int..xl-2: x[j] = x[j+1]
|
||||||
else:
|
setLen(x, xl-1)
|
||||||
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 =
|
proc insert(x: var string, item: char, i = 0.Natural) {.noSideEffect.} =
|
||||||
if r.rand(0..20) == 0:
|
let xl = x.len
|
||||||
result = ""
|
setLen(x, xl+1)
|
||||||
else:
|
var j = xl-1
|
||||||
let oldSize = value.len
|
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 = value
|
||||||
result.setLen(max(1, oldSize + r.rand(sizeIncreaseHint)))
|
while result.len != 0 and r.rand(bool):
|
||||||
result.setLen(mutate(cast[ptr UncheckedArray[byte]](addr result[0]), oldSize, result.len))
|
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.} =
|
proc mutateUtf8String*(value: sink string; userMax, sizeIncreaseHint: int; r: var Rand): string {.inline.} =
|
||||||
result = mutateString(value, userMax, sizeIncreaseHint, r)
|
result = mutateString(value, userMax, sizeIncreaseHint, r)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user