[MNG-7846] Break out of endless loop (#1206)

This is most probably "just" about broken Throwable implementations.
Some override getCause but does not perform checks to what it was inited
as "this" means "not yet inited" actually.

---

https://issues.apache.org/jira/browse/MNG-7846
This commit is contained in:
Tamas Cservenak 2023-07-19 17:37:28 +02:00 committed by GitHub
parent 4a5b6c5f2b
commit 36db1e35ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 3 deletions

View File

@ -225,7 +225,8 @@ public class DefaultExceptionHandler implements ExceptionHandler {
private String getMessage(String message, Throwable exception) { private String getMessage(String message, Throwable exception) {
String fullMessage = (message != null) ? message : ""; String fullMessage = (message != null) ? message : "";
for (Throwable t = exception; t != null; t = t.getCause()) { // To break out of possible endless loop when getCause returns "this"
for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
String exceptionMessage = t.getMessage(); String exceptionMessage = t.getMessage();
if (t instanceof AbstractMojoExecutionException) { if (t instanceof AbstractMojoExecutionException) {

View File

@ -20,6 +20,7 @@ package org.apache.maven.exception;
import java.io.IOException; import java.io.IOException;
import java.net.ConnectException; import java.net.ConnectException;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecution;
@ -95,4 +96,32 @@ class DefaultExceptionHandlerTest {
String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException"; String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
assertEquals(expectedReference, summary.getReference()); assertEquals(expectedReference, summary.getReference());
} }
@Test
void testHandleExceptionLoopInCause() {
// Some broken exception that does return "this" as getCause
AtomicReference<Throwable> causeRef = new AtomicReference<>(null);
Exception cause2 = new RuntimeException("loop") {
@Override
public synchronized Throwable getCause() {
return causeRef.get();
}
};
causeRef.set(cause2);
Plugin plugin = new Plugin();
Exception cause = new PluginContainerException(plugin, null, null, cause2);
cause2.initCause(cause);
PluginDescriptor pluginDescriptor = new PluginDescriptor();
MojoDescriptor mojoDescriptor = new MojoDescriptor();
mojoDescriptor.setPluginDescriptor(pluginDescriptor);
MojoExecution mojoExecution = new MojoExecution(mojoDescriptor);
Throwable exception = new PluginExecutionException(mojoExecution, null, cause);
DefaultExceptionHandler handler = new DefaultExceptionHandler();
ExceptionSummary summary = handler.handleException(exception);
String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
assertEquals(expectedReference, summary.getReference());
}
} }

View File

@ -150,7 +150,9 @@ public final class CLIReportingUtils {
if (e != null) { if (e != null) {
logger.error(e.getMessage()); logger.error(e.getMessage());
for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) { for (Throwable cause = e.getCause();
cause != null && cause != cause.getCause();
cause = cause.getCause()) {
logger.error("Caused by: {}", cause.getMessage()); logger.error("Caused by: {}", cause.getMessage());
} }
} }

View File

@ -79,7 +79,7 @@ public class MavenSimpleLogger extends SimpleLogger {
writeThrowable(se, stream, "Suppressed", prefix + " "); writeThrowable(se, stream, "Suppressed", prefix + " ");
} }
Throwable cause = t.getCause(); Throwable cause = t.getCause();
if (cause != null) { if (cause != null && t != cause) {
writeThrowable(cause, stream, "Caused by", prefix); writeThrowable(cause, stream, "Caused by", prefix);
} }
} }