# HG changeset patch # User kizune # Date 1403186822 -14400 # Thu Jun 19 18:07:02 2014 +0400 # Node ID ad88ac6bac57e540e87fdb5d9ad15528b1beee11 # Parent f0137fa5ba5298a73f14ae508463dc7e890a70a5 8000650, PR2462: unpack200.exe should check gzip crc Reviewed-by: ksrini diff -r f0137fa5ba52 -r ad88ac6bac57 src/share/native/com/sun/java/util/jar/pack/main.cpp --- openjdk/jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp Thu Apr 23 13:48:02 2015 -0400 +++ openjdk/jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp Thu Jun 19 18:07:02 2014 +0400 @@ -62,6 +62,13 @@ 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 @@ -385,6 +392,7 @@ u.start(); } } else { + u.gzcrc = 0; u.start(peek, sizeof(peek)); } @@ -425,7 +433,23 @@ status = 1; } - if (u.infileptr != null) { + 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."); + } + } fclose(u.infileptr); u.infileptr = null; } diff -r f0137fa5ba52 -r ad88ac6bac57 src/share/native/com/sun/java/util/jar/pack/unpack.h --- openjdk/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h Thu Apr 23 13:48:02 2015 -0400 +++ openjdk/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h Thu Jun 19 18:07:02 2014 +0400 @@ -171,6 +171,7 @@ 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; diff -r f0137fa5ba52 -r ad88ac6bac57 src/share/native/com/sun/java/util/jar/pack/zip.cpp --- openjdk/jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp Thu Apr 23 13:48:02 2015 -0400 +++ openjdk/jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp Thu Jun 19 18:07:02 2014 +0400 @@ -551,6 +551,7 @@ break; } int nr = readlen - zs.avail_out; + u->gzcrc = crc32(u->gzcrc, (const unsigned char *)bufptr, nr); numread += nr; bufptr += nr; assert(numread <= maxlen); @@ -589,6 +590,7 @@ zstream = NEW(z_stream, 1); u->gzin = this; u->read_input_fn = read_input_via_gzip; + u->gzcrc = crc32(0L, Z_NULL, 0); } void gunzip::start(int magic) { diff -r f0137fa5ba52 -r ad88ac6bac57 test/tools/pack200/PackChecksum.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ openjdk/jdk/test/tools/pack200/PackChecksum.java Thu Jun 19 18:07:02 2014 +0400 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, 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 + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +/* + * @test + * @bug 8000650 + * @summary unpack200.exe should check gzip crc + * @compile -XDignore.symbol.file Utils.java PackChecksum.java + * @run main PackChecksum + * @author kizune + */ +public class PackChecksum { + + public static void main(String... args) throws Exception { + testChecksum(); + } + + static void testChecksum() throws Exception { + + // Create a fresh .jar file + File testFile = new File("src_tools.jar"); + File testPack = new File("src_tools.pack.gz"); + generateJar(testFile); + List cmdsList = new ArrayList<>(); + + // 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 + 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); + raf.close(); + + File dstFile = new File("dst_tools.jar"); + cmdsList.clear(); + cmdsList.add(Utils.getUnpack200Cmd()); + cmdsList.add(testPack.getName()); + cmdsList.add(dstFile.getName()); + + boolean passed = false; + try { + Utils.runExec(cmdsList); + } catch (RuntimeException re) { + // unpack200 should exit with non-zero exit code + passed = true; + } + + // 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."); + } + } + + static void generateJar(File result) throws IOException { + if (result.exists()) { + result.delete(); + } + + try (JarOutputStream output = new JarOutputStream(new FileOutputStream(result)); ) { + for (int i = 0 ; i < 100 ; i++) { + JarEntry e = new JarEntry("F-" + i + ".txt"); + output.putNextEntry(e); + } + output.flush(); + output.close(); + } + } + +}