--- 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<String, Entry> 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<Section> 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) {