Skip to content

bug (batch, low): Extism empty-input, Starlark dict key collision, Risor uint64 wrap, and minor edge cases #165

Description

@robbyt

A batch of confirmed low-severity correctness edge cases, grouped to limit issue noise. Split out any that warrant a dedicated fix.

1. Extism sends zero bytes instead of {} when input is empty

engines/extism/internal/converters.go:9-11:

if len(inputData) == 0 { return nil, nil }

Eval with no static or context data passes nil to CallWithContext; a guest that would accept {} fails to parse empty input.

Repro (confirmed): Eval with no data → execution failed: unexpected end of JSON input.

Fix: marshal the empty map to {} when the intent is "no data ⇒ empty object"; otherwise document the behavior.

2. Starlark dict → map collides stringified keys and drops unreadable entries

engines/starlark/internal/converters.go:79-97: non-string keys are stringified via k.String(); distinct keys that render identically overwrite each other, and v.Get(k) errors are silently skipped.

Repro (confirmed): _ = {1: "a", "1": "b"}Interface() == map[1:b] (one entry; 1: "a" lost).

Fix: disambiguate non-string keys (or return an error), and propagate Get errors.

3. Risor uint64 values above MaxInt64 wrap silently

engines/risor/internal/converters.go passes input straight to Risor, whose TypeRegistry.fromGoByKind does NewInt(int64(rv.Uint())).

Repro (confirmed): static data {"big": uint64(math.MaxUint64)}, script ctx["big"]-1. The wrap is upstream in Risor v2, but go-polyscript feeds the value in unguarded, whereas Starlark's converter rejects uint64. Consider a guard or warning for uint64 values exceeding int64 range, for cross-engine consistency.

4. Starlark eval_data universe entry is dead code

engines/starlark/evaluator/evaluator.go:44 adds eval_data to the runtime universe, but it's never in the compile-time predeclared set (compiler/internal/compile/compile.go), so any script referencing it fails to compile. Remove it or wire it into the predeclared set.

5. Extism execHelper misattributes call failures as cancellation

engines/extism/evaluator/evaluator.go:114-118: when the guest fails for its own reason while ctx is cancelled, the real error is replaced with "execution cancelled: context canceled", discarding the cause. (Root cause that cancellation doesn't actually interrupt execution is #155.) Fix: wrap both errors, or prefer ctx.Err() only for wazero's exit-code-canceled sentinel.

Impact

Low individually — edge cases with clear repros, none covered by existing tests. Worth fixing for robustness and cross-engine consistency.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions