Skip to content
Snippets Groups Projects
Unverified Commit 449d5d3b authored by Ariya Hidayat's avatar Ariya Hidayat Committed by GitHub
Browse files

Custom expression tokenizer: rewind on an unterminated string literal (#18969)

parent b334ccd6
No related branches found
No related tags found
No related merge requests found
...@@ -215,10 +215,17 @@ export function tokenize(expression) { ...@@ -215,10 +215,17 @@ export function tokenize(expression) {
} }
} }
const type = TOKEN.String; const type = TOKEN.String;
const end = index; let error = null;
const terminated = quote === source[end - 1];
const error = terminated ? null : t`Missing closing quotes`; const terminated = quote === source[index - 1];
return { type, value, start, end, error }; if (!terminated) {
// unterminated string, rewind after the opening quote
index = start + 1;
value = quote;
error = t`Missing closing quotes`;
}
return { type, value, start, end: index, error };
}; };
const scanBracketIdentifier = () => { const scanBracketIdentifier = () => {
......
...@@ -22,8 +22,6 @@ describe("metabase/lib/expressions/completer", () => { ...@@ -22,8 +22,6 @@ describe("metabase/lib/expressions/completer", () => {
expect(partialMatch("X OR")).toEqual(null); expect(partialMatch("X OR")).toEqual(null);
expect(partialMatch("42 +")).toEqual(null); expect(partialMatch("42 +")).toEqual(null);
expect(partialMatch("3.14")).toEqual(null); expect(partialMatch("3.14")).toEqual(null);
expect(partialMatch('"Hello')).toEqual(null);
expect(partialMatch("'world")).toEqual(null);
}); });
it("should handle empty input", () => { it("should handle empty input", () => {
......
...@@ -66,6 +66,18 @@ describe("metabase/lib/expressions/tokenizer", () => { ...@@ -66,6 +66,18 @@ describe("metabase/lib/expressions/tokenizer", () => {
expect(errors('"double')[0].message).toEqual("Missing closing quotes"); expect(errors('"double')[0].message).toEqual("Missing closing quotes");
}); });
it("should continue to tokenize when encountering an unterminated string literal", () => {
expect(types("CONCAT(universe') = [answer]")).toEqual([
T.Identifier,
T.Operator,
T.Identifier,
T.String,
T.Operator,
T.Operator,
T.Identifier,
]);
});
it("should tokenize identifiers", () => { it("should tokenize identifiers", () => {
expect(types("Price")).toEqual([T.Identifier]); expect(types("Price")).toEqual([T.Identifier]);
expect(types("Special_Deal")).toEqual([T.Identifier]); expect(types("Special_Deal")).toEqual([T.Identifier]);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment