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;
|
use std::str::FromStr;
|
||||||
#[cfg(any(target_os = "android", target_env = "ohos"))]
|
#[cfg(any(target_os = "android", target_env = "ohos"))]
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::{env, process};
|
use std::{env, fmt, process};
|
||||||
|
|
||||||
use bpaf::*;
|
use bpaf::*;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
|
@ -221,18 +221,48 @@ pub(crate) enum ArgumentParsingResult {
|
||||||
ErrorParsing,
|
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.
|
/// Parse a resolution string into a Size2D.
|
||||||
fn parse_resolution_string(
|
fn parse_resolution_string(
|
||||||
string: String,
|
string: String,
|
||||||
) -> Result<Option<Size2D<u32, DeviceIndependentPixel>>, std::num::ParseIntError> {
|
) -> Result<Option<Size2D<u32, DeviceIndependentPixel>>, ParseResolutionError> {
|
||||||
if string.is_empty() {
|
if string.is_empty() {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
let components = string
|
let (width, height) = string
|
||||||
.split('x')
|
.split_once(['x', 'X'])
|
||||||
.map(|component| component.parse::<u32>())
|
.ok_or(ParseResolutionError::InvalidFormat)?;
|
||||||
.collect::<Result<Vec<_>, std::num::ParseIntError>>()?;
|
|
||||||
Ok(Some(Size2D::new(components[0], components[1])))
|
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>>
|
) -> impl Parser<Option<T>>
|
||||||
where
|
where
|
||||||
S: FromStr + 'static,
|
S: FromStr + 'static,
|
||||||
<S as FromStr>::Err: std::fmt::Display,
|
<S as FromStr>::Err: fmt::Display,
|
||||||
T: Clone + 'static,
|
T: Clone + 'static,
|
||||||
{
|
{
|
||||||
let just_flag = if let Some(c) = short_cmd {
|
let just_flag = if let Some(c) = short_cmd {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue