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

ZipInputStream doesn't verify CRC for empty ZipEntry

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      When reading a Zip entry that uses the STORED compression method with a size of 0, if its CRC value is tampered with, ZipInputStream fails to properly trigger a CRC verification exception.


      ---------- BEGIN SOURCE ----------


      import java.io.*;
      import java.util.zip.*;

      public class StoredCRC {
          public static void realMain(String[] args) throws Throwable {

              try {
                  // Valid empty entry
                  ByteArrayOutputStream baos = new ByteArrayOutputStream();
                  ZipOutputStream zos = new ZipOutputStream(baos);
                  ZipEntry ze = new ZipEntry("empty");
                  ze.setMethod(ZipOutputStream.STORED);
                  ze.setSize(0);
                  CRC32 crc = new CRC32();
                  crc.update(new byte[0]);
                  ze.setCrc(crc.getValue());
                  System.out.println("real crc: " + crc.getValue());
                  zos.putNextEntry(ze);
                  zos.close();

                  // Verify valid read
                  ZipInputStream zis = new ZipInputStream(
                          new ByteArrayInputStream(baos.toByteArray()));
                  check(zis.getNextEntry() != null);
                  check(zis.read() == -1); // Immediate EOF

                  // Corrupt empty entry's CRC
                  byte[] corrupted = baos.toByteArray();
                  corrupted[14] ^= 1; // Toggle CRC byte
                  zis = new ZipInputStream(new ByteArrayInputStream(corrupted));

                  ze = zis.getNextEntry();
                  check(ze != null);
                  check(zis.read() == -1); // Read to EOF
                  System.out.println(ze);
                  System.out.println("Changed crc: " + ze.getCrc());
                  System.out.println();
                  try {
                      zis.getNextEntry();
                      zis.closeEntry();
                      zis.close();
                      fail("Empty entry: No CRC check for zero-length file");
                  } catch (ZipException ex) {
                      check(ex.getMessage().startsWith("invalid entry CRC (expected 0x"));
                  }
              } catch (Throwable t) {
                  unexpected(t);
              }

          }




          //--------------------- Infrastructure ---------------------------
          static volatile int passed = 0, failed = 0;
          static boolean pass() {passed++; return true;}
          static boolean fail() {failed++; Thread.dumpStack(); return false;}
          static boolean fail(String msg) {System.out.println(msg); return fail();}
          static void unexpected(Throwable t) {failed++; t.printStackTrace();}
          static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
          static boolean equal(Object x, Object y) {
              if (x == null ? y == null : x.equals(y)) return pass();
              else return fail(x + " not equal to " + y);}
          public static void main(String[] args) throws Throwable {
              try {realMain(args);} catch (Throwable t) {unexpected(t);}
              System.out.println("\nPassed = " + passed + " failed = " + failed);
              if (failed > 0) throw new AssertionError("Some tests failed");}
      }

      ---------- END SOURCE ----------

            jpai Jaikiran Pai
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: