Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function expression failed with string paramater which contains \ #41

Open
lemanhtien opened this issue Sep 14, 2022 · 1 comment
Open

Comments

@lemanhtien
Copy link

lemanhtien commented Sep 14, 2022

Here is the default test case, which the result is correct

func testCallAnyExpressionSymbolEvaluatorConstant() {
        let expression = AnyExpression("foo('foo', 'bar')", constants: [
            "foo": { ($0[0] as! String) + ($0[1] as! String) } as AnyExpression.SymbolEvaluator,
        ])
        XCTAssertEqual(try expression.evaluate(), "foobar")
        XCTAssertEqual(expression.symbols, [.function("foo", arity: 2)])
    }

Modify the parameter value a bit, by adding "\", then the result is wrong

  func testCallAnyExpressionSymbolEvaluatorConstant() {
        let expression = AnyExpression("foo('foo\\s', 'bar')", constants: [
            "foo": { ($0[0] as! String) + ($0[1] as! String) } as AnyExpression.SymbolEvaluator,
        ])
        XCTAssertEqual(try expression.evaluate(), "foo\\sbar")
        XCTAssertEqual(expression.symbols, [.function("foo", arity: 2)])
    }

I tested several test case, and noticed that if the parameter is string, and it contains \\, the result will be wrong.

Do you have any ideas to update this one? I think it relates to the function parseEscapedIdentifier.

@nicklockwood
Copy link
Owner

@lemanhtien sorry for the late reply. From what I can see, this is behaving correctly. What's confusing is the double escaping.

In Swift strings literals \ is an escaped slash, so you get a single \ in the output.

But when that swift string contains an expression, then that single \ is passed to the expression parser. "\s" is not a known escape sequence so the \ is silently dropped, resulting in "foobar" as the output. To include a literal \ in the value you would need to double-escape the slash, like this:

let expression = AnyExpression("foo('foo\\\\s', 'bar')", constants: [...])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants