github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/signal/signal.go (about) 1 // Copyright 2018 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 // Package signal provides types for working with feedback signal. 5 package signal 6 7 type ( 8 elemType uint64 9 prioType int8 10 ) 11 12 // Signal was hard to refactor when we enabled recvcheck. 13 type Signal map[elemType]prioType // nolint: recvcheck 14 15 func (s Signal) Len() int { 16 return len(s) 17 } 18 19 func (s Signal) Empty() bool { 20 return len(s) == 0 21 } 22 23 func (s Signal) Copy() Signal { 24 c := make(Signal, len(s)) 25 for e, p := range s { 26 c[e] = p 27 } 28 return c 29 } 30 31 func FromRaw(raw []uint64, prio uint8) Signal { 32 if len(raw) == 0 { 33 return nil 34 } 35 s := make(Signal, len(raw)) 36 for _, e := range raw { 37 s[elemType(e)] = prioType(prio) 38 } 39 return s 40 } 41 42 func (s Signal) DiffRaw(raw []uint64, prio uint8) Signal { 43 var res Signal 44 for _, e := range raw { 45 if p, ok := s[elemType(e)]; ok && p >= prioType(prio) { 46 continue 47 } 48 if res == nil { 49 res = make(Signal) 50 } 51 res[elemType(e)] = prioType(prio) 52 } 53 return res 54 } 55 56 func (s Signal) IntersectsWith(other Signal) bool { 57 for e, p := range s { 58 if p1, ok := other[e]; ok && p1 >= p { 59 return true 60 } 61 } 62 return false 63 } 64 65 func (s Signal) Intersection(s1 Signal) Signal { 66 if s1.Empty() { 67 return nil 68 } 69 res := make(Signal, len(s)) 70 for e, p := range s { 71 if p1, ok := s1[e]; ok && p1 >= p { 72 res[e] = p 73 } 74 } 75 return res 76 } 77 78 func (s *Signal) Merge(s1 Signal) { 79 if s1.Empty() { 80 return 81 } 82 s0 := *s 83 if s0 == nil { 84 s0 = make(Signal, len(s1)) 85 *s = s0 86 } 87 for e, p1 := range s1 { 88 if p, ok := s0[e]; !ok || p < p1 { 89 s0[e] = p1 90 } 91 } 92 } 93 94 func (s Signal) ToRaw() []uint64 { 95 var raw []uint64 96 for e := range s { 97 raw = append(raw, uint64(e)) 98 } 99 return raw 100 } 101 102 type Context struct { 103 Signal Signal 104 Context interface{} 105 } 106 107 func Minimize(corpus []Context) []interface{} { 108 type ContextPrio struct { 109 prio prioType 110 idx int 111 } 112 covered := make(map[elemType]ContextPrio) 113 for i, inp := range corpus { 114 for e, p := range inp.Signal { 115 if prev, ok := covered[e]; !ok || p > prev.prio { 116 covered[e] = ContextPrio{ 117 prio: p, 118 idx: i, 119 } 120 } 121 } 122 } 123 indices := make(map[int]struct{}, len(corpus)) 124 for _, cp := range covered { 125 indices[cp.idx] = struct{}{} 126 } 127 result := make([]interface{}, 0, len(indices)) 128 for idx := range indices { 129 result = append(result, corpus[idx].Context) 130 } 131 return result 132 }