Skip to content

Commit 286b9dc

Browse files
authored
Merge pull request #641 from benesch/infinity-overflow
Use checked arithmetic when decoding into chrono types
2 parents bc682b3 + a30f0b6 commit 286b9dc

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

postgres-types/src/chrono_04.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ fn base() -> NaiveDateTime {
1212
impl<'a> FromSql<'a> for NaiveDateTime {
1313
fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveDateTime, Box<dyn Error + Sync + Send>> {
1414
let t = types::timestamp_from_sql(raw)?;
15-
Ok(base() + Duration::microseconds(t))
15+
base()
16+
.checked_add_signed(Duration::microseconds(t))
17+
.ok_or_else(|| "value too large to decode".into())
1618
}
1719

1820
accepts!(TIMESTAMP);
@@ -104,7 +106,10 @@ impl ToSql for DateTime<FixedOffset> {
104106
impl<'a> FromSql<'a> for NaiveDate {
105107
fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveDate, Box<dyn Error + Sync + Send>> {
106108
let jd = types::date_from_sql(raw)?;
107-
Ok(base().date() + Duration::days(i64::from(jd)))
109+
base()
110+
.date()
111+
.checked_add_signed(Duration::days(i64::from(jd)))
112+
.ok_or_else(|| "value too large to decode".into())
108113
}
109114

110115
accepts!(DATE);

tokio-postgres/tests/test/types/chrono_04.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use chrono_04::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
2-
use tokio_postgres::types::{Date, Timestamp};
2+
use std::fmt;
3+
use tokio_postgres::types::{Date, FromSqlOwned, Timestamp};
4+
use tokio_postgres::Client;
35

6+
use crate::connect;
47
use crate::types::test_type;
58

69
#[tokio::test]
@@ -153,3 +156,33 @@ async fn test_time_params() {
153156
)
154157
.await;
155158
}
159+
160+
#[tokio::test]
161+
async fn test_special_params_without_wrapper() {
162+
async fn assert_overflows<T>(client: &mut Client, val: &str, sql_type: &str)
163+
where
164+
T: FromSqlOwned + fmt::Debug,
165+
{
166+
let err = client
167+
.query_one(&*format!("SELECT {}::{}", val, sql_type), &[])
168+
.await
169+
.unwrap()
170+
.try_get::<_, T>(0)
171+
.unwrap_err();
172+
assert_eq!(
173+
err.to_string(),
174+
"error deserializing column 0: value too large to decode"
175+
);
176+
}
177+
178+
let mut client = connect("user=postgres").await;
179+
180+
assert_overflows::<DateTime<Utc>>(&mut client, "'-infinity'", "timestamptz").await;
181+
assert_overflows::<DateTime<Utc>>(&mut client, "'infinity'", "timestamptz").await;
182+
183+
assert_overflows::<NaiveDateTime>(&mut client, "'-infinity'", "timestamp").await;
184+
assert_overflows::<NaiveDateTime>(&mut client, "'infinity'", "timestamp").await;
185+
186+
assert_overflows::<NaiveDate>(&mut client, "'-infinity'", "date").await;
187+
assert_overflows::<NaiveDate>(&mut client, "'infinity'", "date").await;
188+
}

0 commit comments

Comments
 (0)