-
Bug
-
Resolution: Fixed
-
P4
-
8
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8343464 | 21.0.6 | Xiaolong Peng | P4 | Resolved | Fixed | master |
The Format::parseObject (which ClassicFormat implements) explicitly says that it returns `null` in case of error:
* @return An <code>Object</code> parsed from the string. In case of error, returns null.
And it may throw NullPointerException if position is `null`:
* @throws NullPointerException if {@code source} or {@code pos} is null.
However, ClassicFormat::parseObject does not conform to this specification and may leak DateTimeException, reproducer below:
final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.optionalStart()
.appendValue(HOUR_OF_DAY, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalEnd()
.optionalEnd()
.optionalStart()
.appendZoneOrOffsetId()
.optionalEnd()
.optionalStart()
.appendOffset("+HHmm", "Z")
.optionalEnd()
.optionalEnd()
.toFormatter(Locale.ROOT)
.withResolverStyle(ResolverStyle.STRICT);
var object = formatter.toFormat().parseObject("2018-03-30T17-30-28.842Z", new ParsePosition(0));
assert object == null;
The snippet fails with:
java.time.DateTimeException: Value out of range: Hour[0-23], Minute[0-59], Second[0-59]
at java.base/java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.parse(DateTimeFormatterBuilder.java:3708)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.parse(DateTimeFormatterBuilder.java:2360)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.parse(DateTimeFormatterBuilder.java:2360)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.parse(DateTimeFormatterBuilder.java:2370)
at java.base/java.time.format.DateTimeFormatter.parseUnresolved0(DateTimeFormatter.java:2107)
at java.base/java.time.format.DateTimeFormatter$ClassicFormat.parseObject(DateTimeFormatter.java:2236)
* @return An <code>Object</code> parsed from the string. In case of error, returns null.
And it may throw NullPointerException if position is `null`:
* @throws NullPointerException if {@code source} or {@code pos} is null.
However, ClassicFormat::parseObject does not conform to this specification and may leak DateTimeException, reproducer below:
final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.optionalStart()
.appendValue(HOUR_OF_DAY, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2, 2, SignStyle.NOT_NEGATIVE)
.optionalEnd()
.optionalEnd()
.optionalStart()
.appendZoneOrOffsetId()
.optionalEnd()
.optionalStart()
.appendOffset("+HHmm", "Z")
.optionalEnd()
.optionalEnd()
.toFormatter(Locale.ROOT)
.withResolverStyle(ResolverStyle.STRICT);
var object = formatter.toFormat().parseObject("2018-03-30T17-30-28.842Z", new ParsePosition(0));
assert object == null;
The snippet fails with:
java.time.DateTimeException: Value out of range: Hour[0-23], Minute[0-59], Second[0-59]
at java.base/java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.parse(DateTimeFormatterBuilder.java:3708)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.parse(DateTimeFormatterBuilder.java:2360)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.parse(DateTimeFormatterBuilder.java:2360)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.parse(DateTimeFormatterBuilder.java:2370)
at java.base/java.time.format.DateTimeFormatter.parseUnresolved0(DateTimeFormatter.java:2107)
at java.base/java.time.format.DateTimeFormatter$ClassicFormat.parseObject(DateTimeFormatter.java:2236)
- backported by
-
JDK-8343464 ClassicFormat::parseObject (from DateTimeFormatter) does not conform to the javadoc and may leak DateTimeException
- Resolved
- links to
-
Commit openjdk/jdk/fe0ccdf5
-
Commit(master) openjdk/jdk21u-dev/eb8d5fe5
-
Review openjdk/jdk/16586
-
Review(master) openjdk/jdk21u-dev/1101