diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6e07f75a4c..39ad1c1ce6 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,6 @@ # Unreleased + - Fix DefinedAttributeTemplateEngine lexer bug swallowing single-quoted text with escapes (#1906) - ANTLr 4.10.1 - GSON 2.9.0 fixes CVE-2022-25647 diff --git a/core/src/main/antlr4/org/jdbi/v3/core/internal/lexer/DefineStatementLexer.g4 b/core/src/main/antlr4/org/jdbi/v3/core/internal/lexer/DefineStatementLexer.g4 index 070e9e3ea7..f6657f8cfc 100644 --- a/core/src/main/antlr4/org/jdbi/v3/core/internal/lexer/DefineStatementLexer.g4 +++ b/core/src/main/antlr4/org/jdbi/v3/core/internal/lexer/DefineStatementLexer.g4 @@ -13,9 +13,7 @@ */ lexer grammar DefineStatementLexer; -fragment QUOTE: '\'' ; -fragment ESCAPE: '\\' ; -fragment ESCAPE_QUOTE: ESCAPE QUOTE ; +fragment ESCAPE_IN_QUOTE: '\\' ['\\] ; fragment DOUBLE_QUOTE: '"' ; fragment LT: '<' ; fragment GT: '>' ; @@ -25,9 +23,9 @@ fragment NAME: JAVA_LETTER | [0-9]; fragment JAVA_LETTER : [a-zA-Z$_] | ~[\u0000-\u007F\uD800-\uDBFF] | [\uD800-\uDBFF] [\uDC00-\uDFFF]; COMMENT: '/*' .*? '*/' | '--' ~('\r' | '\n')* | '//' ~('\r' | '\n')*; -QUOTED_TEXT: QUOTE (ESCAPE_QUOTE | ~'\'')* QUOTE; +QUOTED_TEXT: '\'' (~['\\\r\n] | ESCAPE_IN_QUOTE)* '\''; DOUBLE_QUOTED_TEXT: DOUBLE_QUOTE (~'"')+ DOUBLE_QUOTE; -ESCAPED_TEXT : ESCAPE . ; +ESCAPED_TEXT : '\\' . ; DEFINE: LT (NAME)+ GT; diff --git a/core/src/test/java/org/jdbi/v3/core/statement/DefinedAttributeTemplateEngineTest.java b/core/src/test/java/org/jdbi/v3/core/statement/DefinedAttributeTemplateEngineTest.java new file mode 100644 index 0000000000..2990f8b2a9 --- /dev/null +++ b/core/src/test/java/org/jdbi/v3/core/statement/DefinedAttributeTemplateEngineTest.java @@ -0,0 +1,49 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jdbi.v3.core.statement; + +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.junit5.H2DatabaseExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DefinedAttributeTemplateEngineTest { + + @RegisterExtension + public H2DatabaseExtension h2Extension = H2DatabaseExtension.instance() + .withConfig(SqlStatements.class, st -> st.setTemplateEngine(new DefinedAttributeTemplateEngine())); + + String renderedSql; + + @Test + public void testBackslash1906() { + final Handle handle = h2Extension.getSharedHandle(); + final SqlLogger captureSql = new SqlLogger() { + @Override + public void logAfterExecution(final StatementContext context) { + renderedSql = context.getRenderedSql(); + } + }; + handle.setSqlLogger(captureSql); + final String backslashSql = "SELECT '\\\\' = '\\\\'"; + handle + .createQuery(backslashSql) + .mapTo(boolean.class) + .one(); + assertThat(renderedSql).isEqualTo(backslashSql); + System.err.println(renderedSql); + } +}