Merge pull request #10685 from eclipse/fix/jetty-12.0.x-dumpStackOverflow

fix infinite recursion in server dump with Path
This commit is contained in:
Lachlan 2023-10-10 12:51:15 +11:00 committed by GitHub
commit 0468f67430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 2 deletions

View File

@ -15,10 +15,12 @@ package org.eclipse.jetty.util.component;
import java.io.IOException;
import java.lang.reflect.Array;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import org.eclipse.jetty.util.StringUtil;
@ -155,7 +157,8 @@ public interface Dumpable
{
dumpContainer(out, indent, (Container)object, extras == 0);
}
if (object instanceof Iterable)
// Dump an Iterable Path because it may contain itself.
if (object instanceof Iterable && !(object instanceof Path))
{
dumpIterable(out, indent, (Iterable<?>)object, extras == 0);
}
@ -237,6 +240,9 @@ public interface Dumpable
for (Iterator i = iterable.iterator(); i.hasNext(); )
{
Object item = i.next();
// Safety net to stop iteration when an Iterable contains itself e.g. Path.
if (Objects.equals(item, iterable))
return;
String nextIndent = indent + ((i.hasNext() || !last) ? "| " : " ");
out.append(indent).append("+: ");
if (item instanceof Dumpable)

View File

@ -652,4 +652,48 @@ public class DemoModulesTests extends AbstractJettyHomeTest
}
}
}
@ParameterizedTest
@MethodSource("provideEnvironmentsToTest")
public void testJettyDemo(String env) throws Exception
{
Path jettyBase = newTestJettyBaseDirectory();
String jettyVersion = System.getProperty("jettyVersion");
JettyHomeTester distribution = JettyHomeTester.Builder.newInstance()
.jettyVersion(jettyVersion)
.jettyBase(jettyBase)
.build();
int httpPort = distribution.freePort();
int sslPort = distribution.freePort();
String[] argsConfig = {
"--add-modules=http," + toEnvironment("demos", env)
};
try (JettyHomeTester.Run runConfig = distribution.start(argsConfig))
{
assertTrue(runConfig.awaitFor(START_TIMEOUT, TimeUnit.SECONDS));
assertEquals(0, runConfig.getExitValue());
String[] argsStart = {
"jetty.http.port=" + httpPort,
"jetty.ssl.port=" + sslPort,
"jetty.server.dumpAfterStart=true"
};
try (JettyHomeTester.Run runStart = distribution.start(argsStart))
{
assertTrue(runStart.awaitConsoleLogsFor("Started oejs.Server@", START_TIMEOUT, TimeUnit.SECONDS));
startHttpClient();
String baseURI = "http://localhost:%d/%s-test".formatted(httpPort, env);
ContentResponse response = client.POST(baseURI + "/dump/info").send();
assertEquals(HttpStatus.OK_200, response.getStatus(), new ResponseDetails(response));
assertThat(response.getContentAsString(), containsString("Dump Servlet"));
assertThat(response.getContentAsString(), containsString("context-override-example:&nbsp;</th><td>a context value"));
}
}
}
}