8161942: java.util.zip.ZipEntry.java not covering UpperLimit range of DOS epoch
Reviewed-by: redestad
This commit is contained in:
parent
149b8bf45d
commit
e944d9f280
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 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
|
||||
@ -568,9 +568,18 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
int pos = off + 4; // reserved 4 bytes
|
||||
if (get16(extra, pos) != 0x0001 || get16(extra, pos + 2) != 24)
|
||||
break;
|
||||
mtime = winTimeToFileTime(get64(extra, pos + 4));
|
||||
atime = winTimeToFileTime(get64(extra, pos + 12));
|
||||
ctime = winTimeToFileTime(get64(extra, pos + 20));
|
||||
long wtime = get64(extra, pos + 4);
|
||||
if (wtime != WINDOWS_TIME_NOT_AVAILABLE) {
|
||||
mtime = winTimeToFileTime(wtime);
|
||||
}
|
||||
wtime = get64(extra, pos + 12);
|
||||
if (wtime != WINDOWS_TIME_NOT_AVAILABLE) {
|
||||
atime = winTimeToFileTime(wtime);
|
||||
}
|
||||
wtime = get64(extra, pos + 20);
|
||||
if (wtime != WINDOWS_TIME_NOT_AVAILABLE) {
|
||||
ctime = winTimeToFileTime(wtime);
|
||||
}
|
||||
break;
|
||||
case EXTID_EXTT:
|
||||
int flag = Byte.toUnsignedInt(extra[off]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 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
|
||||
@ -421,22 +421,36 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
byte[] nameBytes = zc.getBytes(e.name);
|
||||
writeShort(nameBytes.length);
|
||||
|
||||
int elenEXTT = 0; // info-zip extended timestamp
|
||||
int elenEXTT = 0; // info-zip extended timestamp
|
||||
int flagEXTT = 0;
|
||||
long umtime = -1;
|
||||
long uatime = -1;
|
||||
long uctime = -1;
|
||||
if (e.mtime != null) {
|
||||
elenEXTT += 4;
|
||||
flagEXTT |= EXTT_FLAG_LMT;
|
||||
umtime = fileTimeToUnixTime(e.mtime);
|
||||
}
|
||||
if (e.atime != null) {
|
||||
elenEXTT += 4;
|
||||
flagEXTT |= EXTT_FLAG_LAT;
|
||||
uatime = fileTimeToUnixTime(e.atime);
|
||||
}
|
||||
if (e.ctime != null) {
|
||||
elenEXTT += 4;
|
||||
flagEXTT |= EXTT_FLAT_CT;
|
||||
uctime = fileTimeToUnixTime(e.ctime);
|
||||
}
|
||||
if (flagEXTT != 0) {
|
||||
// to use ntfs time if any m/a/ctime is beyond unixtime upper bound
|
||||
if (umtime > UPPER_UNIXTIME_BOUND ||
|
||||
uatime > UPPER_UNIXTIME_BOUND ||
|
||||
uctime > UPPER_UNIXTIME_BOUND) {
|
||||
elen += 36; // NTFS time, total 36 bytes
|
||||
} else {
|
||||
elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data
|
||||
}
|
||||
}
|
||||
if (flagEXTT != 0)
|
||||
elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data
|
||||
writeShort(elen);
|
||||
writeBytes(nameBytes, 0, nameBytes.length);
|
||||
if (hasZip64) {
|
||||
@ -446,15 +460,31 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeLong(e.csize);
|
||||
}
|
||||
if (flagEXTT != 0) {
|
||||
writeShort(EXTID_EXTT);
|
||||
writeShort(elenEXTT + 1); // flag + data
|
||||
writeByte(flagEXTT);
|
||||
if (e.mtime != null)
|
||||
writeInt(fileTimeToUnixTime(e.mtime));
|
||||
if (e.atime != null)
|
||||
writeInt(fileTimeToUnixTime(e.atime));
|
||||
if (e.ctime != null)
|
||||
writeInt(fileTimeToUnixTime(e.ctime));
|
||||
if (umtime > UPPER_UNIXTIME_BOUND ||
|
||||
uatime > UPPER_UNIXTIME_BOUND ||
|
||||
uctime > UPPER_UNIXTIME_BOUND) {
|
||||
writeShort(EXTID_NTFS); // id
|
||||
writeShort(32); // data size
|
||||
writeInt(0); // reserved
|
||||
writeShort(0x0001); // NTFS attr tag
|
||||
writeShort(24);
|
||||
writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE
|
||||
: fileTimeToWinTime(e.mtime));
|
||||
writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE
|
||||
: fileTimeToWinTime(e.atime));
|
||||
writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE
|
||||
: fileTimeToWinTime(e.ctime));
|
||||
} else {
|
||||
writeShort(EXTID_EXTT);
|
||||
writeShort(elenEXTT + 1); // flag + data
|
||||
writeByte(flagEXTT);
|
||||
if (e.mtime != null)
|
||||
writeInt(umtime);
|
||||
if (e.atime != null)
|
||||
writeInt(uatime);
|
||||
if (e.ctime != null)
|
||||
writeInt(uctime);
|
||||
}
|
||||
}
|
||||
writeExtra(e.extra);
|
||||
locoff = written;
|
||||
@ -528,18 +558,30 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
// cen info-zip extended timestamp only outputs mtime
|
||||
// but set the flag for a/ctime, if present in loc
|
||||
int flagEXTT = 0;
|
||||
long umtime = -1;
|
||||
long uatime = -1;
|
||||
long uctime = -1;
|
||||
if (e.mtime != null) {
|
||||
elen += 4; // + mtime(4)
|
||||
flagEXTT |= EXTT_FLAG_LMT;
|
||||
umtime = fileTimeToUnixTime(e.mtime);
|
||||
}
|
||||
if (e.atime != null) {
|
||||
flagEXTT |= EXTT_FLAG_LAT;
|
||||
uatime = fileTimeToUnixTime(e.atime);
|
||||
}
|
||||
if (e.ctime != null) {
|
||||
flagEXTT |= EXTT_FLAT_CT;
|
||||
uctime = fileTimeToUnixTime(e.ctime);
|
||||
}
|
||||
if (flagEXTT != 0) {
|
||||
elen += 5; // headid + sz + flag
|
||||
// to use ntfs time if any m/a/ctime is beyond unixtime upper bound
|
||||
if (umtime > UPPER_UNIXTIME_BOUND ||
|
||||
uatime > UPPER_UNIXTIME_BOUND ||
|
||||
uctime > UPPER_UNIXTIME_BOUND) {
|
||||
elen += 36; // NTFS time total 36 bytes
|
||||
} else {
|
||||
elen += 9; // headid(2) + sz(2) + flag(1) + mtime (4)
|
||||
}
|
||||
}
|
||||
writeShort(elen);
|
||||
byte[] commentBytes;
|
||||
@ -568,14 +610,30 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeLong(xentry.offset);
|
||||
}
|
||||
if (flagEXTT != 0) {
|
||||
writeShort(EXTID_EXTT);
|
||||
if (e.mtime != null) {
|
||||
writeShort(5); // flag + mtime
|
||||
writeByte(flagEXTT);
|
||||
writeInt(fileTimeToUnixTime(e.mtime));
|
||||
if (umtime > UPPER_UNIXTIME_BOUND ||
|
||||
uatime > UPPER_UNIXTIME_BOUND ||
|
||||
uctime > UPPER_UNIXTIME_BOUND) {
|
||||
writeShort(EXTID_NTFS); // id
|
||||
writeShort(32); // data size
|
||||
writeInt(0); // reserved
|
||||
writeShort(0x0001); // NTFS attr tag
|
||||
writeShort(24);
|
||||
writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE
|
||||
: fileTimeToWinTime(e.mtime));
|
||||
writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE
|
||||
: fileTimeToWinTime(e.atime));
|
||||
writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE
|
||||
: fileTimeToWinTime(e.ctime));
|
||||
} else {
|
||||
writeShort(1); // flag only
|
||||
writeByte(flagEXTT);
|
||||
writeShort(EXTID_EXTT);
|
||||
if (e.mtime != null) {
|
||||
writeShort(5); // flag + mtime
|
||||
writeByte(flagEXTT);
|
||||
writeInt(umtime);
|
||||
} else {
|
||||
writeShort(1); // flag only
|
||||
writeByte(flagEXTT);
|
||||
}
|
||||
}
|
||||
}
|
||||
writeExtra(e.extra);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -38,6 +38,9 @@ class ZipUtils {
|
||||
// used to adjust values between Windows and java epoch
|
||||
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
|
||||
|
||||
// used to indicate the corresponding windows time is not available
|
||||
public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
|
||||
*/
|
||||
@ -53,6 +56,11 @@ class ZipUtils {
|
||||
return (ftime.to(TimeUnit.MICROSECONDS) - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* The upper bound of the 32-bit unix time, the "year 2038 problem".
|
||||
*/
|
||||
public static final long UPPER_UNIXTIME_BOUND = 0x7fffffff;
|
||||
|
||||
/**
|
||||
* Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914
|
||||
* @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914 8161942
|
||||
* @summary Test ZOS and ZIS timestamp in extra field correctly
|
||||
*/
|
||||
|
||||
@ -32,6 +32,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -40,37 +41,52 @@ import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
|
||||
|
||||
public class TestExtraTime {
|
||||
|
||||
public static void main(String[] args) throws Throwable{
|
||||
|
||||
File src = new File(System.getProperty("test.src", "."), "TestExtraTime.java");
|
||||
if (src.exists()) {
|
||||
if (!src.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
|
||||
|
||||
for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
|
||||
|
||||
// ms-dos 1980 epoch problem
|
||||
test0(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
|
||||
// negative epoch time
|
||||
test0(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra);
|
||||
|
||||
long time = src.lastModified();
|
||||
FileTime mtime = FileTime.from(time, TimeUnit.MILLISECONDS);
|
||||
FileTime atime = FileTime.from(time + 300000, TimeUnit.MILLISECONDS);
|
||||
FileTime ctime = FileTime.from(time - 300000, TimeUnit.MILLISECONDS);
|
||||
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
|
||||
test(FileTime.from(time, TimeUnit.MILLISECONDS),
|
||||
FileTime.from(time + 300000, TimeUnit.MILLISECONDS),
|
||||
FileTime.from(time - 300000, TimeUnit.MILLISECONDS),
|
||||
tz, extra);
|
||||
|
||||
for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
|
||||
test(mtime, null, null, null, extra);
|
||||
// now
|
||||
time = Instant.now().toEpochMilli();
|
||||
test(FileTime.from(time, TimeUnit.MILLISECONDS),
|
||||
FileTime.from(time + 300000, TimeUnit.MILLISECONDS),
|
||||
FileTime.from(time - 300000, TimeUnit.MILLISECONDS),
|
||||
tz, extra);
|
||||
|
||||
// ms-dos 1980 epoch problem
|
||||
test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
|
||||
// negative epoch time
|
||||
test(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra);
|
||||
// unix 2038
|
||||
time = 0x80000000L;
|
||||
test(FileTime.from(time, TimeUnit.SECONDS),
|
||||
FileTime.from(time, TimeUnit.SECONDS),
|
||||
FileTime.from(time, TimeUnit.SECONDS),
|
||||
tz, extra);
|
||||
|
||||
// non-default tz
|
||||
test(mtime, null, null, tz, extra);
|
||||
|
||||
test(mtime, atime, null, null, extra);
|
||||
test(mtime, null, ctime, null, extra);
|
||||
test(mtime, atime, ctime, null, extra);
|
||||
|
||||
test(mtime, atime, null, tz, extra);
|
||||
test(mtime, null, ctime, tz, extra);
|
||||
test(mtime, atime, ctime, tz, extra);
|
||||
}
|
||||
// mtime < unix 2038
|
||||
time = 0x7fffffffL;
|
||||
test(FileTime.from(time, TimeUnit.SECONDS),
|
||||
FileTime.from(time + 30000, TimeUnit.SECONDS),
|
||||
FileTime.from(time + 30000, TimeUnit.SECONDS),
|
||||
tz, extra);
|
||||
}
|
||||
|
||||
testNullHandling();
|
||||
@ -80,6 +96,18 @@ public class TestExtraTime {
|
||||
|
||||
static void test(FileTime mtime, FileTime atime, FileTime ctime,
|
||||
TimeZone tz, byte[] extra) throws Throwable {
|
||||
test0(mtime, null, null, null, extra);
|
||||
test0(mtime, null, null, tz, extra); // non-default tz
|
||||
test0(mtime, atime, null, null, extra);
|
||||
test0(mtime, null, ctime, null, extra);
|
||||
test0(mtime, atime, ctime, null, extra);
|
||||
test0(mtime, atime, null, tz, extra);
|
||||
test0(mtime, null, ctime, tz, extra);
|
||||
test0(mtime, atime, ctime, tz, extra);
|
||||
}
|
||||
|
||||
static void test0(FileTime mtime, FileTime atime, FileTime ctime,
|
||||
TimeZone tz, byte[] extra) throws Throwable {
|
||||
System.out.printf("--------------------%nTesting: [%s]/[%s]/[%s]%n",
|
||||
mtime, atime, ctime);
|
||||
TimeZone tz0 = TimeZone.getDefault();
|
||||
@ -120,13 +148,14 @@ public class TestExtraTime {
|
||||
Path zpath = Paths.get(System.getProperty("test.dir", "."),
|
||||
"TestExtraTime.zip");
|
||||
Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath);
|
||||
ZipFile zf = new ZipFile(zpath.toFile());
|
||||
ze = zf.getEntry("TestExtraTime.java");
|
||||
// ZipFile read entry from cen, which does not have a/ctime,
|
||||
// for now.
|
||||
check(mtime, null, null, ze, extra);
|
||||
zf.close();
|
||||
Files.delete(zpath);
|
||||
try (ZipFile zf = new ZipFile(zpath.toFile())) {
|
||||
ze = zf.getEntry("TestExtraTime.java");
|
||||
// ZipFile read entry from cen, which does not have a/ctime,
|
||||
// for now.
|
||||
check(mtime, null, null, ze, extra);
|
||||
} finally {
|
||||
Files.delete(zpath);
|
||||
}
|
||||
}
|
||||
|
||||
static void check(FileTime mtime, FileTime atime, FileTime ctime,
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8075526 8135108 8155616
|
||||
* @bug 8075526 8135108 8155616 8161942
|
||||
* @summary Test timestamp via ZipEntry.get/setTimeLocal()
|
||||
*/
|
||||
|
||||
@ -65,6 +65,9 @@ public class TestLocalTime {
|
||||
test(LocalDateTime.of(1968, 04, 28, 2, 51, 25));
|
||||
test(LocalDateTime.of(1970, 04, 26, 2, 31, 52));
|
||||
|
||||
// for #8161942
|
||||
test(LocalDateTime.of(2200, 04, 26, 2, 31, 52)); // unix 2038
|
||||
|
||||
} finally {
|
||||
TimeZone.setDefault(tz0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user