noir-lang / noir

Noir is a domain specific language for zero knowledge proofs
https://noir-lang.org
Apache License 2.0
884 stars 194 forks source link

(fuzzer) - Parsing ambiguity with expressions and lambdas #3232

Closed pczarn closed 4 weeks ago

pczarn commented 1 year ago

Aim

Tried to parse the following Noir code found by the parser-fuzzer:

fn foo() -> fn(u32) -> u32 {
    {
        // some statements
    }
    |arg: u32| arg + 123
}

As well as this valid Rust code in Rust:

fn foo() -> impl Fn(u32) -> u32 {
    {
        // ...
    }
    |arg: u32| arg + 123
}

Expected Behavior

Expected a successful parse.

Bug

The parser attempts to parse lambda | as operators in an expression {} | ... | expr.

The parse error is, expected binary operator, found colon: ParserError { expected_tokens: {}, expected_labels: {BinaryOperator}, found: Colon, reason: None, span: Span(Span { start: ByteIndex(70), end: ByteIndex(71) }) }]

This means making a formal grammar for Noir that follows the parser is hard.

To Reproduce

Try to parse code with a block followed by a lambda expression.

Installation Method

Compiled from source.

Additional Context

Found by the parser-fuzzer tool.

Would you like to submit a PR for this Issue?

No

jfecher commented 1 year ago

Hmm I wonder how rust parses {} || a; as two statements rather than a Binop(Or, Block, Var("a"))

pczarn commented 1 year ago

Changed the title after finding a more troubling cases:

fn foo() -> fn(u32) -> u32 {
    if bar == baz {
        // something
    }
    |arg: u32| arg + 123
}
asterite commented 4 weeks ago

This was already fixed in the past where a block expression was also eventually parsed as a block statement. (this works fine in master)