piotr-oles/rsql

emit and parse fail to respect some escaping rules for quotes and backslashes

TimHambourger opened this issue · 0 comments

emit and parse both fail to respect some of the escaping rules for quotes and backslashes from rsql-parser (relevant excerpts quoted below). The result is that ValueNodes whose value contains double quotes get corrupted when round-tripping through emit then parse.

@rsql version 1.3.2
Node version 16.15.1

Repro steps
Run the following snippet in an ES6 JS environment:

import builder from "@rsql/builder";
import { emit } from "@rsql/emitter";
import { parse } from "@rsql/parser";

const node = builder.comparison("selector", "==", "foo\"bar\\baz");
console.log(node.right.value);

const rsql = emit(node);
console.log(rsql);

const roundTrippedNode = parse(rsql);
// In TS we'd need to assert that roundTrippedNode is a ComparisonNode for this to compile.
console.log(roundTrippedNode.right.value);

Expected outcome
Console contains the following logged values (per rsql-parser escaping rules):

foo"bar\baz
selector=="foo\"bar\\baz"
foo"bar\baz

Actual outcome
Console contains the following logged values:

foo"bar\baz
selector=="fo\"bar\baz"
fo\"bar\baz

Relevant rsql-parser escaping rules
From https://github.com/jirutka/rsql-parser#grammar-and-semantic (emphasis added):

If you need to use both single and double quotes inside a quoted argument, then you must escape one of them using \ (backslash). If you want to use \ literally, then double it as \\. Backslash has a special meaning only inside a quoted argument, not in unquoted argument.

Analysis
emit escapes " (double quote) as \", but in the process it consumes the preceding character. Furthermore, emit fails to escape \ (backslash) as \\, as is required if (and only if) the value is being wrapped in quotes.

Meanwhile, parse correctly continues parsing the ValueNode's value past the \" sequence, i.e. it doesn't mistake the " in \" as ending the ValueNode's value. But parse fails to consume the \ in \" in the process, as it fails to consume the later \ in bar\baz.