This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 6e466f25c1 In the unlikely event a Servlet instance is serialized...
6e466f25c1 is described below
commit 6e466f25c1d0e64e02aa3739803d4332bd677a08
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Oct 23 22:14:24 2026 +0100
In the unlikely event a Servlet instance is serialized...
---
java/javax/servlet/http/HttpServlet.java | 22 ++++++++++++++++++++--
test/javax/servlet/http/TestHttpServlet.java | 21 +++++++++++++++++++++
2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/java/javax/servlet/http/HttpServlet.java
b/java/javax/servlet/http/HttpServlet.java
index 4fb47ba129..d37e3aab0b 100644
--- a/java/javax/servlet/http/HttpServlet.java
+++ b/java/javax/servlet/http/HttpServlet.java
@@ -17,6 +17,7 @@
package javax.servlet.http;
import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
@@ -86,12 +87,15 @@ public abstract class HttpServlet extends GenericServlet {
private static final List<String> SENSITIVE_HTTP_HEADERS =
Arrays.asList("authorization", "cookie", "x-forwarded",
"forwarded", "proxy-authorization");
- private final transient Object cachedAllowHeaderValueLock = new Object();
+ // Non-final so it can be recreated on deserialization
+ private transient Object cachedAllowHeaderValueLock = new Object();
/**
* Cached value of the HTTP {@code Allow} header for this servlet.
+ * <p>
+ * Derived cache that is recomputed lazily.
*/
- private volatile String cachedAllowHeaderValue = null;
+ private transient volatile String cachedAllowHeaderValue = null;
/**
* Does nothing, because this is an abstract class.
@@ -648,6 +652,20 @@ public abstract class HttpServlet extends GenericServlet {
}
+ /**
+ * Restores the transient lock object used to guard the cached Allow
header after deserialization. The cached
+ * header is recomputed lazily so it isn't restored here.
+ *
+ * @param stream the object input stream
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be found
+ */
+ private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
+ stream.defaultReadObject();
+ cachedAllowHeaderValueLock = new Object();
+ }
+
+
private static class TomcatHack {
private static final Class<?> REQUEST_FACADE_CLAZZ;
diff --git a/test/javax/servlet/http/TestHttpServlet.java
b/test/javax/servlet/http/TestHttpServlet.java
index 2955255a8b..b033f31b61 100644
--- a/test/javax/servlet/http/TestHttpServlet.java
+++ b/test/javax/servlet/http/TestHttpServlet.java
@@ -16,7 +16,11 @@
*/
package javax.servlet.http;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
@@ -219,6 +223,23 @@ public class TestHttpServlet extends TomcatBaseTest {
}
+ @Test
+ public void testDoOptionsAfterDeserialization() throws Exception {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ // Serialize before the Allow header cache has been initialized.
+ try (ObjectOutputStream stream = new ObjectOutputStream(bytes)) {
+ stream.writeObject(new OptionsServlet());
+ }
+
+ OptionsServlet servlet;
+ try (ObjectInputStream stream = new ObjectInputStream(new
ByteArrayInputStream(bytes.toByteArray()))) {
+ servlet = (OptionsServlet) stream.readObject();
+ }
+
+ doTestDoOptions(servlet, "GET, HEAD, OPTIONS");
+ }
+
+
@Test
public void testDoOptionsSub() throws Exception {
doTestDoOptions(new OptionsServletSub(), "GET, HEAD, POST, OPTIONS");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]