Skip to content

bug: Starlark result conversion is lossy — big ints become 0, tuples/sets/bytes become nil #157

Description

@robbyt

Summary

ConvertStarlarkValueToInterface in engines/starlark/internal/converters.go silently loses data for several legal result types. Scripts return valid values; Interface() returns a wrong value or nil and only logs an error.

1. Big ints convert to 0

engines/starlark/internal/converters.go:59-61:

case starlarkLib.Int:
	i, _ := v.Int64()   // ok flag discarded
	return i, nil

starlark-go's Int64() returns (0, false) for ints that don't fit in int64. Discarding ok yields 0.

Repro (confirmed): _ = 1 << 64Inspect() reports 18446744073709551616, Interface() returns 0.

Fix: check ok; on failure fall back to v.BigInt() (*big.Int), a float, a string, or an explicit error — not a silent 0.

2. Tuple, set, and bytes results become nil

ConvertStarlarkValueToInterface (converters.go:53-102) has no case for starlark.Tuple, *starlark.Set, or starlark.Bytes, so they hit the default branch and return an error; Interface() (engines/starlark/evaluator/response.go:101-108) logs it and returns nil. Meanwhile Type() (response.go:50-77) advertises "tuple"data.TUPLE and "set"data.SET, so Type() and Interface() disagree.

Repro (confirmed):

  • _ = (1, 2, 3)Type() == data.TUPLE, Interface() == nil
  • _ = set([1, 2])Type() == data.SET, Interface() == nil
  • _ = b"abc"Interface() == nil, and Type() == data.ERROR ("bytes" is also unmapped in the Type() switch, hitting its default at response.go:73-75)

Fix: add conversion cases — starlark.Tuple[]any, *starlark.Set[]any, starlark.Bytes[]byte or string. For the Type() switch, note there is no data.BYTES constant (platform/data/types.go), so either map "bytes"data.STRING or add a BYTES constant.

Impact

High — legal script results are silently corrupted (big ints) or dropped to nil (tuple/set/bytes) while the type system reports success. No existing test covers these cases.

Fix

Handle all four types in ConvertStarlarkValueToInterface, resolve "bytes" in Type(), and add table tests for big-int, tuple, set, and bytes results asserting Type() and Interface() agree.

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