melib/datetime: fix overflow panic on early date input
parent
eb501b6d50
commit
6afac835e0
|
@ -74,7 +74,7 @@ pub fn timestamp_to_string(timestamp: UnixTimestamp, fmt: Option<&str>) -> Strin
|
||||||
s.to_string_lossy().to_string()
|
s.to_string_lossy().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tm_to_secs(tm: ::libc::tm) -> UnixTimestamp {
|
fn tm_to_secs(tm: ::libc::tm) -> std::result::Result<i64, ()> {
|
||||||
let mut is_leap = false;
|
let mut is_leap = false;
|
||||||
let mut year = tm.tm_year;
|
let mut year = tm.tm_year;
|
||||||
let mut month = tm.tm_mon;
|
let mut month = tm.tm_mon;
|
||||||
|
@ -87,19 +87,19 @@ fn tm_to_secs(tm: ::libc::tm) -> UnixTimestamp {
|
||||||
}
|
}
|
||||||
year += adj;
|
year += adj;
|
||||||
}
|
}
|
||||||
let mut t = year_to_secs(year as u64, &mut is_leap);
|
let mut t = year_to_secs(year.into(), &mut is_leap)?;
|
||||||
t += month_to_secs(month as usize, is_leap);
|
t += month_to_secs(month.try_into().unwrap_or(0), is_leap);
|
||||||
t += 86400 * (tm.tm_mday as u64 - 1);
|
t += 86400 * (tm.tm_mday - 1) as i64;
|
||||||
t += 3600 * (tm.tm_hour as u64);
|
t += 3600 * (tm.tm_hour) as i64;
|
||||||
t += 60 * (tm.tm_min as u64);
|
t += 60 * (tm.tm_min) as i64;
|
||||||
t += tm.tm_sec as u64;
|
t += tm.tm_sec as i64;
|
||||||
t
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn year_to_secs(year: u64, is_leap: &mut bool) -> u64 {
|
fn year_to_secs(year: i64, is_leap: &mut bool) -> std::result::Result<i64, ()> {
|
||||||
if year < 100 {
|
if year < -100 {
|
||||||
/* Sorry time travelers. */
|
/* Sorry time travelers. */
|
||||||
return 0;
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if year - 2 <= 136 {
|
if year - 2 <= 136 {
|
||||||
|
@ -111,7 +111,9 @@ fn year_to_secs(year: u64, is_leap: &mut bool) -> u64 {
|
||||||
} else {
|
} else {
|
||||||
*is_leap = false;
|
*is_leap = false;
|
||||||
}
|
}
|
||||||
return 31536000 * (y - 70) + 86400 * leaps;
|
return Ok((31536000 * (y - 70) + 86400 * leaps)
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cycles = (year - 100) / 400;
|
let cycles = (year - 100) / 400;
|
||||||
|
@ -154,11 +156,14 @@ fn year_to_secs(year: u64, is_leap: &mut bool) -> u64 {
|
||||||
|
|
||||||
leaps += 97 * cycles + 24 * centuries - if *is_leap { 1 } else { 0 };
|
leaps += 97 * cycles + 24 * centuries - if *is_leap { 1 } else { 0 };
|
||||||
|
|
||||||
return (year - 100) * 31536000 + leaps * 86400 + 946684800 + 86400;
|
return Ok(match (year - 100).overflowing_mul(31536000) {
|
||||||
|
(_, true) => return Err(()),
|
||||||
|
(res, false) => res + leaps * 86400 + 946684800 + 86400,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn month_to_secs(month: usize, is_leap: bool) -> u64 {
|
fn month_to_secs(month: usize, is_leap: bool) -> i64 {
|
||||||
const SECS_THROUGH_MONTH: [u64; 12] = [
|
const SECS_THROUGH_MONTH: [i64; 12] = [
|
||||||
0,
|
0,
|
||||||
31 * 86400,
|
31 * 86400,
|
||||||
59 * 86400,
|
59 * 86400,
|
||||||
|
@ -172,7 +177,7 @@ fn month_to_secs(month: usize, is_leap: bool) -> u64 {
|
||||||
304 * 86400,
|
304 * 86400,
|
||||||
334 * 86400,
|
334 * 86400,
|
||||||
];
|
];
|
||||||
let mut t = SECS_THROUGH_MONTH[month as usize];
|
let mut t = SECS_THROUGH_MONTH[month];
|
||||||
if is_leap && month >= 2 {
|
if is_leap && month >= 2 {
|
||||||
t += 86400;
|
t += 86400;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +231,9 @@ where
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (tm_to_secs(new_tm) as i64 - tm_gmtoff) as u64;
|
return tm_to_secs(new_tm)
|
||||||
|
.map(|res| (res - tm_gmtoff) as u64)
|
||||||
|
.unwrap_or(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1052,7 +1052,7 @@ mod tests {
|
||||||
use crate::make_address;
|
use crate::make_address;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_subject() {
|
fn test_phrase() {
|
||||||
let words = b"=?iso-8859-7?B?W215Y291cnNlcy5udHVhLmdyIC0gyvXs4fTp6t4g6uHpIMri4e306ere?=
|
let words = b"=?iso-8859-7?B?W215Y291cnNlcy5udHVhLmdyIC0gyvXs4fTp6t4g6uHpIMri4e306ere?=
|
||||||
=?iso-8859-7?B?INb18+nq3l0gzd3hIMHt4erv3+358+c6IMzF0c/TIMHQz9TFy8XTzMHU?=
|
=?iso-8859-7?B?INb18+nq3l0gzd3hIMHt4erv3+358+c6IMzF0c/TIMHQz9TFy8XTzMHU?=
|
||||||
=?iso-8859-7?B?2c0gwiDUzC4gysHNLiDFzsXUwdPH0yAyMDE3LTE4OiDTx8zFydnTxw==?=";
|
=?iso-8859-7?B?2c0gwiDUzC4gysHNLiDFzsXUwdPH0yAyMDE3LTE4OiDTx8zFydnTxw==?=";
|
||||||
|
@ -1145,7 +1145,10 @@ mod tests {
|
||||||
debug!("{:?}", date(__s));
|
debug!("{:?}", date(__s));
|
||||||
assert_eq!(date(s).unwrap(), date(_s).unwrap());
|
assert_eq!(date(s).unwrap(), date(_s).unwrap());
|
||||||
assert_eq!(date(_s).unwrap(), date(__s).unwrap());
|
assert_eq!(date(_s).unwrap(), date(__s).unwrap());
|
||||||
|
let val = b"Fri, 23 Dec 0001 21:20:36 -0800 (PST)";
|
||||||
|
assert_eq!(date(val).unwrap(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_attachments() {
|
fn test_attachments() {
|
||||||
//FIXME: add file
|
//FIXME: add file
|
||||||
|
|
Loading…
Reference in New Issue