datetime: fix panic on invalid cstr conversion
parent
330134af5a
commit
5d07a5147b
|
@ -201,7 +201,8 @@ impl<V: VCardVersion> TryInto<Card> for VCard<V> {
|
||||||
T102200Z
|
T102200Z
|
||||||
T102200-0800
|
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") {
|
if let Some(val) = self.0.remove("EMAIL") {
|
||||||
card.set_email(val.value);
|
card.set_email(val.value);
|
||||||
|
|
|
@ -235,7 +235,8 @@ impl std::convert::From<EmailObject> for crate::Envelope {
|
||||||
env.set_datetime(d);
|
env.set_datetime(d);
|
||||||
}
|
}
|
||||||
if let Some(ref mut sent_at) = t.sent_at {
|
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_datetime(unix);
|
||||||
env.set_date(std::mem::replace(sent_at, String::new()).as_bytes());
|
env.set_date(std::mem::replace(sent_at, String::new()).as_bytes());
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
pub type UnixTimestamp = u64;
|
pub type UnixTimestamp = u64;
|
||||||
|
|
||||||
use libc::{timeval, timezone};
|
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);
|
let i: i64 = timestamp.try_into().unwrap_or(0);
|
||||||
localtime_r(&i as *const i64, &mut new_tm as *mut ::libc::tm);
|
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 {
|
let format: &CStr = if let Some(ref s) = fmt {
|
||||||
&s
|
&s
|
||||||
} else {
|
} else {
|
||||||
unsafe { CStr::from_bytes_with_nul_unchecked(b"%a, %d %b %Y %T %z\0") }
|
unsafe { CStr::from_bytes_with_nul_unchecked(b"%a, %d %b %Y %T %z\0") }
|
||||||
};
|
};
|
||||||
let s: CString;
|
let mut vec: [u8; 256] = [0; 256];
|
||||||
unsafe {
|
let ret = unsafe {
|
||||||
let mut vec: [u8; 256] = [0; 256];
|
strftime(
|
||||||
let ret = strftime(
|
|
||||||
vec.as_mut_ptr() as *mut _,
|
vec.as_mut_ptr() as *mut _,
|
||||||
256,
|
256,
|
||||||
format.as_ptr(),
|
format.as_ptr(),
|
||||||
&new_tm as *const _,
|
&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, ()> {
|
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;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rfc822_to_timestamp<T>(s: T) -> UnixTimestamp
|
pub fn rfc822_to_timestamp<T>(s: T) -> Result<UnixTimestamp>
|
||||||
where
|
where
|
||||||
T: Into<Vec<u8>>,
|
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() };
|
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
|
||||||
for fmt in &[
|
for fmt in &[
|
||||||
&b"%a, %e %h %Y %H:%M:%S \0"[..],
|
&b"%a, %e %h %Y %H:%M:%S \0"[..],
|
||||||
|
@ -231,19 +234,19 @@ where
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return tm_to_secs(new_tm)
|
return Ok(tm_to_secs(new_tm)
|
||||||
.map(|res| (res - tm_gmtoff) as u64)
|
.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
|
where
|
||||||
T: Into<Vec<u8>>,
|
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() };
|
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"[..]] {
|
for fmt in &[&b"%Y-%m-%dT%H:%M:%S\0"[..], &b"%Y-%m-%d\0"[..]] {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -284,31 +287,31 @@ where
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return tm_to_secs(new_tm)
|
return Ok(tm_to_secs(new_tm)
|
||||||
.map(|res| (res - tm_gmtoff) as u64)
|
.map(|res| (res - tm_gmtoff) as u64)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Handle non-local timezone?
|
// 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
|
where
|
||||||
T: Into<Vec<u8>>,
|
T: Into<Vec<u8>>,
|
||||||
{
|
{
|
||||||
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
|
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
|
||||||
let fmt = CString::new(fmt).unwrap();
|
let fmt = CString::new(fmt)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let ret = strptime(
|
let ret = strptime(
|
||||||
CString::new(s).unwrap().as_ptr(),
|
CString::new(s)?.as_ptr(),
|
||||||
fmt.as_ptr(),
|
fmt.as_ptr(),
|
||||||
&mut new_tm as *mut _,
|
&mut new_tm as *mut _,
|
||||||
);
|
);
|
||||||
if ret.is_null() {
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -664,7 +664,7 @@ pub fn date(input: &[u8]) -> Result<UnixTimestamp> {
|
||||||
parsed_result[pos] = b'+';
|
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]>,
|
named!(pub message_id<&[u8]>,
|
||||||
|
|
|
@ -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 {
|
impl From<&str> for MeliError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(kind: &str) -> MeliError {
|
fn from(kind: &str) -> MeliError {
|
||||||
|
|
Loading…
Reference in New Issue