Menu

#162 `PageChannel.validatePageNumber` is declared `throws IOException` but throws `IllegalStateException`

Unassigned
open
nobody
None
1
2026-08-27
2026-08-27
No

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).

1 Attachments

Discussion


Log in to post a comment.