Mpeg: Check memory access range on GetPointer().

This commit is contained in:
Unknown W. Brackets 2022-08-07 14:58:14 -07:00
parent fb0ed6e165
commit c44d787df4
3 changed files with 59 additions and 48 deletions

View file

@ -974,7 +974,9 @@ static bool decodePmpVideo(PSPPointer<SceMpegRingBuffer> ringbuffer, u32 pmpctxA
for (int i = 0; i < pmp_nBlocks; i++){ for (int i = 0; i < pmp_nBlocks; i++){
auto lli = PSPPointer<SceMpegLLI>::Create(pmp_videoSource); auto lli = PSPPointer<SceMpegLLI>::Create(pmp_videoSource);
// add source block into pmpframes // add source block into pmpframes
pmpframes->add(Memory::GetPointerWrite(lli->pSrc), lli->iSize); const uint8_t *ptr = Memory::GetPointerRange(lli->pSrc, lli->iSize);
if (ptr)
pmpframes->add(ptr, lli->iSize);
// get next block // get next block
pmp_videoSource += sizeof(SceMpegLLI); pmp_videoSource += sizeof(SceMpegLLI);
} }
@ -1502,7 +1504,6 @@ void PostPutAction::run(MipsCall &call) {
MpegContext *ctx = getMpegCtx(ringbuffer->mpeg); MpegContext *ctx = getMpegCtx(ringbuffer->mpeg);
int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets; int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets;
const u8 *data = Memory::GetPointer(ringbuffer->data + writeOffset * 2048);
int packetsAddedThisRound = currentMIPS->r[MIPS_REG_V0]; int packetsAddedThisRound = currentMIPS->r[MIPS_REG_V0];
if (packetsAddedThisRound > 0) { if (packetsAddedThisRound > 0) {
@ -1514,9 +1515,10 @@ void PostPutAction::run(MipsCall &call) {
// TODO: Faster / less wasteful validation. // TODO: Faster / less wasteful validation.
std::unique_ptr<MpegDemux> demuxer(new MpegDemux(packetsAddedThisRound * 2048, 0)); std::unique_ptr<MpegDemux> demuxer(new MpegDemux(packetsAddedThisRound * 2048, 0));
int readOffset = ringbuffer->packetsRead % (s32)ringbuffer->packets; int readOffset = ringbuffer->packetsRead % (s32)ringbuffer->packets;
uint32_t bufSize = Memory::ValidSize(ringbuffer->data + readOffset * 2048, packetsAddedThisRound * 2048);
const u8 *buf = Memory::GetPointer(ringbuffer->data + readOffset * 2048); const u8 *buf = Memory::GetPointer(ringbuffer->data + readOffset * 2048);
bool invalid = false; bool invalid = false;
for (int i = 0; i < packetsAddedThisRound; ++i) { for (uint32_t i = 0; i < bufSize / 2048; ++i) {
demuxer->addStreamData(buf, 2048); demuxer->addStreamData(buf, 2048);
buf += 2048; buf += 2048;
@ -1548,7 +1550,9 @@ void PostPutAction::run(MipsCall &call) {
WARN_LOG(ME, "sceMpegRingbufferPut clamping packetsAdded old=%i new=%i", packetsAddedThisRound, ringbuffer->packets - ringbuffer->packetsAvail); WARN_LOG(ME, "sceMpegRingbufferPut clamping packetsAdded old=%i new=%i", packetsAddedThisRound, ringbuffer->packets - ringbuffer->packetsAvail);
packetsAddedThisRound = ringbuffer->packets - ringbuffer->packetsAvail; packetsAddedThisRound = ringbuffer->packets - ringbuffer->packetsAvail;
} }
int actuallyAdded = ctx->mediaengine == NULL ? 8 : ctx->mediaengine->addStreamData(data, packetsAddedThisRound * 2048) / 2048; const u8 *data = Memory::GetPointer(ringbuffer->data + writeOffset * 2048);
uint32_t dataSize = Memory::ValidSize(ringbuffer->data + writeOffset * 2048, packetsAddedThisRound * 2048);
int actuallyAdded = ctx->mediaengine == NULL ? 8 : ctx->mediaengine->addStreamData(data, dataSize) / 2048;
if (actuallyAdded != packetsAddedThisRound) { if (actuallyAdded != packetsAddedThisRound) {
WARN_LOG_REPORT(ME, "sceMpegRingbufferPut(): unable to enqueue all added packets, going to overwrite some frames."); WARN_LOG_REPORT(ME, "sceMpegRingbufferPut(): unable to enqueue all added packets, going to overwrite some frames.");
} }
@ -2175,10 +2179,13 @@ static int __MpegAvcConvertToYuv420(const void *data, u32 bufferOutputAddr, int
u32 *imageBuffer = (u32*)data; u32 *imageBuffer = (u32*)data;
int sizeY = width * height; int sizeY = width * height;
int sizeCb = sizeY >> 2; int sizeCb = sizeY >> 2;
u8 *Y = (u8*)Memory::GetPointer(bufferOutputAddr); u8 *Y = Memory::GetPointerWriteRange(bufferOutputAddr, sizeY + sizeCb + sizeCb);
u8 *Cb = Y + sizeY; u8 *Cb = Y + sizeY;
u8 *Cr = Cb + sizeCb; u8 *Cr = Cb + sizeCb;
if (!Y)
return hleLogError(ME, 0, "Bad output buffer pointer for yuv conv: %08x", bufferOutputAddr);
for (int y = 0; y < height; y += 2) { for (int y = 0; y < height; y += 2) {
for (int x = 0; x < width; x += 2) { for (int x = 0; x < width; x += 2) {
u32 abgr0 = imageBuffer[width * (y + 0) + x + 0]; u32 abgr0 = imageBuffer[width * (y + 0) + x + 0];

View file

@ -777,24 +777,6 @@ inline void writeVideoLineABGR4444(void *destp, const void *srcp, int width) {
} }
int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMode) { int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMode) {
if (!Memory::IsValidAddress(bufferPtr) || frameWidth > 2048) {
// Clearly invalid values. Let's just not.
ERROR_LOG_REPORT(ME, "Ignoring invalid video decode address %08x/%x", bufferPtr, frameWidth);
return 0;
}
u8 *buffer = Memory::GetPointerWrite(bufferPtr);
#ifdef USE_FFMPEG
if (!m_pFrame || !m_pFrameRGB)
return 0;
// lock the image size
int height = m_desHeight;
int width = m_desWidth;
u8 *imgbuf = buffer;
const u8 *data = m_pFrameRGB->data[0];
int videoLineSize = 0; int videoLineSize = 0;
switch (videoPixelMode) { switch (videoPixelMode) {
case GE_CMODE_32BIT_ABGR8888: case GE_CMODE_32BIT_ABGR8888:
@ -807,7 +789,25 @@ int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMo
break; break;
} }
int videoImageSize = videoLineSize * height; int videoImageSize = videoLineSize * m_desHeight;
if (!Memory::IsValidRange(bufferPtr, videoImageSize) || frameWidth > 2048) {
// Clearly invalid values. Let's just not.
ERROR_LOG_REPORT(ME, "Ignoring invalid video decode address %08x/%x", bufferPtr, frameWidth);
return 0;
}
u8 *buffer = Memory::GetPointerWriteUnchecked(bufferPtr);
#ifdef USE_FFMPEG
if (!m_pFrame || !m_pFrameRGB)
return 0;
// lock the image size
int height = m_desHeight;
int width = m_desWidth;
u8 *imgbuf = buffer;
const u8 *data = m_pFrameRGB->data[0];
bool swizzle = Memory::IsVRAMAddress(bufferPtr) && (bufferPtr & 0x00200000) == 0x00200000; bool swizzle = Memory::IsVRAMAddress(bufferPtr) && (bufferPtr & 0x00200000) == 0x00200000;
if (swizzle) { if (swizzle) {
@ -867,22 +867,6 @@ int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMo
int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int videoPixelMode, int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int videoPixelMode,
int xpos, int ypos, int width, int height) { int xpos, int ypos, int width, int height) {
if (!Memory::IsValidAddress(bufferPtr) || frameWidth > 2048) {
// Clearly invalid values. Let's just not.
ERROR_LOG_REPORT(ME, "Ignoring invalid video decode address %08x/%x", bufferPtr, frameWidth);
return 0;
}
u8 *buffer = Memory::GetPointerWrite(bufferPtr);
#ifdef USE_FFMPEG
if (!m_pFrame || !m_pFrameRGB)
return 0;
// lock the image size
u8 *imgbuf = buffer;
const u8 *data = m_pFrameRGB->data[0];
int videoLineSize = 0; int videoLineSize = 0;
switch (videoPixelMode) { switch (videoPixelMode) {
case GE_CMODE_32BIT_ABGR8888: case GE_CMODE_32BIT_ABGR8888:
@ -894,8 +878,24 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid
videoLineSize = frameWidth * sizeof(u16); videoLineSize = frameWidth * sizeof(u16);
break; break;
} }
int videoImageSize = videoLineSize * height; int videoImageSize = videoLineSize * height;
if (!Memory::IsValidRange(bufferPtr, videoImageSize) || frameWidth > 2048) {
// Clearly invalid values. Let's just not.
ERROR_LOG_REPORT(ME, "Ignoring invalid video decode address %08x/%x", bufferPtr, frameWidth);
return 0;
}
u8 *buffer = Memory::GetPointerWriteUnchecked(bufferPtr);
#ifdef USE_FFMPEG
if (!m_pFrame || !m_pFrameRGB)
return 0;
// lock the image size
u8 *imgbuf = buffer;
const u8 *data = m_pFrameRGB->data[0];
bool swizzle = Memory::IsVRAMAddress(bufferPtr) && (bufferPtr & 0x00200000) == 0x00200000; bool swizzle = Memory::IsVRAMAddress(bufferPtr) && (bufferPtr & 0x00200000) == 0x00200000;
if (swizzle) { if (swizzle) {
imgbuf = new u8[videoImageSize]; imgbuf = new u8[videoImageSize];
@ -1006,11 +1006,10 @@ int MediaEngine::getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2)
} }
int MediaEngine::getAudioSamples(u32 bufferPtr) { int MediaEngine::getAudioSamples(u32 bufferPtr) {
if (!Memory::IsValidAddress(bufferPtr)) { u8 *buffer = Memory::GetPointerWriteRange(bufferPtr, 8192);
if (buffer == nullptr) {
ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr); ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr);
} }
u8 *buffer = Memory::GetPointerWrite(bufferPtr);
if (!m_demux) { if (!m_demux) {
return 0; return 0;
} }

View file

@ -252,7 +252,10 @@ bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int
} }
// convert audio to AV_SAMPLE_FMT_S16 // convert audio to AV_SAMPLE_FMT_S16
int swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples); int swrRet = 0;
if (outbuf != nullptr) {
swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples);
}
if (swrRet < 0) { if (swrRet < 0) {
ERROR_LOG(ME, "swr_convert: Error while converting: %d", swrRet); ERROR_LOG(ME, "swr_convert: Error while converting: %d", swrRet);
return false; return false;
@ -338,7 +341,7 @@ size_t AuCtx::FindNextMp3Sync() {
// return output pcm size, <0 error // return output pcm size, <0 error
u32 AuCtx::AuDecode(u32 pcmAddr) { u32 AuCtx::AuDecode(u32 pcmAddr) {
u32 outptr = PCMBuf + nextOutputHalf * PCMBufSize / 2; u32 outptr = PCMBuf + nextOutputHalf * PCMBufSize / 2;
auto outbuf = Memory::GetPointerWrite(outptr); auto outbuf = Memory::GetPointerWriteRange(outptr, PCMBufSize / 2);
int outpcmbufsize = 0; int outpcmbufsize = 0;
if (pcmAddr) if (pcmAddr)
@ -380,10 +383,12 @@ u32 AuCtx::AuDecode(u32 pcmAddr) {
if (outpcmbufsize == 0 && !end) { if (outpcmbufsize == 0 && !end) {
// If we didn't decode anything, we fill this half of the buffer with zeros. // If we didn't decode anything, we fill this half of the buffer with zeros.
outpcmbufsize = PCMBufSize / 2; outpcmbufsize = PCMBufSize / 2;
memset(outbuf, 0, outpcmbufsize); if (outbuf != nullptr)
memset(outbuf, 0, outpcmbufsize);
} else if ((u32)outpcmbufsize < PCMBufSize) { } else if ((u32)outpcmbufsize < PCMBufSize) {
// TODO: Not sure it actually zeros this out. // TODO: Not sure it actually zeros this out.
memset(outbuf + outpcmbufsize, 0, PCMBufSize / 2 - outpcmbufsize); if (outbuf != nullptr)
memset(outbuf + outpcmbufsize, 0, PCMBufSize / 2 - outpcmbufsize);
} }
if (outpcmbufsize != 0) if (outpcmbufsize != 0)