2017-09-26 2:20 GMT+03:00  <ma...@apache.org>:
> Author: markt
> Date: Mon Sep 25 23:20:56 2017
> New Revision: 1809669
>
> URL: http://svn.apache.org/viewvc?rev=1809669&view=rev
> Log:
> Add some additional checks required on Windows to keep all the checks in one 
> place and to avoid exceptions later in the processing.
> Includes utility class to determine if platform is Windows and performance 
> test case for alternative implementations.
>
> Added:
>     tomcat/trunk/java/org/apache/tomcat/util/compat/JrePlatform.java   (with 
> props)
>     
> tomcat/trunk/test/org/apache/catalina/webresources/TestAbstractFileResourceSetPerformance.java
>    (with props)
> Modified:
>     
> tomcat/trunk/java/org/apache/catalina/webresources/AbstractFileResourceSet.java

> Added: 
> tomcat/trunk/test/org/apache/catalina/webresources/TestAbstractFileResourceSetPerformance.java
> URL: 
> http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/webresources/TestAbstractFileResourceSetPerformance.java?rev=1809669&view=auto
> ==============================================================================
> --- 
> tomcat/trunk/test/org/apache/catalina/webresources/TestAbstractFileResourceSetPerformance.java
>  (added)
> +++ 
> tomcat/trunk/test/org/apache/catalina/webresources/TestAbstractFileResourceSetPerformance.java
>  Mon Sep 25 23:20:56 2017

> +package org.apache.catalina.webresources;
> +
> +import java.util.regex.Pattern;
> +
> +import org.junit.Test;
> +
> +public class TestAbstractFileResourceSetPerformance {
> +
> +    private static final Pattern UNSAFE_WINDOWS_FILENAME_PATTERN = 
> Pattern.compile(" $|[\"<>]");
> +
> +    private static final int LOOPS = 10_000_000;
> +
> +    /*
> +     * Checking individual characters is about 3 times faster on markt's dev
> +     * PC for typical length file names. The file names need to get to ~65
> +     * characters before the Pattern matching is faster.
> +     */
> +    @Test
> +    public void testFileNameFiltering() {
> +
> +        long start = System.nanoTime();
> +        for (int i = 0; i < LOOPS; i++) {
> +            UNSAFE_WINDOWS_FILENAME_PATTERN.matcher("testfile.jsp 
> ").matches();

This matches() here is wrong. With the pattern above it should be ".find()".

Using find() makes the result even worse,
find(): 1641ns per iteration.
matches(): 352ns per iteration

> +        }
> +        long end = System.nanoTime();
> +        System.out.println("Regular expression took " + (end - start) + "ns 
> or " +
> +                (end-start)/LOOPS + "ns per iteration");
> +
> +        start = System.nanoTime();
> +        for (int i = 0; i < LOOPS; i++) {
> +            checkForBadChars("testfile.jsp ");
> +        }
> +        end = System.nanoTime();
> +        System.out.println("char[] check took " + (end - start) + "ns or " +
> +                (end-start)/LOOPS + "ns per iteration");


        start = System.nanoTime();
        for (int i = 0; i < LOOPS; i++) {
            checkForBadChars2("testfile.jsp ");
        }
        end = System.nanoTime();
        System.out.println("charAt() check took " + (end - start) + "ns or " +
                (end-start)/LOOPS + "ns per iteration");

> +    }
> +
> +    private boolean checkForBadChars(String filename) {
> +        char[] chars = filename.toCharArray();
> +        for (char c : chars) {
> +            if (c == '\"' || c == '<' || c == '>') {
> +                return false;
> +            }
> +        }
> +        if (chars[chars.length -1] == ' ') {
> +            return false;
> +        }
> +        return true;
> +    }

Second variant, without array copying:

    private boolean checkForBadChars2(String filename) {
        final int len = filename.length();
        for (int i = 0; i < len; i++) {
            char c = filename.charAt(i);
            if (c == '\"' || c == '<' || c == '>') {
                return false;
            }
        }
        if (filename.charAt(len - 1) == ' ') {
            return false;
        }
        return true;
    }

My result:
    [junit] char[] check took 1019605894ns or 101ns per iteration
    [junit] charAt() check took 773188173ns or 77ns per iteration

    [junit] char[] check took 978054736ns or 97ns per iteration
    [junit] charAt() check took 842951721ns or 84ns per iteration


> +}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to