[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.

Backport of 36db1e35ca

---

https://issues.apache.org/jira/browse/MNG-7846
This commit is contained in:
Tamas Cservenak 2023-07-19 17:42:02 +02:00
parent 3f37e6a2f6
commit 2963769b77
4 changed files with 35 additions and 3 deletions

View File

@ -222,7 +222,8 @@ public class DefaultExceptionHandler implements ExceptionHandler {
private String getMessage(String message, Throwable exception) {
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();
if (t instanceof AbstractMojoExecutionException) {

View File

@ -20,6 +20,7 @@ package org.apache.maven.exception;
import java.io.IOException;
import java.net.ConnectException;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution;
@ -95,4 +96,32 @@ public class DefaultExceptionHandlerTest {
String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
assertEquals(expectedReference, summary.getReference());
}
@Test
public 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

@ -144,7 +144,9 @@ public final class CLIReportingUtils {
if (e != null) {
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());
}
}

View File

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