Fix AbstractZipUnArchiver handling of zip entries with unspecified modification time by Copilot · Pull Request #393 · codehaus-plexus/plexus-archiver (original) (raw)
Problem
According to the ZIP specification, ZipEntry.getTime() can legally return -1 to indicate that the modification time is not specified. However, AbstractZipUnArchiver was passing this value directly to new Date(-1) and eventually to File.setLastModified(-1), which throws IllegalArgumentException: Negative time.
This caused extraction failures when attempting to unzip JAR files with entries that do not have a modification time set:
java.lang.IllegalArgumentException: Negative time
at java.io.File.setLastModified (File.java:1441)
at org.codehaus.plexus.archiver.AbstractUnArchiver.extractFile (AbstractUnArchiver.java:374)
at org.codehaus.plexus.archiver.zip.AbstractZipUnArchiver.execute (AbstractZipUnArchiver.java:221)
Solution
Added checks for -1 modification time (in addition to the existing check for 0) in two locations:
ZipEntryFileInfo.getLastModified(): Now returnsPlexusIoResource.UNKNOWN_MODIFICATION_DATE(which is0) whenzipEntry.getTime()returns either-1or0AbstractZipUnArchiver.execute(): Sanitizes the modification time before creating theDateobject by checking if it's-1or0, and replacing it withUNKNOWN_MODIFICATION_DATE
This ensures that File.setLastModified() is never called with a negative value, while properly handling zip entries with unspecified modification times according to the ZIP specification.
Testing
Added testZipWithNegativeModificationTime() which:
- Creates a zip file with an entry having
-1modification time using Apache Commons Compress - Extracts it using
ZipUnArchiver - Verifies the extraction succeeds and file content is correct
All existing tests continue to pass.
Fixes #262
Original prompt
This section details on the original issue you should resolve
<issue_title>AbstractZipUnArchiver does not check for unspecified modification time</issue_title>
<issue_description>Attempting to unzip a jar with entries which do not have a modification time fails. This is readily reproducible with this patch: https://git.opendaylight.org/gerrit/c/controller/+/95334 which ends up hitting this codepath via maven-dependency-plugin:Caused by: java.lang.IllegalArgumentException: Negative time at java.io.File.setLastModified (File.java:1441) at org.codehaus.plexus.archiver.AbstractUnArchiver.extractFile (AbstractUnArchiver.java:374) at org.codehaus.plexus.archiver.zip.AbstractZipUnArchiver.execute (AbstractZipUnArchiver.java:221) at org.codehaus.plexus.archiver.zip.AbstractZipUnArchiver.execute (AbstractZipUnArchiver.java:180) at org.codehaus.plexus.archiver.AbstractUnArchiver.extract (AbstractUnArchiver.java:149) at org.apache.maven.plugins.dependency.AbstractDependencyMojo.unpack (AbstractDependencyMojo.java:313) at org.apache.maven.plugins.dependency.AbstractDependencyMojo.unpack (AbstractDependencyMojo.java:224) at org.apache.maven.plugins.dependency.fromDependencies.UnpackDependenciesMojo.doExecute (UnpackDependenciesMojo.java:107) at org.apache.maven.plugins.dependency.AbstractDependencyMojo.execute (AbstractDependencyMojo.java:144) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:208) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192) at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105) at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956) at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290) at org.apache.maven.cli.MavenCli.main (MavenCli.java:194) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:566) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289) at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415) at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)The problem seems to be here:
https://github.com/codehaus-plexus/plexus-archiver/blob/master/src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipUnArchiver.java#L209ZipEntry.getTime() can legally return -1 to indicate 'modification time is not specifed'. This is not checked and passed directly to Date(long), wfrom whence it is extracted verbatim and passed to File.setLastModified() -- where negative values are explicitly forbidden.</issue_description>
Comments on the Issue (you are @copilot in this section)
@plamentotevDo you know which file caused the issue? While `ZipEntry.getTime()` is allowed to return `-1` to indicate that no modification time was specified, I did a quick check and it should be specified (the value is always set). Did you debug why it is not set (or set to this value)? Maybe there is some other issue causing the value to not be set.
Fixes #170
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.