Hi,

Creating a new manifest as a copy from an existing one using the copy
constructor assigns the new manifest individual sections entries map
the same values which are references to attributes as the original
rather than copying them as well deeply resulting in two manifests
pointing to the same attributes instances modifications to which always
affect both manifests. See test and proposed fix in the attached patch.

Regards,
Philipp
diff -r 3f224e4a891e src/java.base/share/classes/java/util/jar/Manifest.java
--- a/src/java.base/share/classes/java/util/jar/Manifest.java	Fri Jan 18 17:34:43 2019 -0800
+++ b/src/java.base/share/classes/java/util/jar/Manifest.java	Sat Jan 19 19:20:10 2019 +0100
@@ -109,7 +109,9 @@
      */
     public Manifest(Manifest man) {
         attr.putAll(man.getMainAttributes());
-        entries.putAll(man.getEntries());
+        for (Map.Entry<String, Attributes> e : man.getEntries().entrySet()) {
+            entries.put(e.getKey(), new Attributes(e.getValue()));
+        }
         jv = man.jv;
     }
 
diff -r 3f224e4a891e test/jdk/java/util/jar/Manifest/ManifestCopyConstructor.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/jar/Manifest/ManifestCopyConstructor.java	Sat Jan 19 19:20:10 2019 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @run testng ManifestCopyConstructor
+ * @summary Checks Manifest copy constructor deeply copies attributes.
+ */
+public class ManifestCopyConstructor {
+
+    @Test
+    public void testDeepCopyAttributes() throws Exception {
+        Manifest m1 = new Manifest();
+        Attributes a1 = new Attributes();
+        m1.getEntries().put("x", a1);
+        Manifest m2 = new Manifest(m1);
+
+        // modify attributes a1 of manifest m1 after m2 was copied from m1
+        a1.putValue("x", "x");
+        assertNotNull(m1.getAttributes("x").getValue("x"));
+
+        // expect earlier copy unaffected
+        assertNull(m2.getAttributes("x").getValue("x"));
+
+        // modify attributes of copied manifest m2
+        m2.getAttributes("x").putValue("y", "y");
+        assertNotNull(m2.getAttributes("x").getValue("y"));
+
+        // expect original manifest m1 unaffected
+        assertNull(m1.getAttributes("x").getValue("y"));
+    }
+
+}

Reply via email to