github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/ifuzz/ifuzz_test.go (about) 1 // Copyright 2017 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 ifuzz 5 6 import ( 7 "encoding/hex" 8 "math/rand" 9 "testing" 10 11 "github.com/google/syzkaller/pkg/ifuzz/iset" 12 "github.com/google/syzkaller/pkg/testutil" 13 ) 14 15 var allArches = []string{ArchX86, ArchPowerPC, ArchArm64} 16 17 func TestMode(t *testing.T) { 18 for _, arch := range allArches { 19 t.Run(arch, func(t *testing.T) { 20 testMode(t, arch) 21 }) 22 } 23 } 24 25 func testMode(t *testing.T, arch string) { 26 all := make(map[iset.Insn]bool) 27 for mode := iset.Mode(0); mode < iset.ModeLast; mode++ { 28 for priv := 0; priv < 2; priv++ { 29 for exec := 0; exec < 2; exec++ { 30 insns := allInsns(arch, mode, priv != 0, exec != 0) 31 t.Logf("mode=%v priv=%v exec=%v: %v instructions", mode, priv, exec, len(insns)) 32 for _, insn := range insns { 33 all[insn] = true 34 } 35 } 36 } 37 } 38 t.Logf("total: %v instructions", len(all)) 39 } 40 41 func TestDecode(t *testing.T) { 42 for _, arch := range allArches { 43 t.Run(arch, func(t *testing.T) { 44 testDecode(t, arch) 45 }) 46 } 47 } 48 49 func testDecode(t *testing.T, arch string) { 50 insnset := iset.Arches[arch] 51 xedEnabled := false 52 if _, err := insnset.DecodeExt(0, nil); err == nil { 53 xedEnabled = true 54 } 55 r := rand.New(testutil.RandSource(t)) 56 57 for repeat := 0; repeat < 10; repeat++ { 58 for mode := iset.Mode(0); mode < iset.ModeLast; mode++ { 59 cfg := &iset.Config{ 60 Mode: mode, 61 Priv: true, 62 Exec: true, 63 } 64 failed := false 65 for _, insn := range allInsns(arch, mode, true, true) { 66 name, _, pseudo, _ := insn.Info() 67 text0 := insn.Encode(cfg, r) 68 text := text0 69 repeat: 70 size, err := insnset.Decode(mode, text) 71 if err != nil { 72 t.Errorf("decoding %v %v failed (mode=%v): %v", name, hex.EncodeToString(text), mode, err) 73 if len(text) != len(text0) { 74 t.Errorf("whole: %v", hex.EncodeToString(text0)) 75 } 76 failed = true 77 continue 78 } 79 if xedEnabled { 80 xedSize, xedErr := insnset.DecodeExt(mode, text) 81 if xedErr != nil { 82 t.Errorf("xed decoding %v %v failed (mode=%v): %v", name, hex.EncodeToString(text), mode, xedErr) 83 if len(text) != len(text0) { 84 t.Errorf("whole: %v", hex.EncodeToString(text0)) 85 } 86 failed = true 87 continue 88 } 89 if size != xedSize { 90 t.Errorf("decoding %v %v failed (mode=%v): decoded %v/%v, xed decoded %v/%v", 91 name, hex.EncodeToString(text), mode, size, xedSize, size, len(text)) 92 if len(text) != len(text0) { 93 t.Errorf("whole: %v", hex.EncodeToString(text0)) 94 } 95 failed = true 96 continue 97 } 98 } 99 if pseudo && size >= 0 && size < len(text) { 100 text = text[size:] 101 goto repeat 102 } 103 if size != len(text) { 104 t.Errorf("decoding %v %v failed (mode=%v): decoded %v/%v", 105 name, hex.EncodeToString(text), mode, size, len(text)) 106 if len(text) != len(text0) { 107 t.Errorf("whole: %v", hex.EncodeToString(text0)) 108 } 109 failed = true 110 } 111 } 112 if failed { 113 return 114 } 115 } 116 } 117 } 118 119 func TestGenerate(t *testing.T) { 120 for _, arch := range allArches { 121 t.Run(arch, func(t *testing.T) { 122 testGenerate(t, arch) 123 }) 124 } 125 } 126 127 func testGenerate(t *testing.T, arch string) { 128 insnset := iset.Arches[arch] 129 r := rand.New(testutil.RandSource(t)) 130 for mode := iset.Mode(0); mode < iset.ModeLast; mode++ { 131 for repeat := 1; repeat < 10; repeat++ { 132 if len(insnset.GetInsns(mode, iset.TypeUser)) == 0 { 133 continue 134 } 135 cfg := &iset.Config{ 136 Arch: arch, 137 Mode: mode, 138 Priv: true, 139 Exec: true, 140 Len: repeat, 141 } 142 text := Generate(cfg, r) 143 for len(text) != 0 { 144 size, err := insnset.Decode(mode, text) 145 if size == 0 || err != nil { 146 t.Errorf("failed to decode text: % x", text) 147 break 148 } 149 text = text[size:] 150 } 151 } 152 } 153 } 154 155 func allInsns(arch string, mode iset.Mode, priv, exec bool) []iset.Insn { 156 insnset := iset.Arches[arch] 157 insns := insnset.GetInsns(mode, iset.TypeUser) 158 if priv { 159 insns = append(insns, insnset.GetInsns(mode, iset.TypePriv)...) 160 if exec { 161 insns = append(insns, insnset.GetInsns(mode, iset.TypeExec)...) 162 } 163 } 164 return insns 165 }