-
Notifications
You must be signed in to change notification settings - Fork 45
Description
At the moment, most (if not all) Fluent parsers are implemented with recursive descent. Therefore, they are vulnerable to stack overflow. If a Fluent file comes from an untrusted source, a malicious user can bring the parser down with such resource as a = {{{{{…500 times…{{{{{
(0.5 KB!). The impact varies between different environments: in some, a runtime raises an exception that can be recovered from; in others, the whole process is terminated.
I think, parsing such extremely deeply nested constructs as Junk
(even if they are otherwise well-formed) fits Fluent’s recovery strategy well.
Non-recursive parsers are unaffected by this issue, but it seems a good idea if they would impose similiar limits. Although they are able to construct an AST in such pathological cases, it cannot be processed recursively by other parts of the program.
I spotted these cycles in the grammar that need to be taken care of:
inline_placeable → InlineExpression → inline_placeable
,inline_placeable → SelectExpression → InlineExpression → inline_placeable
,InlineExpression → (FunctionReference | TermReference) → CallArguments → argument_list → Argument → InlineExpression
,Pattern → PatternElement → inline_placeable → SelectExpression → variant_list → (Variant | DefaultVariant) → Pattern
.
There is also block_placeable
, but it’s defined in terms of inline_placeable
, so it likely won’t need special handling. Worth mentioning, anyway.