This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 7b66b74484 In the unlikely event a Servlet instance is serialized...
7b66b74484 is described below
commit 7b66b74484b38a5ecb5845743c9885b8cbe6d779
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Oct 23 22:14:24 2026 +0100
In the unlikely event a Servlet instance is serialized...
---
java/jakarta/servlet/http/HttpServlet.java | 23 +++++++++++++++++++++--
test/jakarta/servlet/http/TestHttpServlet.java | 21 +++++++++++++++++++++
2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/java/jakarta/servlet/http/HttpServlet.java
b/java/jakarta/servlet/http/HttpServlet.java
index 51bf4666f3..e73ea30835 100644
--- a/java/jakarta/servlet/http/HttpServlet.java
+++ b/java/jakarta/servlet/http/HttpServlet.java
@@ -17,6 +17,7 @@
package jakarta.servlet.http;
import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serial;
@@ -99,12 +100,15 @@ public abstract class HttpServlet extends GenericServlet {
@Deprecated(forRemoval = true, since = "Servlet 6.0")
public static final String LEGACY_DO_HEAD =
"jakarta.servlet.http.legacyDoHead";
- 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;
/**
* Cached value read from {@link HttpServlet#LEGACY_DO_HEAD} system
property.
@@ -759,6 +763,21 @@ 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
+ */
+ @Serial
+ 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/jakarta/servlet/http/TestHttpServlet.java
b/test/jakarta/servlet/http/TestHttpServlet.java
index 1fb3816c3b..9651c4d954 100644
--- a/test/jakarta/servlet/http/TestHttpServlet.java
+++ b/test/jakarta/servlet/http/TestHttpServlet.java
@@ -16,7 +16,11 @@
*/
package jakarta.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]