diff options
| author | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-01 17:17:54 +0100 |
|---|---|---|
| committer | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-01 17:29:56 +0100 |
| commit | 3d6156434a96c75e30fc4cfa65409fb2800d737a (patch) | |
| tree | 62f4f1e510128f403e6f9f669b2bc62fa23a6d64 | |
| parent | 130c255ed91e2bf8f726b38101cc5fc2abcf3935 (diff) | |
nx2: guard empty and overflowing 216 map requests, log failed whole-backing
A zero-size request at a region start wrapped last_block and wrote past the
region's blocks; the offset + size memory bounds check could overflow. Both are
guest-controlled. Also log an error when a sparse tiled image sharing the zeroed
block can't be backed whole before a GPU write.
| -rw-r--r-- | src/core/hle/service/nx2_gsv.h | 7 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 5 |
2 files changed, 10 insertions, 2 deletions
diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index 39ef402024..628bdeda5b 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -941,6 +941,9 @@ private: void ApplySparseMapRequest(const SparseMapRequest& request) { ++m_tile_requests; + if (request.size == 0) { + return; + } const u64 gpu_address = request.gpu_address; const u64 size = request.size; auto& registry = Nvidia::Devices::Nx2GpuMemoryRegistry::Get(); @@ -972,7 +975,7 @@ private: } ++m_tile_maps; const auto memory = m_memory.find(request.memory_handle); - if (memory == m_memory.end() || request.offset + size > memory->second.size) { + if (memory == m_memory.end() || request.offset > memory->second.size || size > memory->second.size - request.offset) { LOG_WARNING(Service, "nx2:gpu 216 map [{:#x}, +{:#x}] of unknown memory {} offset {:#x}", gpu_address, size, request.memory_handle, request.offset); return; @@ -1050,7 +1053,7 @@ private: return; } const auto memory = m_memory.find(request.memory_handle); - if (memory == m_memory.end() || request.offset + size > memory->second.size) { + if (memory == m_memory.end() || request.offset > memory->second.size || size > memory->second.size - request.offset) { LOG_WARNING(Service, "nx2:gpu 216 map [{:#x}, +{:#x}] of unknown memory {} offset {:#x}", gpu_address, size, request.memory_handle, request.offset); return; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 5f655e5b60..33ca051482 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -3113,6 +3113,11 @@ void TextureCache<P>::PrepareImage(ImageId image_id, bool is_modification, bool if (BackSparseTilesWhole(image)) { image.dirty_ranges.clear(); RefreshSparseTiles(image); + } else { + LOG_ERROR(HW_GPU, + "Sparse tiled image {:#x}: out of memory backing it whole, the GPU " + "write lands in the shared zeroed block", + image.gpu_addr); } } } |
