Skip to content

Commit ec1065e

Browse files
[TRUNK-15304] Duration panic (#728)
The issue is that Duration panics if you give it negative numbers or some special f64 values. Since we already use Option to handle parsing this, flat_mapping a condition to check for these.
1 parent 8546d25 commit ec1065e

File tree

1 file changed

+66
-1
lines changed

1 file changed

+66
-1
lines changed

context/src/junit/parser.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,10 @@ mod parse_attr {
756756
parse_string_attr(e, "name")
757757
}
758758

759+
fn is_legal_seconds(candidate: &f64) -> bool {
760+
candidate.is_finite() && (candidate.is_sign_positive() || *candidate == 0.0)
761+
}
762+
759763
pub fn timestamp(
760764
e: &BytesStart,
761765
date_parser: &mut JunitDateParser,
@@ -765,7 +769,15 @@ mod parse_attr {
765769

766770
pub fn time(e: &BytesStart) -> Option<Duration> {
767771
parse_string_attr_into_other_type(e, "time")
768-
.map(|seconds: f64| Duration::from_secs_f64(seconds))
772+
.iter()
773+
.filter_map(|seconds: &f64| {
774+
if is_legal_seconds(seconds) {
775+
Some(Duration::from_secs_f64(*seconds))
776+
} else {
777+
None
778+
}
779+
})
780+
.next()
769781
}
770782

771783
pub fn assertions(e: &BytesStart) -> Option<usize> {
@@ -816,6 +828,59 @@ mod parse_attr {
816828
) -> Option<T> {
817829
parse_string_attr(e, attr_name).and_then(|value| value.parse::<T>().ok())
818830
}
831+
832+
#[cfg(test)]
833+
mod tests {
834+
use std::{borrow::Cow, time::Duration};
835+
836+
use quick_xml::{
837+
events::{attributes::Attribute, BytesStart},
838+
name::QName,
839+
};
840+
841+
use super::{is_legal_seconds, time};
842+
843+
#[test]
844+
fn test_is_legal_seconds() {
845+
assert!(is_legal_seconds(&2.0e64));
846+
assert!(is_legal_seconds(&2.0));
847+
848+
assert!(is_legal_seconds(&0.0));
849+
assert!(is_legal_seconds(&-0.0));
850+
851+
assert!(!is_legal_seconds(&-2.0));
852+
assert!(!is_legal_seconds(&-2.0e64));
853+
854+
assert!(!is_legal_seconds(&f64::MIN));
855+
assert!(is_legal_seconds(&f64::MIN_POSITIVE));
856+
assert!(is_legal_seconds(&f64::MAX));
857+
858+
assert!(!is_legal_seconds(&f64::NAN));
859+
860+
assert!(!is_legal_seconds(&f64::INFINITY));
861+
assert!(!is_legal_seconds(&f64::NEG_INFINITY));
862+
}
863+
864+
#[test]
865+
fn test_legal_time() {
866+
let mut legal_time = BytesStart::new(Cow::from("legal_time"));
867+
legal_time.push_attribute(Attribute {
868+
key: QName(b"time"),
869+
value: Cow::from(b"1.0"),
870+
});
871+
assert_eq!(time(&legal_time), Some(Duration::from_secs_f64(1.0)));
872+
}
873+
874+
#[test]
875+
fn test_illegal_time() {
876+
let mut illegal_time = BytesStart::new(Cow::from("legal_time"));
877+
illegal_time.push_attribute(Attribute {
878+
key: QName(b"time"),
879+
value: Cow::from(b"-1.0"),
880+
});
881+
assert_eq!(time(&illegal_time), None);
882+
}
883+
}
819884
}
820885

821886
mod unescape_and_truncate {

0 commit comments

Comments
 (0)