From b00f1b7c396bb4d982f33d3ff7cd488e712c90e5 Mon Sep 17 00:00:00 2001 From: seonwoo_jung <79202163+seonwooj0810@users.noreply.github.com> Date: Tue, 30 Jun 2026 15:13:57 +0900 Subject: [PATCH] fix(template): treat invalid expression pattern modifier as literal A header-map (or any template) value such as "{test:[abc}" parses as a {name:pattern} expression, but the ':' value modifier ("[abc") is not a valid regular expression. Expression's constructor compiles it eagerly with Pattern.compile, so an invalid modifier threw PatternSyntaxException during template construction (gh-2739) instead of the value being used as-is. Expressions.create already returns null to signal "this is not a usable expression, treat the chunk as a literal". Extend that contract to a PatternSyntaxException from the value modifier: catch it and return null so the chunk falls back to a literal. Valid expressions such as {id:[0-9]+} are unaffected. Signed-off-by: seonwoo_jung <79202163+seonwooj0810@users.noreply.github.com> --- .../main/java/feign/template/Expressions.java | 25 +++++++++++++------ .../java/feign/template/ExpressionsTest.java | 11 ++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/feign/template/Expressions.java b/core/src/main/java/feign/template/Expressions.java index 65fa5123e2..e37872fff6 100644 --- a/core/src/main/java/feign/template/Expressions.java +++ b/core/src/main/java/feign/template/Expressions.java @@ -22,6 +22,7 @@ import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; public final class Expressions { @@ -104,15 +105,23 @@ public static Expression create(final String value) { } } - /* check for an operator */ - if (PATH_STYLE_OPERATOR.equalsIgnoreCase(operator)) { - return new PathStyleExpression(variableName, variablePattern); - } + try { + /* check for an operator */ + if (PATH_STYLE_OPERATOR.equalsIgnoreCase(operator)) { + return new PathStyleExpression(variableName, variablePattern); + } - /* default to simple */ - return SimpleExpression.isSimpleExpression(value) - ? new SimpleExpression(variableName, variablePattern) - : null; // Return null if it can't be validated as a Simple Expression -- Probably a Literal + /* default to simple; null if it can't be validated as a Simple Expression -- probably a literal */ + return SimpleExpression.isSimpleExpression(value) + ? new SimpleExpression(variableName, variablePattern) + : null; + } catch (PatternSyntaxException e) { + /* + * the ':' value modifier did not contain a valid regular expression, so this is not a usable + * expression -- treat it as a literal instead of failing template construction. + */ + return null; + } } private static String stripBraces(String expression) { diff --git a/core/src/test/java/feign/template/ExpressionsTest.java b/core/src/test/java/feign/template/ExpressionsTest.java index 0586bd231e..49af8aec27 100644 --- a/core/src/test/java/feign/template/ExpressionsTest.java +++ b/core/src/test/java/feign/template/ExpressionsTest.java @@ -44,6 +44,17 @@ void malformedExpression() { } } + @Test + void invalidPatternModifierIsTreatedAsLiteral() { + /* + * gh-2739: a header-map value such as "{test:[abc}" parses as a "{name:pattern}" expression, + * but the ':' modifier ("[abc") is not a valid regular expression. Compiling it must not blow + * up template construction with a PatternSyntaxException -- it should fall back to a literal. + */ + Expression expression = Expressions.create("{test:[abc}"); + assertThatObject(expression).isNull(); + } + @Test void malformedBodyTemplate() { String bodyTemplate = "{" + "a".repeat(65536) + "}";