aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/aflow/tool/codeeditor
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-26 16:44:09 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-26 17:04:48 +0000
commite7922f79bc8da0b8ef96a080e463141bb5e79694 (patch)
tree2f5905aae03c3cfd1b657d755668db6565f07972 /pkg/aflow/tool/codeeditor
parentcf894e043b8ae1ea6e4093d14f327ad678fa4cf3 (diff)
pkg/aflow: add helper for tool testing
Add simple codeeditor tests to test testing.
Diffstat (limited to 'pkg/aflow/tool/codeeditor')
-rw-r--r--pkg/aflow/tool/codeeditor/codeeditor.go15
-rw-r--r--pkg/aflow/tool/codeeditor/codeeditor_test.go79
2 files changed, 93 insertions, 1 deletions
diff --git a/pkg/aflow/tool/codeeditor/codeeditor.go b/pkg/aflow/tool/codeeditor/codeeditor.go
index f67abbd69..ce2d7afb7 100644
--- a/pkg/aflow/tool/codeeditor/codeeditor.go
+++ b/pkg/aflow/tool/codeeditor/codeeditor.go
@@ -4,7 +4,11 @@
package codeeditor
import (
+ "path/filepath"
+ "strings"
+
"github.com/google/syzkaller/pkg/aflow"
+ "github.com/google/syzkaller/pkg/osutil"
)
var Tool = aflow.NewFuncTool("codeeditor", codeeditor, `
@@ -26,7 +30,16 @@ type args struct {
}
func codeeditor(ctx *aflow.Context, state state, args args) (struct{}, error) {
- // TODO: check that the SourceFile is not escaping.
+ if strings.Contains(filepath.Clean(args.SourceFile), "..") {
+ return struct{}{}, aflow.BadCallError("SourceFile %q is outside of the source tree", args.SourceFile)
+ }
+ file := filepath.Join(state.KernelScratchSrc, args.SourceFile)
+ if !osutil.IsExist(file) {
+ return struct{}{}, aflow.BadCallError("SourceFile %q does not exist", args.SourceFile)
+ }
+ if strings.TrimSpace(args.CurrentCode) == "" {
+ return struct{}{}, aflow.BadCallError("CurrentCode snippet is empty")
+ }
// If SourceFile is incorrect, or CurrentCode is not matched, return aflow.BadCallError
// with an explanation. Say that it needs to increase context if CurrentCode is not matched.
// Try to do as fuzzy match for CurrentCode as possible (strip line numbers,
diff --git a/pkg/aflow/tool/codeeditor/codeeditor_test.go b/pkg/aflow/tool/codeeditor/codeeditor_test.go
new file mode 100644
index 000000000..4ba556f1b
--- /dev/null
+++ b/pkg/aflow/tool/codeeditor/codeeditor_test.go
@@ -0,0 +1,79 @@
+// Copyright 2026 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 codeeditor
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/google/syzkaller/pkg/aflow"
+ "github.com/google/syzkaller/pkg/osutil"
+ "github.com/stretchr/testify/require"
+)
+
+func TestCodeeditorEscapingPath(t *testing.T) {
+ aflow.TestTool(t, Tool,
+ state{
+ KernelScratchSrc: "whatever",
+ },
+ args{
+ SourceFile: "../../passwd",
+ },
+ struct{}{},
+ `SourceFile "../../passwd" is outside of the source tree`,
+ )
+}
+
+func TestCodeeditorMissingPath(t *testing.T) {
+ aflow.TestTool(t, Tool,
+ state{
+ KernelScratchSrc: t.TempDir(),
+ },
+ args{
+ SourceFile: "missing-file",
+ },
+ struct{}{},
+ `SourceFile "missing-file" does not exist`,
+ )
+}
+
+func TestCodeeditorEmptyCurrentCode(t *testing.T) {
+ dir := writeTestFile(t, "foo", "data")
+ aflow.TestTool(t, Tool,
+ state{
+ KernelScratchSrc: dir,
+ },
+ args{
+ SourceFile: "foo",
+ },
+ struct{}{},
+ `CurrentCode snippet is empty`,
+ )
+}
+
+func writeTestFile(t *testing.T, filename, data string) string {
+ dir := t.TempDir()
+ if err := osutil.WriteFile(filepath.Join(dir, filename), []byte(data)); err != nil {
+ t.Fatal(err)
+ }
+ return dir
+}
+
+func Fuzz(f *testing.F) {
+ dir := f.TempDir()
+ const filename = "src.c"
+ fullFilename := filepath.Join(dir, filename)
+ f.Fuzz(func(t *testing.T, fileData []byte, curCode, newCode string) {
+ require.NoError(t, osutil.WriteFile(fullFilename, fileData))
+ aflow.FuzzTool(t, Tool,
+ state{
+ KernelScratchSrc: dir,
+ },
+ args{
+ SourceFile: filename,
+ CurrentCode: curCode,
+ NewCode: newCode,
+ })
+ })
+}