google / go-jsonnet

Apache License 2.0
1.63k stars 235 forks source link

parseYaml panics when passed empty string #714

Open BronzeDeer opened 1 year ago

BronzeDeer commented 1 year ago
# Also present in v0.20.0
$ jsonnet --version

Jsonnet commandline interpreter (Go implementation) v0.19.1

$ echo "std.parseYaml('')" > test.jsonnet

$ jsonnet test.jsonnet

INTERNAL ERROR: (CRASH) runtime error: index out of range [0] with length 0
goroutine 1 [running]:
runtime/debug.Stack()
        runtime/debug/stack.go:24 +0x65
github.com/google/go-jsonnet.(*VM).Evaluate.func1()
        github.com/google/go-jsonnet/vm.go:182 +0x45
panic({0x5a9b00, 0xc00001c768})
        runtime/panic.go:884 +0x212
github.com/google/go-jsonnet.builtinParseYAML(0xc0000d6540?, {0x619618?, 0xc000010be8?})
        github.com/google/go-jsonnet/builtins.go:1390 +0x3c5
github.com/google/go-jsonnet.(*unaryBuiltin).evalCall(0xc0000cd020, {{0xc000012058, 0x1, 0x1}, {0x926340, 0x0, 0x0}, 0x0}, 0x0?)
        github.com/google/go-jsonnet/builtins.go:1930 +0x309
github.com/google/go-jsonnet.(*valueFunction).call(0xc0000b7360, 0xc0000d6540?, {{0xc000012058, 0x1, 0x1}, {0x926340, 0x0, 0x0}, 0x0})
        github.com/google/go-jsonnet/value.go:349 +0x137
github.com/google/go-jsonnet.(*interpreter).evaluateTailCall(0x619d20?, 0xc00003e100?, {{0xc000012058, 0x1, 0x1}, {0x926340, 0x0, 0x0}, 0x0}, 0x1)
        github.com/google/go-jsonnet/interpreter.go:999 +0xa5
github.com/google/go-jsonnet.(*interpreter).evaluate(0xc0000e75e0, {0x619d20, 0xc00003e100?}, 0x0?)
        github.com/google/go-jsonnet/interpreter.go:593 +0x29a5
github.com/google/go-jsonnet.(*interpreter).EvalInCleanEnv(0xc0000e75e0, 0xc?, {0x619d20, 0xc00003e100}, 0x0?)
        github.com/google/go-jsonnet/interpreter.go:981 +0x70
github.com/google/go-jsonnet.evaluateAux(0xc0000e75e0, {0x619d20, 0xc00003e100}, 0xc0000cd3e0?)
        github.com/google/go-jsonnet/interpreter.go:1288 +0x19b
github.com/google/go-jsonnet.evaluate({0x619d20, 0xc00003e100}, 0xc0002dfd00?, 0x5468ee?, 0x592c00?, 0xc0000cd380?, 0x7ffd44ded579?, {0x619268?, 0xc000012020?}, 0x0)
        github.com/google/go-jsonnet/interpreter.go:1323 +0x8d
github.com/google/go-jsonnet.(*VM).Evaluate(0xc0000cd3e0?, {0x619d20?, 0xc00003e100?})
        github.com/google/go-jsonnet/vm.go:185 +0xb9
github.com/google/go-jsonnet.(*VM).EvaluateFile(0xc0002dff08, {0x7ffd44ded579?, 0x10?})
        github.com/google/go-jsonnet/vm.go:414 +0xbd
main.main()
        github.com/google/go-jsonnet/cmd/jsonnet/cmd.go:458 +0x8b3

The fix itself is easy by adding an empty check before the return, however care needs to be taken to correctly parse an empty yaml document according to spec. Based on https://stackoverflow.com/a/62467269, returning null for an empty yaml document is likely the only spec-compliant answer. On the other Hand, if we follow the documented restrictions of the std.parseYaml then we should instead throw an error stating that scalars at the root are not supported. On the other, other Hand, the parser currently actually supports parsing both documents consisting only of comments and integer scalars, partially invalidating the documented restriction.

If you can give me guidance as to what the expected behaviour should be (return null, return empty map, return error) I'd be happy to provide a pull request