Skip to content

Commit

Permalink
SetBuiltinFunctions and SetBuiltinModules (#120)
Browse files Browse the repository at this point in the history
* `SetBuiltinFunctions` and `SetBuiltinModules`

* nil implies no built in functions.

* Additional tests.

* Cleanup

* Updated SetBuiltinFunctions

* Docs updated.
  • Loading branch information
geseq authored and d5 committed Feb 28, 2019
1 parent 39112d2 commit 7cc683e
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 135 deletions.
2 changes: 1 addition & 1 deletion cmd/bench/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func runVM(bytecode *compiler.Bytecode) (time.Duration, objects.Object, error) {

start := time.Now()

v := runtime.NewVM(bytecode, globals, nil)
v := runtime.NewVM(bytecode, globals, nil, nil)
if err := v.Run(); err != nil {
return time.Since(start), nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/tengo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func compileAndRun(data []byte, inputFile string) (err error) {
return
}

machine := runtime.NewVM(bytecode, nil, nil)
machine := runtime.NewVM(bytecode, nil, nil, nil)

err = machine.Run()
if err != nil {
Expand All @@ -165,7 +165,7 @@ func runCompiled(data []byte) (err error) {
return
}

machine := runtime.NewVM(bytecode, nil, nil)
machine := runtime.NewVM(bytecode, nil, nil, nil)

err = machine.Run()
if err != nil {
Expand Down Expand Up @@ -216,7 +216,7 @@ func runREPL(in io.Reader, out io.Writer) {

bytecode := c.Bytecode()

machine := runtime.NewVM(bytecode, globals, nil)
machine := runtime.NewVM(bytecode, globals, nil, nil)
if err := machine.Run(); err != nil {
_, _ = fmt.Fprintln(out, err.Error())
continue
Expand Down
30 changes: 17 additions & 13 deletions docs/interoperability.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,33 +118,37 @@ Users can add and use a custom user type in Tengo code by implementing [Object](

To securely compile and execute _potentially_ unsafe script code, you can use the following Script functions.

#### Script.DisableBuiltinFunction(name string)
#### Script.SetBuiltinFunctions(funcs []*objects.BuiltinFunction)

DisableBuiltinFunction disables and removes a builtin function from the compiler. Compiler will reports a compile-time error if the given name is referenced.
SetBuiltinFunctions resets all builtin functions in the compiler to the ones provided in the input parameter. Compiler will report a compile-time error if the a function not set is referenced. All builtin functions are included by default unless `SetBuiltinFunctions` is called.

```golang
s := script.New([]byte(`print([1, 2, 3])`))

s.DisableBuiltinFunction("print")
s.SetBuiltinFunctions(nil)

_, err := s.Run() // compile error
```
_, err := s.Run() // compile error

s.SetBuiltinFunctions([]*objects.BuiltinFunction{&objects.Builtins[0]})

Note that when a script is being added to another script as a module (via `Script.AddModule`), it does not inherit the disabled builtin function list from the main script.
_, err := s.Run() // prints [1, 2, 3]
```

#### Script.DisableStdModule(name string)
#### Script.SetBuiltinModules(modules map[string]*objects.ImmutableMap)

DisableStdModule disables a [standard library](https://github.com/d5/tengo/blob/master/docs/stdlib.md) module. Compile will report a compile-time error if the code tries to import the module with the given name.
SetBuiltinModules resets all [standard library](https://github.com/d5/tengo/blob/master/docs/stdlib.md) modules with modules provided in the input parameter. Compile will report a compile-time error if the code tries to import a module that hasn't been included. All standard library modules are included by default unless `SetBuiltinModules` is called.

```golang
s := script.New([]byte(`import("exec")`))
s := script.New([]byte(`math := import("math"); a := math.abs(-19.84)`))

s.DisableStdModule("exec")
s.SetBuiltinModules(nil)

_, err := s.Run() // compile error
```
_, err := s.Run() // compile error

s.SetBuiltinModules(map[string]*objects.ImmutableMap{"math": objectPtr(*stdlib.Modules["math"])})

Note that when a script is being added to another script as a module (via `Script.AddModule`), it does not inherit the disabled standard module list from the main script.
_, err := s.Run() // a = 19.84
```

#### Script.SetUserModuleLoader(loader compiler.ModuleLoader)

Expand Down
132 changes: 63 additions & 69 deletions objects/builtins.go
Original file line number Diff line number Diff line change
@@ -1,135 +1,129 @@
package objects

// NamedBuiltinFunc is a named builtin function.
type NamedBuiltinFunc struct {
Name string
Func CallableFunc
}

// Builtins contains all default builtin functions.
var Builtins = []NamedBuiltinFunc{
var Builtins = []BuiltinFunction{
{
Name: "print",
Func: builtinPrint,
Name: "print",
Value: builtinPrint,
},
{
Name: "printf",
Func: builtinPrintf,
Name: "printf",
Value: builtinPrintf,
},
{
Name: "sprintf",
Func: builtinSprintf,
Name: "sprintf",
Value: builtinSprintf,
},
{
Name: "len",
Func: builtinLen,
Name: "len",
Value: builtinLen,
},
{
Name: "copy",
Func: builtinCopy,
Name: "copy",
Value: builtinCopy,
},
{
Name: "append",
Func: builtinAppend,
Name: "append",
Value: builtinAppend,
},
{
Name: "string",
Func: builtinString,
Name: "string",
Value: builtinString,
},
{
Name: "int",
Func: builtinInt,
Name: "int",
Value: builtinInt,
},
{
Name: "bool",
Func: builtinBool,
Name: "bool",
Value: builtinBool,
},
{
Name: "float",
Func: builtinFloat,
Name: "float",
Value: builtinFloat,
},
{
Name: "char",
Func: builtinChar,
Name: "char",
Value: builtinChar,
},
{
Name: "bytes",
Func: builtinBytes,
Name: "bytes",
Value: builtinBytes,
},
{
Name: "time",
Func: builtinTime,
Name: "time",
Value: builtinTime,
},
{
Name: "is_int",
Func: builtinIsInt,
Name: "is_int",
Value: builtinIsInt,
},
{
Name: "is_float",
Func: builtinIsFloat,
Name: "is_float",
Value: builtinIsFloat,
},
{
Name: "is_string",
Func: builtinIsString,
Name: "is_string",
Value: builtinIsString,
},
{
Name: "is_bool",
Func: builtinIsBool,
Name: "is_bool",
Value: builtinIsBool,
},
{
Name: "is_char",
Func: builtinIsChar,
Name: "is_char",
Value: builtinIsChar,
},
{
Name: "is_bytes",
Func: builtinIsBytes,
Name: "is_bytes",
Value: builtinIsBytes,
},
{
Name: "is_array",
Func: builtinIsArray,
Name: "is_array",
Value: builtinIsArray,
},
{
Name: "is_immutable_array",
Func: builtinIsImmutableArray,
Name: "is_immutable_array",
Value: builtinIsImmutableArray,
},
{
Name: "is_map",
Func: builtinIsMap,
Name: "is_map",
Value: builtinIsMap,
},
{
Name: "is_immutable_map",
Func: builtinIsImmutableMap,
Name: "is_immutable_map",
Value: builtinIsImmutableMap,
},
{
Name: "is_time",
Func: builtinIsTime,
Name: "is_time",
Value: builtinIsTime,
},
{
Name: "is_error",
Func: builtinIsError,
Name: "is_error",
Value: builtinIsError,
},
{
Name: "is_undefined",
Func: builtinIsUndefined,
Name: "is_undefined",
Value: builtinIsUndefined,
},
{
Name: "is_function",
Func: builtinIsFunction,
Name: "is_function",
Value: builtinIsFunction,
},
{
Name: "is_callable",
Func: builtinIsCallable,
Name: "is_callable",
Value: builtinIsCallable,
},
{
Name: "to_json",
Func: builtinToJSON,
Name: "to_json",
Value: builtinToJSON,
},
{
Name: "from_json",
Func: builtinFromJSON,
Name: "from_json",
Value: builtinFromJSON,
},
{
Name: "type_name",
Func: builtinTypeName,
Name: "type_name",
Value: builtinTypeName,
},
}
27 changes: 14 additions & 13 deletions runtime/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ var (
truePtr = &objects.TrueValue
falsePtr = &objects.FalseValue
undefinedPtr = &objects.UndefinedValue
builtinFuncs []objects.Object
)

// VM is a virtual machine that executes the bytecode compiled by Compiler.
Expand All @@ -43,11 +42,12 @@ type VM struct {
curIPLimit int
ip int
aborting int64
builtinFuncs []objects.Object
builtinModules map[string]*objects.Object
}

// NewVM creates a VM.
func NewVM(bytecode *compiler.Bytecode, globals []*objects.Object, builtinModules map[string]*objects.Object) *VM {
func NewVM(bytecode *compiler.Bytecode, globals []*objects.Object, builtinFuncs []objects.Object, builtinModules map[string]*objects.Object) *VM {
if globals == nil {
globals = make([]*objects.Object, GlobalsSize)
}
Expand All @@ -56,6 +56,16 @@ func NewVM(bytecode *compiler.Bytecode, globals []*objects.Object, builtinModule
builtinModules = stdlib.Modules
}

if builtinFuncs == nil {
builtinFuncs = make([]objects.Object, len(objects.Builtins))
for idx, fn := range objects.Builtins {
builtinFuncs[idx] = &objects.BuiltinFunction{
Name: fn.Name,
Value: fn.Value,
}
}
}

frames := make([]Frame, MaxFrames)
frames[0].fn = bytecode.MainFunction
frames[0].freeVars = nil
Expand All @@ -74,6 +84,7 @@ func NewVM(bytecode *compiler.Bytecode, globals []*objects.Object, builtinModule
curInsts: frames[0].fn.Instructions,
curIPLimit: len(frames[0].fn.Instructions) - 1,
ip: -1,
builtinFuncs: builtinFuncs,
builtinModules: builtinModules,
}
}
Expand Down Expand Up @@ -1183,7 +1194,7 @@ mainloop:
break mainloop
}

v.stack[v.sp] = &builtinFuncs[builtinIndex]
v.stack[v.sp] = &v.builtinFuncs[builtinIndex]
v.sp++

case compiler.OpGetBuiltinModule:
Expand Down Expand Up @@ -1412,13 +1423,3 @@ func indexAssign(dst, src *objects.Object, selectors []*objects.Object) error {

return nil
}

func init() {
builtinFuncs = make([]objects.Object, len(objects.Builtins))
for i, b := range objects.Builtins {
builtinFuncs[i] = &objects.BuiltinFunction{
Name: b.Name,
Value: b.Func,
}
}
}
2 changes: 1 addition & 1 deletion runtime/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func traceCompileRun(file *ast.File, symbols map[string]objects.Object, userModu
trace = append(trace, fmt.Sprintf("\n[Compiled Constants]\n\n%s", strings.Join(bytecode.FormatConstants(), "\n")))
trace = append(trace, fmt.Sprintf("\n[Compiled Instructions]\n\n%s\n", strings.Join(bytecode.FormatInstructions(), "\n")))

v = runtime.NewVM(bytecode, globals, nil)
v = runtime.NewVM(bytecode, globals, nil, nil)

err = v.Run()
{
Expand Down
Loading

0 comments on commit 7cc683e

Please sign in to comment.