Skip to content

Commit 973d0a1

Browse files
committed
incusd/scriptlet: Add function args checks in scriptlet validation
Signed-off-by: Benjamin Somers <[email protected]>
1 parent 39b3d8b commit 973d0a1

File tree

1 file changed

+37
-11
lines changed
  • internal/server/scriptlet/load

1 file changed

+37
-11
lines changed

internal/server/scriptlet/load/load.go

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package load
33
import (
44
"fmt"
55
"slices"
6+
"sort"
67
"sync"
78

89
"go.starlark.net/starlark"
@@ -34,7 +35,7 @@ func compile(programName string, src string, preDeclared []string) (*starlark.Pr
3435
}
3536

3637
// validate validates a scriptlet by compiling it and checking the presence of required functions.
37-
func validate(compiler func(string, string) (*starlark.Program, error), programName string, src string, requiredFunctions []string) error {
38+
func validate(compiler func(string, string) (*starlark.Program, error), programName string, src string, requiredFunctions map[string][]string) error {
3839
prog, err := compiler(programName, src)
3940
if err != nil {
4041
return err
@@ -49,19 +50,44 @@ func validate(compiler func(string, string) (*starlark.Program, error), programN
4950
globals.Freeze()
5051

5152
var notFound []string
52-
for _, funName := range requiredFunctions {
53+
for funName, requiredArgs := range requiredFunctions {
5354
// The function is missing if its name is not found in the globals.
54-
requiredFun := globals[funName]
55-
if requiredFun == nil {
55+
funv := globals[funName]
56+
if funv == nil {
5657
notFound = append(notFound, funName)
5758
continue
5859
}
5960

6061
// The function is missing if its name is not bound to a function.
61-
_, ok := requiredFun.(*starlark.Function)
62+
fun, ok := funv.(*starlark.Function)
6263
if !ok {
6364
notFound = append(notFound, funName)
6465
}
66+
67+
// Get the function arguments.
68+
argc := fun.NumParams()
69+
var args []string
70+
for i := range argc {
71+
arg, _ := fun.Param(i)
72+
args = append(args, arg)
73+
}
74+
75+
// Return an error early if the function does not have the right arguments.
76+
match := len(args) == len(requiredArgs)
77+
if match {
78+
sort.Strings(args)
79+
sort.Strings(requiredArgs)
80+
for i := range args {
81+
if args[i] != requiredArgs[i] {
82+
match = false
83+
break
84+
}
85+
}
86+
}
87+
88+
if !match {
89+
return fmt.Errorf("The function %q defines arguments %q (expected: %q)", funName, args, requiredArgs)
90+
}
6591
}
6692

6793
switch len(notFound) {
@@ -130,8 +156,8 @@ func InstancePlacementCompile(name string, src string) (*starlark.Program, error
130156

131157
// InstancePlacementValidate validates the instance placement scriptlet.
132158
func InstancePlacementValidate(src string) error {
133-
return validate(InstancePlacementCompile, nameInstancePlacement, src, []string{
134-
"instance_placement",
159+
return validate(InstancePlacementCompile, nameInstancePlacement, src, map[string][]string{
160+
"instance_placement": []string{"request", "candidate_members"},
135161
})
136162
}
137163

@@ -173,8 +199,8 @@ func QEMUCompile(name string, src string) (*starlark.Program, error) {
173199

174200
// QEMUValidate validates the QEMU scriptlet.
175201
func QEMUValidate(src string) error {
176-
return validate(QEMUCompile, prefixQEMU, src, []string{
177-
"qemu_hook",
202+
return validate(QEMUCompile, prefixQEMU, src, map[string][]string{
203+
"qemu_hook": []string{"hook_name"},
178204
})
179205
}
180206

@@ -200,8 +226,8 @@ func AuthorizationCompile(name string, src string) (*starlark.Program, error) {
200226

201227
// AuthorizationValidate validates the authorization scriptlet.
202228
func AuthorizationValidate(src string) error {
203-
return validate(AuthorizationCompile, nameAuthorization, src, []string{
204-
"authorize",
229+
return validate(AuthorizationCompile, nameAuthorization, src, map[string][]string{
230+
"authorize": []string{"details", "object", "entitlement"},
205231
})
206232
}
207233

0 commit comments

Comments
 (0)