From 275b3d0591c51376e1a90468d7761dd6cd940ff9 Mon Sep 17 00:00:00 2001
From: markt
Date: Sun, 28 Jan 2007 00:55:24 +0000
Subject: [PATCH] Port fix bug 39088 that prevents infinite loops when an
exception is thrown the returns itself for getRootCause(). Also port changes
that enable the root cause to be found when the nesting is particularly
extreme.
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@500716 13f79535-47bb-0310-9956-ffa450edef68
---
java/org/apache/catalina/core/StandardWrapper.java | 60 ++++++++++++++++++----
.../apache/catalina/valves/ErrorReportValve.java | 47 +++++++++++++++--
webapps/docs/changelog.xml | 4 ++
3 files changed, 95 insertions(+), 16 deletions(-)
diff --git a/java/org/apache/catalina/core/StandardWrapper.java b/java/org/apache/catalina/core/StandardWrapper.java
index ed0003ea3..9dc8d4b6f 100644
--- a/java/org/apache/catalina/core/StandardWrapper.java
+++ b/java/org/apache/catalina/core/StandardWrapper.java
@@ -31,6 +31,8 @@ import java.util.Stack;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.sql.SQLException;
+
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
@@ -60,6 +62,7 @@ import org.apache.catalina.Wrapper;
import org.apache.catalina.security.SecurityUtil;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.InstanceSupport;
+import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.log.SystemLogHandler;
import org.apache.tomcat.util.modeler.Registry;
@@ -291,7 +294,19 @@ public class StandardWrapper
*/
protected static Properties restrictedServlets = null;
+
+ private static Class jspExceptionClazz;
+ static {
+ try {
+ jspExceptionClazz = Class.forName("javax.servlet.jsp.JspException");
+ } catch (ClassNotFoundException e) {
+ // Expected if jsp-api not on classpath, eg when embedding
+ jspExceptionClazz = null;
+ }
+ }
+
+
// ------------------------------------------------------------- Properties
@@ -675,20 +690,43 @@ public class StandardWrapper
* @param e The servlet exception
*/
public static Throwable getRootCause(ServletException e) {
- Throwable rootCause = e;
- Throwable rootCauseCheck = null;
- // Extra aggressive rootCause finding
- int loops = 0;
- do {
- loops++;
- rootCauseCheck = rootCause.getCause();
- if (rootCauseCheck != null)
- rootCause = rootCauseCheck;
- } while (rootCauseCheck != null && (loops < 20));
- return rootCause;
+ Throwable rootCause = e.getRootCause();
+ return findRootCause(e, rootCause);
}
+ /*
+ * Work through the root causes using specific methods for well known types
+ * and getCause() for the rest. Stop when the next rootCause is null or
+ * an exception is found that has itself as its own rootCause.
+ */
+ private static final Throwable findRootCause(Throwable theException,
+ Throwable theRootCause) {
+
+ Throwable deeperRootCause = null;
+
+ if (theRootCause == null || theRootCause == theException) {
+ return theException;
+ }
+
+ if (theRootCause instanceof ServletException) {
+ deeperRootCause = ((ServletException) theRootCause).getRootCause();
+ } else if (jspExceptionClazz!=null &&
+ jspExceptionClazz.isAssignableFrom(theRootCause.getClass())) {
+ deeperRootCause = (Throwable)IntrospectionUtils.getProperty(
+ theRootCause, "rootCause");
+ } else if (theRootCause instanceof SQLException) {
+ deeperRootCause = ((SQLException) theRootCause).getNextException();
+ }
+ if (deeperRootCause == null) {
+ deeperRootCause = theRootCause.getCause();
+ }
+
+ return findRootCause(theRootCause, deeperRootCause);
+ }
+
+
+
/**
* Refuse to add a child Container, because Wrappers are the lowest level
* of the Container hierarchy.
diff --git a/java/org/apache/catalina/valves/ErrorReportValve.java b/java/org/apache/catalina/valves/ErrorReportValve.java
index a703addfb..1a2d62200 100644
--- a/java/org/apache/catalina/valves/ErrorReportValve.java
+++ b/java/org/apache/catalina/valves/ErrorReportValve.java
@@ -21,6 +21,7 @@ package org.apache.catalina.valves;
import java.io.IOException;
import java.io.Writer;
+import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -33,6 +34,7 @@ import org.apache.catalina.connector.Response;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.util.StringManager;
+import org.apache.tomcat.util.IntrospectionUtils;
/**
* Implementation of a Valve that outputs HTML error pages.
@@ -71,6 +73,18 @@ public class ErrorReportValve
StringManager.getManager(Constants.Package);
+ private static Class jspExceptionClazz;
+
+ static {
+ try {
+ jspExceptionClazz = Class.forName("javax.servlet.jsp.JspException");
+ } catch (ClassNotFoundException e) {
+ // Expected if jsp-api not on classpath, eg when embedding
+ jspExceptionClazz = null;
+ }
+ }
+
+
// ------------------------------------------------------------- Properties
@@ -216,9 +230,9 @@ public class ErrorReportValve
sb.append(RequestUtil.filter(stackTrace));
sb.append("
");
- int loops = 0;
Throwable rootCause = throwable.getCause();
- while (rootCause != null && (loops < 10)) {
+ Throwable nestedRootCause = null;
+ while (rootCause != null) {
stackTrace = getPartialServletStackTrace(rootCause);
sb.append("");
sb.append(sm.getString("errorReportValve.rootCause"));
@@ -226,10 +240,33 @@ public class ErrorReportValve
sb.append(RequestUtil.filter(stackTrace));
sb.append("
");
// In case root cause is somehow heavily nested
- rootCause = rootCause.getCause();
- loops++;
+ try {
+ if (rootCause instanceof ServletException) {
+ nestedRootCause =
+ ((ServletException) rootCause).getRootCause();
+ } else if (jspExceptionClazz!=null &&
+ jspExceptionClazz.isAssignableFrom(
+ rootCause.getClass())) {
+ nestedRootCause = (Throwable)IntrospectionUtils.
+ getProperty(rootCause, "rootCause");
+ } else if (rootCause instanceof SQLException) {
+ nestedRootCause = ((SQLException) rootCause).
+ getNextException();
+ }
+ if (nestedRootCause == null) {
+ nestedRootCause = rootCause.getCause();
+ }
+
+ if (rootCause == nestedRootCause)
+ rootCause = null;
+ else {
+ rootCause = nestedRootCause;
+ nestedRootCause = null;
+ }
+ } catch (ClassCastException e) {
+ rootCause = null;
+ }
}
-
sb.append("");
sb.append(sm.getString("errorReportValve.note"));
sb.append(" ");
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 5fcab1ff6..2dd0dd986 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -31,6 +31,10 @@
web.xml. (markt)
+ 39088: Prevent infinte loops when an exception is thrown
+ that returns itself for getRootCause(). (markt)
+
+
41217: Set secure attribute on SSO cookie when cookie is
created during a secure request. Patch provided by Chris Halstead.
(markt)
--
2.11.0