Uploaded image for project: 'JBoss Enterprise Application Platform'
  1. JBoss Enterprise Application Platform
  2. JBEAP-14689

[GSS](7.1.z) UNDERTOW-1332 - NullPointerException at HttpServletRequestImpl.getLocalAddr

    Details

    • Target Release:
    • Fix Build:
      CR1
    • Steps to Reproduce:
      Hide
      • Using with ProxyPeerAddressHandler:
      1. Enable proxy-address-forwarding attribute on the http-listener:
        /subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding,value=true)
        
      2. Deploy web app web application calling "ServletRequest#getLocalAddr()" like the following jsp:
        <% out.println("request.getLocalAddr(): " + request.getLocalAddr()); %>
        
      3. Sent a request to the JSP with sending "X-Forwarded-Host" header:
        curl -v http://localhost:8080/test/test.jsp -H "X-Forwarded-Host: test"
        
      • Using with AJP:
      1. Enable ajp-listener
        /subsystem=undertow/server=default-server/ajp-listener=ajp:add(socket-binding=ajp)
        
      2. Deploy web app web application calling "ServletRequest#getLocalAddr()" like the following jsp:
        <% out.println("request.getLocalAddr(): " + request.getLocalAddr()); %>
        
      3. Setup Apache httpd/mod_proxy_ajp
        ProxyPass /test/ ajp://127.0.0.1:8009/test/
        
      4. Sent a request to the JSP through httpd/mod_proxy
        curl -v http://localhost/test/test.jsp
        
      Show
      Using with ProxyPeerAddressHandler: Enable proxy-address-forwarding attribute on the http-listener: /subsystem=undertow/server= default -server/http-listener= default :write-attribute(name=proxy-address-forwarding,value= true ) Deploy web app web application calling "ServletRequest#getLocalAddr()" like the following jsp: <% out.println( "request.getLocalAddr(): " + request.getLocalAddr()); %> Sent a request to the JSP with sending "X-Forwarded-Host" header: curl -v http: //localhost:8080/test/test.jsp -H "X-Forwarded-Host: test" Using with AJP: Enable ajp-listener /subsystem=undertow/server= default -server/ajp-listener=ajp:add(socket-binding=ajp) Deploy web app web application calling "ServletRequest#getLocalAddr()" like the following jsp: <% out.println( "request.getLocalAddr(): " + request.getLocalAddr()); %> Setup Apache httpd/mod_proxy_ajp ProxyPass /test/ ajp: //127.0.0.1:8009/test/ Sent a request to the JSP through httpd/mod_proxy curl -v http: //localhost/test/test.jsp
    • Workaround Description:
      Hide

      This issue can be workaround by either of the followings:

      • Using io.undertow.server.handlers.LocalNameResolvingHandler ('resolve-local-name' in expression-filter). This can avoid this NPE issue unless the destination address (Host header in AJP request or the X-Forwarded-Host header in HTTP request) is really unresolved. However, using this handler can impact performance. If a DNS server is unresponsive this could potentially add seconds to the request processing time:
      /subsystem=undertow/configuration=filter/expression-filter=resolve-local-name-filter:add(expression=resolve-local-name)
      /subsystem=undertow/server=default-server/host=default-host/filter-ref=resolve-local-name-filter:add()
      
              <subsystem xmlns="urn:jboss:domain:undertow:4.0">
                  ...
                  <server name="default-server">
                      ...
                      <host name="default-host" alias="localhost">
                          ...
                          <filter-ref name="resolve-local-name-filter"/> <!-- add this -->
                      </host>
                  </server>
                  ...
                  <filters>
                      ...(snip)...
                      <expression-filter name="resolve-local-name-filter" expression="resolve-local-name"/> <!-- add this -->
                  </filters>
              </subsystem>
      
      • Using Servlet Filter with HttpServletRequestWrapper to override getLocalAddr(). For example:
      @WebFilter("/*")
      public class ExampleFilter implements Filter {
      
          public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
              throws IOException, ServletException {
      
              if (!(req instanceof HttpServletRequest)) {
                  chain.doFilter(req, res);
                  return;
              }
      
              HttpServletRequest request = (HttpServletRequest) req;
              HttpServletResponse response = (HttpServletResponse) res;
      
              HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request) {
                  @Override
                  public String getLocalAddr() {
                      try {
                          return request.getLocalAddr();
                      } catch(NullPointerException npe) {
                          // NPE happnes at request.getLocalAddr(), so try to resolve from request.getLocalName() instead
                          try {
                              return InetAddress.getByName(request.getLocalName()).getHostAddress();
                          } catch(Exception e){
                              // Can not be resolved. Just return request.getLocalName() instread
                              return request.getLocalName();
                          }
                      }
                  }
              };
      
              chain.doFilter(wrappedRequest, res);
          }
      
          ...
      }
      
      Show
      This issue can be workaround by either of the followings: Using io.undertow.server.handlers.LocalNameResolvingHandler ('resolve-local-name' in expression-filter). This can avoid this NPE issue unless the destination address (Host header in AJP request or the X-Forwarded-Host header in HTTP request) is really unresolved. However, using this handler can impact performance. If a DNS server is unresponsive this could potentially add seconds to the request processing time: /subsystem=undertow/configuration=filter/expression-filter=resolve-local-name-filter:add(expression=resolve-local-name) /subsystem=undertow/server= default -server/host= default -host/filter-ref=resolve-local-name-filter:add() <subsystem xmlns= "urn:jboss:domain:undertow:4.0" > ... <server name= " default -server" > ... <host name= " default -host" alias= "localhost" > ... <filter-ref name= "resolve-local-name-filter" /> <!-- add this --> </host> </server> ... <filters> ...(snip)... <expression-filter name= "resolve-local-name-filter" expression= "resolve-local-name" /> <!-- add this --> </filters> </subsystem> Using Servlet Filter with HttpServletRequestWrapper to override getLocalAddr(). For example: @WebFilter( "/*" ) public class ExampleFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { if (!(req instanceof HttpServletRequest)) { chain.doFilter(req, res); return ; } HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request) { @Override public String getLocalAddr() { try { return request.getLocalAddr(); } catch (NullPointerException npe) { // NPE happnes at request.getLocalAddr(), so try to resolve from request.getLocalName() instead try { return InetAddress.getByName(request.getLocalName()).getHostAddress(); } catch (Exception e){ // Can not be resolved. Just return request.getLocalName() instread return request.getLocalName(); } } } }; chain.doFilter(wrappedRequest, res); } ... }
    • Sprint:
      EAP 7.1.3

      Description

      The following NPE happenes when calling "HttpServletRequest.getLocalAddr()":

      UT005023: Exception handling request to /test/index.jsp: org.apache.jasper.JasperException: java.lang.NullPointerException
      	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:473)
      	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:403)
      	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:347)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
      	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
      	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
      	at io.undertow.jsp.JspFileHandler.handleRequest(JspFileHandler.java:32)
      	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:64)
      	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
      	at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
      	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
      	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
      	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
      	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
      	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
      	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
      	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
      	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
      	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
      	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
      	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
      	at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
      	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
      	at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
      	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
      	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
      	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
      	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
      	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
      	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
      	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
      	at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
      	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
      	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
      	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
      	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
      	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
      	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
      	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
      	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:330)
      	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:812)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      	at java.lang.Thread.run(Thread.java:748)
      Caused by: java.lang.NullPointerException
      	at io.undertow.servlet.spec.HttpServletRequestImpl.getLocalAddr(HttpServletRequestImpl.java:937)
      	at org.apache.jsp.index_jsp._jspService(index_jsp.java:151)
      	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
      	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
      	... 43 more
      

      The same issue was reported in UNDERTOW-1332.

      UNDERTOW-1332 says this issue happens at calling "ServletRequest#getLocalAddr()" when enabling proxy-address-forwarding attribute on the http-listener and "X-Forwarded-Host" header exists on the request.

      In addition to the condition using ProxyPeerAddressHandler, this NPE issue also happens with ajp-listener regardless of having "X-Forwarded-Host" header in the request.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  swd847 Stuart Douglas
                  Reporter:
                  mmiura Masafumi Miura
                  Tester:
                  Peter Mackay
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  5 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: