diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index 994591c8d..dd055418c 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp @@ -4,6 +4,7 @@ #include #include +#include "common/logging/log.h" #include "common/scratch_buffer.h" #include "common/settings.h" #include "video_core/host1x/codecs/h264.h" @@ -32,12 +33,27 @@ H264::~H264() = default; std::span H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, size_t* out_configuration_size, bool is_first_frame) { H264DecoderContext context; + + // Validate picture info memory is mapped before reading + if (!host1x.GMMU().IsFullyMappedRange(state.picture_info_offset, sizeof(H264DecoderContext))) { + LOG_WARNING(HW_GPU, "H264 picture info at unmapped GPU memory 0x{:016X}", + state.picture_info_offset); + *out_configuration_size = 0; + return {}; + } host1x.GMMU().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext)); const s64 frame_number = context.h264_parameter_set.frame_number.Value(); if (!is_first_frame && frame_number != 0) { frame.resize_destructive(context.stream_len); - host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); + // Validate bitstream memory is mapped before reading + if (!host1x.GMMU().IsFullyMappedRange(state.frame_bitstream_offset, frame.size())) { + LOG_WARNING(HW_GPU, "H264 bitstream at unmapped GPU memory 0x{:016X} (size: {} KB)", + state.frame_bitstream_offset, frame.size() / 1024); + std::memset(frame.data(), 0, frame.size()); + } else { + host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); + } *out_configuration_size = 0; return frame; } @@ -158,8 +174,16 @@ std::span H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters std::memcpy(frame.data(), encoded_header.data(), encoded_header.size()); *out_configuration_size = encoded_header.size(); - host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data() + encoded_header.size(), - context.stream_len); + + // Validate bitstream memory is mapped before reading + if (!host1x.GMMU().IsFullyMappedRange(state.frame_bitstream_offset, context.stream_len)) { + LOG_WARNING(HW_GPU, "H264 bitstream at unmapped GPU memory 0x{:016X} (size: {} KB)", + state.frame_bitstream_offset, context.stream_len / 1024); + std::memset(frame.data() + encoded_header.size(), 0, context.stream_len); + } else { + host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data() + encoded_header.size(), + context.stream_len); + } return frame; } diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 676042421..00e048792 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -82,6 +82,12 @@ void Vic::Execute() { LOG_ERROR(Service_NVDRV, "VIC Luma address not set."); return; } + // Validate config struct memory is mapped before reading + if (!host1x.GMMU().IsFullyMappedRange(config_struct_address + 0x20, sizeof(u64))) { + LOG_WARNING(HW_GPU, "VIC config at unmapped GPU memory 0x{:016X}", + config_struct_address + 0x20); + return; + } const VicConfig config{host1x.GMMU().Read(config_struct_address + 0x20)}; auto frame = nvdec_processor->GetFrame(); if (!frame) { @@ -168,12 +174,24 @@ void Vic::WriteRGBFrame(std::unique_ptr frame, const VicConfig& c Texture::SwizzleSubrect(luma_buffer, frame_buff, 4, width, height, 1, 0, 0, width, height, block_height, 0, width * 4); - host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); + // Validate output memory is mapped before writing + if (host1x.GMMU().IsFullyMappedRange(output_surface_luma_address, size)) { + host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); + } else { + LOG_WARNING(HW_GPU, "VIC RGB output at unmapped GPU memory 0x{:016X} (size: {} KB)", + output_surface_luma_address, size / 1024); + } } else { // send pitch linear frame const size_t linear_size = width * height * 4; - host1x.GMMU().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, - linear_size); + // Validate output memory is mapped before writing + if (host1x.GMMU().IsFullyMappedRange(output_surface_luma_address, linear_size)) { + host1x.GMMU().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, + linear_size); + } else { + LOG_WARNING(HW_GPU, "VIC RGB output at unmapped GPU memory 0x{:016X} (size: {} KB)", + output_surface_luma_address, linear_size / 1024); + } } } @@ -199,7 +217,13 @@ void Vic::WriteYUVFrame(std::unique_ptr frame, const VicConfig& c const std::size_t dst = y * aligned_width; std::memcpy(luma_buffer.data() + dst, luma_src + src, frame_width); } - host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), luma_buffer.size()); + // Validate luma output memory is mapped before writing + if (host1x.GMMU().IsFullyMappedRange(output_surface_luma_address, luma_buffer.size())) { + host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), luma_buffer.size()); + } else { + LOG_WARNING(HW_GPU, "VIC YUV luma output at unmapped GPU memory 0x{:016X} (size: {} KB)", + output_surface_luma_address, luma_buffer.size() / 1024); + } // Chroma const std::size_t half_height = frame_height / 2; @@ -238,8 +262,14 @@ void Vic::WriteYUVFrame(std::unique_ptr frame, const VicConfig& c ASSERT(false); break; } - host1x.GMMU().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), - chroma_buffer.size()); + // Validate chroma output memory is mapped before writing + if (host1x.GMMU().IsFullyMappedRange(output_surface_chroma_address, chroma_buffer.size())) { + host1x.GMMU().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), + chroma_buffer.size()); + } else { + LOG_WARNING(HW_GPU, "VIC YUV chroma output at unmapped GPU memory 0x{:016X} (size: {} KB)", + output_surface_chroma_address, chroma_buffer.size() / 1024); + } } } // namespace Host1x