Merge "Only allow .scl files to load other .scl files" into main am: 7c8607715d

Original change: https://android-review.googlesource.com/c/platform/build/+/2820037

Change-Id: Id6e4070155b608d2845db563275057cbfdcf1d58
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Cole Faust
2023-11-07 22:08:04 +00:00
committed by Automerger Merge Worker
7 changed files with 84 additions and 15 deletions

View File

@@ -31,11 +31,11 @@ import (
type ExecutionMode int
const (
ExecutionModeRbc ExecutionMode = iota
ExecutionModeMake ExecutionMode = iota
ExecutionModeScl ExecutionMode = iota
)
const allowExternalEntrypointKey = "allowExternalEntrypoint"
const callerDirKey = "callerDir"
const callingFileKey = "callingFile"
const executionModeKey = "executionMode"
const shellKey = "shell"
@@ -58,7 +58,7 @@ var rbcBuiltins starlark.StringDict = starlark.StringDict{
"rblf_wildcard": starlark.NewBuiltin("rblf_wildcard", wildcard),
}
var makeBuiltins starlark.StringDict = starlark.StringDict{
var sclBuiltins starlark.StringDict = starlark.StringDict{
"struct": starlark.NewBuiltin("struct", starlarkstruct.Make),
"json": starlarkjson.Module,
}
@@ -128,7 +128,8 @@ func loader(thread *starlark.Thread, module string) (starlark.StringDict, error)
module = module[:pipePos]
}
}
modulePath, err := cleanModuleName(module, thread.Local(callerDirKey).(string), allowExternalEntrypoint)
callingFile := thread.Local(callingFileKey).(string)
modulePath, err := cleanModuleName(module, filepath.Dir(callingFile), allowExternalEntrypoint)
if err != nil {
return nil, err
}
@@ -150,6 +151,13 @@ func loader(thread *starlark.Thread, module string) (starlark.StringDict, error)
// Load or return default
if mustLoad {
if strings.HasSuffix(callingFile, ".scl") && !strings.HasSuffix(modulePath, ".scl") {
return nil, fmt.Errorf(".scl files can only load other .scl files: %q loads %q", callingFile, modulePath)
}
// Switch into scl mode from here on
if strings.HasSuffix(modulePath, ".scl") {
mode = ExecutionModeScl
}
childThread := &starlark.Thread{Name: "exec " + module, Load: thread.Load}
// Cheating for the sake of testing:
// propagate starlarktest's Reporter key, otherwise testing
@@ -161,14 +169,14 @@ func loader(thread *starlark.Thread, module string) (starlark.StringDict, error)
// Only the entrypoint starlark file allows external loads.
childThread.SetLocal(allowExternalEntrypointKey, false)
childThread.SetLocal(callerDirKey, filepath.Dir(modulePath))
childThread.SetLocal(callingFileKey, modulePath)
childThread.SetLocal(executionModeKey, mode)
childThread.SetLocal(shellKey, thread.Local(shellKey))
if mode == ExecutionModeRbc {
globals, err := starlark.ExecFile(childThread, modulePath, nil, rbcBuiltins)
e = &modentry{globals, err}
} else if mode == ExecutionModeMake {
globals, err := starlark.ExecFile(childThread, modulePath, nil, makeBuiltins)
} else if mode == ExecutionModeScl {
globals, err := starlark.ExecFile(childThread, modulePath, nil, sclBuiltins)
e = &modentry{globals, err}
} else {
return nil, fmt.Errorf("unknown executionMode %d", mode)
@@ -338,7 +346,7 @@ func Run(filename string, src interface{}, mode ExecutionMode, allowExternalEntr
if mode == ExecutionModeRbc {
// In rbc mode, rblf_log is used to print to stderr
fmt.Println(msg)
} else if mode == ExecutionModeMake {
} else if mode == ExecutionModeScl {
fmt.Fprintln(os.Stderr, msg)
}
},
@@ -365,13 +373,13 @@ func Run(filename string, src interface{}, mode ExecutionMode, allowExternalEntr
var results starlark.StringDict
mainThread.SetLocal(allowExternalEntrypointKey, allowExternalEntrypoint)
mainThread.SetLocal(callerDirKey, filepath.Dir(filename))
mainThread.SetLocal(callingFileKey, filename)
mainThread.SetLocal(executionModeKey, mode)
mainThread.SetLocal(shellKey, shellPath)
if mode == ExecutionModeRbc {
results, err = starlark.ExecFile(mainThread, filename, src, rbcBuiltins)
} else if mode == ExecutionModeMake {
results, err = starlark.ExecFile(mainThread, filename, src, makeBuiltins)
} else if mode == ExecutionModeScl {
results, err = starlark.ExecFile(mainThread, filename, src, sclBuiltins)
} else {
return results, nil, fmt.Errorf("unknown executionMode %d", mode)
}

View File

@@ -19,6 +19,7 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"go.starlark.net/resolve"
@@ -126,7 +127,7 @@ func TestLoad(t *testing.T) {
t.Fatal(err)
}
thread.SetLocal(allowExternalEntrypointKey, false)
thread.SetLocal(callerDirKey, dir)
thread.SetLocal(callingFileKey, "testdata/load.star")
thread.SetLocal(executionModeKey, ExecutionModeRbc)
if _, err := starlark.ExecFile(thread, "testdata/load.star", nil, rbcBuiltins); err != nil {
if err, ok := err.(*starlark.EvalError); ok {
@@ -136,6 +137,55 @@ func TestLoad(t *testing.T) {
}
}
func TestBzlLoadsScl(t *testing.T) {
moduleCache = make(map[string]*modentry)
dir := dataDir()
if err := os.Chdir(filepath.Dir(dir)); err != nil {
t.Fatal(err)
}
vars, _, err := Run("testdata/bzl_loads_scl.bzl", nil, ExecutionModeScl, false)
if err != nil {
t.Fatal(err)
}
if val, ok := vars["foo"]; !ok {
t.Fatalf("Failed to load foo variable")
} else if val.(starlark.String) != "bar" {
t.Fatalf("Expected \"bar\", got %q", val)
}
}
func TestNonEntrypointBzlLoadsScl(t *testing.T) {
moduleCache = make(map[string]*modentry)
dir := dataDir()
if err := os.Chdir(filepath.Dir(dir)); err != nil {
t.Fatal(err)
}
vars, _, err := Run("testdata/bzl_loads_scl_2.bzl", nil, ExecutionModeScl, false)
if err != nil {
t.Fatal(err)
}
if val, ok := vars["foo"]; !ok {
t.Fatalf("Failed to load foo variable")
} else if val.(starlark.String) != "bar" {
t.Fatalf("Expected \"bar\", got %q", val)
}
}
func TestSclLoadsBzl(t *testing.T) {
moduleCache = make(map[string]*modentry)
dir := dataDir()
if err := os.Chdir(filepath.Dir(dir)); err != nil {
t.Fatal(err)
}
_, _, err := Run("testdata/scl_incorrectly_loads_bzl.scl", nil, ExecutionModeScl, false)
if err == nil {
t.Fatal("Expected failure")
}
if !strings.Contains(err.Error(), ".scl files can only load other .scl files") {
t.Fatalf("Expected error to contain \".scl files can only load other .scl files\": %q", err.Error())
}
}
func TestShell(t *testing.T) {
exerciseStarlarkTestFile(t, "testdata/shell.star")
}

View File

@@ -55,13 +55,13 @@ func getMode() rbcrun.ExecutionMode {
case "rbc":
return rbcrun.ExecutionModeRbc
case "make":
return rbcrun.ExecutionModeMake
return rbcrun.ExecutionModeScl
case "":
quit("-mode flag is required.")
default:
quit("Unknown -mode value %q, expected 1 of \"rbc\", \"make\"", *modeFlag)
}
return rbcrun.ExecutionModeMake
return rbcrun.ExecutionModeScl
}
var makeStringReplacer = strings.NewReplacer("#", "\\#", "$", "$$")
@@ -175,7 +175,7 @@ func main() {
quit("%s\n", err)
}
}
if mode == rbcrun.ExecutionModeMake {
if mode == rbcrun.ExecutionModeScl {
if err := printVarsInMakeFormat(variables); err != nil {
quit("%s\n", err)
}

View File

@@ -0,0 +1,3 @@
load(":test_scl.scl", _foo = "foo")
foo = _foo

View File

@@ -0,0 +1,3 @@
load(":bzl_loads_scl.bzl", _foo = "foo")
foo = _foo

View File

@@ -0,0 +1,3 @@
load(":bzl_loads_scl.bzl", _foo = "foo")
foo = _foo

2
tools/rbcrun/testdata/test_scl.scl vendored Normal file
View File

@@ -0,0 +1,2 @@
foo = "bar"