summaryrefslogtreecommitdiffstats
path: root/melib
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2020-05-06 18:46:38 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2020-05-06 18:46:38 +0300
commit5d07a5147bb6563b2e945b046f3ba568a256e933 (patch)
tree65f299c78e8435e3765c17f662bfd5a46c5490cb /melib
parent330134af5a9d180093828405fad26d3ffd1696a8 (diff)
datetime: fix panic on invalid cstr conversion
Diffstat (limited to 'melib')
-rw-r--r--melib/src/addressbook/vcard.rs3
-rw-r--r--melib/src/backends/jmap/objects/email.rs3
-rw-r--r--melib/src/datetime.rs51
-rw-r--r--melib/src/email/parser.rs2
-rw-r--r--melib/src/error.rs7
5 files changed, 39 insertions, 27 deletions
diff --git a/melib/src/addressbook/vcard.rs b/melib/src/addressbook/vcard.rs
index bc57e739..ac06215c 100644
--- a/melib/src/addressbook/vcard.rs
+++ b/melib/src/addressbook/vcard.rs
@@ -201,7 +201,8 @@ impl<V: VCardVersion> TryInto<Card> for VCard<V> {
T102200Z
T102200-0800
*/
- card.birthday = crate::datetime::timestamp_from_string(val.value.as_str(), "%Y%m%d");
+ card.birthday = crate::datetime::timestamp_from_string(val.value.as_str(), "%Y%m%d")
+ .unwrap_or_default();
}
if let Some(val) = self.0.remove("EMAIL") {
card.set_email(val.value);
diff --git a/melib/src/backends/jmap/objects/email.rs b/melib/src/backends/jmap/objects/email.rs
index f303889c..ab5bbd17 100644
--- a/melib/src/backends/jmap/objects/email.rs
+++ b/melib/src/backends/jmap/objects/email.rs
@@ -235,7 +235,8 @@ impl std::convert::From<EmailObject> for crate::Envelope {
env.set_datetime(d);
}
if let Some(ref mut sent_at) = t.sent_at {
- let unix = crate::datetime::rfc3339_to_timestamp(sent_at.as_bytes().to_vec());
+ let unix =
+ crate::datetime::rfc3339_to_timestamp(sent_at.as_bytes().to_vec()).unwrap_or(0);
env.set_datetime(unix);
env.set_date(std::mem::replace(sent_at, String::new()).as_bytes());
}
diff --git a/melib/src/datetime.rs b/melib/src/datetime.rs
index 33571db5..643b3107 100644
--- a/melib/src/datetime.rs
+++ b/melib/src/datetime.rs
@@ -22,6 +22,8 @@
use std::convert::TryInto;
use std::ffi::{CStr, CString};
+use crate::error::Result;
+
pub type UnixTimestamp = u64;
use libc::{timeval, timezone};
@@ -53,25 +55,26 @@ pub fn timestamp_to_string(timestamp: UnixTimestamp, fmt: Option<&str>) -> Strin
let i: i64 = timestamp.try_into().unwrap_or(0);
localtime_r(&i as *const i64, &mut new_tm as *mut ::libc::tm);
}
- let fmt = fmt.map(|slice| CString::new(slice).unwrap());
+ let fmt = fmt
+ .map(|slice| CString::new(slice))
+ .map(|res| res.ok())
+ .and_then(|opt| opt);
let format: &CStr = if let Some(ref s) = fmt {
&s
} else {
unsafe { CStr::from_bytes_with_nul_unchecked(b"%a, %d %b %Y %T %z\0") }
};
- let s: CString;
- unsafe {
- let mut vec: [u8; 256] = [0; 256];
- let ret = strftime(
+ let mut vec: [u8; 256] = [0; 256];
+ let ret = unsafe {
+ strftime(
vec.as_mut_ptr() as *mut _,
256,
format.as_ptr(),
&new_tm as *const _,
- );
- s = CString::new(&vec[0..ret]).unwrap();
- }
+ )
+ };
- s.to_string_lossy().to_string()
+ String::from_utf8_lossy(&vec[0..ret]).into_owned()
}
fn tm_to_secs(tm: ::libc::tm) -> std::result::Result<i64, ()> {
@@ -184,11 +187,11 @@ fn month_to_secs(month: usize, is_leap: bool) -> i64 {
return t;
}
-pub fn rfc822_to_timestamp<T>(s: T) -> UnixTimestamp
+pub fn rfc822_to_timestamp<T>(s: T) -> Result<UnixTimestamp>
where
T: Into<Vec<u8>>,
{
- let s = CString::new(s).unwrap();
+ let s = CString::new(s)?;
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
for fmt in &[
&b"%a, %e %h %Y %H:%M:%S \0"[..],
@@ -231,19 +234,19 @@ where
0
}
};
- return tm_to_secs(new_tm)
+ return Ok(tm_to_secs(new_tm)
.map(|res| (res - tm_gmtoff) as u64)
- .unwrap_or(0);
+ .unwrap_or(0));
}
}
- return 0;
+ return Ok(0);
}
-pub fn rfc3339_to_timestamp<T>(s: T) -> UnixTimestamp
+pub fn rfc3339_to_timestamp<T>(s: T) -> Result<UnixTimestamp>
where
T: Into<Vec<u8>>,
{
- let s = CString::new(s).unwrap();
+ let s = CString::new(s)?;
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
for fmt in &[&b"%Y-%m-%dT%H:%M:%S\0"[..], &b"%Y-%m-%d\0"[..]] {
unsafe {
@@ -284,31 +287,31 @@ where
0
}
};
- return tm_to_secs(new_tm)
+ return Ok(tm_to_secs(new_tm)
.map(|res| (res - tm_gmtoff) as u64)
- .unwrap_or(0);
+ .unwrap_or(0));
}
}
- return 0;
+ return Ok(0);
}
// FIXME: Handle non-local timezone?
-pub fn timestamp_from_string<T>(s: T, fmt: &str) -> Option<UnixTimestamp>
+pub fn timestamp_from_string<T>(s: T, fmt: &str) -> Result<Option<UnixTimestamp>>
where
T: Into<Vec<u8>>,
{
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
- let fmt = CString::new(fmt).unwrap();
+ let fmt = CString::new(fmt)?;
unsafe {
let ret = strptime(
- CString::new(s).unwrap().as_ptr(),
+ CString::new(s)?.as_ptr(),
fmt.as_ptr(),
&mut new_tm as *mut _,
);
if ret.is_null() {
- return None;
+ return Ok(None);
}
- return Some(mktime(&new_tm as *const _) as u64);
+ return Ok(Some(mktime(&new_tm as *const _) as u64));
}
}
diff --git a/melib/src/email/parser.rs b/melib/src/email/parser.rs
index 849440cd..3240d5c6 100644
--- a/melib/src/email/parser.rs
+++ b/melib/src/email/parser.rs
@@ -664,7 +664,7 @@ pub fn date(input: &[u8]) -> Result<UnixTimestamp> {
parsed_result[pos] = b'+';
}
- Ok(crate::datetime::rfc822_to_timestamp(parsed_result.trim()))
+ crate::datetime::rfc822_to_timestamp(parsed_result.trim())
}
named!(pub message_id<&[u8]>,
diff --git a/melib/src/error.rs b/melib/src/error.rs
index b66fdb63..984d25d2 100644
--- a/melib/src/error.rs
+++ b/melib/src/error.rs
@@ -167,6 +167,13 @@ impl From<serde_json::error::Error> for MeliError {
}
}
+impl From<std::ffi::NulError> for MeliError {
+ #[inline]
+ fn from(kind: std::ffi::NulError) -> MeliError {
+ MeliError::new(format!("{}", kind))
+ }
+}
+
impl From<&str> for MeliError {
#[inline]
fn from(kind: &str) -> MeliError {