This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new f9797cdfe0 FELIX-6619 : Configadmin interpolator can run into a
StackOverflow
f9797cdfe0 is described below
commit f9797cdfe0036b378afba2699602e0a679282249
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Thu Jul 20 07:47:22 2023 +0200
FELIX-6619 : Configadmin interpolator can run into a StackOverflow
---
.../plugin/interpolation/Interpolator.java | 42 ++++++++++++++--------
.../plugin/interpolation/InterpolatorTest.java | 11 ++++++
2 files changed, 39 insertions(+), 14 deletions(-)
diff --git
a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Interpolator.java
b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Interpolator.java
index 8fd727869f..640af5956f 100755
---
a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Interpolator.java
+++
b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Interpolator.java
@@ -18,7 +18,9 @@ package org.apache.felix.configadmin.plugin.interpolation;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -109,6 +111,10 @@ public class Interpolator {
* @return Replaced object (or original value)
*/
public static Object replace(final String value, final Provider provider) {
+ return replaceInternal(value, provider, new HashSet<>());
+ }
+
+ private static Object replaceInternal(final String value, final Provider
provider, final Set<String> visited) {
String result = value;
int index = -1;
while (index < result.length()) {
@@ -136,7 +142,7 @@ public class Interpolator {
final Map<String, String> directives;
final String name;
if (dirPos != -1) {
- directives = parseDirectives(replace(postfix.substring(dirPos
+ 1), provider).toString());
+ directives =
parseDirectives(replaceInternal(postfix.substring(dirPos + 1), provider,
visited).toString());
name = postfix.substring(0, dirPos);
} else {
directives = Collections.emptyMap();
@@ -144,22 +150,30 @@ public class Interpolator {
}
// recursive replacement
- final Object newName = replace(name, provider);
+ final Object newName = replaceInternal(name, provider, visited);
+
+ final String id = type.concat(":").concat(name);
+ if (!visited.add(id)) {
+ // endless recursion -> leave as is and continue
+ index = index + START.length();
- Object replacement = provider.provide(type, newName.toString(),
directives);
- if (replacement == null) {
- // no replacement found -> leave as is and continue
- index = index + START.length();
} else {
- // if replacement is not a string and placeholder is complete
string, return that object
- if (!(replacement instanceof String) && boundaries[0] == 0 &&
boundaries[1] == result.length() - 1) {
- return replacement;
+ Object replacement = provider.provide(type,
newName.toString(), directives);
+ if (replacement == null) {
+ // no replacement found -> leave as is and continue
+ index = index + START.length();
+ } else {
+ // if replacement is not a string and placeholder is
complete string, return that object
+ if (!(replacement instanceof String) && boundaries[0] == 0
&& boundaries[1] == result.length() - 1) {
+ return replacement;
+ }
+ // replace and continue with replacement
+ replacement = replaceInternal(replacement.toString(),
provider, visited);
+ final String val = replacement.toString();
+ result = result.substring(0,
boundaries[0]).concat(val).concat(result.substring(boundaries[1] + 1));
+ index = boundaries[0] + val.length();
}
- // replace and continue with replacement
- replacement = replace(replacement.toString(), provider);
- final String val = replacement.toString();
- result = result.substring(0,
boundaries[0]).concat(val).concat(result.substring(boundaries[1] + 1));
- index = boundaries[0] + val.length();
+ visited.remove(id);
}
}
return result;
diff --git
a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolatorTest.java
b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolatorTest.java
index b2132cad33..9197c5d9f8 100755
---
a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolatorTest.java
+++
b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolatorTest.java
@@ -64,6 +64,17 @@ public class InterpolatorTest {
}));
}
+ @Test
+ public void testRecursionViaPlaceholder() {
+ assertEquals("$[foo:bar]",
+ Interpolator.replace("$[foo:bar]", (type, name, dir) -> {
+ if ("foo".equals(type) && "bar".equals(name)) {
+ return "$[foo:bar]";
+ }
+ return null;
+ }));
+ }
+
@Test
public void testEscaping() {
final Provider p = new Provider() {