blob: 4efe39b69a2c7d7bdf29e9161f5088a57ebb6deb [file] [log] [blame]
/*
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* @test
* @bug 4770745 6218846 6218848 6237956
* @summary test for correct detection and reporting of corrupted zip files
* @author Martin Buchholz
*/
import java.util.*;
import java.util.zip.*;
import java.io.*;
import static java.lang.System.*;
import static java.util.zip.ZipFile.*;
public class CorruptedZipFiles {
static int passed = 0, failed = 0;
static void fail(String msg) {
failed++;
err.println(msg);
}
static void unexpected(Throwable t) {
failed++;
t.printStackTrace();
}
public static void main(String[] args) throws Exception {
ZipOutputStream zos = new ZipOutputStream(
new FileOutputStream("x.zip"));
ZipEntry e = new ZipEntry("x");
zos.putNextEntry(e);
zos.write((int)'x');
zos.close();
zos = null;
int len = (int)(new File("x.zip").length());
byte[] good = new byte[len];
FileInputStream fis = new FileInputStream("x.zip");
fis.read(good);
fis.close();
fis = null;
new File("x.zip").delete();
int endpos = len - ENDHDR;
int cenpos = u16(good, endpos+ENDOFF);
int locpos = u16(good, cenpos+CENOFF);
if (u32(good, endpos) != ENDSIG) fail("Where's ENDSIG?");
if (u32(good, cenpos) != CENSIG) fail("Where's CENSIG?");
if (u32(good, locpos) != LOCSIG) fail("Where's LOCSIG?");
if (u16(good, locpos+LOCNAM) != u16(good,cenpos+CENNAM))
fail("Name field length mismatch");
if (u16(good, locpos+LOCEXT) != u16(good,cenpos+CENEXT))
fail("Extra field length mismatch");
byte[] bad;
err.println("corrupted ENDSIZ");
bad = good.clone();
bad[endpos+ENDSIZ]=(byte)0xff;
checkZipException(bad, ".*bad central directory size.*");
err.println("corrupted ENDOFF");
bad = good.clone();
bad[endpos+ENDOFF]=(byte)0xff;
checkZipException(bad, ".*bad central directory offset.*");
err.println("corrupted CENSIG");
bad = good.clone();
bad[cenpos]++;
checkZipException(bad, ".*bad signature.*");
err.println("corrupted CENFLG");
bad = good.clone();
bad[cenpos+CENFLG] |= 1;
checkZipException(bad, ".*encrypted entry.*");
err.println("corrupted CENNAM 1");
bad = good.clone();
bad[cenpos+CENNAM]++;
checkZipException(bad, ".*bad header size.*");
err.println("corrupted CENNAM 2");
bad = good.clone();
bad[cenpos+CENNAM]--;
checkZipException(bad, ".*bad header size.*");
err.println("corrupted CENNAM 3");
bad = good.clone();
bad[cenpos+CENNAM] = (byte)0xfd;
bad[cenpos+CENNAM+1] = (byte)0xfd;
checkZipException(bad, ".*bad header size.*");
err.println("corrupted CENEXT 1");
bad = good.clone();
bad[cenpos+CENEXT]++;
checkZipException(bad, ".*bad header size.*");
err.println("corrupted CENEXT 2");
bad = good.clone();
bad[cenpos+CENEXT] = (byte)0xfd;
bad[cenpos+CENEXT+1] = (byte)0xfd;
checkZipException(bad, ".*bad header size.*");
err.println("corrupted CENCOM");
bad = good.clone();
bad[cenpos+CENCOM]++;
checkZipException(bad, ".*bad header size.*");
err.println("corrupted CENHOW");
bad = good.clone();
bad[cenpos+CENHOW] = 2;
checkZipException(bad, ".*bad compression method.*");
err.println("corrupted LOCSIG");
bad = good.clone();
bad[locpos]++;
checkZipExceptionInGetInputStream(bad, ".*bad signature.*");
out.printf("passed = %d, failed = %d%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
}
static int uniquifier = 432;
static void checkZipExceptionImpl(byte[] data,
String msgPattern,
boolean getInputStream) {
String zipName = "bad" + (uniquifier++) + ".zip";
try {
FileOutputStream fos = new FileOutputStream(zipName);
fos.write(data);
fos.close();
ZipFile zf = new ZipFile(zipName);
if (getInputStream) {
InputStream is = zf.getInputStream(new ZipEntry("x"));
is.read();
}
fail("Failed to throw expected ZipException");
zf.close();
} catch (ZipException e) {
if (e.getMessage().matches(msgPattern))
passed++;
else
unexpected(e);
} catch (Throwable t) {
unexpected(t);
}
finally {
new File(zipName).delete();
}
}
static void checkZipException(byte[] data, String msgPattern) {
checkZipExceptionImpl(data, msgPattern, false);
}
static void checkZipExceptionInGetInputStream(byte[] data, String msgPattern) {
checkZipExceptionImpl(data, msgPattern, true);
}
static int u8(byte[] data, int offset) {
return data[offset]&0xff;
}
static int u16(byte[] data, int offset) {
return u8(data,offset) + (u8(data,offset+1)<<8);
}
static int u32(byte[] data, int offset) {
return u16(data,offset) + (u16(data,offset+2)<<16);
}
// The following can be deleted once this bug is fixed:
// 6225935: "import static" accessibility rules for symbols different for no reason
static final long LOCSIG = ZipFile.LOCSIG;
static final long EXTSIG = ZipFile.EXTSIG;
static final long CENSIG = ZipFile.CENSIG;
static final long ENDSIG = ZipFile.ENDSIG;
static final int LOCHDR = ZipFile.LOCHDR;
static final int EXTHDR = ZipFile.EXTHDR;
static final int CENHDR = ZipFile.CENHDR;
static final int ENDHDR = ZipFile.ENDHDR;
static final int LOCVER = ZipFile.LOCVER;
static final int LOCFLG = ZipFile.LOCFLG;
static final int LOCHOW = ZipFile.LOCHOW;
static final int LOCTIM = ZipFile.LOCTIM;
static final int LOCCRC = ZipFile.LOCCRC;
static final int LOCSIZ = ZipFile.LOCSIZ;
static final int LOCLEN = ZipFile.LOCLEN;
static final int LOCNAM = ZipFile.LOCNAM;
static final int LOCEXT = ZipFile.LOCEXT;
static final int CENVEM = ZipFile.CENVEM;
static final int CENVER = ZipFile.CENVER;
static final int CENFLG = ZipFile.CENFLG;
static final int CENHOW = ZipFile.CENHOW;
static final int CENTIM = ZipFile.CENTIM;
static final int CENCRC = ZipFile.CENCRC;
static final int CENSIZ = ZipFile.CENSIZ;
static final int CENLEN = ZipFile.CENLEN;
static final int CENNAM = ZipFile.CENNAM;
static final int CENEXT = ZipFile.CENEXT;
static final int CENCOM = ZipFile.CENCOM;
static final int CENDSK = ZipFile.CENDSK;
static final int CENATT = ZipFile.CENATT;
static final int CENATX = ZipFile.CENATX;
static final int CENOFF = ZipFile.CENOFF;
static final int ENDSUB = ZipFile.ENDSUB;
static final int ENDTOT = ZipFile.ENDTOT;
static final int ENDSIZ = ZipFile.ENDSIZ;
static final int ENDOFF = ZipFile.ENDOFF;
static final int ENDCOM = ZipFile.ENDCOM;
}