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:

  1. ZipEntryFileInfo.getLastModified(): Now returns PlexusIoResource.UNKNOWN_MODIFICATION_DATE (which is 0) when zipEntry.getTime() returns either -1 or 0
  2. AbstractZipUnArchiver.execute(): Sanitizes the modification time before creating the Date object by checking if it's -1 or 0, and replacing it with UNKNOWN_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:

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#L209

ZipEntry.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.