mirror of
https://github.com/reactos/syzkaller.git
synced 2024-12-18 00:58:10 +00:00
f7498af7af
Also mixin resource constructors and some signature of flags values for successful calls into fallback coverage.
194 lines
3.2 KiB
Go
194 lines
3.2 KiB
Go
// Copyright 2018 syzkaller project authors. All rights reserved.
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
// Package signal provides types for working with feedback signal.
|
|
package signal
|
|
|
|
import (
|
|
"sort"
|
|
)
|
|
|
|
type (
|
|
elemType uint32
|
|
prioType int8
|
|
)
|
|
|
|
type Signal map[elemType]prioType
|
|
|
|
type Serial struct {
|
|
Elems []elemType
|
|
Prios []prioType
|
|
}
|
|
|
|
func (s Signal) Len() int {
|
|
return len(s)
|
|
}
|
|
|
|
func (s Signal) Empty() bool {
|
|
return len(s) == 0
|
|
}
|
|
|
|
func (s Signal) Copy() Signal {
|
|
c := make(Signal, len(s))
|
|
for e, p := range s {
|
|
c[e] = p
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (s *Signal) Split(n int) Signal {
|
|
if s.Empty() {
|
|
return nil
|
|
}
|
|
c := make(Signal, n)
|
|
for e, p := range *s {
|
|
delete(*s, e)
|
|
c[e] = p
|
|
n--
|
|
if n == 0 {
|
|
break
|
|
}
|
|
}
|
|
if len(*s) == 0 {
|
|
*s = nil
|
|
}
|
|
return c
|
|
}
|
|
|
|
func FromRaw(raw []uint32, prio uint8) Signal {
|
|
if len(raw) == 0 {
|
|
return nil
|
|
}
|
|
s := make(Signal, len(raw))
|
|
for _, e := range raw {
|
|
s[elemType(e)] = prioType(prio)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s Signal) Serialize() Serial {
|
|
if s.Empty() {
|
|
return Serial{}
|
|
}
|
|
res := Serial{
|
|
Elems: make([]elemType, len(s)),
|
|
Prios: make([]prioType, len(s)),
|
|
}
|
|
i := 0
|
|
for e, p := range s {
|
|
res.Elems[i] = e
|
|
res.Prios[i] = p
|
|
i++
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (ser Serial) Deserialize() Signal {
|
|
if len(ser.Elems) != len(ser.Prios) {
|
|
panic("corrupted Serial")
|
|
}
|
|
if len(ser.Elems) == 0 {
|
|
return nil
|
|
}
|
|
s := make(Signal, len(ser.Elems))
|
|
for i, e := range ser.Elems {
|
|
s[e] = ser.Prios[i]
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s Signal) Diff(s1 Signal) Signal {
|
|
if s1.Empty() {
|
|
return nil
|
|
}
|
|
var res Signal
|
|
for e, p1 := range s1 {
|
|
if p, ok := s[e]; ok && p >= p1 {
|
|
continue
|
|
}
|
|
if res == nil {
|
|
res = make(Signal)
|
|
}
|
|
res[e] = p1
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (s Signal) DiffRaw(raw []uint32, prio uint8) Signal {
|
|
var res Signal
|
|
for _, e := range raw {
|
|
if p, ok := s[elemType(e)]; ok && p >= prioType(prio) {
|
|
continue
|
|
}
|
|
if res == nil {
|
|
res = make(Signal)
|
|
}
|
|
res[elemType(e)] = prioType(prio)
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (s Signal) Intersection(s1 Signal) Signal {
|
|
if s1.Empty() {
|
|
return nil
|
|
}
|
|
res := make(Signal, len(s))
|
|
for e, p := range s {
|
|
if p1, ok := s1[e]; ok && p1 >= p {
|
|
res[e] = p
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (s *Signal) Merge(s1 Signal) {
|
|
if s1.Empty() {
|
|
return
|
|
}
|
|
s0 := *s
|
|
if s0 == nil {
|
|
s0 = make(Signal, len(s1))
|
|
*s = s0
|
|
}
|
|
for e, p1 := range s1 {
|
|
if p, ok := s0[e]; !ok || p < p1 {
|
|
s0[e] = p1
|
|
}
|
|
}
|
|
}
|
|
|
|
type Context struct {
|
|
Signal Signal
|
|
Context interface{}
|
|
}
|
|
|
|
func Minimize(corpus []Context) []interface{} {
|
|
sort.Slice(corpus, func(i, j int) bool {
|
|
return corpus[i].Signal.Len() > corpus[j].Signal.Len()
|
|
})
|
|
type ContextPrio struct {
|
|
prio prioType
|
|
idx int
|
|
}
|
|
covered := make(map[elemType]ContextPrio)
|
|
for i, inp := range corpus {
|
|
for e, p := range inp.Signal {
|
|
if prev, ok := covered[e]; !ok || p > prev.prio {
|
|
covered[e] = ContextPrio{
|
|
prio: p,
|
|
idx: i,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
indices := make(map[int]struct{}, len(corpus))
|
|
for _, cp := range covered {
|
|
indices[cp.idx] = struct{}{}
|
|
}
|
|
result := make([]interface{}, 0, len(indices))
|
|
for idx := range indices {
|
|
result = append(result, corpus[idx].Context)
|
|
}
|
|
return result
|
|
}
|