DatabaseBuilder.open, UsageMap.read, and PageChannel.validatePageNumber are all declared throws IOException. A malformed Jet 4 MDB makes validatePageNumber throw IllegalStateException instead. Callers that catch IOException for a bad file do not catch this.
DatabaseBuilder.open(new File("crash-107db845b1fe3fee58a3b1da3a4646e604af329b"));
24576-byte Jet 4 MDB (6 pages). Stack:
java.lang.IllegalStateException: invalid page number 169285950
at com.healthmarketscience.jackcess.impl.PageChannel.validatePageNumber(PageChannel.java:203)
at com.healthmarketscience.jackcess.impl.PageChannel.readPage(PageChannel.java:219)
at com.healthmarketscience.jackcess.impl.TempPageHolder.setPage(TempPageHolder.java:86)
at com.healthmarketscience.jackcess.impl.UsageMap$ReferenceHandler.<init>(UsageMap.java:724)
at com.healthmarketscience.jackcess.impl.UsageMap.initHandler(UsageMap.java:146)
at com.healthmarketscience.jackcess.impl.UsageMap.read(UsageMap.java:135)
at com.healthmarketscience.jackcess.impl.PageChannel.initialize(PageChannel.java:117)
at com.healthmarketscience.jackcess.impl.DatabaseImpl.open(DatabaseImpl.java:458)
at com.healthmarketscience.jackcess.DatabaseBuilder.open(DatabaseBuilder.java:278)
The global usage map is a reference map. ReferenceHandler walks page pointers from the file; page 169285950 is far past the end of a 6-page file. validatePageNumber does:
if ((pageNumber <= INVALID_PAGE_NUMBER) || (pageNumber >= nextPageNumber)) {
throw new IllegalStateException("invalid page number " + pageNumber);
}
This is not an accidental throw: the method is used from readPage, writePage, and deallocatePage, so any of those can leak the same IllegalStateException when the file names a page that does not exist. The same ReferenceHandler constructor already throws IOException when the pointed-at page has the wrong page type.
Suggested fix: throw IOException for an out-of-range page number that came from the file, matching the declared contract and the existing wrong-page-type handling. (UsageMap.read similarly throws IllegalStateException for pageNum <= 0; that is the same class of file-data error.)
The input is attached.
Found by the CISPA Fandango Team when investigating OSS-Fuzz findings (OSS-Fuzz target mdb-apache-tika-JackcessParserFuzzer).