8189969: Manifest better manifest entries
authorweijun
Thu, 14 Dec 2017 08:21:36 +0800
changeset 49778 3e6ce108d269
parent 49777 4a8508247ac3
child 49779 ade43608ac3d
8189969: Manifest better manifest entries Reviewed-by: mullan
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<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) {