aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/cover/canonicalizer_test.go
diff options
context:
space:
mode:
authorLiz Prucka <lizprucka@google.com>2023-05-12 17:04:20 -0500
committerAleksandr Nogikh <wp32pw@gmail.com>2023-05-25 10:44:34 +0200
commit51e154a0c54cd90de8e7f061a462420c69a58787 (patch)
tree2fbb542d1a3a876bff03004c6c5b3392c099a922 /pkg/cover/canonicalizer_test.go
parent4bce1a3e705a8b62de8194bdb28f5eef89c8feec (diff)
pkg/cover: disable canonicalization when modules change
Added a check to make sure instance's modules match the canonical modules. If not, abort fuzzing.
Diffstat (limited to 'pkg/cover/canonicalizer_test.go')
-rw-r--r--pkg/cover/canonicalizer_test.go132
1 files changed, 64 insertions, 68 deletions
diff --git a/pkg/cover/canonicalizer_test.go b/pkg/cover/canonicalizer_test.go
index 4d004aa32..8965b45d9 100644
--- a/pkg/cover/canonicalizer_test.go
+++ b/pkg/cover/canonicalizer_test.go
@@ -7,6 +7,7 @@ package cover_test
import (
"fmt"
+ "reflect"
"strconv"
"testing"
@@ -22,37 +23,38 @@ type RPCServer struct {
type Fuzzer struct {
instModules *cover.CanonicalizerInstance
+ testCov []uint32
+ goalOut []uint32
}
+type canonicalizeValue int
+
+const (
+ Canonicalize canonicalizeValue = iota
+ Decanonicalize
+)
+
// Confirms there is no change to coverage if modules aren't instantiated.
func TestNilModules(t *testing.T) {
serv := &RPCServer{
fuzzers: make(map[string]*Fuzzer),
}
- serv.Connect("f1", nil)
- serv.Connect("f2", nil)
+ serv.connect("f1", nil)
+ serv.connect("f2", nil)
- testCov := []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- goalOut := []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
+ serv.fuzzers["f1"].testCov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
+ serv.fuzzers["f1"].goalOut = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- for name, fuzzer := range serv.fuzzers {
- fuzzer.instModules.Canonicalize(testCov)
- for idx, cov := range testCov {
- if cov != goalOut[idx] {
- failMsg := fmt.Errorf("fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
- name, goalOut[idx], cov)
- t.Fatalf("failed in canonicalization. %v", failMsg)
- }
- }
+ serv.fuzzers["f2"].testCov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
+ serv.fuzzers["f2"].goalOut = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
+ if err := serv.runTest(Canonicalize); err != "" {
+ t.Fatalf("failed in canonicalization: %v", err)
+ }
- fuzzer.instModules.Decanonicalize(testCov)
- for idx, cov := range testCov {
- if cov != goalOut[idx] {
- failMsg := fmt.Errorf("fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
- name, goalOut[idx], cov)
- t.Fatalf("failed in decanonicalization. %v", failMsg)
- }
- }
+ serv.fuzzers["f1"].goalOut = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
+ serv.fuzzers["f2"].goalOut = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
+ if err := serv.runTest(Decanonicalize); err != "" {
+ t.Fatalf("failed in decanonicalization: %v", err)
}
}
@@ -63,76 +65,58 @@ func TestModules(t *testing.T) {
}
// Create modules at the specified address offsets.
- var f1Modules, f2Modules []host.KernelModule
f1ModuleAddresses := []uint64{0x00015000, 0x00020000, 0x00030000, 0x00040000, 0x00045000}
f1ModuleSizes := []uint64{0x5000, 0x5000, 0x10000, 0x5000, 0x10000}
+ f1Modules := initModules(f1ModuleAddresses, f1ModuleSizes)
+ serv.connect("f1", f1Modules)
f2ModuleAddresses := []uint64{0x00015000, 0x00040000, 0x00045000, 0x00020000, 0x00030000}
f2ModuleSizes := []uint64{0x5000, 0x5000, 0x10000, 0x5000, 0x10000}
- for idx, address := range f1ModuleAddresses {
- f1Modules = append(f1Modules, host.KernelModule{
- Name: strconv.FormatInt(int64(idx), 10),
- Addr: address,
- Size: f1ModuleSizes[idx],
- })
- }
- for idx, address := range f2ModuleAddresses {
- f2Modules = append(f2Modules, host.KernelModule{
- Name: strconv.FormatInt(int64(idx), 10),
- Addr: address,
- Size: f2ModuleSizes[idx],
- })
- }
-
- serv.Connect("f1", f1Modules)
- serv.Connect("f2", f2Modules)
-
- testCov := make(map[string][]uint32)
- goalOutCanonical := make(map[string][]uint32)
- goalOutDecanonical := make(map[string][]uint32)
+ f2Modules := initModules(f2ModuleAddresses, f2ModuleSizes)
+ serv.connect("f2", f2Modules)
// f1 is the "canonical" fuzzer as it is first one instantiated.
// This means that all coverage output should be the same as the inputs.
- testCov["f1"] = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
- 0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
- goalOutCanonical["f1"] = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
+ serv.fuzzers["f1"].testCov = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
- goalOutDecanonical["f1"] = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
+ serv.fuzzers["f1"].goalOut = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
// The modules addresss are inverted between: (2 and 4), (3 and 5),
// affecting the output canonical coverage values in these ranges.
- testCov["f2"] = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
+ serv.fuzzers["f2"].testCov = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
- goalOutCanonical["f2"] = []uint32{0x00010000, 0x00015000, 0x00040000, 0x00025000, 0x00045000,
+ serv.fuzzers["f2"].goalOut = []uint32{0x00010000, 0x00015000, 0x00040000, 0x00025000, 0x00045000,
0x0004a000, 0x00020000, 0x00030000, 0x0003b000, 0x00055000}
- goalOutDecanonical["f2"] = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
+ if err := serv.runTest(Canonicalize); err != "" {
+ t.Fatalf("failed in canonicalization: %v", err)
+ }
+
+ serv.fuzzers["f1"].goalOut = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
+ serv.fuzzers["f2"].goalOut = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
+ 0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
+ if err := serv.runTest(Decanonicalize); err != "" {
+ t.Fatalf("failed in decanonicalization: %v", err)
+ }
+}
+func (serv *RPCServer) runTest(val canonicalizeValue) string {
for name, fuzzer := range serv.fuzzers {
- // Test address conversion from instance to canonical.
- fuzzer.instModules.Canonicalize(testCov[name])
- for idx, cov := range testCov[name] {
- if cov != goalOutCanonical[name][idx] {
- failMsg := fmt.Errorf("fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
- name, goalOutCanonical[name][idx], cov)
- t.Fatalf("failed in canonicalization. %v", failMsg)
- }
+ if val == Canonicalize {
+ fuzzer.instModules.Canonicalize(fuzzer.testCov)
+ } else {
+ fuzzer.instModules.Decanonicalize(fuzzer.testCov)
}
-
- // Test address conversion from canonical to instance.
- fuzzer.instModules.Decanonicalize(testCov[name])
- for idx, cov := range testCov[name] {
- if cov != goalOutDecanonical[name][idx] {
- failMsg := fmt.Errorf("fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
- name, goalOutDecanonical[name][idx], cov)
- t.Fatalf("failed in decanonicalization. %v", failMsg)
- }
+ if !reflect.DeepEqual(fuzzer.testCov, fuzzer.goalOut) {
+ return fmt.Sprintf("fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
+ name, fuzzer.goalOut, fuzzer.testCov)
}
}
+ return ""
}
-func (serv *RPCServer) Connect(name string, modules []host.KernelModule) {
+func (serv *RPCServer) connect(name string, modules []host.KernelModule) {
if !serv.modulesInitialized {
serv.canonicalModules = cover.NewCanonicalizer(modules)
serv.modulesInitialized = true
@@ -142,3 +126,15 @@ func (serv *RPCServer) Connect(name string, modules []host.KernelModule) {
instModules: serv.canonicalModules.NewInstance(modules),
}
}
+
+func initModules(addrs, sizes []uint64) []host.KernelModule {
+ var modules []host.KernelModule
+ for idx, addr := range addrs {
+ modules = append(modules, host.KernelModule{
+ Name: strconv.FormatInt(int64(idx), 10),
+ Addr: addr,
+ Size: sizes[idx],
+ })
+ }
+ return modules
+}