diff --git a/CHANGELOG.md b/CHANGELOG.md index f5440760..d9ebc035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fix a crash with Connection module when connecting to a loopback serial port (#954) + ### Removed ## [4.1.0] - 2025-09-18 diff --git a/espflash/src/connection/mod.rs b/espflash/src/connection/mod.rs index 03d09a7a..d921ea52 100644 --- a/espflash/src/connection/mod.rs +++ b/espflash/src/connection/mod.rs @@ -397,31 +397,24 @@ impl Connection { let value = match response.len() { 10 | 12 => CommandResponseValue::ValueU32(u32::from_le_bytes( - response[4..][..4].try_into().unwrap(), + response[4..][..4].try_into()?, + )), + // MD5 is in ASCII + 44 => CommandResponseValue::ValueU128(u128::from_str_radix( + std::str::from_utf8(&response[8..][..32])?, + 16, + )?), + // MD5 is BE bytes + 26 => CommandResponseValue::ValueU128(u128::from_be_bytes( + response[8..][..16].try_into()?, )), - 44 => { - // MD5 is in ASCII - CommandResponseValue::ValueU128( - u128::from_str_radix( - std::str::from_utf8(&response[8..][..32]).unwrap(), - 16, - ) - .unwrap(), - ) - } - 26 => { - // MD5 is BE bytes - CommandResponseValue::ValueU128(u128::from_be_bytes( - response[8..][..16].try_into().unwrap(), - )) - } _ => CommandResponseValue::Vector(response.clone()), }; let header = CommandResponse { resp: response[0], return_op: response[1], - return_length: u16::from_le_bytes(response[2..][..2].try_into().unwrap()), + return_length: u16::from_le_bytes(response[2..][..2].try_into()?), value, error: response[response.len() - status_len + 1], status: response[response.len() - status_len], diff --git a/espflash/src/error.rs b/espflash/src/error.rs index 86885bad..2d56c617 100644 --- a/espflash/src/error.rs +++ b/espflash/src/error.rs @@ -2,7 +2,7 @@ #[cfg(feature = "serialport")] use std::fmt::{Display, Formatter}; -use std::{array::TryFromSliceError, io}; +use std::{array::TryFromSliceError, io, num::ParseIntError, str::Utf8Error}; use miette::Diagnostic; #[cfg(feature = "serialport")] @@ -294,6 +294,14 @@ pub enum Error { #[error(transparent)] TryFromSlice(CoreError), + /// Error while trying to parse int from text + #[error(transparent)] + ParseIntError(CoreError), + + /// Error while trying to parse UTF-8 from bytes + #[error(transparent)] + Utf8Error(CoreError), + /// Failed to open file #[error("Failed to open file: {0}")] FileOpenError(String, #[source] io::Error), @@ -380,6 +388,18 @@ impl From for Error { } } +impl From for Error { + fn from(err: ParseIntError) -> Self { + Self::ParseIntError(Box::new(err)) + } +} + +impl From for Error { + fn from(err: Utf8Error) -> Self { + Self::Utf8Error(Box::new(err)) + } +} + impl From for Error { fn from(err: object::Error) -> Self { Self::InvalidElf(err.into()) diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index f68a2549..86cdbdf8 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -1051,8 +1051,8 @@ impl Flasher { { let metadata = image_format.metadata(); if metadata.contains_key("app_size") && metadata.contains_key("part_size") { - let app_size = metadata["app_size"].parse::().unwrap(); - let part_size = metadata["part_size"].parse::().unwrap(); + let app_size = metadata["app_size"].parse::()?; + let part_size = metadata["part_size"].parse::()?; crate::cli::display_image_size(app_size, Some(part_size)); }