[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 36db1e35cac5e8c72bf0c795dd08756e50079e05

---

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 @@ private boolean isNoteworthyException(Throwable exception) {
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 @@
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 void testHandleExceptionNoClassDefFoundErrorNull() {
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 static void showError(Logger logger, String message, Throwable e, boolean
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 @@ private void printStackTrace(Throwable t, PrintStream stream, String prefix) {
writeThrowable(se, stream, "Suppressed", prefix + " ");
}
Throwable cause = t.getCause();
if (cause != null) {
if (cause != null && t != cause) {
writeThrowable(cause, stream, "Caused by", prefix);
}
}