From 9a3002038e891237ff5b561f756a0ff6e32d1d2f Mon Sep 17 00:00:00 2001 From: Ethan Graham Date: Mon, 15 Sep 2025 12:56:38 +0000 Subject: pkg/kfuzztest: add pkg/kfuzztest Add a new package, pkg/kfuzztest, that implements dynamic discovery of KFuzzTest targets by parsing a vmlinux kernel binary. Signed-off-by: Ethan Graham --- pkg/kfuzztest/description_generation_test.go | 103 +++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 pkg/kfuzztest/description_generation_test.go (limited to 'pkg/kfuzztest/description_generation_test.go') diff --git a/pkg/kfuzztest/description_generation_test.go b/pkg/kfuzztest/description_generation_test.go new file mode 100644 index 000000000..d68a96b18 --- /dev/null +++ b/pkg/kfuzztest/description_generation_test.go @@ -0,0 +1,103 @@ +// Copyright 2025 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 kfuzztest + +import ( + "fmt" + "os" + "path" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/syzkaller/pkg/osutil" + "github.com/google/syzkaller/sys/targets" + "github.com/stretchr/testify/require" +) + +type testData struct { + dir string + desc string +} + +func TestBuildDescriptions(t *testing.T) { + testCases, err := readTestCases("./testdata") + require.NoError(t, err) + + target := targets.Get(targets.Linux, targets.AMD64) + for _, tc := range testCases { + t.Run(tc.dir, func(t *testing.T) { + runTest(t, target, tc) + }) + } +} + +// Tests that the description inferred from a compiled binary matches an +// expected description. +func runTest(t *testing.T, target *targets.Target, tc testData) { + // Compile the C binary containing the metadata. + cmd := flags(tc.dir) + out, err := osutil.RunCmd(time.Hour, "", target.CCompiler, cmd...) + require.NoErrorf(t, err, "Failed to compile: %s", string(out)) + // Cleanup the compiled binary. + defer func() { + out, err := osutil.RunCmd(time.Hour, "", "rm", path.Join(tc.dir, "bin")) + if err != nil { + require.NoErrorf(t, err, "Failed to cleanup: %s", string(out)) + } + }() + + binaryPath := path.Join(tc.dir, "bin") + desc, err := ExtractDescription(binaryPath) + require.NoError(t, err) + + if diffDesc := cmp.Diff(tc.desc, desc); diffDesc != "" { + fmt.Print(diffDesc) + t.Fail() + return + } +} + +func flags(testDir string) []string { + return []string{ + "-g", + "-T", + path.Join(testDir, "..", "linker.ld"), + "-o", + path.Join(testDir, "bin"), + path.Join(testDir, "prog.c"), + } +} + +func readTestCases(dir string) ([]testData, error) { + var testCases []testData + testDirs, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + + for _, subDir := range testDirs { + if !subDir.IsDir() { + continue + } + testData, err := readTestdata(path.Join(dir, subDir.Name())) + if err != nil { + return nil, err + } + testCases = append(testCases, testData) + } + + return testCases, nil +} + +func readTestdata(testDir string) (testData, error) { + content, err := os.ReadFile(path.Join(testDir, "desc.txt")) + if err != nil { + return testData{}, err + } + + return testData{ + dir: testDir, + desc: string(content), + }, nil +} -- cgit mrf-deployment