Skip to content

fix(builtin): guard against missing args in builtins#943

Open
thevilledev wants to merge 1 commit intoexpr-lang:masterfrom
thevilledev:fix/fuzz-5912218922450944
Open

fix(builtin): guard against missing args in builtins#943
thevilledev wants to merge 1 commit intoexpr-lang:masterfrom
thevilledev:fix/fuzz-5912218922450944

Conversation

@thevilledev
Copy link
Contributor

@thevilledev thevilledev commented Mar 7, 2026

Motivation

Relates to #941.

OSS-Fuzz finding has a fuzzed expression which calls join() with zero arguments inside a method call on an any-typed value (e.g. fn().N(join())). The type checker's callNode() skips argument validation when the callee resolves to an unknown type, so the invalid call passes compilation. At runtime join() accesses args[0] on an empty slice, producing a Go runtime panic instead of a clean error.

I found similar issues from other builtins, relying solely on compile-time validation that can be bypassed.

Changes

Add runtime len(args) guards to a number of builtin functions. Each now returns a descriptive error. This error is already part of the allowlist in the fuzzing harness.

I also removed some autogenerated test lines that called first and last with wrong arity. These tests were passing because of defer recover() silently swallowing the panic.

Further comments

I think there is a chance to fix this in the checker, to provide compile-time rejection. But I guess it'll be quite complicated because of optional chaining on unknown types for a number of different expressions. This fix is the conservative kind just to have clean and descriptive runtime errors.

The type checker skips argument validation for calls where the
callee has unknown type (e.g. method calls on any-typed values).
This allowed builtins like join() to reach runtime with zero
arguments, panicking on args[0] access.

Add runtime len(args) guards to a number of builtin functions that
previously accessed args elements without bounds checking.

Also fix date() to check len(args) a second time after stripping
a leading *time.Location argument.

Relates to OSS-Fuzz finding in expr-lang#941.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
@thevilledev thevilledev force-pushed the fix/fuzz-5912218922450944 branch from 4bf22b5 to bcac8d1 Compare March 10, 2026 20:07
@thevilledev thevilledev marked this pull request as ready for review March 11, 2026 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant