Bug 25835

Summary: Synchronization problem with RequestFilterValve
Product: Tomcat 4 Reporter: Slavik Markovich <slavik.markovich>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P3    
Version: 4.1.29   
Target Milestone: ---   
Hardware: All   
OS: All   

Description Slavik Markovich 2003-12-31 14:24:13 UTC
Copied from the mailing list:
I'm having some problems with using RemoteAddrValve to allow only certain
addresses to access an Engine.

I'm using tomcat 4.1.27 with jdk1.3.1 on Solaris.

I've configured the following:
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="a.b.c.d"/>
under the engine. I know I should have escaped the '.' (regexp) but it should
work as is.

I'm receiving once in every few thousands of requests the following error:
2003-12-26 11:26:51 CoyoteAdapter An exception or error occurred in the
container during the request processing
java.lang.StringIndexOutOfBoundsException: String index out of range: 11
        at java.lang.String.charAt(String.java:511)
        at
org.apache.regexp.StringCharacterIterator.charAt(StringCharacterIterator.java:90)
        at org.apache.regexp.RE.matchNodes(RE.java:1161)
        at org.apache.regexp.RE.matchAt(RE.java:1448)
        at org.apache.regexp.RE.match(RE.java:1540)
        at org.apache.regexp.RE.match(RE.java:1468)
        at org.apache.regexp.RE.match(RE.java:1561)
        at
org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:335)
        at
org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:131)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:577)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
        at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:601)
        at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:392)
        at
org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
        at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)
        at java.lang.Thread.run(Thread.java:479)

Also, once in every few thousands of requests I'm receiving a 403 access denied
error on a valid address (I can see that in the access log).

After checking the RequestFilterValve class, I can see it saves the compiled
regular expressions (RE) and reuses them to check every request. Looking at
regexp documentations, it is explicitly stated that RE is not thread-safe. Am I
missing something? It looks like under load, this valve fails.

Also, I can see that the RequestFilterValve class didn't change in the 5.0.16
version either.

Possible solution:
Synchronizing the process method would be a bad idea (bottleneck for all
requests) so it looks like there won't be any choice but to recreate the RE as
local variables.
There is also a possibility (ugly one) of serializing the array of RE to a byte
array and de-serializing it in the process method.
Comment 1 Mark Thomas 2005-07-04 22:42:30 UTC
This has been fixed in CVS for 4.1.x and will be included in 4.1.32+

For the record, this was fixed in 5.5.x as part of the migration to
java.util.regexp.*