From a2294d4d18077927c01c5cc8065563085d837c5b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 21 Oct 2025 06:56:52 +0000 Subject: [PATCH] Fix: Prevent buffer overflow and improve reconnect logic Co-authored-by: virus191288 --- guest-js/auto-reconnect-manager.ts | 18 +++++++++++++----- src/desktop_api.rs | 6 ++++++ src/error.rs | 5 ++--- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/guest-js/auto-reconnect-manager.ts b/guest-js/auto-reconnect-manager.ts index 91042c7..7b3b7be 100644 --- a/guest-js/auto-reconnect-manager.ts +++ b/guest-js/auto-reconnect-manager.ts @@ -128,15 +128,18 @@ export class AutoReconnectManager { return; } - // Проверяем лимит ДО увеличения счётчика - if (this.maxAttempts !== null && this.currentAttempts >= this.maxAttempts) { + // Atomically check limit and increment counter to prevent race conditions + const currentAttempt = this.currentAttempts + 1; + + if (this.maxAttempts !== null && currentAttempt > this.maxAttempts) { logError(`Auto-reconnect failed after ${this.maxAttempts} attempts`); if (this.callback) { this.callback(false, this.currentAttempts); } return; } - this.currentAttempts++; + + this.currentAttempts = currentAttempt; logInfo(`Auto-reconnect attempt ${this.currentAttempts}${this.maxAttempts !== null ? `/${this.maxAttempts}` : ''}`); @@ -160,11 +163,16 @@ export class AutoReconnectManager { this.callback(false, this.currentAttempts); } - // Schedule next attempt - if (this.enabled) { + // Schedule next attempt only if still enabled and within limits + if (this.enabled && (this.maxAttempts === null || this.currentAttempts < this.maxAttempts)) { this.timer = setTimeout(() => { this.performAttempt(); }, this.interval); + } else if (this.enabled && this.maxAttempts !== null && this.currentAttempts >= this.maxAttempts) { + logError(`Auto-reconnect stopped: maximum attempts (${this.maxAttempts}) reached`); + if (this.callback) { + this.callback(false, this.currentAttempts); + } } } } diff --git a/src/desktop_api.rs b/src/desktop_api.rs index 3f9d93b..5e247f3 100644 --- a/src/desktop_api.rs +++ b/src/desktop_api.rs @@ -465,6 +465,7 @@ impl SerialPort { let thread_handle = thread::spawn(move || { let mut combined_buffer: Vec = Vec::with_capacity(size.unwrap_or(1024)); let mut start_time = Instant::now(); + let max_buffer_size = size.unwrap_or(1024) * 10; // Limit buffer growth to prevent memory leaks loop { match rx.try_recv() { Ok(_) => break, @@ -483,6 +484,11 @@ impl SerialPort { let mut buffer = vec![0; size.unwrap_or(1024)]; match serial.read(&mut buffer) { Ok(n) => { + // Prevent buffer from growing too large to avoid memory leaks + if combined_buffer.len() + n > max_buffer_size { + log_warn!("Buffer size limit reached, clearing buffer to prevent memory leak"); + combined_buffer.clear(); + } combined_buffer.extend_from_slice(&buffer[..n]); } Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {} diff --git a/src/error.rs b/src/error.rs index 6184ada..c50e9c1 100755 --- a/src/error.rs +++ b/src/error.rs @@ -100,6 +100,5 @@ impl From for Error { } } -// Implementing Send and Sync for Error -unsafe impl Send for Error {} -unsafe impl Sync for Error {} +// Error is automatically Send and Sync because all its fields are Send and Sync +// String is Send and Sync, so Error is safe to use across threads