mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-11-01 04:47:53 +00:00
nvdrv, video_core: Don't index out of bounds when given invalid syncpoint ID
- Use .at() instead of raw indexing when dealing with untrusted indices. - For the special case of WaitFence with syncpoint id UINT32_MAX, instead of crashing, log an error and ignore. This is what I get when running Super Mario Maker 2.
This commit is contained in:
parent
5d1447897a
commit
e8b2fd21d8
2 changed files with 20 additions and 13 deletions
|
@ -37,7 +37,7 @@ public:
|
||||||
* @returns The lower bound for the specified syncpoint.
|
* @returns The lower bound for the specified syncpoint.
|
||||||
*/
|
*/
|
||||||
u32 GetSyncpointMin(u32 syncpoint_id) const {
|
u32 GetSyncpointMin(u32 syncpoint_id) const {
|
||||||
return syncpoints[syncpoint_id].min.load(std::memory_order_relaxed);
|
return syncpoints.at(syncpoint_id).min.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +46,7 @@ public:
|
||||||
* @returns The upper bound for the specified syncpoint.
|
* @returns The upper bound for the specified syncpoint.
|
||||||
*/
|
*/
|
||||||
u32 GetSyncpointMax(u32 syncpoint_id) const {
|
u32 GetSyncpointMax(u32 syncpoint_id) const {
|
||||||
return syncpoints[syncpoint_id].max.load(std::memory_order_relaxed);
|
return syncpoints.at(syncpoint_id).max.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -95,22 +95,29 @@ void GPU::WaitFence(u32 syncpoint_id, u32 value) {
|
||||||
if (!is_async) {
|
if (!is_async) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (syncpoint_id == UINT32_MAX) {
|
||||||
|
// TODO: Research what this does.
|
||||||
|
LOG_ERROR(HW_GPU, "Waiting for syncpoint -1 not implemented");
|
||||||
|
return;
|
||||||
|
}
|
||||||
MICROPROFILE_SCOPE(GPU_wait);
|
MICROPROFILE_SCOPE(GPU_wait);
|
||||||
std::unique_lock lock{sync_mutex};
|
std::unique_lock lock{sync_mutex};
|
||||||
sync_cv.wait(lock, [=, this] { return syncpoints[syncpoint_id].load() >= value; });
|
sync_cv.wait(lock, [=, this] { return syncpoints.at(syncpoint_id).load() >= value; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::IncrementSyncPoint(const u32 syncpoint_id) {
|
void GPU::IncrementSyncPoint(const u32 syncpoint_id) {
|
||||||
syncpoints[syncpoint_id]++;
|
auto& syncpoint = syncpoints.at(syncpoint_id);
|
||||||
|
syncpoint++;
|
||||||
std::lock_guard lock{sync_mutex};
|
std::lock_guard lock{sync_mutex};
|
||||||
sync_cv.notify_all();
|
sync_cv.notify_all();
|
||||||
if (!syncpt_interrupts[syncpoint_id].empty()) {
|
auto& interrupt = syncpt_interrupts.at(syncpoint_id);
|
||||||
u32 value = syncpoints[syncpoint_id].load();
|
if (!interrupt.empty()) {
|
||||||
auto it = syncpt_interrupts[syncpoint_id].begin();
|
u32 value = syncpoint.load();
|
||||||
while (it != syncpt_interrupts[syncpoint_id].end()) {
|
auto it = interrupt.begin();
|
||||||
|
while (it != interrupt.end()) {
|
||||||
if (value >= *it) {
|
if (value >= *it) {
|
||||||
TriggerCpuInterrupt(syncpoint_id, *it);
|
TriggerCpuInterrupt(syncpoint_id, *it);
|
||||||
it = syncpt_interrupts[syncpoint_id].erase(it);
|
it = interrupt.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
it++;
|
it++;
|
||||||
|
@ -119,22 +126,22 @@ void GPU::IncrementSyncPoint(const u32 syncpoint_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const {
|
u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const {
|
||||||
return syncpoints[syncpoint_id].load();
|
return syncpoints.at(syncpoint_id).load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value) {
|
void GPU::RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value) {
|
||||||
auto& interrupt = syncpt_interrupts[syncpoint_id];
|
auto& interrupt = syncpt_interrupts.at(syncpoint_id);
|
||||||
bool contains = std::any_of(interrupt.begin(), interrupt.end(),
|
bool contains = std::any_of(interrupt.begin(), interrupt.end(),
|
||||||
[value](u32 in_value) { return in_value == value; });
|
[value](u32 in_value) { return in_value == value; });
|
||||||
if (contains) {
|
if (contains) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
syncpt_interrupts[syncpoint_id].emplace_back(value);
|
interrupt.emplace_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) {
|
bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) {
|
||||||
std::lock_guard lock{sync_mutex};
|
std::lock_guard lock{sync_mutex};
|
||||||
auto& interrupt = syncpt_interrupts[syncpoint_id];
|
auto& interrupt = syncpt_interrupts.at(syncpoint_id);
|
||||||
const auto iter =
|
const auto iter =
|
||||||
std::find_if(interrupt.begin(), interrupt.end(),
|
std::find_if(interrupt.begin(), interrupt.end(),
|
||||||
[value](u32 interrupt_value) { return value == interrupt_value; });
|
[value](u32 interrupt_value) { return value == interrupt_value; });
|
||||||
|
|
Loading…
Reference in a new issue