Thanks for the fix. I had looked into it, it’s a nice catch, glad you find it.

The patch looks good, and test is sufficient, I have tested it with jdk.jdk 
repo. I will help you to push the fix. The only minor improvement I like to see 
is to verify content after the escape character, which I took the liberty to do 
it. Webrev coming soon.

Cheers,
Henry

> On Sep 26, 2018, at 4:03 PM, Bo Zhang <zhangbo...@gmail.com> wrote:
> 
> Can anyone please take a look?
> 
> Thank you.
> 
>> On 25 Sep 2018, at 14:27, Bo Zhang <zhangbo...@gmail.com> wrote:
>> 
>> Hi all,
>> 
>> This is my first time to try to submit a patch. Please forgive me if I did 
>> anything inappropriate. I’ve signed the OCA with the name “Bo Zhang”.
>> 
>> Bug description:
>> 
>> 8210810 <https://bugs.openjdk.java.net/browse/JDK-8210810>: Incorrect 
>> argument file parser behavior in certain cases
>> 
>> Previously, if a quoted backslash character appears at argument file
>> parser buffer boundary (i.e. 4096th/8192nd/... character of an argument
>> file is backslash '\'), the segment before the backslash character will
>> be added into argument twice due to a missing anchor position reset
>> operation.
>> 
>> For example, you have an argument file:
>> 
>> -cp "...a\\b"
>> 
>> and the 4096th and 4097th characters happen to be both '\', the result
>> generated by the argument file parser would be:
>> 
>> -cp "...aa\\b”
>> 
>> This patch fixes the issue by resetting anchor position correctly
>> in this case.
>> 
>> I’m a little surprised that this issue has existed for several years 
>> unnoticed.
>> 
>> 
>> Patch:
>> 
>> # HG changeset patch
>> # User Bo Zhang <zhangbo...@gmail.com <mailto:zhangbo...@gmail.com>>
>> # Date 1537835887 -28800
>> #      Tue Sep 25 08:38:07 2018 +0800
>> # Node ID 34f2803ad62cde8c82e3dfcf0b66e80276bd7352
>> # Parent  16f0deae8fa6ef85f7230308e1fe7556bd007c39
>> 8210810: Incorrect argument file parser behavior in certain cases
>> 
>> Previously, if a quoted backslash character appears at argument file
>> parser buffer boundary (i.e. 4096th/8192nd/... character of an argument
>> file is backslash '\'), the segment before the backslash character will
>> be added into argument twice due to a missing anchor position reset
>> operation.
>> 
>> For example, you have an argument file:
>> 
>> -cp "...a\\b"
>> 
>> and the 4096th and 4097th characters happen to be both '\', the result
>> generated by the argument file parser would be:
>> 
>> -cp "...aa\\b"
>> 
>> This patch fixes the issue by resetting anchor position correctly
>> in this case.
>> 
>> diff --git a/src/java.base/share/native/libjli/args.c 
>> b/src/java.base/share/native/libjli/args.c
>> --- a/src/java.base/share/native/libjli/args.c
>> +++ b/src/java.base/share/native/libjli/args.c
>> @@ -262,6 +262,8 @@
>>                     continue;
>>                 }
>>                 JLI_List_addSubstring(pctx->parts, anchor, nextc - anchor);
>> +                // anchor after backslash character
>> +                anchor = nextc + 1;
>>                 pctx->state = IN_ESCAPE;
>>                 break;
>>             case '\'':
>> diff --git a/test/jdk/tools/launcher/Test8210810.java 
>> b/test/jdk/tools/launcher/Test8210810.java
>> new file mode 100644
>> --- /dev/null
>> +++ b/test/jdk/tools/launcher/Test8210810.java
>> @@ -0,0 +1,107 @@
>> +/*
>> + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
>> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 only, as
>> + * published by the Free Software Foundation.
>> + *
>> + * This code is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * version 2 for more details (a copy is included in the LICENSE file that
>> + * accompanied this code).
>> + *
>> + * You should have received a copy of the GNU General Public License version
>> + * 2 along with this work; if not, write to the Free Software Foundation,
>> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> + *
>> + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
>> + * or visit www.oracle.com <http://www.oracle.com/> if you need additional 
>> information or have any
>> + * questions.
>> + */
>> +
>> +/*
>> + * @test
>> + * @bug 8210810
>> + * @summary Incorrect argument file parser behavior when backslash appears 
>> at buffer boundary
>> + * @modules java.base
>> + * @author Bo Zhang
>> + * @build TestHelper
>> + * @run main Test8210810
>> + */
>> +
>> +/*
>> + * 8210810: Previously, if a quoted backslash character appears at argument 
>> file
>> + * parser buffer boundary (i.e. 4096th/8192nd/... character of an argument
>> + * file is backslash '\'), the segment before the backslash character will
>> + * be added into argument twice due to a missing anchor position reset
>> + * operation. This test creates a special argument file which can reproduce 
>> this issue.
>> + */
>> +import java.io.File;
>> +import java.nio.file.Files;
>> +import java.io.IOException;
>> +import java.util.Arrays;
>> +
>> +public class Test8210810 extends TestHelper {
>> +    // Buffer size in args.c readArgFile() method
>> +    private static final int ARG_FILE_PARSER_BUF_SIZE = 4096;
>> +    public static void main(String... args) throws Exception {
>> +        new Test8210810().canParseArgFileCorrectly();
>> +    }
>> +
>> +    private void canParseArgFileCorrectly() throws IOException {
>> +        File testJar = createTestClassWhichPrintsClasspath();
>> +        File argFile = createArgFileWithSpecificClasspath();
>> +        TestResult result = doExec(javaCmd, "@argFile", "Foo");
>> +
>> +        long zCountInArgFile = countZ(new 
>> String(Files.readAllBytes(argFile.toPath())));
>> +        long zCountReadByParser = countZ(result.testOutput.get(0));
>> +        if(zCountInArgFile != zCountReadByParser) {
>> +            throw new RuntimeException("Classpath parsed by parser is 
>> different from argument file!");
>> +        }
>> +
>> +        testJar.delete();
>> +        argFile.delete();
>> +    }
>> +
>> +    private long countZ(String str) {
>> +        return str.chars().filter(ch -> ch == 'z').count();
>> +    }
>> +
>> +    private File createTestClassWhichPrintsClasspath() throws IOException {
>> +        File testJar = new File("test.jar");
>> +        testJar.delete();
>> +
>> +        StringBuilder tsrc = new StringBuilder();
>> +        tsrc.append("public static void main(String... args) {\n");
>> +        tsrc.append("   System.out.println(\"Classpath:\" + 
>> System.getProperty(\"java.class.path\"));\n");
>> +        tsrc.append("}\n");
>> +        createJar(testJar, new File("Foo"), tsrc.toString());
>> +        return testJar;
>> +    }
>> +
>> +    // Create a file whose 4096th and 4097th characters are both '\' 
>> (backslash)
>> +    // File content:
>> +    // |-cp "test.jar:zzzzz...zzz\\"|
>> +    private File createArgFileWithSpecificClasspath() throws IOException {
>> +        File argFile = new File("argFile");
>> +        argFile.delete();
>> +
>> +        StringBuilder arg = new StringBuilder("-cp \"test.jar");
>> +        arg.append(File.pathSeparator);
>> +
>> +        int fillingCharactersCount = ARG_FILE_PARSER_BUF_SIZE - 1 - 
>> arg.length();
>> +
>> +        for(int i = 0; i < fillingCharactersCount; ++i) {
>> +            arg.append('z');
>> +        }
>> +
>> +        arg.append('\\'); // 4096th character in the arg file
>> +        arg.append('\\'); // 4097th character in the arg file
>> +        arg.append('"');
>> +
>> +        createAFile(argFile, Arrays.asList(arg.toString()));
>> +        return argFile;
>> +    }
>> +}
>> 
>> Unit test:
>> 
>> Included in the patch. It creates a special argument file whose 4096th and 
>> 4097th characters are both ‘\’. Then it compares the classpath read in the 
>> VM and the classpath in the argument file to verify they’re identical.
>> 
>> <8210810.patch>
>> 
> 

Reply via email to