diff options
| -rw-r--r-- | prog/any.go | 9 | ||||
| -rw-r--r-- | prog/any_test.go | 2 | ||||
| -rw-r--r-- | prog/mutation.go | 11 | ||||
| -rw-r--r-- | prog/test/fuzz_test.go | 7 |
4 files changed, 22 insertions, 7 deletions
diff --git a/prog/any.go b/prog/any.go index a5106683d..a9d275b1d 100644 --- a/prog/any.go +++ b/prog/any.go @@ -60,11 +60,16 @@ func (target *Target) isAnyPtr(typ Type) bool { return ok && ptr.Elem == target.any.array } -func (p *Prog) complexPtrs() (res []*PointerArg) { +type complexPtr struct { + arg *PointerArg + call *Call +} + +func (p *Prog) complexPtrs() (res []complexPtr) { for _, c := range p.Calls { ForeachArg(c, func(arg Arg, ctx *ArgCtx) { if ptrArg, ok := arg.(*PointerArg); ok && p.Target.isComplexPtr(ptrArg) { - res = append(res, ptrArg) + res = append(res, complexPtr{ptrArg, c}) ctx.Stop = true } }) diff --git a/prog/any_test.go b/prog/any_test.go index 2d08d92fb..36484aa90 100644 --- a/prog/any_test.go +++ b/prog/any_test.go @@ -28,7 +28,7 @@ func TestIsComplexPtr(t *testing.T) { calls := r.generateParticularCall(s, meta) p := &Prog{Target: target, Calls: calls} for _, arg := range p.complexPtrs() { - compl[arg.Res.Type().String()] = true + compl[arg.arg.Res.Type().String()] = true } } } diff --git a/prog/mutation.go b/prog/mutation.go index 0181aaa43..022ebce62 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -93,12 +93,12 @@ func (ctx *mutator) squashAny() bool { return false } ptr := complexPtrs[r.Intn(len(complexPtrs))] - if !p.Target.isAnyPtr(ptr.Type()) { - p.Target.squashPtr(ptr) + if !p.Target.isAnyPtr(ptr.arg.Type()) { + p.Target.squashPtr(ptr.arg) } var blobs []*DataArg var bases []*PointerArg - ForeachSubArg(ptr, func(arg Arg, ctx *ArgCtx) { + ForeachSubArg(ptr.arg, func(arg Arg, ctx *ArgCtx) { if data, ok := arg.(*DataArg); ok && arg.Dir() != DirOut { blobs = append(blobs, data) bases = append(bases, ctx.Base) @@ -107,6 +107,10 @@ func (ctx *mutator) squashAny() bool { if len(blobs) == 0 { return false } + // Note: we need to call analyze before we mutate the blob. + // After mutation the blob can grow out of bounds of the data area + // and analyze will crash with out-of-bounds access while marking existing allocations. + s := analyze(ctx.ct, ctx.corpus, p, ptr.call) // TODO(dvyukov): we probably want special mutation for ANY. // E.g. merging adjacent ANYBLOBs (we don't create them, // but they can appear in future); or replacing ANYRES @@ -118,7 +122,6 @@ func (ctx *mutator) squashAny() bool { arg.data = mutateData(r, arg.Data(), 0, maxBlobLen) // Update base pointer if size has increased. if baseSize < base.Res.Size() { - s := analyze(ctx.ct, ctx.corpus, p, p.Calls[0]) newArg := r.allocAddr(s, base.Type(), base.Dir(), base.Res.Size(), base.Res) *base = *newArg } diff --git a/prog/test/fuzz_test.go b/prog/test/fuzz_test.go index 3774b2fba..f01905ea3 100644 --- a/prog/test/fuzz_test.go +++ b/prog/test/fuzz_test.go @@ -23,6 +23,13 @@ mutate7() mutate8() `, `E`, + ` +test$str0(&(0x7f0000ffffd5)=ANY=[0]) +test$res2() +test$res2() +test$res2() +test$res2() +`, } { t.Logf("test #%v: %q", i, data) inp := []byte(data)[:len(data):len(data)] |
