Menu

#161 `UsageMap.read` throws `IndexOutOfBoundsException` on a corrupt usage-map row pointer

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

DatabaseBuilder.open and UsageMap.read are declared throws IOException. A malformed Jet 4 MDB makes UsageMap.read throw IndexOutOfBoundsException instead, while reading the global usage map during PageChannel.initialize. Callers that catch IOException for a bad file do not catch this.

DatabaseBuilder.open(new File("crash-083680cb14186e1be3e26b93946ea43c538d2e62"));

32768-byte Jet 4 MDB. Stack:

java.lang.IndexOutOfBoundsException
    at java.base/java.nio.Buffer.checkIndex(Buffer.java:743)
    at java.base/java.nio.HeapByteBuffer.get(HeapByteBuffer.java:169)
    at com.healthmarketscience.jackcess.impl.UsageMap.read(UsageMap.java:133)
    at com.healthmarketscience.jackcess.impl.PageChannel.initialize(PageChannel.java:117)
    at com.healthmarketscience.jackcess.impl.DatabaseImpl.<init>(DatabaseImpl.java:598)
    at com.healthmarketscience.jackcess.impl.DatabaseImpl.open(DatabaseImpl.java:458)
    at com.healthmarketscience.jackcess.DatabaseBuilder.open(DatabaseBuilder.java:278)

UsageMap.read does:

short rowStart = TableImpl.findRowStart(tableBuffer, rowNum, format);
int rowEnd = TableImpl.findRowEnd(tableBuffer, rowNum, format);
tableBuffer.limit(rowEnd);
byte mapType = tableBuffer.get(rowStart); // IndexOutOfBoundsException

If the row pointer is past rowEnd (or otherwise outside the narrowed buffer), get throws. An unrecognized map type already throws IOException two lines later in initHandler; this path never reaches that.

Suggested fix: if rowStart is not in [0, rowEnd), throw IOException (corrupt usage map) instead of indexing the buffer.

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.