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

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

commit 6fe39d64b6d05d05a71cd905c9e158cffebaf4c4
Author: opencode <[email protected]>
AuthorDate: Mon Oct 19 11:33:38 2026 +0200

    Avoid NullPointerException releasing a PageContext when the pool
    size changed
    
    JspFactoryImpl is installed as the JVM-wide default JspFactory while
    its pool size is set per web application at startup. The per-thread
    PageContext pool is created by getPageContext only when pooling is
    enabled at that moment, but releasePageContext dereferenced the thread
    local pool unconditionally whenever pooling was enabled at release
    time. A thread that obtained a PageContext while pooling was disabled
    and released it after the shared pool size was increased (a second web
    application with pooling enabled started in between) threw a
    NullPointerException from the release, failing the request.
    
    Return the context to the pool only when the current thread actually
    has one, and make poolSize volatile since it is written by web
    application start threads and read by request threads without
    synchronization.
    
    Found by code review.
---
 java/org/apache/jasper/runtime/JspFactoryImpl.java | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/jasper/runtime/JspFactoryImpl.java 
b/java/org/apache/jasper/runtime/JspFactoryImpl.java
index 7b61fec7ca..9e6d753c1e 100644
--- a/java/org/apache/jasper/runtime/JspFactoryImpl.java
+++ b/java/org/apache/jasper/runtime/JspFactoryImpl.java
@@ -44,7 +44,7 @@ public class JspFactoryImpl extends JspFactory {
     }
 
     private final ThreadLocal<PageContextPool> localPool = new ThreadLocal<>();
-    private int poolSize = -1;
+    private volatile int poolSize = -1;
 
     @Override
     public PageContext getPageContext(Servlet servlet, ServletRequest request, 
ServletResponse response,
@@ -118,7 +118,14 @@ public class JspFactoryImpl extends JspFactory {
     private void internalReleasePageContext(PageContext pc) {
         pc.release();
         if (poolSize > 0 && (pc instanceof PageContextImpl)) {
-            localPool.get().put(pc);
+            // The thread local pool is only created by getPageContext() when
+            // pooling is enabled at that moment. The pool size may be changed
+            // (by the start of another web application) after this context was
+            // obtained on this thread, leaving the pool null here.
+            PageContextPool pool = localPool.get();
+            if (pool != null) {
+                pool.put(pc);
+            }
         }
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to