mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-27 23:31:47 +00:00
8150469: unpack200 fails to compare crc correctly
Reviewed-by: jrose
This commit is contained in:
parent
50abd159dd
commit
472c39e35b
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. 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
|
||||
@ -90,6 +90,12 @@ extern int assert_failed(const char*);
|
||||
#define U_NEW(T, n) (T*) u->alloc(scale_size(n, sizeof(T)))
|
||||
#define T_NEW(T, n) (T*) u->temp_alloc(scale_size(n, sizeof(T)))
|
||||
|
||||
// Dealing with big-endian arch
|
||||
#ifdef _BIG_ENDIAN
|
||||
#define SWAP_INT(a) (((a>>24)&0xff) | ((a<<8)&0xff0000) | ((a>>8)&0xff00) | ((a<<24)&0xff000000))
|
||||
#else
|
||||
#define SWAP_INT(a) (a)
|
||||
#endif
|
||||
|
||||
// bytes and byte arrays
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. 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
|
||||
@ -171,7 +171,6 @@ struct unpacker {
|
||||
bytes inbytes; // direct
|
||||
gunzip* gzin; // gunzip filter, if any
|
||||
jar* jarout; // output JAR file
|
||||
uint gzcrc; // CRC gathered from gzip content
|
||||
|
||||
#ifndef PRODUCT
|
||||
int nowrite;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. 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
|
||||
@ -341,6 +341,7 @@ void jar::write_central_directory() {
|
||||
void jar::openJarFile(const char* fname) {
|
||||
if (!jarfp) {
|
||||
PRINTCR((1, "jar::openJarFile: opening %s\n",fname));
|
||||
jarname = fname;
|
||||
jarfp = fopen(fname, "wb");
|
||||
if (!jarfp) {
|
||||
fprintf(u->errstrm, "Error: Could not open jar file: %s\n",fname);
|
||||
@ -551,7 +552,8 @@ static jlong read_input_via_gzip(unpacker* u,
|
||||
break;
|
||||
}
|
||||
int nr = readlen - zs.avail_out;
|
||||
u->gzcrc = crc32(u->gzcrc, (const unsigned char *)bufptr, nr);
|
||||
u->gzin->gzlen += nr;
|
||||
u->gzin->gzcrc = crc32(u->gzin->gzcrc, (const unsigned char *)bufptr, nr);
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
@ -562,15 +564,44 @@ static jlong read_input_via_gzip(unpacker* u,
|
||||
zs.avail_in -= TRAILER_LEN;
|
||||
} else {
|
||||
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
|
||||
// any extraneous data, as we don't support concatenated .gz
|
||||
// files just yet.
|
||||
// any extraneous data, as we don't support concatenated .gz files.
|
||||
int extra = (int) read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.avail_in += extra - TRAILER_LEN;
|
||||
}
|
||||
// %%% should check final CRC and length here
|
||||
// %%% should check for concatenated *.gz files here
|
||||
if (zs.avail_in > 0)
|
||||
u->abort("garbage after end of deflated input stream");
|
||||
|
||||
// at this point we know there are no trailing bytes,
|
||||
// we are safe to get the crc and len.
|
||||
if (u->gzin->gzcrc != 0) {
|
||||
// Read the CRC information from the gzip container
|
||||
fseek(u->infileptr, -TRAILER_LEN, SEEK_END);
|
||||
uint filecrc;
|
||||
uint filelen;
|
||||
fread(&filecrc, sizeof(filecrc), 1, u->infileptr);
|
||||
fread(&filelen, sizeof(filelen), 1, u->infileptr);
|
||||
filecrc = SWAP_INT(filecrc);
|
||||
filelen = SWAP_INT(filelen);
|
||||
if (u->gzin->gzcrc != filecrc ||
|
||||
// rfc1952; ISIZE is the input size modulo 2^32
|
||||
u->gzin->gzlen != (filelen & 0xffffffff)) { // CRC error
|
||||
|
||||
PRINTCR((1, "crc: 0x%x 0x%x\n", u->gzin->gzcrc, filecrc));
|
||||
PRINTCR((1, "len: 0x%x 0x%x\n", u->gzin->gzlen, filelen));
|
||||
|
||||
if (u->jarout != null) {
|
||||
// save the file name first, if any
|
||||
const char* outfile = u->jarout->jarname;
|
||||
u->jarout->closeJarFile(false);
|
||||
if (outfile != null) {
|
||||
remove(outfile);
|
||||
}
|
||||
}
|
||||
// Print out the error and exit with return code != 0
|
||||
u->abort("CRC error, invalid compressed data.");
|
||||
}
|
||||
}
|
||||
// pop this filter off:
|
||||
u->gzin->free();
|
||||
break;
|
||||
@ -590,7 +621,8 @@ void gunzip::init(unpacker* u_) {
|
||||
zstream = NEW(z_stream, 1);
|
||||
u->gzin = this;
|
||||
u->read_input_fn = read_input_via_gzip;
|
||||
u->gzcrc = crc32(0, Z_NULL, 0);
|
||||
u->gzin->gzcrc = crc32(0, Z_NULL, 0);
|
||||
u->gzin->gzlen = 0;
|
||||
}
|
||||
|
||||
void gunzip::start(int magic) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. 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
|
||||
@ -34,6 +34,8 @@ struct jar {
|
||||
FILE* jarfp;
|
||||
int default_modtime;
|
||||
|
||||
const char* jarname;
|
||||
|
||||
// Used by unix2dostime:
|
||||
int modtime_cache;
|
||||
uLong dostime_cache;
|
||||
@ -98,6 +100,9 @@ struct gunzip {
|
||||
void* zstream; // inflater state
|
||||
char inbuf[1 << 14]; // input buffer
|
||||
|
||||
uint gzcrc; // CRC gathered from gzip *container* content
|
||||
uint gzlen; // CRC gathered length
|
||||
|
||||
void init(unpacker* u_); // pushes new value on u->read_input_fn
|
||||
|
||||
void free();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. 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
|
||||
@ -62,13 +62,6 @@ int main(int argc, char **argv) {
|
||||
return unpacker::run(argc, argv);
|
||||
}
|
||||
|
||||
// Dealing with big-endian arch
|
||||
#ifdef _BIG_ENDIAN
|
||||
#define SWAP_INT(a) (((a>>24)&0xff) | ((a<<8)&0xff0000) | ((a>>8)&0xff00) | ((a<<24)&0xff000000))
|
||||
#else
|
||||
#define SWAP_INT(a) (a)
|
||||
#endif
|
||||
|
||||
// Single-threaded, implementation, not reentrant.
|
||||
// Includes a weak error check against MT access.
|
||||
#ifndef THREAD_SELF
|
||||
@ -366,6 +359,7 @@ int unpacker::run(int argc, char **argv) {
|
||||
|
||||
if (strcmp(destination_file, "-") == 0) {
|
||||
jarout.jarfp = stdout;
|
||||
jarout.jarname = null;
|
||||
if (u.errstrm == stdout) // do not mix output
|
||||
u.set_option(UNPACK_LOG_FILE, LOGFILE_STDERR);
|
||||
} else {
|
||||
@ -385,11 +379,12 @@ int unpacker::run(int argc, char **argv) {
|
||||
// Oops; must slap an input filter on this data.
|
||||
setup_gzin(&u);
|
||||
u.gzin->start(magic);
|
||||
u.gzin->gzcrc = 0;
|
||||
u.gzin->gzlen = 0;
|
||||
if (!u.aborting()) {
|
||||
u.start();
|
||||
}
|
||||
} else {
|
||||
u.gzcrc = 0;
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
|
||||
@ -422,31 +417,13 @@ int unpacker::run(int argc, char **argv) {
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int status = 0;
|
||||
if (u.aborting()) {
|
||||
fprintf(u.errstrm, "Error: %s\n", u.get_abort_message());
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (!u.aborting() && u.infileptr != null) {
|
||||
if (u.gzcrc != 0) {
|
||||
// Read the CRC information from the gzip container
|
||||
fseek(u.infileptr, -8, SEEK_END);
|
||||
uint filecrc;
|
||||
fread(&filecrc, sizeof(filecrc), 1, u.infileptr);
|
||||
if (u.gzcrc != SWAP_INT(filecrc)) { // CRC error
|
||||
if (strcmp(destination_file, "-") != 0) {
|
||||
// Output is not stdout, remove it, it's broken
|
||||
if (u.jarout != null)
|
||||
u.jarout->closeJarFile(false);
|
||||
remove(destination_file);
|
||||
}
|
||||
// Print out the error and exit with return code != 0
|
||||
u.abort("CRC error, invalid compressed data.");
|
||||
}
|
||||
}
|
||||
if (u.infileptr != null) {
|
||||
fclose(u.infileptr);
|
||||
u.infileptr = null;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. 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
|
||||
@ -31,65 +31,136 @@ import java.util.jar.JarOutputStream;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8000650
|
||||
* @bug 8000650 8150469
|
||||
* @summary unpack200.exe should check gzip crc
|
||||
* @compile -XDignore.symbol.file Utils.java PackChecksum.java
|
||||
* @run main PackChecksum
|
||||
* @author kizune
|
||||
*/
|
||||
public class PackChecksum {
|
||||
final int TRAILER_LEN = 8;
|
||||
final List<String> cmdsList = new ArrayList<>();
|
||||
static enum Case {
|
||||
CRC32,
|
||||
ISIZE,
|
||||
BOTH;
|
||||
|
||||
};
|
||||
public static void main(String... args) throws Exception {
|
||||
testChecksum();
|
||||
new PackChecksum().run();
|
||||
}
|
||||
void run() throws Exception {
|
||||
testBrokenTrailer(Case.CRC32); // negative
|
||||
testBrokenTrailer(Case.ISIZE); // negative
|
||||
testBrokenTrailer(Case.BOTH); // negative
|
||||
testMultipleSegments();
|
||||
}
|
||||
|
||||
static void testChecksum() throws Exception {
|
||||
void testMultipleSegments() throws Exception {
|
||||
File inputJar = new File("input.jar");
|
||||
Utils.copyFile(Utils.getGoldenJar(), inputJar);
|
||||
cmdsList.clear();
|
||||
|
||||
File testPack = new File("out.jar.pack.gz");
|
||||
|
||||
cmdsList.clear();
|
||||
cmdsList.add(Utils.getPack200Cmd());
|
||||
// force multiple segments
|
||||
cmdsList.add("--segment-limit=100");
|
||||
cmdsList.add(testPack.getName());
|
||||
cmdsList.add(inputJar.getName());
|
||||
Utils.runExec(cmdsList);
|
||||
|
||||
File destFile = new File("dst.jar");
|
||||
cmdsList.clear();
|
||||
cmdsList.add(Utils.getUnpack200Cmd());
|
||||
cmdsList.add(testPack.getName());
|
||||
cmdsList.add(destFile.getName());
|
||||
try {
|
||||
Utils.runExec(cmdsList);
|
||||
if (!destFile.exists()) {
|
||||
throw new Exception("file not created: " + destFile);
|
||||
}
|
||||
} finally {
|
||||
if (inputJar.exists())
|
||||
inputJar.delete();
|
||||
if (testPack.exists())
|
||||
testPack.delete();
|
||||
if (destFile.exists())
|
||||
destFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
void testBrokenTrailer(Case type) throws Exception {
|
||||
System.out.println("Testing: case " + type);
|
||||
// Create a fresh .jar file
|
||||
File testFile = new File("src_tools.jar");
|
||||
File testPack = new File("src_tools.pack.gz");
|
||||
generateJar(testFile);
|
||||
List<String> cmdsList = new ArrayList<>();
|
||||
|
||||
cmdsList.clear();
|
||||
// Create .pack file
|
||||
cmdsList.add(Utils.getPack200Cmd());
|
||||
cmdsList.add(testPack.getName());
|
||||
cmdsList.add(testFile.getName());
|
||||
Utils.runExec(cmdsList);
|
||||
|
||||
// Mess up with the checksum of the packed file
|
||||
// mutate the checksum of the packed file
|
||||
RandomAccessFile raf = new RandomAccessFile(testPack, "rw");
|
||||
raf.seek(raf.length() - 8);
|
||||
int val = raf.readInt();
|
||||
val = Integer.MAX_VALUE - val;
|
||||
raf.seek(raf.length() - 8);
|
||||
raf.writeInt(val);
|
||||
|
||||
switch (type) {
|
||||
case CRC32:
|
||||
raf.seek(raf.length() - TRAILER_LEN);
|
||||
raf.writeInt(0x0dea0a0d);
|
||||
break;
|
||||
case ISIZE:
|
||||
raf.seek(raf.length() - (TRAILER_LEN/2));
|
||||
raf.writeInt(0x0b0e0e0f);
|
||||
break;
|
||||
default:
|
||||
raf.seek(raf.length() - (TRAILER_LEN));
|
||||
raf.writeLong(0x0dea0a0d0b0e0e0fL);
|
||||
break;
|
||||
}
|
||||
|
||||
raf.close();
|
||||
|
||||
File dstFile = new File("dst_tools.jar");
|
||||
if (dstFile.exists()) {
|
||||
dstFile.delete();
|
||||
}
|
||||
cmdsList.clear();
|
||||
cmdsList.add(Utils.getUnpack200Cmd());
|
||||
cmdsList.add(testPack.getName());
|
||||
cmdsList.add(dstFile.getName());
|
||||
|
||||
boolean passed = false;
|
||||
boolean processFailed = false;
|
||||
try {
|
||||
Utils.runExec(cmdsList);
|
||||
} catch (RuntimeException re) {
|
||||
// unpack200 should exit with non-zero exit code
|
||||
passed = true;
|
||||
}
|
||||
processFailed = true;
|
||||
} finally {
|
||||
// tidy up
|
||||
if (testFile.exists())
|
||||
testFile.delete();
|
||||
|
||||
// tidy up
|
||||
if (testFile.exists()) testFile.delete();
|
||||
if (testPack.exists()) testPack.delete();
|
||||
if (dstFile.exists()) dstFile.delete();
|
||||
if (!passed) {
|
||||
throw new Exception("File with incorrect CRC unpacked without the error.");
|
||||
if (testPack.exists())
|
||||
testPack.delete();
|
||||
|
||||
if (!processFailed) {
|
||||
throw new Exception("case " + type +
|
||||
": file with incorrect CRC, unpacked without the error.");
|
||||
}
|
||||
if (dstFile.exists()) {
|
||||
dstFile.delete();
|
||||
throw new Exception("case " + type +
|
||||
": file exists: " + dstFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void generateJar(File result) throws IOException {
|
||||
void generateJar(File result) throws IOException {
|
||||
if (result.exists()) {
|
||||
result.delete();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user