[fix] fix crash when switching monitors due to race condition and missing bounds checks in screen capturer

This commit is contained in:
dijunkun
2026-06-26 14:44:30 +08:00
parent 3c4000bdbb
commit 9c28cd2ab2
4 changed files with 22 additions and 4 deletions
@@ -111,6 +111,7 @@ int ScreenCapturerDxgi::Resume(int monitor_index) {
}
int ScreenCapturerDxgi::SwitchTo(int monitor_index) {
std::lock_guard<std::mutex> lock(switch_mutex_);
if (monitor_index < 0 || monitor_index >= (int)display_info_list_.size()) {
LOG_ERROR("DXGI: invalid monitor index {}", monitor_index);
return -1;
@@ -121,6 +122,7 @@ int ScreenCapturerDxgi::SwitchTo(int monitor_index) {
if (!CreateDuplicationForMonitor(monitor_index_)) {
LOG_ERROR("DXGI: create duplication failed for monitor {}",
monitor_index_.load());
paused_ = false; // Reset paused_ on failure
return -2;
}
paused_ = false;
@@ -130,6 +132,7 @@ int ScreenCapturerDxgi::SwitchTo(int monitor_index) {
}
int ScreenCapturerDxgi::ResetToInitialMonitor() {
std::lock_guard<std::mutex> lock(switch_mutex_);
if (display_info_list_.empty()) return -1;
int target = initial_monitor_index_;
if (target < 0 || target >= (int)display_info_list_.size()) return -1;
@@ -245,6 +248,7 @@ bool ScreenCapturerDxgi::CreateDuplicationForMonitor(int monitor_index) {
}
bool ScreenCapturerDxgi::RecreateDuplicationForCurrentMonitor() {
std::lock_guard<std::mutex> lock(switch_mutex_);
ReleaseDuplication();
int current_monitor = monitor_index_.load();
if (CreateDuplicationForMonitor(current_monitor)) {
@@ -374,8 +378,14 @@ void ScreenCapturerDxgi::CaptureLoop() {
even_width, even_width, even_height);
if (callback_) {
callback_(nv12_frame_, nv12_size, even_width, even_height,
display_info_list_[monitor_index_].name.c_str());
int idx = monitor_index_.load();
if (idx >= 0 && idx < static_cast<int>(display_info_list_.size())) {
callback_(nv12_frame_, nv12_size, even_width, even_height,
display_info_list_[idx].name.c_str());
} else {
LOG_ERROR("DXGI: CaptureLoop invalid monitor_index {} (list size {})",
idx, display_info_list_.size());
}
}
d3d_context_->Unmap(staging_.Get(), 0);
@@ -72,6 +72,7 @@ class ScreenCapturerDxgi : public ScreenCapturer {
std::thread thread_;
int fps_ = 60;
cb_desktop_data callback_ = nullptr;
std::mutex switch_mutex_;
unsigned char* nv12_frame_ = nullptr;
int nv12_width_ = 0;
@@ -148,7 +148,14 @@ void ScreenCapturerGdi::CaptureLoop() {
continue;
}
const auto& di = display_info_list_[monitor_index_];
int idx = monitor_index_.load();
if (idx < 0 || idx >= static_cast<int>(display_info_list_.size())) {
LOG_ERROR("GDI: CaptureLoop invalid monitor_index {} (list size {})",
idx, display_info_list_.size());
std::this_thread::sleep_for(std::chrono::milliseconds(interval_ms));
continue;
}
const auto& di = display_info_list_[idx];
int left = di.left;
int top = di.top;
int width = di.width & ~1;
@@ -306,7 +306,7 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) {
return 0;
}
if (monitor_index >= display_info_list_.size()) {
if (monitor_index < 0 || monitor_index >= static_cast<int>(display_info_list_.size())) {
LOG_ERROR("Invalid monitor index: {}", monitor_index);
return -1;
}