Skip to content

part.getString will cause OOM without checking maxPostSize, checking maxPostSize first will avoid OOM caused by huge string#419

Closed
tianshuang wants to merge 1 commit into
apache:masterfrom
tianshuang:fixoom
Closed

part.getString will cause OOM without checking maxPostSize, checking maxPostSize first will avoid OOM caused by huge string#419
tianshuang wants to merge 1 commit into
apache:masterfrom
tianshuang:fixoom

Conversation

@tianshuang

Copy link
Copy Markdown
Contributor

In our online server, when the client sends a huge string (hundreds of megabytes) to the server via multipart/form-data, OOM occurs, and the maxPostSize check logic is not executed

…maxPostSize first will avoid OOM caused by huge string
@markt-asf

Copy link
Copy Markdown
Contributor

This report, and the proposed solution is invalid. maxPostSize does not, and should not, apply to a multi-part request explicitly parsed via Request.getParts() or Request.getPart(String).
Further advice is available from the Tomcat users mailing list: http://tomcat.apache.org/lists.html

@markt-asf markt-asf closed this May 20, 2021
@tianshuang

Copy link
Copy Markdown
Contributor Author

I adjusted to check the maxPostSize first to avoid the OOM problem, part.getString will trigger OOM when the string is huge.

@tianshuang

Copy link
Copy Markdown
Contributor Author

If part.getString is called before checking maxPostSize, it may trigger OOM.

@tianshuang

Copy link
Copy Markdown
Contributor Author

stack trace:

  at java.lang.OutOfMemoryError.<init>()V (OutOfMemoryError.java:48)
  at java.lang.StringCoding$StringDecoder.decode([BII)[C (StringCoding.java:149)
  at java.lang.StringCoding.decode(Ljava/lang/String;[BII)[C (StringCoding.java:193)
  at java.lang.String.<init>([BIILjava/lang/String;)V (String.java:426)
  at java.lang.String.<init>([BLjava/lang/String;)V (String.java:491)
  at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.getString(Ljava/lang/String;)Ljava/lang/String; (DiskFileItem.java:327)
  at org.apache.catalina.core.ApplicationPart.getString(Ljava/lang/String;)Ljava/lang/String; (ApplicationPart.java:127)
  at org.apache.catalina.connector.Request.parseParts(Z)V (Request.java:2919)
  at org.apache.catalina.connector.Request.getParts()Ljava/util/Collection; (Request.java:2810)
  at org.apache.catalina.connector.RequestFacade.getParts()Ljava/util/Collection; (RequestFacade.java:1084)
  at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(Ljavax/servlet/http/HttpServletRequest;)V (StandardMultipartHttpServletRequest.java:93)
  at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(Ljavax/servlet/http/HttpServletRequest;Z)V (StandardMultipartHttpServletRequest.java:86)
  at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(Ljavax/servlet/http/HttpServletRequest;)Lorg/springframework/web/multipart/MultipartHttpServletRequest; (StandardServletMultipartResolver.java:91)
  at org.springframework.web.servlet.DispatcherServlet.checkMultipart(Ljavax/servlet/http/HttpServletRequest;)Ljavax/servlet/http/HttpServletRequest; (DispatcherServlet.java:1128)
  at org.springframework.web.servlet.DispatcherServlet.doDispatch(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (DispatcherServlet.java:960)
  at org.springframework.web.servlet.DispatcherServlet.doService(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (DispatcherServlet.java:925)
  at org.springframework.web.servlet.FrameworkServlet.processRequest(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (FrameworkServlet.java:974)
  at org.springframework.web.servlet.FrameworkServlet.doPost(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (FrameworkServlet.java:877)
  at javax.servlet.http.HttpServlet.service(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (HttpServlet.java:652)
  at org.springframework.web.servlet.FrameworkServlet.service(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (FrameworkServlet.java:851)
  at javax.servlet.http.HttpServlet.service(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (HttpServlet.java:733)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:231)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:166)
  at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Ljavax/servlet/FilterChain;)V (HttpPutFormContentFilter.java:109)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (OncePerRequestFilter.java:107)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:166)
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (WsFilter.java:52)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:166)
  at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Ljavax/servlet/FilterChain;)V (CharacterEncodingFilter.java:200)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (OncePerRequestFilter.java:107)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:166)
  at org.apache.catalina.core.StandardWrapperValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (StandardWrapperValve.java:199)
  at org.apache.catalina.core.StandardContextValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (StandardContextValve.java:97)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (AuthenticatorBase.java:544)
  at org.apache.catalina.core.StandardHostValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (StandardHostValve.java:143)
  at org.apache.catalina.valves.ErrorReportValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (ErrorReportValve.java:81)
  at org.apache.catalina.core.StandardEngineValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (StandardEngineValve.java:78)
  at org.apache.catalina.connector.CoyoteAdapter.service(Lorg/apache/coyote/Request;Lorg/apache/coyote/Response;)V (CoyoteAdapter.java:343)
  at org.apache.coyote.http11.Http11Processor.service(Lorg/apache/tomcat/util/net/SocketWrapperBase;)Lorg/apache/tomcat/util/net/AbstractEndpoint$Handler$SocketState; (Http11Processor.java:616)
  at org.apache.coyote.AbstractProcessorLight.process(Lorg/apache/tomcat/util/net/SocketWrapperBase;Lorg/apache/tomcat/util/net/SocketEvent;)Lorg/apache/tomcat/util/net/AbstractEndpoint$Handler$SocketState; (AbstractProcessorLight.java:65)
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(Lorg/apache/tomcat/util/net/SocketWrapperBase;Lorg/apache/tomcat/util/net/SocketEvent;)Lorg/apache/tomcat/util/net/AbstractEndpoint$Handler$SocketState; (AbstractProtocol.java:818)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun()V (NioEndpoint.java:1626)
  at org.apache.tomcat.util.net.SocketProcessorBase.run()V (SocketProcessorBase.java:49)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V (ThreadPoolExecutor.java:1149)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run()V (ThreadPoolExecutor.java:624)
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run()V (TaskThread.java:61)
  at java.lang.Thread.run()V (Thread.java:748)

@tianshuang

Copy link
Copy Markdown
Contributor Author

My solution did not change the original semantics. Please take a closer look. It just adjusted the calling order of part.getString to avoid the OOM problem of large strings. After I compiled tomcat locally and tested it, I solved the OOM problem when part.getString was called in advance for huge strings and insufficient memory.

@markt-asf

Copy link
Copy Markdown
Contributor

Re-opening to take another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants