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  }