From 1d0c2e316116c76c21ebbcb3f12ea887cfe3210b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Locker?= Date: Wed, 8 May 2024 08:42:41 +0200 Subject: [PATCH] Avoid NPE when the input DRL is empty (#5894) --- .../drl/parser/antlr4/MiscDRLParserTest.java | 7 +++++++ .../drools/drl/parser/antlr4/DescrHelper.java | 20 +++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java b/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java index ffc1eeac067..724662f4291 100644 --- a/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java +++ b/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java @@ -153,6 +153,13 @@ private QueryDescr parseAndGetFirstQueryDescrFromFile(String filename) { return parseAndGetFirstQueryDescr(readResource(filename)); } + @Test + void emptySource() { + final String source = ""; + final PackageDescr pkg = parseAndGetPackageDescr(source); + assertThat(pkg.getName()).isEmpty(); + } + @Test void parse_validPackage() { final String source = "package foo.bar.baz"; diff --git a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DescrHelper.java b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DescrHelper.java index b091b8f588f..a822b5ddf76 100644 --- a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DescrHelper.java +++ b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DescrHelper.java @@ -21,6 +21,7 @@ import java.util.List; import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.TerminalNode; import org.drools.drl.ast.descr.AndDescr; import org.drools.drl.ast.descr.AttributeDescr; @@ -38,23 +39,26 @@ private DescrHelper() { } public static T populateCommonProperties(T descr, ParserRuleContext ctx) { + Token startToken = ctx.getStart(); // Start token is never null. + // If the stop token is null, use the start token as both the start end the end. + Token stopToken = ctx.getStop() != null ? ctx.getStop() : startToken; if (descr instanceof ExprConstraintDescr) { // Backward Compatibility Notes: // Old DRL6Parser.constraint() has slightly different behavior for ExprConstraintDescr. Keep it for backward compatibility // When we will update LanguageLevel, we can align this with other Descr. - descr.setStartCharacter(ctx.getStart().getStartIndex()); - descr.setEndCharacter(ctx.getStop().getStopIndex()); - descr.setLocation(ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine()); - descr.setEndLocation(ctx.getStop().getLine(), ctx.getStop().getCharPositionInLine()); + descr.setStartCharacter(startToken.getStartIndex()); + descr.setEndCharacter(stopToken.getStopIndex()); + descr.setLocation(startToken.getLine(), startToken.getCharPositionInLine()); + descr.setEndLocation(stopToken.getLine(), stopToken.getCharPositionInLine()); } else { - descr.setStartCharacter(ctx.getStart().getStartIndex()); + descr.setStartCharacter(startToken.getStartIndex()); // Backward Compatibility Notes: // Old DRL6Parser adds +1 for EndCharacter (except ExprConstraintDescr). This new parser follows the same to keep the backward compatibility. // However, it doesn't look reasonable. When we will update LanguageLevel, we can remove this +1. - descr.setEndCharacter(ctx.getStop().getStopIndex() + 1); - descr.setLocation(ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine()); - descr.setEndLocation(ctx.getStop().getLine(), ctx.getStop().getCharPositionInLine() + ctx.getStop().getText().length() - 1); // last column of the end token + descr.setEndCharacter(stopToken.getStopIndex() + 1); + descr.setLocation(startToken.getLine(), startToken.getCharPositionInLine()); + descr.setEndLocation(stopToken.getLine(), stopToken.getCharPositionInLine() + stopToken.getText().length() - 1); // last column of the end token } return descr; }