Repository: GoogleContainerTools/jib
File: jib-core/src/main/java/com/google/cloud/tools/jib/tar/TarExtractor.java (Java)

Code before:

  /**
   * Extracts a tarball to the specified destination.
   *
   * @param source the tarball to extract
   * @param destination the output directory
   * @throws IOException if extraction fails
   */
  public static void extract(Path source, Path destination) throws IOException {
    extract(source, destination, false);
  }

  /**
   * Extracts a tarball to the specified destination.
   *
   * @param source the tarball to extract
   * @param destination the output directory
   * @param enableReproducibleTimestamps whether or not reproducible timestamps should be used
   * @throws IOException if extraction fails
   * @throws IllegalStateException when reproducible timestamps are enabled but the target root used
   *     for extracting the tar contents is not empty
   */
  public static void extract(Path source, Path destination, boolean enableReproducibleTimestamps)
      throws IOException {
    boolean isEmptyDestination =
        Files.isDirectory(destination) && destination.toFile().list().length == 0;
    if (enableReproducibleTimestamps && Files.exists(destination) && !isEmptyDestination) {
      throw new IllegalStateException(
          "Reproducible timestamps can only be enabled when the target root is an empty directory.");
    }
    String canonicalDestination = destination.toFile().getCanonicalPath();
    List<TarArchiveEntry> entries = new ArrayList<>();
    try (InputStream in = new BufferedInputStream(Files.newInputStream(source));
        TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(in)) {
      for (TarArchiveEntry entry = tarArchiveInputStream.getNextTarEntry();
          entry != null;
          entry = tarArchiveInputStream.getNextTarEntry()) {
        entries.add(entry);
        Path entryPath = destination.resolve(entry.getName());

        String canonicalTarget = entryPath.toFile().getCanonicalPath();
        if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
          String offender = entry.getName() + " from " + source;
          throw new IOException("Blocked unzipping files outside destination: " + offender);
        }
        if (entry.isDirectory()) {
          Files.createDirectories(entryPath);
        } else {
          if (entryPath.getParent() != null) {
            Files.createDirectories(entryPath.getParent());
          }

Review comment (suggestion):
Let's do this computation only when necessary. That is, doing this inside the `if` statement. Perhaps
```java
if (enableReproducibleTimestamps && Files.isDirectory(destination) && destination.toFile().list.length() != 0) {
  throw new ...
}
```
(`isDirectory()` implies `exists()`.)

Code after:

  /**
   * Extracts a tarball to the specified destination.
   *
   * @param source the tarball to extract
   * @param destination the output directory
   * @throws IOException if extraction fails
   */
  public static void extract(Path source, Path destination) throws IOException {
    extract(source, destination, false);
  }

  /**
   * Extracts a tarball to the specified destination.
   *
   * @param source the tarball to extract
   * @param destination the output directory
   * @param enableReproducibleTimestamps whether or not reproducible timestamps should be used
   * @throws IOException if extraction fails
   * @throws IllegalStateException when reproducible timestamps are enabled but the target root used
   *     for extracting the tar contents is not empty
   */
  public static void extract(Path source, Path destination, boolean enableReproducibleTimestamps)
      throws IOException {
    if (enableReproducibleTimestamps
        && Files.isDirectory(destination)
        && destination.toFile().list().length != 0) {
      throw new IllegalStateException(
          "Cannot enable reproducible timestamps. They can only be enabled when the target root doesn't exist or is an empty directory");
    }
    String canonicalDestination = destination.toFile().getCanonicalPath();
    List<TarArchiveEntry> entries = new ArrayList<>();
    try (InputStream in = new BufferedInputStream(Files.newInputStream(source));
        TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(in)) {
      for (TarArchiveEntry entry = tarArchiveInputStream.getNextTarEntry();
          entry != null;
          entry = tarArchiveInputStream.getNextTarEntry()) {
        entries.add(entry);
        Path entryPath = destination.resolve(entry.getName());

        String canonicalTarget = entryPath.toFile().getCanonicalPath();
        if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
          String offender = entry.getName() + " from " + source;
          throw new IOException("Blocked unzipping files outside destination: " + offender);
        }
        if (entry.isDirectory()) {
          Files.createDirectories(entryPath);
        } else {
          if (entryPath.getParent() != null) {
            Files.createDirectories(entryPath.getParent());
          }