Skip to content

Prevent circular load.properties #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
37 changes: 29 additions & 8 deletions avaje-config/src/main/java/io/avaje/config/InitialLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ void loadViaCommandLine(String[] args) {

private void loadCommandLineArg(String arg) {
if (isValidExtension(arg)) {
loadViaPaths(arg);
for (String path : splitPaths(arg)) {
loadWithExtensionCheck(loadContext.eval(path));
}
}
}

Expand Down Expand Up @@ -193,7 +195,32 @@ private boolean loadTest() {
private void loadViaIndirection() {
String paths = loadContext.indirectLocation();
if (paths != null) {
loadViaPaths(paths);
var stack = new ArrayDeque<String>();
splitAndAddPaths(stack, paths);
String path;
var sentinel = 0;
while ((path = stack.poll()) != null) {
loadWithExtensionCheck(loadContext.eval(path));
var newPath = loadContext.indirectLocation();
if (newPath == null) throw new IllegalStateException("truly impossible");
if (!paths.equals(newPath)) {
paths = newPath;
splitAndAddPaths(stack, paths);
}

sentinel++;
if (sentinel == 69) {
throw new IllegalStateException(
"Failed to resolve load.properties after 69 iterations. Perhaps Circular load.properties reference?");
}
}
}
}

private void splitAndAddPaths(ArrayDeque<String> stack, String paths) {
var split = splitPaths(paths);
for (int i = split.length - 1; i >= 0; i--) {
stack.addFirst(split[i]);
}
}

Expand All @@ -217,12 +244,6 @@ private void loadViaProfiles(Source source) {
}
}

private void loadViaPaths(String paths) {
for (String path : splitPaths(paths)) {
loadWithExtensionCheck(loadContext.eval(path));
}
}

int size() {
return loadContext.size();
}
Expand Down
12 changes: 12 additions & 0 deletions avaje-config/src/test/java/io/avaje/config/InitialLoaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,16 @@ void load_withSuppressTestResource() {
System.clearProperty("suppressTestResource");
}
}

@Test
void load_withLoadPropertyChain() {
InitialLoader loader = newInitialLoader();
loader.loadWithExtensionCheck("test-properties/chain/main.properties");
var properties = evalFor(loader.load());
assertThat(properties.get("value.a").value()).isEqualTo("true");
assertThat(properties.get("value.b").value()).isEqualTo("true");
assertThat(properties.get("value.c").value()).isEqualTo("true");
assertThat(properties.get("value.d").value()).isEqualTo("true");
assertThat(properties.get("override").value()).isEqualTo("d");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
value.a=true
override=a
load.properties=test-properties/chain/c.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
value.b=true
override=b
load.properties=test-properties/chain/c.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
value.c=true
override=c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
value.d=true
override=d
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
load.properties=test-properties/chain/a.properties test-properties/chain/b.properties, test-properties/chain/d.properties