Hi Philipp

The change mostly looks fine. You might want to put everything into a patch 
file so Vincent can recreate a webrev and post it to cr.openjdk.java.net.

One thing I would suggest for the test is that instead of using jarsigner 
-verify and check the text in output you can open it as a JarFile, consume the 
content of an entry, and look into its getCertificates().

Also, you might want to reuse test/lib/jdk/test/lib/SecurityTools.java, and 
there is also JarUtils.java you can use. Maybe Files.copy(InputStream,Path) can 
be used in copyClassToFile().

Thanks
Max

> On Sep 20, 2017, at 7:41 AM, Philipp Kunz <philipp.k...@paratix.ch> wrote:
> 
> Hello Vincent
> 
> Here may be the fix for JDK-6695402. First a test.
> 
> BEGIN /jdk10/jdk/test/sun/security/tools/jarsigner/MultibyteUnicodeName.java
> /*
>  * Copyright (c) 1999, 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 if you need additional information or have any
>  * questions.
>  */
> 
> /*
>  * @test
>  * @bug JDK-6695402
>  * @summary verify signatures of jars containing classes with names with 
> multi-
>  *          byte unicode characters broken across lines
>  * @library /test/lib
>  * @modules jdk.jartool/sun.tools.jar
>  *          jdk.jartool/sun.security.tools.jarsigner
>  * @build jdk.test.lib.JDKToolLauncher
>  *        jdk.test.lib.process.*
>  * @run main MultibyteUnicodeName
>  */
> 
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.io.UnsupportedEncodingException;
> import java.nio.file.Files;
> import java.nio.file.Paths;
> import java.util.jar.JarFile;
> import java.util.jar.Manifest;
> import java.util.stream.Collectors;
> import java.util.Arrays;
> import java.util.Map;
> import java.util.jar.Attributes.Name;
> import java.util.jar.JarEntry;
> 
> import static java.nio.charset.StandardCharsets.UTF_8;
> 
> import sun.security.tools.jarsigner.Resources;
> 
> import jdk.test.lib.JDKToolLauncher;
> import jdk.test.lib.process.OutputAnalyzer;
> import jdk.test.lib.process.ProcessTools;
> 
> public class MultibyteUnicodeName {
>     
>     public static void main(String[] args) throws Throwable {
>         try {
>             prepare();
>             
>             testSignJar("test.jar");
>             testSignJarNoManifest("test-no-manifest.jar");
>             testSignJarUpdate("test-update.jar");
>             testSignJarWithIndex("test-index.jar");
>             testSignJarAddIndex("test-add-index.jar");
>             
>         } finally {
>             Files.deleteIfExists(Paths.get(keystoreFileName));
>             Files.deleteIfExists(Paths.get(ManifestFileName));
>             Files.deleteIfExists(Paths.get(refClassFilename));
>             Files.deleteIfExists(Paths.get(testClassFilename));
>         }
>     }
>     
>     static final String alias = "a";
>     static final String keystoreFileName = "test.jks";
>     static final String ManifestFileName = "MANIFEST.MF";
>     
>     static class A1234567890B1234567890C1234567890D12345678exyz { }
>     static class A1234567890B1234567890C1234567890D12345678éxyz { }
>     
>     static final String refClassFilename = 
> MultibyteUnicodeName.class.getSimpleName() + 
>             "$" + 
> A1234567890B1234567890C1234567890D12345678exyz.class.getSimpleName() + 
> ".class";
>     static final String testClassFilename = 
> MultibyteUnicodeName.class.getSimpleName() + 
>             "$" + 
> A1234567890B1234567890C1234567890D12345678éxyz.class.getSimpleName() + 
> ".class";
>     
>     static void prepare() throws Throwable {
>         tool("keytool", "-keystore", keystoreFileName, "-genkeypair", 
> "-storepass", "changeit",
>                 "-keypass", "changeit", "-storetype", "JKS", "-alias", alias, 
> "-dname", "CN=X",
>                 "-validity", "366")
>                 .shouldHaveExitValue(0);
>         
>         Files.write(Paths.get(ManifestFileName),
>                 (Name.MANIFEST_VERSION.toString() + ": 
> 1.0\r\n").getBytes(UTF_8.name()));
>         copyClassToFile(refClassFilename);
>         copyClassToFile(testClassFilename);
>     }
>     
>     static void copyClassToFile(String classFilename) throws IOException {
>         try (
>             InputStream asStream = 
> MultibyteUnicodeName.class.getResourceAsStream(classFilename);
>             ByteArrayOutputStream buf = new ByteArrayOutputStream();
>         ) {
>             int b;
>             while ((b = asStream.read()) != -1) buf.write(b);
>             Files.write(Paths.get(classFilename), buf.toByteArray());
>         }
>     }
> 
>     static void testSignJar(String jarFileName) throws Throwable {
>         try {
>             tool("jar", "cvfm", jarFileName, 
>                     ManifestFileName, refClassFilename, testClassFilename)
>                     .shouldHaveExitValue(0);
>             verifyJarSignature(jarFileName);
> 
>         } finally {
>             Files.deleteIfExists(Paths.get(jarFileName));
>         }
>     }
> 
>     static void testSignJarNoManifest(String jarFileName) throws Throwable {
>         try {
>             tool("jar", "cvf", jarFileName, refClassFilename, 
> testClassFilename)
>                 .shouldHaveExitValue(0);
>             verifyJarSignature(jarFileName);
> 
>         } finally {
>             Files.deleteIfExists(Paths.get(jarFileName));
>         }
>     }
>     
>     static void testSignJarUpdate(String jarFileName) throws Throwable {
>         try {
>             tool("jar", "cvfm", jarFileName, ManifestFileName, 
> refClassFilename)
>                 .shouldHaveExitValue(0);
>             tool("jarsigner", "-keystore", keystoreFileName, "-storetype", 
> "JKS",
>                     "-storepass", "changeit", "-debug", jarFileName, alias)
>                 .shouldHaveExitValue(0);
>             tool("jar", "uvf", jarFileName, testClassFilename)
>                 .shouldHaveExitValue(0);
>             verifyJarSignature(jarFileName);
> 
>         } finally {
>             Files.deleteIfExists(Paths.get(jarFileName));
>         }
>     }
>     
>     static void testSignJarWithIndex(String jarFileName) throws Throwable {
>         try {
>             tool("jar", "cvfm", jarFileName, 
>                     ManifestFileName, refClassFilename, testClassFilename)
>                 .shouldHaveExitValue(0);
>             tool("jar", "iv", jarFileName).shouldHaveExitValue(0);
>             verifyJarSignature(jarFileName);
> 
>         } finally {
>             Files.deleteIfExists(Paths.get(jarFileName));
>         }
>     }
> 
>     static void testSignJarAddIndex(String jarFileName) throws Throwable {
>         try {
>             tool("jar", "cvfm", jarFileName, 
>                     ManifestFileName, refClassFilename, testClassFilename)
>                 .shouldHaveExitValue(0);
>             tool("jarsigner", "-keystore", keystoreFileName, "-storetype", 
> "JKS",
>                     "-storepass", "changeit", "-debug", jarFileName, alias)
>                 .shouldHaveExitValue(0);
>             tool("jar", "iv", jarFileName).shouldHaveExitValue(0);
>             verifyJarSignature(jarFileName);
> 
>         } finally {
>             Files.deleteIfExists(Paths.get(jarFileName));
>         }
>     }
>     
>     static Map<String, String> jarsignerResources = Arrays.stream(new 
> Resources().getContents()).
>             collect(Collectors.toMap(e -> (String) e[0], e -> (String) e[1]));
>             
>     static void verifyJarSignature(String jarFileName) throws Throwable {
>         // actually sign the jar
>         tool("jarsigner", "-keystore", keystoreFileName, "-storetype", "JKS",
>                 "-storepass", "changeit", "-debug", jarFileName, alias)
>                 .shouldHaveExitValue(0);
>         
>         verifyClassNameLineBroken(jarFileName);
>         
>         // check for no unsigned entries
>         tool("jarsigner", "-verify", "-keystore", keystoreFileName, 
> "-storetype", "JKS",
>                 "-storepass", "changeit", "-debug", jarFileName, alias)
>                 .shouldHaveExitValue(0)
>                 .shouldNotContain(jarsignerResources.get(
>                         
> "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
>         
>         // check that both classes with and without multi-byte unicode 
> characters in their names are signed
>         tool("jarsigner", "-verify", "-verbose", "-keystore", 
> keystoreFileName, "-storetype", "JKS",
>                 "-storepass", "changeit", "-debug", jarFileName, alias)
>                 .shouldHaveExitValue(0)
>                 .shouldMatch("^" + jarsignerResources.get("s") + 
> jarsignerResources.get("m") + jarsignerResources.get("k") + ".+" + 
> refClassFilename.replaceAll("\\$", "\\\\\\$") + "$")
>                 .shouldMatch("^" + jarsignerResources.get("s") + 
> jarsignerResources.get("m") + jarsignerResources.get("k") + ".+" + 
> testClassFilename.replaceAll("\\$", "\\\\\\$") + "$");
>         
>         // check that both classes with and without multi-byte unicode 
> characters in their names have signing certificates
>         tool("jarsigner", "-verify", "-verbose", "-certs", "-keystore", 
> keystoreFileName, 
>                 "-storetype", "JKS", "-storepass", "changeit", "-debug", 
> jarFileName, alias)
>                 .shouldHaveExitValue(0)
>                 .shouldMatch(refClassFilename.replaceAll("\\$", "\\\\\\$") + 
> "\\s*\\R*\\s*(\\[" + jarsignerResources.get("entry.was.signed.on") + " 
> .*\\]\\R*)?\\s*X.509, CN=X \\(" + alias + "\\)")
>                 .shouldMatch(testClassFilename.replaceAll("\\$", "\\\\\\$") + 
> "\\s*\\R*\\s*(\\[" + jarsignerResources.get("entry.was.signed.on") + " 
> .*\\]\\R*)?\\s*X.509, CN=X \\(" + alias + "\\)");
>     }
>     
>     /**
>      * it would be too easy to miss the actual test case by just renaming an 
> identifier so that
>      * the multi-byte encoded character would not any longer be broken across 
> a line break.
>      *
>      * this test verifies that the actual test case is tested based on the 
> manifest
>      * and not based on the signature file because at the moment, the 
> signature file
>      * does not even contain the desired entry at all.
>      *
>      * this relies on the Manifest breaking lines unaware of bytes that 
> belong to the same
>      * multi-ybte utf characters.
>      */
>     static void verifyClassNameLineBroken(String jarFileName) throws 
> IOException {
>         byte[] eAcute = "é".getBytes(UTF_8);
>         byte[] eAcuteBroken = new byte[] {eAcute[0], '\r', '\n', ' ', 
> eAcute[1]};
>         
>         try (
>             JarFile jar = new JarFile(jarFileName);
>         ) {
>             if (jar.getManifest().getAttributes(testClassFilename) == null) {
>                 throw new AssertionError(testClassFilename + " not found in 
> manifest");
>             }
>             
>             JarEntry manifestEntry = jar.getJarEntry(JarFile.MANIFEST_NAME);
>             try (
>                 InputStream manifestIs = jar.getInputStream(manifestEntry);
>             ) {
>                 int bytesMatched = 0;
>                 for (int b = manifestIs.read(); b > -1; b = 
> manifestIs.read()) {
>                     if ((byte) b == eAcuteBroken[bytesMatched]) {
>                         bytesMatched++;
>                         if (bytesMatched == eAcuteBroken.length) {
>                             break;
>                         }
>                     } else {
>                         bytesMatched = 0;
>                     }
>                 }
>                 if (bytesMatched < eAcuteBroken.length) {
>                     throw new AssertionError("self-test failed: "
>                             + "multi-byte utf-8 character not broken across 
> lines");
>                 }
>             }
>         }
>     }
>     
>     static OutputAnalyzer tool(String tool, String... args)
>             throws Throwable {
>         JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK(tool);
>         for (String arg : args) {
>             if (arg .startsWith("-J")) {
>                 l.addVMArg(arg.substring(2));
>             } else {
>                 l.addToolArg(arg);
>             }
>         }
>         return ProcessTools.executeCommand(l.getCommand());
>     }
>     
> }
> END /jdk10/jdk/test/sun/security/tools/jarsigner/MultibyteUnicodeName.java
> 
> 
> There are three e with acutes, on lines 84, 89, and 227, just in case the 
> mail suffers bad encoding which might not be absolutely unconceivable 
> regarding the bug's subject.
> 
> In contrast to the bug description it uses a nested class with a two-byte 
> UTF-8 character rather than one in its own file. I chose to do it that way 
> because then the complete test goes into one file and therefore I assume the 
> overview is kept easier. The test still demonstrates exactly JDK-6695402's 
> problem.
> 
> It may not have been necessary to also test jar files with indexes but i 
> consider it necessary to have signing unsigned as well as partially signed 
> jars tested, so why not have one more case tested, too?
> 
> There might also be a more elegant approach to get class files into a jar 
> file as to get their contents through the class loader. I chose to use real 
> class files rather than dummy contents in files named *.class or for instance 
> plain text files in the jar the signing of which to be tested in order to 
> stay as close to the original bug problem as possible even though I don't 
> have any notion that it would make a difference. The amount of code used to 
> copy the class file contents around is comparatively small with respect to 
> the whole test case amount of code.
>   
> For the demonstration that the multi-byte character actually makes the 
> alleged difference, I concluded that it was necessary to have another class 
> name not previously affected by the bug in order to compare the effects of 
> just different names. Otherwise the signing could fail to any other reason 
> undetectably.
> 
> In order to express a condition to tell successful from failed test runs the 
> best approach I found was to analyze the jarsigner tool's output which is in 
> my opinion not the most desirable option. I'd have preferred output from a 
> clearer structured api but then I guess the output format will not change too 
> often in the foreseeable future. For instance the check for the s, m, and k 
> flags is more pragmatical approach than obviously perfectly failsafe when 
> operating with regular expressions to match it with the output. Other parts 
> such as 'X.509' and 'CN=' are not even jarsigner tool resources. I put at 
> least a reference to sun.security.tools.jarsigner.Resources.
> 
> Finally, I afforded kind of a self-test that protects the test from 
> undetected failing because renaming the main class which would move the 
> two-byte unicode character to a position not suitable for the test. It may 
> not be absolutely necessary.
> 
> 
> 
> BEGIN PATH
> diff -r ddc25f646c2e 
> src/java.base/share/classes/sun/security/util/ManifestDigester.java
> --- a/src/java.base/share/classes/sun/security/util/ManifestDigester.java    
> Thu Aug 31 22:21:20 2017 -0700
> +++ b/src/java.base/share/classes/sun/security/util/ManifestDigester.java    
> Wed Sep 20 00:56:15 2017 +0200
> @@ -28,6 +28,7 @@
>  import java.security.*;
>  import java.util.HashMap;
>  import java.io.ByteArrayOutputStream;
> +import static java.nio.charset.StandardCharsets.UTF_8;
>  
>  /**
>   * This class is used to compute digests on sections of the Manifest.
> @@ -112,7 +113,7 @@
>          rawBytes = bytes;
>          entries = new HashMap<>();
>  
> -        ByteArrayOutputStream baos = new ByteArrayOutputStream();
> +        ByteArrayOutputStream nameBuf = new ByteArrayOutputStream();
>  
>          Position pos = new Position();
>  
> @@ -131,50 +132,40 @@
>  
>              if (len > 6) {
>                  if (isNameAttr(bytes, start)) {
> -                    StringBuilder nameBuf = new StringBuilder(sectionLen);
> +                    nameBuf.reset();
> +                    nameBuf.write(bytes, start+6, len-6);
>  
> -                    try {
> -                        nameBuf.append(
> -                            new String(bytes, start+6, len-6, "UTF8"));
> +                    int i = start + len;
> +                    if ((i-start) < sectionLen) {
> +                        if (bytes[i] == '\r') {
> +                            i += 2;
> +                        } else {
> +                            i += 1;
> +                        }
> +                    }
>  
> -                        int i = start + len;
> -                        if ((i-start) < sectionLen) {
> -                            if (bytes[i] == '\r') {
> -                                i += 2;
> -                            } else {
> -                                i += 1;
> -                            }
> +                    while ((i-start) < sectionLen) {
> +                        if (bytes[i++] == ' ') {
> +                            // name is wrapped
> +                            int wrapStart = i;
> +                            while (((i-start) < sectionLen)
> +                                    && (bytes[i++] != '\n'));
> +                            if (bytes[i-1] != '\n')
> +                                return; // XXX: exception?
> +                            int wrapLen;
> +                            if (bytes[i-2] == '\r')
> +                                wrapLen = i-wrapStart-2;
> +                            else
> +                                wrapLen = i-wrapStart-1;
> +
> +                            nameBuf.write(bytes, wrapStart, wrapLen);
> +                        } else {
> +                            break;
>                          }
> +                    }
>  
> -                        while ((i-start) < sectionLen) {
> -                            if (bytes[i++] == ' ') {
> -                                // name is wrapped
> -                                int wrapStart = i;
> -                                while (((i-start) < sectionLen)
> -                                        && (bytes[i++] != '\n'));
> -                                    if (bytes[i-1] != '\n')
> -                                        return; // XXX: exception?
> -                                    int wrapLen;
> -                                    if (bytes[i-2] == '\r')
> -                                        wrapLen = i-wrapStart-2;
> -                                    else
> -                                        wrapLen = i-wrapStart-1;
> -
> -                            nameBuf.append(new String(bytes, wrapStart,
> -                                                      wrapLen, "UTF8"));
> -                            } else {
> -                                break;
> -                            }
> -                        }
> -
> -                        entries.put(nameBuf.toString(),
> -                            new Entry(start, sectionLen, sectionLenWithBlank,
> -                                rawBytes));
> -
> -                    } catch (java.io.UnsupportedEncodingException uee) {
> -                        throw new IllegalStateException(
> -                            "UTF8 not available on platform");
> -                    }
> +                    entries.put(new String(nameBuf.toByteArray(), UTF_8),
> +                        new Entry(start, sectionLen, sectionLenWithBlank, 
> rawBytes));
>                  }
>              }
>              start = pos.startOfNext;
> END PATCH
> 
> 
> The patch is mostly so big because indentation has changed in many lines.
> 
> There was baos there before without apparent use. The patch renames it and 
> puts it into use. It came in very handy because if it would not have been 
> there already, I would have had to defined one of my own.
> 
> The main point of the patch is that manifest section names that are broken 
> across lines at possibly arbitrary bytes are no longer converted into strings 
> for each manifest line and then joined. Parts of names broken across lines 
> are now joined first when they are still byte sequences and only when the 
> complete byte sequence is available after processing all manifest lines that 
> contain the same manifest section name decoded into a unicode string.
> 
> For decoding the bytes into a string I chose a different string constructor 
> than was used before that does not any longer declare 
> UnsupportedEncodingException rendering the try/catch redundant. It couldn't 
> have ever occurred anyway taking into consideration that UTF-8 is mandatory 
> for every Java platform, StandardCharsets says. The difference according to 
> the documentation is that the previously     used String constructor returned 
> undefined strings for invalid byte sequences whereas the one used in the 
> patch will replace unparseable portions with valid 'unknown' characters.
> 
> One question I cannot still answer yet is how the ManifestDigester can be 
> changed at all without complete test coverage or risking to break existing 
> signatures. I already started on that but it's quite a piece of work to 
> almost formally prove that all manifests will continue to produce identical 
> digests, except of course for the ones now fixed.
> 
> Regards,
> Philipp
> 
> 
> On 17.09.2017 21:25, Philipp Kunz wrote:
>> Hello Vincent
>> 
>> I narrowed the error down so far and suspect now that it is an effect of 
>> sun.security.util.ManifestDigester's constructor, lines 134 and 163-164, in 
>> combination with java.util.jar.Manifest.make72Safe. Manifest breaks 
>> multi-byte characters in manifest section names across lines and 
>> ManifestDigester fails to restore them correctly, which both sounds wrong 
>> but ManifestDigester sure is.
>> 
>> Just fixing it would be too tempting but then I would not know (I mean not 
>> know for sure with evidence from tests) if any existing jar-signature would 
>> still be valid and I don't want to break existing signatures. When I had a 
>> look at the tests specific for Manifest and ManifestDigester I found very 
>> little. There are many more different situations and corner cases and 
>> combinations thereof to cover with tests than it looks like at first glance 
>> so that writing tests that cover all relevant cases looks to me like quite 
>> an effort. I have the impression that test coverage was not a priority when 
>> the subjected code was developed or at least the tests might not have been 
>> contributed to the open JDK project. Hence, while I'm continuing to complete 
>> these tests I miss, if       someone has an idea how to simplify that so 
>> that I can still convince at least myself that no existing signature will 
>> break or where possibly more testcases are that I haven't discovered so far, 
>> please let me know.
>> 
>> I'm also wondering how much performance should be taken into consideration. 
>> There are a few hints such as reusing byte arrays that suggest that it is an 
>> issue. Will a patch be rejected if it slows down some tests beyond a certain 
>> limit for so little added value or what might be the acceptance criteria 
>> here? I don't expect insuperable difficulties with performance but would 
>> still appreciate some general idea.
>> 
>> My desired or currently preferred approach to fix JDK-6695402 would be to 
>> let ManifestDigester any kind of use or extend Manifest in order to let 
>> Manifest identify the manifest sections thereby preventing the parsing 
>> duplicated that identifies the manifest sections.
>> 
>> As a new contributor I could use and would appreciate some guidance 
>> particularly about what kind and completeness of test coverage and 
>> performance tuning applies or is suggested in the context of the given bug. 
>> Otherwise I fear I might contribute too many tests which would have to be 
>> reviewed and maintained or quite some work would be for nothing if a patch 
>> would not satisfy performance requirements.
>> 
>> Regards,
>> Philipp
>> 
>> 
>> 
>> On 01.09.2017 15:20, Vincent Ryan wrote:
>>> That all sounds fine. Let me know when your patch is ready to submit.
>>> Thanks.
>>> 
>>> 
>>>> On 1 Sep 2017, at 13:15, Philipp Kunz <philipp.k...@paratix.ch> wrote:
>>>> 
>>>> Hello Vincent
>>>> 
>>>> Thank you for sponsoring!
>>>> So far, I have become a contributor by signing the OCA which has been 
>>>> accepted. Dalibor Topic wrote that he can confirm and it's also here: 
>>>> http://www.oracle.com/technetwork/community/oca-486395.html#p -> Paratix 
>>>> GmbH
>>>> Therefore I think I have followed the steps in 
>>>> http://openjdk.java.net/contribute/ at least the ones before actual patch 
>>>> submission.
>>>> 
>>>> Currently, I'm working on getting the existing test cases running locally. 
>>>> Unfortunately, I started with jdk 9 and switched to 10 now. I figured 
>>>> these commands run at least the relevant tests with 9 and hope this also 
>>>> applies to 10:
>>>> make run-test-tier1
>>>> make run-test TEST="jdk/test"
>>>> they report errors and failures but it hasn't been completed and released 
>>>> which might explain it. If I run the tests I assume relevant for my patch
>>>> make run-test TEST="jtreg:jdk/test/sun/security/tools/jarsigner 
>>>> jtreg:jdk/test/java/util/jar"
>>>> then it reports zero errors and failures which may be a good starting 
>>>> point.
>>>> Do you think that sounds reasonable or do you have another suggestion how 
>>>> to run the tests?
>>>> 
>>>> Next, I will add a test for JDK-6695402 before actually fixing it. As an 
>>>> example, I'll try something in the style of 
>>>> http://hg.openjdk.java.net/jdk9/dev/jdk/file/65464a307408/test/java/util/jar/Manifest/CreateManifest.java.
>>>>  This way, I try to demonstrate the improvement.
>>>> 
>>>> I guess I have identified the following line as the cause: value = new 
>>>> String(vb, 0, 0, vb.length);
>>>> http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/51f5d60713b5/src/java.base/share/classes/java/util/jar/Manifest.java#l157
>>>> So I'll try to remove it first including the whole four line if block.
>>>> 
>>>> Philipp
>>>> 
>>>> 
>>>> On 01.09.2017 10:00, Vincent Ryan wrote:
>>>>> Hello Philipp,
>>>>> 
>>>>> I’m happy to sponsor your fix for JDK 10. Have you followed these steps: 
>>>>> http://openjdk.java.net/contribute/ ?
>>>>> 
>>>>> Thanks.
>>>>> 
>>>>> 
>>>>>> On 1 Sep 2017, at 08:58, Vincent Ryan <vincent.x.r...@oracle.com> wrote:
>>>>>> 
>>>>>> Moved to security-dev
>>>>>> 
>>>>>> 
>>>>>>> On 1 Sep 2017, at 08:28, Philipp Kunz <philipp.k...@paratix.ch> wrote:
>>>>>>> 
>>>>>>> Hello everyone
>>>>>>> 
>>>>>>> I have been developing with Java for around 17 years now and when I 
>>>>>>> encountered some bug I decided to attempt to fix it: 
>>>>>>> https://bugs.openjdk.java.net/browse/JDK-6695402. This also looks like 
>>>>>>> it may not be too big a piece for a first contribution.
>>>>>>> 
>>>>>>> I read through quite some guides and all kinds of documents but could 
>>>>>>> not yet help myself with the following questions:
>>>>>>> 
>>>>>>> May I login to jira to add comments to bugs? If so, how would I request 
>>>>>>> or receive credentials? Or are mailing lists preferred?
>>>>>>> 
>>>>>>> Another question is whether I should apply it to jdk9, but it may be 
>>>>>>> too late now, or to jdk10, and backporting can be considered later. 
>>>>>>> Probably it wouldn't even make much a difference for the patch itself.
>>>>>>> 
>>>>>>> One more question I have is how or where to find the sources from 
>>>>>>> before migration to mercurial. Because some lines of code I intend to 
>>>>>>> change go back farther and in the history I find only 'initial commit'. 
>>>>>>> With such a history I might be able better to understand why it's there 
>>>>>>> and prevent to make the same mistake again.
>>>>>>> 
>>>>>>> I guess the appropriate mailing list for above mentioned bug is 
>>>>>>> security-dev. Is it correct that I can send a patch there and just hope 
>>>>>>> for some sponsor to pick it up? Of course I'd be glad if some sponsor 
>>>>>>> would contact me and maybe provide some assistance or if someone would 
>>>>>>> confirm that sending a patch to the mailing list is the right way to 
>>>>>>> find a sponsor.
>>>>>>> 
>>>>>>> Philipp Kunz
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
>> 
>> 
>> 
>> 
>> <Mail Attachment.png>
>> 
>> Paratix GmbH
>> St Peterhofstatt 11
>> 8001 Zürich
>> 
>> +41 (0)76 397 79 35
>> philipp.k...@paratix.ch
> 

Reply via email to