The block table read from an NPDRM PBP's PSAR blob is only reversibly
XOR-scrambled, not otherwise validated, so a crafted file fully
controls table_[block].size/offset and the header's LBA/block-size
fields. Several of these were used without checks:
- table_[block].size could exceed blockSize_, causing ReadAt and the
KIRK cipher update to write past the end of blockBuf_/tempBuf_ (both
allocated as exactly blockSize_ bytes) - a heap buffer overflow.
- The block index derived from blockNumber (which can come from an
attacker-influenced /sce_lbn.../_size... raw sector open) was never
bounds-checked against numBlocks_ before indexing table_[].
- blockLBAs_ could be 0, dividing by zero both when computing
numBlocks_ and when computing the block index in ReadBlock.
- lbaSize_ could underflow if lbaEnd < lbaStart, and tableSize_
(numBlocks_ * sizeof(table_info)) was computed in 32-bit, so a large
numBlocks_ could wrap it to a small value - passing the "did we read
the whole table" check while only actually reading (and
descrambling) a small prefix, leaving the rest of the table_ array
as untouched, uninitialized heap memory that ReadBlock() would later
trust.
Reject all of these instead.