From 993c4c4cab21ace8970d094da03291b21547ab83 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 19 Oct 2022 12:22:31 +0200 Subject: [PATCH] WW-3529 Fixes using RegEx related characters in named pattern --- .../util/NamedVariablePatternMatcher.java | 71 +++++++++++-------- .../util/NamedVariablePatternMatcherTest.java | 27 +++++-- 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java b/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java index cb848868d..24e5e9b35 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java @@ -18,6 +18,8 @@ */ package com.opensymphony.xwork2.util; +import org.apache.commons.lang3.StringUtils; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -57,7 +59,7 @@ import java.util.regex.Pattern; * * *

- * Excaping hasn't been implemented since the intended use of these patterns will be in matching URLs. + * Escaping hasn't been implemented since the intended use of these patterns will be in matching URLs. *

* * @since 2.1 @@ -75,38 +77,47 @@ public class NamedVariablePatternMatcher implements PatternMatcher 0) { - List varNames = new ArrayList<>(); - StringBuilder varName = null; - for (int x=0; x varNames = new ArrayList<>(); + int s = 0; + while (s < len) { + int e = data.indexOf('{', s); + if (e < 0 && data.indexOf('}') > -1) { + throw new IllegalArgumentException("Missing openning '{' in [" + data + "]!"); + } + if (e < 0) { + regex.append(Pattern.quote(data.substring(s))); + break; + } + if (e > s) { + regex.append(Pattern.quote(data.substring(s, e))); + } + s = e + 1; + e = data.indexOf('}', s); + if (e < 0) { + return null; + } + String varName = data.substring(s, e); + if (StringUtils.isEmpty(varName)) { + throw new IllegalArgumentException("Missing variable name in [" + data + "]!"); + } + varNames.add(varName); + regex.append("([^/]+)"); + s = e + 1; + } + return new CompiledPattern(Pattern.compile(regex.toString()), varNames); } /** * Tries to process the data against the compiled expression. If successful, the map will contain * the matched data, using the specified variable names in the original pattern. * - * @param map The map of variables + * @param map The map of variables * @param data The data to match * @param expr The compiled pattern * @return True if matched, false if not matched, the data was null, or the data was an empty string @@ -116,8 +127,8 @@ public class NamedVariablePatternMatcher implements PatternMatcher 0) { Matcher matcher = expr.getPattern().matcher(data); if (matcher.matches()) { - for (int x=0; x variableNames; + private final Pattern pattern; + private final List variableNames; public CompiledPattern(Pattern pattern, List variableNames) { diff --git a/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java b/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java index e11fb6870..b5eda4f0a 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcherTest.java @@ -37,15 +37,18 @@ public class NamedVariablePatternMatcherTest { assertNull(matcher.compilePattern(null)); assertNull(matcher.compilePattern("")); - CompiledPattern pattern = matcher.compilePattern("foo"); - assertEquals("foo", pattern.getPattern().pattern()); + CompiledPattern pattern = matcher.compilePattern("action.{format}"); + assertEquals("\\Qaction.\\E([^/]+)", pattern.getPattern().pattern()); + + pattern = matcher.compilePattern("foo"); + assertEquals("\\Qfoo\\E", pattern.getPattern().pattern()); pattern = matcher.compilePattern("foo{jim}"); - assertEquals("foo([^/]+)", pattern.getPattern().pattern()); + assertEquals("\\Qfoo\\E([^/]+)", pattern.getPattern().pattern()); assertEquals("jim", pattern.getVariableNames().get(0)); pattern = matcher.compilePattern("foo{jim}/{bob}"); - assertEquals("foo([^/]+)/([^/]+)", pattern.getPattern().pattern()); + assertEquals("\\Qfoo\\E([^/]+)\\Q/\\E([^/]+)", pattern.getPattern().pattern()); assertEquals("jim", pattern.getVariableNames().get(0)); assertEquals("bob", pattern.getVariableNames().get(1)); assertTrue(pattern.getPattern().matcher("foostar/jie").matches()); @@ -53,12 +56,26 @@ public class NamedVariablePatternMatcherTest { } @Test(expected = IllegalArgumentException.class) - public void testCompileWithMismatchedBracketsParses() { + public void testCompileWithMissingVariableName() { + NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); + + matcher.compilePattern("{}"); + } + + @Test(expected = IllegalArgumentException.class) + public void testCompileWithMissingOpeningBracket1() { NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); matcher.compilePattern("}"); } + @Test(expected = IllegalArgumentException.class) + public void testCompileWithMissingOpeningBracket2() { + NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher(); + + matcher.compilePattern("test}"); + } + @Test public void testMatch() { NamedVariablePatternMatcher matcher = new NamedVariablePatternMatcher();