Clamp the module function scan to the text range it already validated

The no-code-sections path validates textStart..textEnd, then derives its
actual scan boundaries from modinfo->libent/libstub without checking those
land inside it. flash0:/kd/sysmem.prx and loadcore.prx from a real firmware
dump put them tens of megabytes past the end of the text, so the scan walked
off into unmapped memory - a debug assert in Read_Instruction, and a pointless
134MB scan in release builds.

For a well-formed module every boundary is already inside the range, so this
is a no-op there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik Rydgård
2026-09-08 15:31:29 -06:00
committed by Henrik Rydgård
co-authored by Claude Opus 5
parent 4d795f5130
commit fb976d4f61
+18 -5
View File
@@ -1695,16 +1695,29 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
u32 scanEnd = module->textEnd;
if (Memory::IsValid4AlignedRange(scanStart, scanEnd - scanStart)) {
// libent/libstub come from the module's own header, and nothing has checked that
// they land inside the range validated just above. flash0:/kd/sysmem.prx and
// loadcore.prx from a real firmware dump put them tens of megabytes past the end
// of the text. So let's clamp.
const u32 textStart = scanStart;
auto clampToText = [textStart, scanEnd](u32 addr) {
return std::min(std::max(addr, textStart), scanEnd);
};
auto scanRange = [&insertSymbols](u32 from, u32 to) {
if (from < to) {
insertSymbols = MIPSAnalyst::ScanForFunctions(from, to, insertSymbols);
}
};
// Skip the exports and imports sections, they're not code.
if (scanEnd >= std::min(modinfo->libent, modinfo->libstub)) {
insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub), insertSymbols);
scanStart = std::min(modinfo->libentend, modinfo->libstubend);
scanRange(scanStart, clampToText(std::min(modinfo->libent, modinfo->libstub)));
scanStart = clampToText(std::min(modinfo->libentend, modinfo->libstubend));
}
if (scanEnd >= std::max(modinfo->libent, modinfo->libstub)) {
insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub), insertSymbols);
scanStart = std::max(modinfo->libentend, modinfo->libstubend);
scanRange(scanStart, clampToText(std::max(modinfo->libent, modinfo->libstub)));
scanStart = clampToText(std::max(modinfo->libentend, modinfo->libstubend));
}
insertSymbols = MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, insertSymbols);
scanRange(scanStart, scanEnd);
} else {
ERROR_LOG(Log::Loader, "Bad text scan range %08x-%08x", scanStart, scanEnd);
}