Only allow .scl files to load other .scl files

.scl files are starlark configuraiont language files, which is starlark
without any of the bazel buildin symbols.

This is to match bazel's behavior, and it doesn't make sense for
scl files to load bzl files.

We should change all the release config bzl files to scl, and then
also make it so that when using executionModeScl you can only load
scl files.

Test: go test
Change-Id: I196bcf3a4548118791ed1d47c2d37e46a1ef86c4
This commit is contained in:
Cole Faust
2023-11-07 11:14:58 -08:00
parent 253bd067da
commit 5b8dda087d
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"