Description
An FT.AGGREGATE APPLY (or other expression stage) that calls a string function on a schema field which is not loaded into the evaluation record aborts the server via a fatal CHECK(false). The field evaluates to a Nil Value, and the string-coercion path asserts on Nil. Reachable by any client that can run FT.AGGREGATE (a @read command).
Steps to reproduce
FT.CREATE idx ON HASH PREFIX 1 doc: SCHEMA n NUMERIC t TAG
HSET doc:1 n 5 t a
FT.AGGREGATE idx '@n:[0 100]' APPLY 'upper(@t)' AS r
Server aborts (Error: Server closed the connection; PING then refused). Also crashes with lower(@t), substr(@t,0,5), contains(@t,'x'), strlen(@n). Requires >=1 matching record so the APPLY stage executes. Contrast: LOAD 1 @t APPLY upper(@t) is safe (field populated), and upper('abc') literal is safe.
Crash output
valkey ... crashed by signal: 6, si_code: -6
F0000 ... value.cc:145] Check failed: false
valkey_search::expr::Value::AsStringView()
<- valkey_search::expr::FuncUpper
<- expr::FunctionCall::Evaluate
<- aggregate::Apply::Execute
Root cause
src/expr/value.cc: Value::AsStringView() (and AsString()) end in CHECK(false) for the Nil variant (value.cc:145 / :159). The string functions (FuncUpper/FuncLower/FuncSubstr/FuncContains/strlen, value.cc ~400-470) call AsStringView()/AsString() on their argument with no IsNil() guard, unlike the numeric functions. A schema field not explicitly LOADed evaluates to a default-constructed Nil Value, so upper(@t) reaches CHECK(false) and aborts. Aggregation stages run on the main thread (blocked-client reply), so the abort kills the whole server.
Suggested fix
Return Value::Nil(...) (or an error) from the string functions when the operand is Nil, and/or convert the CHECK(false) in AsStringView/AsString to a returned error.
Environment
- valkey-search
origin/main (8c260db); also reproduces on valkey/valkey-bundle:unstable
- Confirmed live on current
main: value.cc:145 CHECK(false) is unchanged.
This issue was generated by AI but verified, with love, by a human.
Description
An
FT.AGGREGATEAPPLY(or other expression stage) that calls a string function on a schema field which is not loaded into the evaluation record aborts the server via a fatalCHECK(false). The field evaluates to a NilValue, and the string-coercion path asserts on Nil. Reachable by any client that can runFT.AGGREGATE(a@readcommand).Steps to reproduce
Server aborts (
Error: Server closed the connection; PING then refused). Also crashes withlower(@t),substr(@t,0,5),contains(@t,'x'),strlen(@n). Requires >=1 matching record so the APPLY stage executes. Contrast:LOAD 1 @t APPLY upper(@t)is safe (field populated), andupper('abc')literal is safe.Crash output
Root cause
src/expr/value.cc:Value::AsStringView()(andAsString()) end inCHECK(false)for the Nil variant (value.cc:145 / :159). The string functions (FuncUpper/FuncLower/FuncSubstr/FuncContains/strlen, value.cc ~400-470) callAsStringView()/AsString()on their argument with noIsNil()guard, unlike the numeric functions. A schema field not explicitlyLOADed evaluates to a default-constructed NilValue, soupper(@t)reachesCHECK(false)and aborts. Aggregation stages run on the main thread (blocked-client reply), so the abort kills the whole server.Suggested fix
Return
Value::Nil(...)(or an error) from the string functions when the operand is Nil, and/or convert theCHECK(false)inAsStringView/AsStringto a returned error.Environment
origin/main(8c260db); also reproduces onvalkey/valkey-bundle:unstablemain:value.cc:145CHECK(false)is unchanged.This issue was generated by AI but verified, with love, by a human.