On Tue, Mar 3, 2020 at 5:20 PM Martin Buchholz <marti...@google.com> wrote:
>
> Looks Good To Me ... except you should fix that "delfated" typo.
>

Thanks. Corrected the typo along with some comment shortening suggested by Alan:

http://cr.openjdk.java.net/~simonis/webrevs/2020/8240333.01/

> Those looking for a zip implementation career path

:-))

> can try to fix up all the compressedSize in the local headers so that they 
> are correctly filled in.  Which is hard because you don't know the 
> compressedSize when you are writing the local entry header with putNextEntry.
>

You can't know it be fore you are doing it :)

> On Tue, Mar 3, 2020 at 3:02 AM Volker Simonis <volker.simo...@gmail.com> 
> wrote:
>>
>> Hi,
>>
>> can I please get a review for the following small fix:
>>
>> http://cr.openjdk.java.net/~simonis/webrevs/2020/8240333/
>> https://bugs.openjdk.java.net/browse/JDK-8240333
>>
>> The "jmod" tool needs to update .jar files as well as .jmod files when
>> adding hashes to the module-info file. This is handled in the method
>> jdk.tools.jmod.JmodTask.updateModularJar() for modular jar files and
>> in the methods jdk.tools.jmod.JmodTask.updateJmodFile() and
>> jdk.tools.jmod.JmodOutputStream.writeEntry() for .jmod files.
>>
>> Unfortunately, both implementations are incorrect because they are
>> writing the JarEntry/ZipEntry entries which they reading from the
>> ZipInputStream verbatim to the ZipOutputStream. This approach is not
>> correct, because Zip/Entry/JarEntry contains both, the compressed and
>> uncompressed size of the corresponding entry. But the original
>> Deflater which initially compressed that entry can be either different
>> from the current one or it might have used a different compression
>> level compared to the current Deflater which re-deflates the entry
>> data.
>>
>> When the newly created entry is closed, the new compressed size will
>> be checked against the original compressed size if that was recorded
>> in the ZipEntry/JarEntry entry and an exception will be thrown, when
>> they differ. For modular jar files it looks as follows:
>>
>> $ jmod hash --module-path . --hash-modules .*
>> Error: java.util.zip.ZipException: invalid entry compressed size
>> (expected 58 but got 57 bytes)
>> java.io.UncheckedIOException: java.util.zip.ZipException: invalid
>> entry compressed size (expected 58 but got 57 bytes)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.lambda$updateModularJar$3(JmodTask.java:995)
>> at 
>> java.base/java.util.zip.ZipFile$EntrySpliterator.tryAdvance(ZipFile.java:571)
>> at java.base/java.util.Spliterator.forEachRemaining(Spliterator.java:326)
>> at 
>> java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.updateModularJar(JmodTask.java:980)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.updateModuleInfo(JmodTask.java:957)
>> at jdk.jlink/jdk.tools.jmod.JmodTask.lambda$hashModules$3(JmodTask.java:300)
>> at java.base/java.util.HashMap.forEach(HashMap.java:1425)
>> at jdk.jlink/jdk.tools.jmod.JmodTask.hashModules(JmodTask.java:291)
>> at jdk.jlink/jdk.tools.jmod.JmodTask.run(JmodTask.java:220)
>> at jdk.jlink/jdk.tools.jmod.Main.main(Main.java:34)
>> Suppressed: java.util.zip.ZipException: invalid entry compressed size
>> (expected 58 but got 57 bytes)
>> at 
>> java.base/java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
>> at java.base/java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:360)
>> at 
>> java.base/java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:237)
>> at java.base/java.util.zip.ZipOutputStream.close(ZipOutputStream.java:377)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.updateModularJar(JmodTask.java:976)
>> ... 6 more
>> Caused by: java.util.zip.ZipException: invalid entry compressed size
>> (expected 58 but got 57 bytes)
>> at 
>> java.base/java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.lambda$updateModularJar$3(JmodTask.java:992)
>> ... 10 more
>>
>> For jmod files it looks like this:
>>
>> $ jmod hash --module-path . --hash-modules .*
>> Error: java.util.zip.ZipException: invalid entry compressed size
>> (expected 383 but got 377 bytes)
>> java.io.UncheckedIOException: java.util.zip.ZipException: invalid
>> entry compressed size (expected 383 but got 377 bytes)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.lambda$updateJmodFile$4(JmodTask.java:1021)
>> at 
>> java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
>> at 
>> java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
>> at 
>> java.base/java.util.zip.ZipFile$EntrySpliterator.tryAdvance(ZipFile.java:571)
>> at java.base/java.util.Spliterator.forEachRemaining(Spliterator.java:326)
>> at 
>> java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
>> at 
>> java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
>> at 
>> java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
>> at 
>> java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
>> at 
>> java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
>> at 
>> java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.updateJmodFile(JmodTask.java:1009)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.updateModuleInfo(JmodTask.java:955)
>> at jdk.jlink/jdk.tools.jmod.JmodTask.lambda$hashModules$3(JmodTask.java:300)
>> at java.base/java.util.HashMap.forEach(HashMap.java:1425)
>> at jdk.jlink/jdk.tools.jmod.JmodTask.hashModules(JmodTask.java:291)
>> at jdk.jlink/jdk.tools.jmod.JmodTask.run(JmodTask.java:220)
>> at jdk.jlink/jdk.tools.jmod.Main.main(Main.java:34)
>> Suppressed: java.util.zip.ZipException: invalid entry compressed size
>> (expected 383 but got 377 bytes)
>> at 
>> java.base/java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
>> at java.base/java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:360)
>> at 
>> java.base/java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:237)
>> at java.base/java.util.zip.ZipOutputStream.close(ZipOutputStream.java:377)
>> at jdk.jlink/jdk.tools.jmod.JmodOutputStream.close(JmodOutputStream.java:114)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.updateJmodFile(JmodTask.java:1006)
>> ... 6 more
>> Caused by: java.util.zip.ZipException: invalid entry compressed size
>> (expected 383 but got 377 bytes)
>> at 
>> java.base/java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodOutputStream.writeEntry(JmodOutputStream.java:97)
>> at 
>> jdk.jlink/jdk.tools.jmod.JmodTask$Hasher.lambda$updateJmodFile$4(JmodTask.java:1018)
>> ... 17 more
>>
>> The errors can be provoked by creating the initial jar or jmod files
>> with a different zlib implementation (e.g.
>> LD_LIBRARY_PATH=/ziptests/build/zlib-cloudflare jar -cf ../mb_cf.jar
>> *)
>>
>> The fix is simple. Instead of copying the ZipEntry/JarEntry entries
>> verbatim to the output stream, simply write newly created ZipEntry
>> entries to the output stream which only contain the required
>> attributes. This is also the way how this is done by the jar tool,
>> when it updates jar files.
>>
>> For the modular jar file case, creating a new entry is not feasible,
>> because at that specific location we are dealing with JerEntry entries
>> which can contain additional information. Unfortunately, it is not
>> possible to set this information on a newly created JarEntry entry.
>> But we can still reset the "compressedSize" of the JarEntry to "-1"
>> which also prevents the additional check after the entry has been
>> written.
>>
>> Thank you and best regards,
>> Volker
>>
>> PS: and by the way, this is the last bug related to the wrong usage of
>> ZipOutputSream.putNextEntry() within the OpenJDK :) I've scanned all
>> the sources and couldn't find any other suspicious places.

Reply via email to