aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--prog/any.go9
-rw-r--r--prog/any_test.go2
-rw-r--r--prog/mutation.go11
-rw-r--r--prog/test/fuzz_test.go7
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)]