jdk9/10 reject zip/jar files where seconds value of timestamp is out of supported range 0 - 59
Hello, When iterating on the zip entries (and printing the time stamps) of an old sqljdbc.jar the exception "java.time.DateTimeException: Invalid value for SecondOfMinute (valid values 0 - 59): 60" occured (issue has been seen on Windows). Looks like the dosToJavaTime function in ZipUtils.java of jdk9/jdk10 is a bit more "sensitive" about the input it gets, compared to jdk8. In both implementations : java.base/share/classes/java/util/zip/ZipUtils.java jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java the computation of the "seconds" values is done by public static long dosToJavaTime(long dtime) { ... (int) ((dtime << 1) & 0x3e)); ... } 0x3e is binary 111110 or decimal 62, so larger values than the supported maximum 59 can occur (maybe only with old/problematic archives but still we had such an example). When looking a bit more closely into it, we found that the "second = 60" value was coming from a long value 930973758 that was passed to ZipUtils.dosToJavaTime as dtime argument. (found this out by adding an enhanced chained exception to jdk9 showing the dtime value passed to dosToJavaTime). Here is an example of the iteration on entries of such a "bad" zip file : C:\JVM\openjdk10\bin\java ZipIterate Iterate von ZipFile: -------------------------------------- name of ZipEntry:com/microsoft/sqlserver/jdbc/AppDTVImpl$SetValueOp.class Exception in thread "main" java.time.DateTimeException: Invalid value for SecondOfMinute (valid values 0 - 59): 60 at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311) at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:714) at java.base/java.time.LocalTime.of(LocalTime.java:322) at java.base/java.time.LocalDateTime.of(LocalDateTime.java:337) at java.base/java.util.zip.ZipUtils.dosToJavaTime(ZipUtils.java:101) at java.base/java.util.zip.ZipUtils.extendedDosToJavaTime(ZipUtils.java:114) at java.base/java.util.zip.ZipEntry.getTime(ZipEntry.java:198) at ZipIterate.main(ZipIterate.java:37) A similar problem (dealing with days/months not seconds out of supported range) is described here : https://bugs.openjdk.java.net/browse/JDK-8184940 "JDK 9 rejects zip files where the modified day or month is 0" Compared to jdk8, this is a regression so I think it would be good to have a better handling of problematic out of range seconds-values. Do you think it would be sufficient to adjust the out of range seconds to the supported max-value 59 ? Or is something more sophisticated prefered ? I found the enhanced chained exception showing the dtime long values helpful too, should I submit it ? Best regards, Matthias
Hi, it appears this is a difference where java.util.Date is carrying the overflow(s), while the java.time-based implementation is more strict. Same issue assumedly exist for most fields in the dos format (minutes can be 0-63, hours 0-31, days 0-31...). The dosToJavaTime implementation was changed to use java.time mostly as a cleanup (https://bugs.openjdk.java.net/browse/JDK-8066644), but this difference in strictness was overlooked.. Most compelling option for now might be to revert to the code in 8: public static long dosToJavaTime8(long dtime) { @SuppressWarnings("deprecation") // Use of date constructor. Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80), (int)(((dtime >> 21) & 0x0f) - 1), (int)((dtime >> 16) & 0x1f), (int)((dtime >> 11) & 0x1f), (int)((dtime >> 5) & 0x3f), (int)((dtime << 1) & 0x3e)); return d.getTime(); } /Claes On 2017-10-06 14:24, Baesken, Matthias wrote:
Hello,
When iterating on the zip entries (and printing the time stamps) of an old sqljdbc.jar the exception
"java.time.DateTimeException: Invalid value for SecondOfMinute (valid values 0 - 59): 60" occured (issue has been seen on Windows).
Looks like the dosToJavaTime function in ZipUtils.java of jdk9/jdk10 is a bit more "sensitive" about the input it gets, compared to jdk8. In both implementations :
java.base/share/classes/java/util/zip/ZipUtils.java jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java
the computation of the "seconds" values is done by
public static long dosToJavaTime(long dtime) { ... (int) ((dtime << 1) & 0x3e)); ... }
0x3e is binary 111110 or decimal 62, so larger values than the supported maximum 59 can occur (maybe only with old/problematic archives but still we had such an example).
When looking a bit more closely into it, we found that the "second = 60" value was coming from a long value 930973758 that was passed to ZipUtils.dosToJavaTime as dtime argument.
(found this out by adding an enhanced chained exception to jdk9 showing the dtime value passed to dosToJavaTime).
Here is an example of the iteration on entries of such a "bad" zip file :
C:\JVM\openjdk10\bin\java ZipIterate
Iterate von ZipFile: -------------------------------------- name of ZipEntry:com/microsoft/sqlserver/jdbc/AppDTVImpl$SetValueOp.class Exception in thread "main" java.time.DateTimeException: Invalid value for SecondOfMinute (valid values 0 - 59): 60 at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311) at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:714) at java.base/java.time.LocalTime.of(LocalTime.java:322) at java.base/java.time.LocalDateTime.of(LocalDateTime.java:337) at java.base/java.util.zip.ZipUtils.dosToJavaTime(ZipUtils.java:101) at java.base/java.util.zip.ZipUtils.extendedDosToJavaTime(ZipUtils.java:114) at java.base/java.util.zip.ZipEntry.getTime(ZipEntry.java:198) at ZipIterate.main(ZipIterate.java:37)
A similar problem (dealing with days/months not seconds out of supported range) is described here : https://bugs.openjdk.java.net/browse/JDK-8184940 "JDK 9 rejects zip files where the modified day or month is 0"
Compared to jdk8, this is a regression so I think it would be good to have a better handling of problematic out of range seconds-values.
Do you think it would be sufficient to adjust the out of range seconds to the supported max-value 59 ? Or is something more sophisticated prefered ? I found the enhanced chained exception showing the dtime long values helpful too, should I submit it ?
Best regards, Matthias
https://bugs.openjdk.java.net/browse/JDK-8188869 really wanted to suggest to just unzip/jar & jar those jar files again, as a workaround ... -sherman On 10/6/17, 7:02 AM, Claes Redestad wrote:
Hi,
it appears this is a difference where java.util.Date is carrying the overflow(s), while the java.time-based implementation is more strict. Same issue assumedly exist for most fields in the dos format (minutes can be 0-63, hours 0-31, days 0-31...).
The dosToJavaTime implementation was changed to use java.time mostly as a cleanup (https://bugs.openjdk.java.net/browse/JDK-8066644), but this difference in strictness was overlooked..
Most compelling option for now might be to revert to the code in 8:
public static long dosToJavaTime8(long dtime) { @SuppressWarnings("deprecation") // Use of date constructor. Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80), (int)(((dtime >> 21) & 0x0f) - 1), (int)((dtime >> 16) & 0x1f), (int)((dtime >> 11) & 0x1f), (int)((dtime >> 5) & 0x3f), (int)((dtime << 1) & 0x3e)); return d.getTime(); }
/Claes
On 2017-10-06 14:24, Baesken, Matthias wrote:
Hello,
When iterating on the zip entries (and printing the time stamps) of an old sqljdbc.jar the exception
"java.time.DateTimeException: Invalid value for SecondOfMinute (valid values 0 - 59): 60" occured (issue has been seen on Windows).
Looks like the dosToJavaTime function in ZipUtils.java of jdk9/jdk10 is a bit more "sensitive" about the input it gets, compared to jdk8. In both implementations :
java.base/share/classes/java/util/zip/ZipUtils.java jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java
the computation of the "seconds" values is done by
public static long dosToJavaTime(long dtime) { ... (int) ((dtime << 1) & 0x3e)); ... }
0x3e is binary 111110 or decimal 62, so larger values than the supported maximum 59 can occur (maybe only with old/problematic archives but still we had such an example).
When looking a bit more closely into it, we found that the "second = 60" value was coming from a long value 930973758 that was passed to ZipUtils.dosToJavaTime as dtime argument.
(found this out by adding an enhanced chained exception to jdk9 showing the dtime value passed to dosToJavaTime).
Here is an example of the iteration on entries of such a "bad" zip file :
C:\JVM\openjdk10\bin\java ZipIterate
Iterate von ZipFile: -------------------------------------- name of ZipEntry:com/microsoft/sqlserver/jdbc/AppDTVImpl$SetValueOp.class Exception in thread "main" java.time.DateTimeException: Invalid value for SecondOfMinute (valid values 0 - 59): 60 at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311) at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:714) at java.base/java.time.LocalTime.of(LocalTime.java:322) at java.base/java.time.LocalDateTime.of(LocalDateTime.java:337) at java.base/java.util.zip.ZipUtils.dosToJavaTime(ZipUtils.java:101) at java.base/java.util.zip.ZipUtils.extendedDosToJavaTime(ZipUtils.java:114) at java.base/java.util.zip.ZipEntry.getTime(ZipEntry.java:198) at ZipIterate.main(ZipIterate.java:37)
A similar problem (dealing with days/months not seconds out of supported range) is described here : https://bugs.openjdk.java.net/browse/JDK-8184940 "JDK 9 rejects zip files where the modified day or month is 0"
Compared to jdk8, this is a regression so I think it would be good to have a better handling of problematic out of range seconds-values.
Do you think it would be sufficient to adjust the out of range seconds to the supported max-value 59 ? Or is something more sophisticated prefered ? I found the enhanced chained exception showing the dtime long values helpful too, should I submit it ?
Best regards, Matthias
participants (3)
-
Baesken, Matthias
-
Claes Redestad
-
Xueming Shen