summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-10-02 20:14:51 +0200
committerMatthias Beyer <mail@beyermatthias.de>2021-10-19 12:16:20 +0200
commit88ef8ed941b85b64be43d151ebdc316d0500a1b7 (patch)
tree4f4971dbad7c32e1edfa252ae4bbcc8052a11d1c /src
parent3a2e5abee70fe69126d4bfa6c8bb0de4dba38fa9 (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.rs46
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"
+ }
+}