From 88ef8ed941b85b64be43d151ebdc316d0500a1b7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 2 Oct 2021 20:14:51 +0200 Subject: 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 --- src/file/format/yaml.rs | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'src') 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> { 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::().unwrap())) + value + .parse::() + .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" + } +} -- cgit v1.2.3