diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index cf78967e13..e3c4d742bb 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -637,6 +637,14 @@ static u32 sceSasGetGrain(u32 core) { } static u32 sceSasSetGrain(u32 core, int grain) { + // Unlike sceSasInit, this took no validation at all - a bad grain size could + // both throw on the allocation below and (for a moderately large but successfully + // allocated value beyond PSP_SAS_MAX_GRAIN) read out of bounds of the fixed-size + // mixTemp_ buffer during mixing. Apply the same bounds sceSasInit uses. + if (grain < 0x40 || grain > 0x800 || (grain & 0x1F) != 0) { + ERROR_LOG_REPORT(Log::sceSas, "sceSasSetGrain(%08x, %i): bad grain size", core, grain); + return hleNoLog(SCE_SAS_ERROR_INVALID_GRAIN); + } __SasDrain(); sas->SetGrainSize(grain); return hleLogInfo(Log::sceSas, 0); diff --git a/Core/HW/SasReverb.cpp b/Core/HW/SasReverb.cpp index 2b7199dca2..63e61aa11a 100644 --- a/Core/HW/SasReverb.cpp +++ b/Core/HW/SasReverb.cpp @@ -169,7 +169,11 @@ const char *SasReverb::GetPresetName(int preset) { } void SasReverb::SetPreset(int preset) { - if (preset < (int)ARRAY_SIZE(presets)) + // -1 means "off"; anything else must be a valid index into presets[]. Only the + // upper bound was checked before, so a value below -1 (e.g. from a corrupted + // savestate - the sceSasRevType HLE call itself already clamps to [-1, 8]) would + // index presets[] negatively below. + if (preset >= -1 && preset < (int)ARRAY_SIZE(presets)) preset_ = preset; if (preset_ != -1) { pos_ = BUFSIZE - presets[preset_].size;