unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
blob 165edd3b4a9aa5efb614b24980c3e1e16a610c14 13307 bytes (raw)
name: packages/patches/openjdk-10-module-reproducibility.patch 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
 
From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
From: Alan Bateman <alanb@openjdk.org>
Date: Wed, 29 Apr 2020 08:38:28 +0100
Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
 files depends on timestamps

Reviewed-by: mchung
---

--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-13 19:24:10.655695284 +0200
+++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-14 02:43:48.610326492 +0200
@@ -27,9 +27,8 @@
 
 import java.io.PrintStream;
 import java.lang.module.Configuration;
+import java.lang.module.ModuleReference;
 import java.lang.module.ResolvedModule;
-import java.net.URI;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayDeque;
 import java.util.Collections;
@@ -39,8 +38,8 @@
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.Consumer;
-import java.util.function.Function;
 import java.util.stream.Stream;
 import static java.util.stream.Collectors.*;
 
@@ -101,7 +100,7 @@
         // the modules to record the hashes - it is the first matching
         // module and has not been hashed during the traversal.
         Set<String> mods = new HashSet<>();
-        Map<String, ModuleHashes> hashes = new HashMap<>();
+        Map<String, ModuleHashes> hashes = new TreeMap<>();
         builder.build()
                .orderedNodes()
                .filter(mn -> roots.contains(mn) && !mods.contains(mn))
@@ -116,27 +115,17 @@
                    mods.addAll(ns);
 
                    if (!ns.isEmpty()) {
-                       Map<String, Path> moduleToPath = ns.stream()
-                           .collect(toMap(Function.identity(), this::moduleToPath));
-                       hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
+                       Set<ModuleReference> mrefs = ns.stream()
+                               .map(name -> configuration.findModule(name)
+                                                         .orElseThrow(InternalError::new))
+                               .map(ResolvedModule::reference)
+                               .collect(toSet());
+                       hashes.put(mn, ModuleHashes.generate(mrefs, "SHA-256"));
                    }
                });
         return hashes;
     }
 
-    private Path moduleToPath(String name) {
-        ResolvedModule rm = configuration.findModule(name).orElseThrow(
-            () -> new InternalError("Selected module " + name + " not on module path"));
-
-        URI uri = rm.reference().location().get();
-        Path path = Paths.get(uri);
-        String fn = path.getFileName().toString();
-        if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
-            throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
-        }
-        return path;
-    }
-
     /*
      * Utility class
      */diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	1970-01-01 01:00:01.000000000 +0100
+++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	2022-04-12 16:58:05.639985936 +0200
@@ -26,17 +26,21 @@
 package jdk.internal.module;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.UncheckedIOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.Path;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.function.Supplier;
 
 /**
  * The result of hashing the contents of a number of module artifacts.
@@ -60,8 +64,8 @@
      * @param algorithm   the algorithm used to create the hashes
      * @param nameToHash  the map of module name to hash value
      */
-    public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
-        this.algorithm = algorithm;
+    ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
+        this.algorithm = Objects.requireNonNull(algorithm);
         this.nameToHash = Collections.unmodifiableMap(nameToHash);
     }
 
@@ -95,54 +99,125 @@
     }
 
     /**
-     * Computes the hash for the given file with the given message digest
-     * algorithm.
+     * Computes a hash from the names and content of a module.
      *
+     * @param reader the module reader to access the module content
+     * @param algorithm the name of the message digest algorithm to use
+     * @return the hash
+     * @throws IllegalArgumentException if digest algorithm is not supported
      * @throws UncheckedIOException if an I/O error occurs
      * @throws RuntimeException if the algorithm is not available
      */
-    public static byte[] computeHash(Path file, String algorithm) {
+    private static byte[] computeHash(ModuleReader reader, String algorithm) {
+        MessageDigest md;
         try {
-            MessageDigest md = MessageDigest.getInstance(algorithm);
-
-            // Ideally we would just mmap the file but this consumes too much
-            // memory when jlink is running concurrently on very large jmods
-            try (FileChannel fc = FileChannel.open(file)) {
-                ByteBuffer bb = ByteBuffer.allocate(32*1024);
-                while (fc.read(bb) > 0) {
-                    bb.flip();
-                    md.update(bb);
-                    assert bb.remaining() == 0;
-                    bb.clear();
-                }
-            }
-
-            return md.digest();
+            md = MessageDigest.getInstance(algorithm);
         } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
+            throw new IllegalArgumentException(e);
+        }
+        try {
+            byte[] buf = new byte[32*1024];
+            reader.list().sorted().forEach(rn -> {
+                md.update(rn.getBytes(StandardCharsets.UTF_8));
+                try (InputStream in = reader.open(rn).orElseThrow(java.util.NoSuchElementException::new)) {
+                    int n;
+                    while ((n = in.read(buf)) > 0) {
+                        md.update(buf, 0, n);
+                    }
+                } catch (IOException ioe) {
+                    throw new UncheckedIOException(ioe);
+                }
+            });
         } catch (IOException ioe) {
             throw new UncheckedIOException(ioe);
         }
+        return md.digest();
     }
 
     /**
-     * Computes the hash for every entry in the given map, returning a
-     * {@code ModuleHashes} to encapsulate the result. The map key is
-     * the entry name, typically the module name. The map value is the file
-     * path to the entry (module artifact).
+     * Computes a hash from the names and content of a module.
      *
+     * @param supplier supplies the module reader to access the module content
+     * @param algorithm the name of the message digest algorithm to use
+     * @return the hash
+     * @throws IllegalArgumentException if digest algorithm is not supported
+     * @throws UncheckedIOException if an I/O error occurs
+     */
+    static byte[] computeHash(Supplier<ModuleReader> supplier, String algorithm) {
+        try (ModuleReader reader = supplier.get()) {
+            return computeHash(reader, algorithm);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    /**
+     * Computes the hash from the names and content of a set of modules. Returns
+     * a {@code ModuleHashes} to encapsulate the result.
+     * @param mrefs the set of modules
+     * @param algorithm the name of the message digest algorithm to use
      * @return ModuleHashes that encapsulates the hashes
+     * @throws IllegalArgumentException if digest algorithm is not supported
+     * @throws UncheckedIOException if an I/O error occurs
      */
-    public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
+    static ModuleHashes generate(Set<ModuleReference> mrefs, String algorithm) {
         Map<String, byte[]> nameToHash = new HashMap<>();
-        for (Map.Entry<String, Path> entry: map.entrySet()) {
-            String name = entry.getKey();
-            Path path = entry.getValue();
-            nameToHash.put(name, computeHash(path, algorithm));
+        for (ModuleReference mref : mrefs) {
+            try (ModuleReader reader = mref.open()) {
+                byte[] hash = computeHash(reader, algorithm);
+                nameToHash.put(mref.descriptor().name(), hash);
+            } catch (IOException ioe) {
+                throw new UncheckedIOException(ioe);
+            }
         }
         return new ModuleHashes(algorithm, nameToHash);
     }
 
+    @Override
+    public int hashCode() {
+        int h = algorithm.hashCode();
+        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
+            h = h * 31 + e.getKey().hashCode();
+            h = h * 31 + Arrays.hashCode(e.getValue());
+        }
+        return h;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ModuleHashes))
+            return false;
+        ModuleHashes other = (ModuleHashes) obj;
+        if (!algorithm.equals(other.algorithm)
+                || nameToHash.size() != other.nameToHash.size())
+            return false;
+        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
+            String name = e.getKey();
+            byte[] hash = e.getValue();
+            if (!Arrays.equals(hash, other.nameToHash.get(name)))
+                return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(algorithm);
+        sb.append(" ");
+        nameToHash.entrySet()
+                .stream()
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> {
+                    sb.append(e.getKey());
+                    sb.append("=");
+                    byte[] ba = e.getValue();
+                    for (byte b : ba) {
+                        sb.append(String.format("%02x", b & 0xff));
+                    }
+                });
+        return sb.toString();
+    }
+
     /**
      * This is used by jdk.internal.module.SystemModules class
      * generated at link time.
diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	1970-01-01 01:00:01.000000000 +0100
+++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	2022-04-12 16:43:12.967868689 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2020, 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
diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	1970-01-01 01:00:01.000000000 +0100
+++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	2022-04-12 16:43:12.971868797 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2020, 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
@@ -95,7 +95,7 @@
                                         Path file) {
         URI uri = file.toUri();
         Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
+        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
         return newModule(attrs, uri, supplier, patcher, hasher);
     }
 
@@ -105,7 +105,7 @@
     static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
         URI uri = file.toUri();
         Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
+        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
         return newModule(attrs, uri, supplier, null, hasher);
     }
 

debug log:

solving 165edd3b4a9aa5efb614b24980c3e1e16a610c14 ...
found 165edd3b4a9aa5efb614b24980c3e1e16a610c14 in https://git.savannah.gnu.org/cgit/guix.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).