# HG changeset patch # User weijun # Date 1513210896 -28800 # Node ID 3e6ce108d2698d59a41628cb17ca6efef8716fbc # Parent 4a8508247ac3f8df2fd8096fa4c0c4776681ede0 8189969: Manifest better manifest entries Reviewed-by: mullan diff -r 4a8508247ac3 -r 3e6ce108d269 src/java.base/share/classes/sun/security/util/ManifestDigester.java --- a/src/java.base/share/classes/sun/security/util/ManifestDigester.java Sun Dec 10 15:29:26 2017 -0800 +++ b/src/java.base/share/classes/sun/security/util/ManifestDigester.java Thu Dec 14 08:21:36 2017 +0800 @@ -26,12 +26,17 @@ package sun.security.util; import java.security.*; +import java.util.ArrayList; import java.util.HashMap; import java.io.ByteArrayOutputStream; +import java.util.List; + import static java.nio.charset.StandardCharsets.UTF_8; /** * This class is used to compute digests on sections of the Manifest. + * Please note that multiple sections might have the same name, and they + * all belong to a single Entry. */ public class ManifestDigester { @@ -40,7 +45,7 @@ /** the raw bytes of the manifest */ private byte[] rawBytes; - /** the offset/length pair for a section */ + /** the entries grouped by names */ private HashMap entries; // key is a UTF-8 string /** state returned by findSection */ @@ -119,8 +124,8 @@ return; // XXX: exception? // create an entry for main attributes - entries.put(MF_MAIN_ATTRS, - new Entry(0, pos.endOfSection + 1, pos.startOfNext, rawBytes)); + entries.put(MF_MAIN_ATTRS, new Entry().addSection( + new Section(0, pos.endOfSection + 1, pos.startOfNext, rawBytes))); int start = pos.startOfNext; while(findSection(start, pos)) { @@ -162,9 +167,10 @@ } } - entries.put(new String(nameBuf.toByteArray(), UTF_8), - new Entry(start, sectionLen, sectionLenWithBlank, - rawBytes)); + entries.computeIfAbsent(new String(nameBuf.toByteArray(), UTF_8), + dummy -> new Entry()) + .addSection(new Section(start, sectionLen, + sectionLenWithBlank, rawBytes)); } } start = pos.startOfNext; @@ -182,13 +188,52 @@ } public static class Entry { + + // One Entry for one name, and one name can have multiple sections. + // According to the JAR File Specification: "If there are multiple + // individual sections for the same file entry, the attributes in + // these sections are merged." + private List
sections = new ArrayList<>(); + boolean oldStyle; + + private Entry addSection(Section sec) + { + sections.add(sec); + return this; + } + + public byte[] digest(MessageDigest md) + { + md.reset(); + for (Section sec : sections) { + if (oldStyle) { + Section.doOldStyle(md, sec.rawBytes, sec.offset, sec.lengthWithBlankLine); + } else { + md.update(sec.rawBytes, sec.offset, sec.lengthWithBlankLine); + } + } + return md.digest(); + } + + /** Netscape doesn't include the new line. Intel and JavaSoft do */ + + public byte[] digestWorkaround(MessageDigest md) + { + md.reset(); + for (Section sec : sections) { + md.update(sec.rawBytes, sec.offset, sec.length); + } + return md.digest(); + } + } + + private static class Section { int offset; int length; int lengthWithBlankLine; byte[] rawBytes; - boolean oldStyle; - public Entry(int offset, int length, + public Section(int offset, int length, int lengthWithBlankLine, byte[] rawBytes) { this.offset = offset; @@ -197,18 +242,7 @@ this.rawBytes = rawBytes; } - public byte[] digest(MessageDigest md) - { - md.reset(); - if (oldStyle) { - doOldStyle(md,rawBytes, offset, lengthWithBlankLine); - } else { - md.update(rawBytes, offset, lengthWithBlankLine); - } - return md.digest(); - } - - private void doOldStyle(MessageDigest md, + private static void doOldStyle(MessageDigest md, byte[] bytes, int offset, int length) @@ -232,16 +266,6 @@ } md.update(bytes, start, i-start); } - - - /** Netscape doesn't include the new line. Intel and JavaSoft do */ - - public byte[] digestWorkaround(MessageDigest md) - { - md.reset(); - md.update(rawBytes, offset, length); - return md.digest(); - } } public Entry get(String name, boolean oldStyle) {