@@ -63,7 +63,7 @@ public LogicalPlan createStatement(String sql, List<SqlTypedParamValue> params)
6363 if (log .isDebugEnabled ()) {
6464 log .debug ("Parsing as statement: {}" , sql );
6565 }
66- return invokeParser ("statement" , sql , params , SqlBaseParser ::singleStatement , AstBuilder ::plan );
66+ return invokeParser (sql , params , SqlBaseParser ::singleStatement , AstBuilder ::plan );
6767 }
6868
6969 /**
@@ -81,11 +81,10 @@ public Expression createExpression(String expression, List<SqlTypedParamValue> p
8181 log .debug ("Parsing as expression: {}" , expression );
8282 }
8383
84- return invokeParser ("expression" , expression , params , SqlBaseParser ::singleExpression , AstBuilder ::expression );
84+ return invokeParser (expression , params , SqlBaseParser ::singleExpression , AstBuilder ::expression );
8585 }
8686
87- private <T > T invokeParser (String name ,
88- String sql ,
87+ private <T > T invokeParser (String sql ,
8988 List <SqlTypedParamValue > params , Function <SqlBaseParser ,
9089 ParserRuleContext > parseFunction ,
9190 BiFunction <AstBuilder , ParserRuleContext , T > visitor ) {
@@ -100,6 +99,7 @@ private <T> T invokeParser(String name,
10099 CommonTokenStream tokenStream = new CommonTokenStream (tokenSource );
101100 SqlBaseParser parser = new SqlBaseParser (tokenStream );
102101
102+ parser .addParseListener (new CircuitBreakerProcessor ());
103103 parser .addParseListener (new PostProcessor (Arrays .asList (parser .getRuleNames ())));
104104
105105 parser .removeErrorListeners ();
@@ -126,11 +126,7 @@ private <T> T invokeParser(String name,
126126 log .info ("Parse tree {} " + tree .toStringTree ());
127127 }
128128
129- try {
130- return visitor .apply (new AstBuilder (paramTokens ), tree );
131- } catch (StackOverflowError e ) {
132- throw new ParsingException ("{} is too large to parse (causes stack overflow)" , name );
133- }
129+ return visitor .apply (new AstBuilder (paramTokens ), tree );
134130 }
135131
136132 private static void debug (SqlBaseParser parser ) {
@@ -162,7 +158,7 @@ private class PostProcessor extends SqlBaseBaseListener {
162158 public void exitBackQuotedIdentifier (SqlBaseParser .BackQuotedIdentifierContext context ) {
163159 Token token = context .BACKQUOTED_IDENTIFIER ().getSymbol ();
164160 throw new ParsingException (
165- "backquoted indetifiers not supported; please use double quotes instead" ,
161+ "backquoted identifiers not supported; please use double quotes instead" ,
166162 null ,
167163 token .getLine (),
168164 token .getCharPositionInLine ());
@@ -213,6 +209,24 @@ public void exitNonReserved(SqlBaseParser.NonReservedContext context) {
213209 }
214210 }
215211
212+ /**
213+ * Used to catch large expressions that can lead to stack overflows
214+ */
215+ private class CircuitBreakerProcessor extends SqlBaseBaseListener {
216+
217+ private static final short MAX_BOOLEAN_ELEMENTS = 1000 ;
218+ private short countElementsInBooleanExpressions = 0 ;
219+
220+ @ Override
221+ public void enterLogicalBinary (SqlBaseParser .LogicalBinaryContext ctx ) {
222+ if (++countElementsInBooleanExpressions == MAX_BOOLEAN_ELEMENTS ) {
223+ throw new ParsingException ("boolean expression is too large to parse, (exceeds {} elements)" ,
224+ MAX_BOOLEAN_ELEMENTS );
225+ }
226+ super .enterLogicalBinary (ctx );
227+ }
228+ }
229+
216230 private static final BaseErrorListener ERROR_LISTENER = new BaseErrorListener () {
217231 @ Override
218232 public void syntaxError (Recognizer <?, ?> recognizer , Object offendingSymbol , int line ,
0 commit comments