diff --git a/postgres-types/src/time_03.rs b/postgres-types/src/time_03.rs index f136fab7c..4deea663f 100644 --- a/postgres-types/src/time_03.rs +++ b/postgres-types/src/time_03.rs @@ -13,7 +13,9 @@ fn base() -> PrimitiveDateTime { impl<'a> FromSql<'a> for PrimitiveDateTime { fn from_sql(_: &Type, raw: &[u8]) -> Result> { let t = types::timestamp_from_sql(raw)?; - Ok(base() + Duration::microseconds(t)) + Ok(base() + .checked_add(Duration::microseconds(t)) + .ok_or("value too large to decode")?) } accepts!(TIMESTAMP); @@ -62,7 +64,10 @@ impl ToSql for OffsetDateTime { impl<'a> FromSql<'a> for Date { fn from_sql(_: &Type, raw: &[u8]) -> Result> { let jd = types::date_from_sql(raw)?; - Ok(base().date() + Duration::days(i64::from(jd))) + Ok(base() + .date() + .checked_add(Duration::days(i64::from(jd))) + .ok_or("value too large to decode")?) } accepts!(DATE); diff --git a/tokio-postgres/tests/test/types/time_03.rs b/tokio-postgres/tests/test/types/time_03.rs index df013c9bf..fca940a97 100644 --- a/tokio-postgres/tests/test/types/time_03.rs +++ b/tokio-postgres/tests/test/types/time_03.rs @@ -1,5 +1,11 @@ +use std::fmt; + +use postgres_types::FromSqlOwned; use time_03::{format_description, OffsetDateTime, PrimitiveDateTime}; -use tokio_postgres::types::{Date, Timestamp}; +use tokio_postgres::{ + types::{Date, Timestamp}, + Client, +}; use crate::types::test_type; @@ -147,3 +153,33 @@ async fn test_time_params() { ) .await; } + +#[tokio::test] +async fn test_special_params_without_wrapper() { + async fn assert_overflows(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 = crate::connect("user=postgres").await; + + assert_overflows::(&mut client, "'-infinity'", "timestamptz").await; + assert_overflows::(&mut client, "'infinity'", "timestamptz").await; + + assert_overflows::(&mut client, "'-infinity'", "timestamp").await; + assert_overflows::(&mut client, "'infinity'", "timestamp").await; + + assert_overflows::(&mut client, "'-infinity'", "date").await; + assert_overflows::(&mut client, "'infinity'", "date").await; +}