diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2021-10-02 20:14:51 +0200 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2021-10-19 12:16:20 +0200 |
commit | 88ef8ed941b85b64be43d151ebdc316d0500a1b7 (patch) | |
tree | 4f4971dbad7c32e1edfa252ae4bbcc8052a11d1c /src | |
parent | 3a2e5abee70fe69126d4bfa6c8bb0de4dba38fa9 (diff) |
Fix panic: Unwrap()ing a f64::parse() should not happen
This fixes a panic where a f64 failed to be parsed, which caused
end-user software to crash.
This patch fixes the problem.
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/file/format/yaml.rs | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/src/file/format/yaml.rs b/src/file/format/yaml.rs index 44b72fb..de67efe 100644 --- a/src/file/format/yaml.rs +++ b/src/file/format/yaml.rs @@ -22,7 +22,7 @@ pub fn parse( }; // TODO: Have a proper error fire if the root of a file is ever not a Table - let value = from_yaml_value(uri, &root); + let value = from_yaml_value(uri, &root)?; match value.kind { ValueKind::Table(map) => Ok(map), @@ -30,33 +30,42 @@ pub fn parse( } } -fn from_yaml_value(uri: Option<&String>, value: &yaml::Yaml) -> Value { +fn from_yaml_value( + uri: Option<&String>, + value: &yaml::Yaml, +) -> Result<Value, Box<dyn Error + Send + Sync>> { match *value { - yaml::Yaml::String(ref value) => Value::new(uri, ValueKind::String(value.clone())), + yaml::Yaml::String(ref value) => Ok(Value::new(uri, ValueKind::String(value.clone()))), yaml::Yaml::Real(ref value) => { // TODO: Figure out in what cases this can panic? - Value::new(uri, ValueKind::Float(value.parse::<f64>().unwrap())) + value + .parse::<f64>() + .map_err(|_| { + Box::new(FloatParsingError(value.to_string())) as Box<(dyn Error + Send + Sync)> + }) + .map(ValueKind::Float) + .map(|f| Value::new(uri, f)) } - yaml::Yaml::Integer(value) => Value::new(uri, ValueKind::Integer(value)), - yaml::Yaml::Boolean(value) => Value::new(uri, ValueKind::Boolean(value)), + yaml::Yaml::Integer(value) => Ok(Value::new(uri, ValueKind::Integer(value))), + yaml::Yaml::Boolean(value) => Ok(Value::new(uri, ValueKind::Boolean(value))), yaml::Yaml::Hash(ref table) => { let mut m = Map::new(); for (key, value) in table { if let Some(k) = key.as_str() { - m.insert(k.to_owned(), from_yaml_value(uri, value)); + m.insert(k.to_owned(), from_yaml_value(uri, value)?); } // TODO: should we do anything for non-string keys? } - Value::new(uri, ValueKind::Table(m)) + Ok(Value::new(uri, ValueKind::Table(m))) } yaml::Yaml::Array(ref array) => { let mut l = Vec::new(); for value in array { - l.push(from_yaml_value(uri, value)); + l.push(from_yaml_value(uri, value)?); } - Value::new(uri, ValueKind::Array(l)) + Ok(Value::new(uri, ValueKind::Array(l))) } // 1. Yaml NULL @@ -64,7 +73,7 @@ fn from_yaml_value(uri: Option<&String>, value: &yaml::Yaml) -> Value { // using the index trait badly or on a type error but we send back nil. // 3. Alias – No idea what to do with this and there is a note in the lib that its // not fully supported yet anyway - _ => Value::new(uri, ValueKind::Nil), + _ => Ok(Value::new(uri, ValueKind::Nil)), } } @@ -82,3 +91,18 @@ impl Error for MultipleDocumentsError { "More than one YAML document provided" } } + +#[derive(Debug, Clone)] +struct FloatParsingError(String); + +impl fmt::Display for FloatParsingError { + fn fmt(&self, format: &mut fmt::Formatter) -> fmt::Result { + write!(format, "Parsing {} as floating point number failed", self.0) + } +} + +impl Error for FloatParsingError { + fn description(&self) -> &str { + "Floating point number parsing failed" + } +} |