Hi,
We're happily using Stripes in several apps, and one of them stopped working once we upgraded Tomcat from 9.0.116 to 9.0.118 (same war, confirmed on both Linux and Windows). Tomcat logs indicated:
java.lang.IllegalArgumentException: The resource path [/WEB-INF/classes/be/betv/wimoos/ui/action/api/ApiArticleListActionBean.class/Êþº¾\u0000\u0000\u00007\u0001/] has been normalized to [null] which is not valid
at org.apache.catalina.webresources.StandardRoot.validate(StandardRoot.java:259)
at org.apache.catalina.webresources.StandardRoot.getResources(StandardRoot.java:303)
at org.apache.catalina.webresources.StandardRoot.getClassLoaderResources(StandardRoot.java:227)
at org.apache.catalina.loader.WebappClassLoaderBase.findResources(WebappClassLoaderBase.java:952)
at org.apache.catalina.loader.WebappClassLoaderBase.getResources(WebappClassLoaderBase.java:1047)
at net.sourceforge.stripes.vfs.VFS.getResources(VFS.java:171)
at net.sourceforge.stripes.vfs.DefaultVFS.list(DefaultVFS.java:93)
at net.sourceforge.stripes.vfs.DefaultVFS.list(DefaultVFS.java:135)
at net.sourceforge.stripes.vfs.DefaultVFS.list(DefaultVFS.java:135)
at net.sourceforge.stripes.vfs.VFS.list(VFS.java:200)
at net.sourceforge.stripes.util.ResolverUtil.find(ResolverUtil.java:202)
at net.sourceforge.stripes.util.ResolverUtil.findImplementations(ResolverUtil.java:164)
at net.sourceforge.stripes.controller.AnnotatedClassActionResolver.findClasses(AnnotatedClassActionResolver.java:683)
at net.sourceforge.stripes.controller.AnnotatedClassActionResolver.init(AnnotatedClassActionResolver.java:118)
at net.sourceforge.stripes.controller.NameBasedActionResolver.init(NameBasedActionResolver.java:125)
at net.sourceforge.stripes.config.DefaultConfiguration.init(DefaultConfiguration.java:121)
After digging through the Tomcat changes for v9.0.118, it appears that a new test was added to org.apache.tomcat.util.http.RequestUtil.normalize(String path, boolean replaceBackSlash), which reads:
// Reject paths containing null bytes
if (path.indexOf(0) > -1) {
return null;
}
That seemingly innocuous change causes org.apache.catalina.webresources.StandardRoot.validate() to now throw an IllegalArgumentException when the path contains null bytes, which leads to the stacktrace above.
So we searched where the offending path /WEB-INF/classes/be/betv/wimoos/ui/action/api/ApiArticleListActionBean.class/Êþº¾\u0000\u0000\u00007\u0001/ came from.
The reason is this code in Stripes' net.sourceforge.stripes.vfs.DefaultVFS.java:
/*
* Some servlet containers allow reading from directory resources like a
* text file, listing the child resources one per line. However, there is no
* way to differentiate between directory and file resources just by reading
* them. To work around that, as each line is read, try to look it up via
* the class loader as a child of the current resource. If any line fails
* then we assume the current resource is not a directory.
*/
is = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
List<String> lines = new ArrayList<String>();
for (String line; (line = reader.readLine()) != null;) {
log.trace("Reader entry: ", line);
lines.add(line);
if (getResources(path + "/" + line).isEmpty()) {
lines.clear();
break;
}
}
When url is a class file, attempting a read as a text file returns binary garbage.
Concatenating that garbage after the path and passing it to getResources() causes that invalid "path" to be evaluated by the classloader. This evaluation fails, now throwing an Exception (instead of returning an empty Enumeration<URL>), which crashes the whole webapp startup.
We fixed the issue in our local Stripes fork by replacing:
if (getResources(path + "/" + line).isEmpty()) {
with:
if (line.indexOf(0) > -1 || getResources(path + "/" + line).isEmpty())
to catch "lines" with null bytes earlier, but probably that is not the most universal way to solve the issue.
Keep on the good work !
Vincent
Hi,
We're happily using Stripes in several apps, and one of them stopped working once we upgraded Tomcat from 9.0.116 to 9.0.118 (same war, confirmed on both Linux and Windows). Tomcat logs indicated:
After digging through the Tomcat changes for v9.0.118, it appears that a new test was added to
org.apache.tomcat.util.http.RequestUtil.normalize(String path, boolean replaceBackSlash), which reads:That seemingly innocuous change causes
org.apache.catalina.webresources.StandardRoot.validate()to now throw anIllegalArgumentExceptionwhen the path contains null bytes, which leads to the stacktrace above.So we searched where the offending path
/WEB-INF/classes/be/betv/wimoos/ui/action/api/ApiArticleListActionBean.class/Êþº¾\u0000\u0000\u00007\u0001/came from.The reason is this code in Stripes'
net.sourceforge.stripes.vfs.DefaultVFS.java:When
urlis a class file, attempting a read as a text file returns binary garbage.Concatenating that garbage after the path and passing it to
getResources()causes that invalid "path" to be evaluated by the classloader. This evaluation fails, now throwing an Exception (instead of returning an emptyEnumeration<URL>), which crashes the whole webapp startup.We fixed the issue in our local Stripes fork by replacing:
with:
to catch "lines" with null bytes earlier, but probably that is not the most universal way to solve the issue.
Keep on the good work !
Vincent