Skip to content

Commit f4f137a

Browse files
author
Jay Conrod
committed
[dev.fuzz] internal/fuzz: only reconstruct inputs when needed on RPC return
If the fuzz RPC finds no error and no new coverage, there's no point in reconstructing the last value. If the minimize RPC does not succeed in minimizing, either because the error can't be reproduced, or new coverage can't be reproduced, or a new error is found with the input, don't marshal or unmarshal the input. Just use the original. Change-Id: I3b0f89b8656a2b36066d82efefac0fff4a61fbee Reviewed-on: https://go-review.googlesource.com/c/go/+/347233 Trust: Jay Conrod <[email protected]> Trust: Katie Hockman <[email protected]> Run-TryBot: Jay Conrod <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Katie Hockman <[email protected]>
1 parent e9674e5 commit f4f137a

File tree

1 file changed

+41
-25
lines changed

1 file changed

+41
-25
lines changed

src/internal/fuzz/worker.go

+41-25
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,9 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m
775775
// to shared memory after completing minimization. If the worker terminates
776776
// unexpectedly before then, the coordinator will use the original input.
777777
resp.Success, err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit, args.KeepCoverage)
778-
writeToMem(vals, mem)
778+
if resp.Success {
779+
writeToMem(vals, mem)
780+
}
779781
if err != nil {
780782
resp.Err = err.Error()
781783
} else if resp.Success {
@@ -1008,21 +1010,31 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args
10081010
}
10091011
mem.setValue(inp)
10101012
wc.memMu <- mem
1011-
defer func() { wc.memMu <- mem }()
10121013

10131014
c := call{Minimize: &args}
10141015
callErr := wc.callLocked(ctx, c, &resp)
10151016
mem, ok = <-wc.memMu
10161017
if !ok {
10171018
return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed
10181019
}
1019-
entryOut.Data = mem.valueCopy()
1020-
h := sha256.Sum256(entryOut.Data)
1021-
name := fmt.Sprintf("%x", h[:4])
1022-
entryOut.Name = name
1023-
entryOut.Parent = entryIn.Parent
1024-
entryOut.Generation = entryIn.Generation
1020+
defer func() { wc.memMu <- mem }()
10251021
resp.Count = mem.header().count
1022+
if resp.Success {
1023+
entryOut.Data = mem.valueCopy()
1024+
entryOut.Values, err = unmarshalCorpusFile(entryOut.Data)
1025+
h := sha256.Sum256(entryOut.Data)
1026+
name := fmt.Sprintf("%x", h[:4])
1027+
entryOut.Name = name
1028+
entryOut.Parent = entryIn.Parent
1029+
entryOut.Generation = entryIn.Generation
1030+
if err != nil {
1031+
panic(fmt.Sprintf("workerClient.minimize unmarshaling minimized value: %v", err))
1032+
}
1033+
} else {
1034+
// Did not minimize, but the original input may still be interesting,
1035+
// for example, if there was an error.
1036+
entryOut = entryIn
1037+
}
10261038

10271039
return entryOut, resp, callErr
10281040
}
@@ -1056,23 +1068,27 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz
10561068
if !bytes.Equal(inp, mem.valueRef()) {
10571069
panic("workerServer.fuzz modified input")
10581070
}
1059-
valuesOut, err := unmarshalCorpusFile(inp)
1060-
if err != nil {
1061-
panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err))
1062-
}
1063-
wc.m.r.restore(mem.header().randState, mem.header().randInc)
1064-
for i := int64(0); i < mem.header().count; i++ {
1065-
wc.m.mutate(valuesOut, cap(mem.valueRef()))
1066-
}
1067-
dataOut := marshalCorpusFile(valuesOut...)
1068-
1069-
h := sha256.Sum256(dataOut)
1070-
name := fmt.Sprintf("%x", h[:4])
1071-
entryOut = CorpusEntry{
1072-
Name: name,
1073-
Parent: entryIn.Name,
1074-
Data: dataOut,
1075-
Generation: entryIn.Generation + 1,
1071+
needEntryOut := callErr != nil || resp.Err != "" ||
1072+
(!args.CoverageOnly && resp.CoverageData != nil)
1073+
if needEntryOut {
1074+
valuesOut, err := unmarshalCorpusFile(inp)
1075+
if err != nil {
1076+
panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err))
1077+
}
1078+
wc.m.r.restore(mem.header().randState, mem.header().randInc)
1079+
for i := int64(0); i < mem.header().count; i++ {
1080+
wc.m.mutate(valuesOut, cap(mem.valueRef()))
1081+
}
1082+
dataOut := marshalCorpusFile(valuesOut...)
1083+
1084+
h := sha256.Sum256(dataOut)
1085+
name := fmt.Sprintf("%x", h[:4])
1086+
entryOut = CorpusEntry{
1087+
Name: name,
1088+
Parent: entryIn.Name,
1089+
Data: dataOut,
1090+
Generation: entryIn.Generation + 1,
1091+
}
10761092
}
10771093

10781094
return entryOut, resp, callErr

0 commit comments

Comments
 (0)