mirror of
https://github.com/servo/servo.git
synced 2025-09-19 11:20:09 +01:00
servoshell: Add ParseResolutionError
to parse elegantly (#39289)
When passing an invalid resolution string (such as `1x1x1`) to the `--screen-size` or `--window-size` argument, Servo starts without any error. Additionally, if the width or height is set to 0, Servo crashes with a SIGSEGV (Address boundary error). This patch addresses the following issue by several changes: 1. Introduce a custom error type ParseResolutionError. 2. Replace the `split()` method with `split_once()`. 3. Make the capital 'X' an acceptable separator. 4. Add a check to prevent crashes when width or height is set to 0. --- Before: ``` ╰─❯ ./servo --screen-size=0 index out of bounds: the len is 1 but the index is 1 (thread main, at ports/servoshell/prefs.rs:236) fish: Job 1, './servo --screen-size=0' terminated by signal SIGSEGV (Address boundary error) ``` ``` ╰─❯ ./servo --screen-size=0x1 xdg_surface#30: error -1: invalid window geometry size (0x1) assertion `left != right` failed left: 0 right: 0 (thread main, at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/surfman-0.10.0/src/platform/unix/wayland/connection.rs:140) fish: Job 1, './servo --screen-size=0x1' terminated by signal SIGSEGV (Address boundary error) ``` After: ``` ╰─❯ ./servo --screen-size=0 Error: couldn't parse `0`: invalid resolution format ``` ``` ╰─❯ ./servo --screen-size=0x1 Error: couldn't parse `0x1`: width and height must be greater than 0 ``` Signed-off-by: Integral <integral@member.fsf.org>
This commit is contained in:
parent
b3b79e049b
commit
2d5eac386f
1 changed files with 38 additions and 8 deletions
|
@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::str::FromStr;
|
||||
#[cfg(any(target_os = "android", target_env = "ohos"))]
|
||||
use std::sync::OnceLock;
|
||||
use std::{env, process};
|
||||
use std::{env, fmt, process};
|
||||
|
||||
use bpaf::*;
|
||||
use euclid::Size2D;
|
||||
|
@ -221,18 +221,48 @@ pub(crate) enum ArgumentParsingResult {
|
|||
ErrorParsing,
|
||||
}
|
||||
|
||||
enum ParseResolutionError {
|
||||
InvalidFormat,
|
||||
ZeroDimension,
|
||||
ParseError(std::num::ParseIntError),
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseResolutionError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ParseResolutionError::InvalidFormat => write!(f, "invalid resolution format"),
|
||||
ParseResolutionError::ZeroDimension => {
|
||||
write!(f, "width and height must be greater than 0")
|
||||
},
|
||||
ParseResolutionError::ParseError(e) => write!(f, "{e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a resolution string into a Size2D.
|
||||
fn parse_resolution_string(
|
||||
string: String,
|
||||
) -> Result<Option<Size2D<u32, DeviceIndependentPixel>>, std::num::ParseIntError> {
|
||||
) -> Result<Option<Size2D<u32, DeviceIndependentPixel>>, ParseResolutionError> {
|
||||
if string.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
let components = string
|
||||
.split('x')
|
||||
.map(|component| component.parse::<u32>())
|
||||
.collect::<Result<Vec<_>, std::num::ParseIntError>>()?;
|
||||
Ok(Some(Size2D::new(components[0], components[1])))
|
||||
let (width, height) = string
|
||||
.split_once(['x', 'X'])
|
||||
.ok_or(ParseResolutionError::InvalidFormat)?;
|
||||
|
||||
let width = width.trim();
|
||||
let height = height.trim();
|
||||
if width.is_empty() || height.is_empty() {
|
||||
return Err(ParseResolutionError::InvalidFormat);
|
||||
}
|
||||
|
||||
let width = width.parse().map_err(ParseResolutionError::ParseError)?;
|
||||
let height = height.parse().map_err(ParseResolutionError::ParseError)?;
|
||||
if width == 0 || height == 0 {
|
||||
return Err(ParseResolutionError::ZeroDimension);
|
||||
}
|
||||
|
||||
Ok(Some(Size2D::new(width, height)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,7 +299,7 @@ fn flag_with_default_parser<S, T>(
|
|||
) -> impl Parser<Option<T>>
|
||||
where
|
||||
S: FromStr + 'static,
|
||||
<S as FromStr>::Err: std::fmt::Display,
|
||||
<S as FromStr>::Err: fmt::Display,
|
||||
T: Clone + 'static,
|
||||
{
|
||||
let just_flag = if let Some(c) = short_cmd {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue