Merge pull request #641 from benesch/infinity-overflow

Use checked arithmetic when decoding into chrono types
This commit is contained in:
Steven Fackler 2020-07-31 09:30:31 -04:00 committed by GitHub
commit 286b9dcd0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 3 deletions

View File

@ -12,7 +12,9 @@ fn base() -> NaiveDateTime {
impl<'a> FromSql<'a> for NaiveDateTime {
fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveDateTime, Box<dyn Error + Sync + Send>> {
let t = types::timestamp_from_sql(raw)?;
Ok(base() + Duration::microseconds(t))
base()
.checked_add_signed(Duration::microseconds(t))
.ok_or_else(|| "value too large to decode".into())
}
accepts!(TIMESTAMP);
@ -104,7 +106,10 @@ impl ToSql for DateTime<FixedOffset> {
impl<'a> FromSql<'a> for NaiveDate {
fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveDate, Box<dyn Error + Sync + Send>> {
let jd = types::date_from_sql(raw)?;
Ok(base().date() + Duration::days(i64::from(jd)))
base()
.date()
.checked_add_signed(Duration::days(i64::from(jd)))
.ok_or_else(|| "value too large to decode".into())
}
accepts!(DATE);

View File

@ -1,6 +1,9 @@
use chrono_04::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
use tokio_postgres::types::{Date, Timestamp};
use std::fmt;
use tokio_postgres::types::{Date, FromSqlOwned, Timestamp};
use tokio_postgres::Client;
use crate::connect;
use crate::types::test_type;
#[tokio::test]
@ -153,3 +156,33 @@ async fn test_time_params() {
)
.await;
}
#[tokio::test]
async fn test_special_params_without_wrapper() {
async fn assert_overflows<T>(client: &mut Client, val: &str, sql_type: &str)
where
T: FromSqlOwned + fmt::Debug,
{
let err = client
.query_one(&*format!("SELECT {}::{}", val, sql_type), &[])
.await
.unwrap()
.try_get::<_, T>(0)
.unwrap_err();
assert_eq!(
err.to_string(),
"error deserializing column 0: value too large to decode"
);
}
let mut client = connect("user=postgres").await;
assert_overflows::<DateTime<Utc>>(&mut client, "'-infinity'", "timestamptz").await;
assert_overflows::<DateTime<Utc>>(&mut client, "'infinity'", "timestamptz").await;
assert_overflows::<NaiveDateTime>(&mut client, "'-infinity'", "timestamp").await;
assert_overflows::<NaiveDateTime>(&mut client, "'infinity'", "timestamp").await;
assert_overflows::<NaiveDate>(&mut client, "'-infinity'", "date").await;
assert_overflows::<NaiveDate>(&mut client, "'infinity'", "date").await;
}