Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8277823

FileSystems.newFileSystem does not handle ZIP created with bad directory paths

    XMLWordPrintable

Details

    • x86_64
    • windows_10

    Description

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10
      openjdk version "17" 2021-09-14
      OpenJDK Runtime Environment (build 17+35-2724)
      OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      Unfortunately it is possible to create a ZIP containing a bad directory entry "../d.txt".
      Reading such a ZIP using NIO calls FileSystems.newFileSystem and Files.find will cause an endless loop.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      See attached test case, this creates a zip file in current directory with one entry "../d.txt".
      Reading the file back with ZipFile works, but using FileSystems.newFileSystem(zip) with Files.find goes into endless loop.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The scanning should either fail - reporting a corrupt ZIP, or it should return single path back for "../d.txt".
      ACTUAL -
      The test program will print series of strings "/.." until reaching:
      Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

      ---------- BEGIN SOURCE ----------
      public class ZipBadEntries {
          /** Create a ZIP with bad directory entry ".." */
          public static void main(String[] args) throws IOException {
              Path zip = Path.of("my.zip");

              System.out.println("Writing "+zip);

              try (ZipOutputStream zout = new ZipOutputStream(Files.newOutputStream(zip))) {
                  ZipEntry bad = new ZipEntry("../d.txt");
                  zout.putNextEntry(bad);
                  zout.write("Hello dotdot/d.txt".getBytes());
              }

              System.out.println("ZipFile "+zip);

              // scan new zip printing each entry:
              try (ZipFile fs = new ZipFile(zip.toFile())) {
                  fs.stream()
                    .map(entry -> entry.getName()+(entry.isDirectory() ? " DIR" : " size="+entry.getSize()))
                    .forEach(System.out::println);
              }

              System.out.println("FileSystems.newFileSystem "+zip);

              // scan new zip printing each entry - this gets stuck in a loop:
              try (FileSystem fs = FileSystems.newFileSystem(zip)) {
                  for (Path root : fs.getRootDirectories()) {
                      System.out.println("Files.find "+root);
                      try(Stream<Path> stream = Files.find(root, Integer.MAX_VALUE, (p,a) -> true)) {
                          stream.forEach(System.out::println);
                      }
                  }
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      None.

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              lancea Lance Andersen
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: