This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new 8aafcedd83 In the unlikely event a Servlet instance is serialized...
8aafcedd83 is described below

commit 8aafcedd83147c410b1aabf3f206207c33e69844
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     | 22 ++++++++++++++++++++--
 test/jakarta/servlet/http/TestHttpServlet.java | 21 +++++++++++++++++++++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/java/jakarta/servlet/http/HttpServlet.java 
b/java/jakarta/servlet/http/HttpServlet.java
index 7e8fed104e..7f1597e5a8 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.UnsupportedEncodingException;
@@ -95,12 +96,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.
@@ -670,6 +674,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/jakarta/servlet/http/TestHttpServlet.java 
b/test/jakarta/servlet/http/TestHttpServlet.java
index c0ec0a0440..03bc9977e3 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]

Reply via email to