Thank you Henry. Feel free to modify it.

Regards,
Bo

> On 27 Sep 2018, at 09:39, Henry Jen <henry....@oracle.com> wrote:
> 
> 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 
>> <mailto:zhangbo...@gmail.com>> wrote:
>> 
>> Can anyone please take a look?
>> 
>> Thank you.
>> 
>>> On 25 Sep 2018, at 14:27, Bo Zhang <zhangbo...@gmail.com 
>>> <mailto: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 
>>> <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> 
>>> <mailto: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/> 
>>> <http://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