You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(parser): a float literal beyond f64's range in a persistent rule stops the engine from starting #397
Found by the iql_statement fuzz target from #301 (local pre-campaign, 3 crash inputs, one root cause).
Problem
The IQL parsers accept float literals that are not finite numbers:
literals beyond f64's range, such as 1e400 or -1.0e309, parse to ±infinity;
Rust's own float spellings inf, infinity and NaN (any case) parse as floats, because the parsers call str::parse::<f64>() before they check for identifiers.
A persistent rule holding one is stored as JSON in the write-ahead log and the rule catalog. JSON has no infinity or NaN, so serde_json writes null. On the next start, StorageEngine::new fails to decode that record, and the engine does not start:
+r(1)
+p(X) <- r(Y), X = Y + 1e400 -> Rule 'p' registered.
(restart)
WalUnreadable { file: ".../persist/wal/current.wal", offset: 98,
reason: "invalid type: null, expected f64 at line 1 column 379" }
Any client that may register a rule (editor and above) can stop the engine from starting with one statement. This is the same class as the persisted-rule depth trap fixed in #295.
The same literals also reach facts (+r(1e400), +r(inf)), vector literals ([1e400], [NaN]), comparisons and type refinements. Those do not break a restart, but they put infinities and NaN into data that no client asked for.
Where
src/parser/mod.rs (parse_term, the negative-literal path, vector literals, parse_arithmetic constants), src/statement/parser.rs (parse_single_term, vector literals) and src/statement/types.rs (refinement arguments) all use parse::<f64>() directly. Only parse_term's first check tested is_finite(), and it then fell through to the other paths.
Fix
Parse every float literal through one function that accepts only decimal syntax (digits, a fraction, an exponent) and refuses a literal beyond f64's range with a validation error. inf, infinity and NaN are then identifiers like any other. Underflow to zero (1e-400) stays accepted.
Activity
fix(parser): refuse float literals beyond f64's range (#397)
test: cargo-fuzz harness for the IQL parser and /ws frames; refuse no…