Properly detect overflow
This commit is contained in:
parent
6635aaf172
commit
4504f9cec8
@ -161,23 +161,23 @@ impl<W: Write> WriteMessage for W {
|
|||||||
try!(buf.write_cstr(portal));
|
try!(buf.write_cstr(portal));
|
||||||
try!(buf.write_cstr(statement));
|
try!(buf.write_cstr(statement));
|
||||||
|
|
||||||
try!(buf.write_u16::<BigEndian>(formats.len() as u16));
|
try!(buf.write_u16::<BigEndian>(try!(u16::from_usize(formats.len()))));
|
||||||
for &format in formats {
|
for &format in formats {
|
||||||
try!(buf.write_i16::<BigEndian>(format));
|
try!(buf.write_i16::<BigEndian>(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(buf.write_u16::<BigEndian>(values.len() as u16));
|
try!(buf.write_u16::<BigEndian>(try!(u16::from_usize(values.len()))));
|
||||||
for value in values {
|
for value in values {
|
||||||
match *value {
|
match *value {
|
||||||
None => try!(buf.write_i32::<BigEndian>(-1)),
|
None => try!(buf.write_i32::<BigEndian>(-1)),
|
||||||
Some(ref value) => {
|
Some(ref value) => {
|
||||||
try!(buf.write_i32::<BigEndian>(value.len() as i32));
|
try!(buf.write_i32::<BigEndian>(try!(i32::from_usize(value.len()))));
|
||||||
try!(buf.write_all(&**value));
|
try!(buf.write_all(&**value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(buf.write_u16::<BigEndian>(result_formats.len() as u16));
|
try!(buf.write_u16::<BigEndian>(try!(u16::from_usize(result_formats.len()))));
|
||||||
for &format in result_formats {
|
for &format in result_formats {
|
||||||
try!(buf.write_i16::<BigEndian>(format));
|
try!(buf.write_i16::<BigEndian>(format));
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ impl<W: Write> WriteMessage for W {
|
|||||||
ident = Some(b'P');
|
ident = Some(b'P');
|
||||||
try!(buf.write_cstr(name));
|
try!(buf.write_cstr(name));
|
||||||
try!(buf.write_cstr(query));
|
try!(buf.write_cstr(query));
|
||||||
try!(buf.write_u16::<BigEndian>(param_types.len() as u16));
|
try!(buf.write_u16::<BigEndian>(try!(u16::from_usize(param_types.len()))));
|
||||||
for &ty in param_types {
|
for &ty in param_types {
|
||||||
try!(buf.write_u32::<BigEndian>(ty));
|
try!(buf.write_u32::<BigEndian>(ty));
|
||||||
}
|
}
|
||||||
@ -246,7 +246,7 @@ impl<W: Write> WriteMessage for W {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add size of length value
|
// add size of length value
|
||||||
try!(self.write_u32::<BigEndian>((buf.len() + mem::size_of::<u32>()) as u32));
|
try!(self.write_u32::<BigEndian>(try!(u32::from_usize(buf.len() + mem::size_of::<u32>()))));
|
||||||
try!(self.write_all(&*buf));
|
try!(self.write_all(&*buf));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -407,3 +407,25 @@ fn read_row_description<R: BufRead>(buf: &mut R) -> io::Result<BackendMessage> {
|
|||||||
|
|
||||||
Ok(RowDescription { descriptions: types })
|
Ok(RowDescription { descriptions: types })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait FromUsize {
|
||||||
|
fn from_usize(x: usize) -> io::Result<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! from_usize {
|
||||||
|
($t:ty) => {
|
||||||
|
impl FromUsize for $t {
|
||||||
|
fn from_usize(x: usize) -> io::Result<$t> {
|
||||||
|
if x > <$t>::max_value() as usize {
|
||||||
|
Err(io::Error::new(io::ErrorKind::InvalidInput, "value too large to transmit"))
|
||||||
|
} else {
|
||||||
|
Ok(x as $t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_usize!(u16);
|
||||||
|
from_usize!(i32);
|
||||||
|
from_usize!(u32);
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
|
|
||||||
|
use std::error;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
|
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
|
||||||
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC};
|
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC};
|
||||||
|
|
||||||
use Result;
|
use Result;
|
||||||
|
use error::Error;
|
||||||
use types::{FromSql, ToSql, IsNull, Type, SessionInfo};
|
use types::{FromSql, ToSql, IsNull, Type, SessionInfo};
|
||||||
|
|
||||||
fn base() -> NaiveDateTime {
|
fn base() -> NaiveDateTime {
|
||||||
@ -61,8 +63,13 @@ impl FromSql for NaiveDate {
|
|||||||
|
|
||||||
impl ToSql for NaiveDate {
|
impl ToSql for NaiveDate {
|
||||||
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
|
||||||
let jd = *self - base().date();
|
let jd = (*self - base().date()).num_days();
|
||||||
try!(w.write_i32::<BigEndian>(jd.num_days() as i32));
|
if jd > i32::max_value() as i64 || jd < i32::min_value() as i64 {
|
||||||
|
let err: Box<error::Error+Sync+Send> = "value too large to transmit".into();
|
||||||
|
return Err(Error::Conversion(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(w.write_i32::<BigEndian>(jd as i32));
|
||||||
Ok(IsNull::No)
|
Ok(IsNull::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,15 +934,15 @@ impl ToSql for HashMap<String, Option<String>> {
|
|||||||
|
|
||||||
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo)
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo)
|
||||||
-> Result<IsNull> {
|
-> Result<IsNull> {
|
||||||
try!(w.write_i32::<BigEndian>(self.len() as i32));
|
try!(w.write_i32::<BigEndian>(try!(downcast(self.len()))));
|
||||||
|
|
||||||
for (key, val) in self {
|
for (key, val) in self {
|
||||||
try!(w.write_i32::<BigEndian>(key.len() as i32));
|
try!(w.write_i32::<BigEndian>(try!(downcast(key.len()))));
|
||||||
try!(w.write_all(key.as_bytes()));
|
try!(w.write_all(key.as_bytes()));
|
||||||
|
|
||||||
match *val {
|
match *val {
|
||||||
Some(ref val) => {
|
Some(ref val) => {
|
||||||
try!(w.write_i32::<BigEndian>(val.len() as i32));
|
try!(w.write_i32::<BigEndian>(try!(downcast(val.len()))));
|
||||||
try!(w.write_all(val.as_bytes()));
|
try!(w.write_all(val.as_bytes()));
|
||||||
}
|
}
|
||||||
None => try!(w.write_i32::<BigEndian>(-1))
|
None => try!(w.write_i32::<BigEndian>(-1))
|
||||||
@ -959,3 +959,12 @@ impl ToSql for HashMap<String, Option<String>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn downcast(len: usize) -> Result<i32> {
|
||||||
|
if len > i32::max_value() as usize {
|
||||||
|
let err: Box<error::Error+Sync+Send> = "value too large to transmit".into();
|
||||||
|
Err(Error::Conversion(err))
|
||||||
|
} else {
|
||||||
|
Ok(len as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ use byteorder::{WriteBytesExt, BigEndian};
|
|||||||
|
|
||||||
use Result;
|
use Result;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use types::{Type, ToSql, Kind, IsNull, SessionInfo};
|
use types::{Type, ToSql, Kind, IsNull, SessionInfo, downcast};
|
||||||
|
|
||||||
/// An adapter type mapping slices to Postgres arrays.
|
/// An adapter type mapping slices to Postgres arrays.
|
||||||
///
|
///
|
||||||
@ -48,14 +48,14 @@ impl<'a, T: 'a + ToSql> ToSql for Slice<'a, T> {
|
|||||||
try!(w.write_i32::<BigEndian>(1)); // has nulls
|
try!(w.write_i32::<BigEndian>(1)); // has nulls
|
||||||
try!(w.write_u32::<BigEndian>(member_type.oid()));
|
try!(w.write_u32::<BigEndian>(member_type.oid()));
|
||||||
|
|
||||||
try!(w.write_i32::<BigEndian>(self.0.len() as i32));
|
try!(w.write_i32::<BigEndian>(try!(downcast(self.0.len()))));
|
||||||
try!(w.write_i32::<BigEndian>(0)); // index offset
|
try!(w.write_i32::<BigEndian>(0)); // index offset
|
||||||
|
|
||||||
let mut inner_buf = vec![];
|
let mut inner_buf = vec![];
|
||||||
for e in self.0 {
|
for e in self.0 {
|
||||||
match try!(e.to_sql(&member_type, &mut inner_buf, ctx)) {
|
match try!(e.to_sql(&member_type, &mut inner_buf, ctx)) {
|
||||||
IsNull::No => {
|
IsNull::No => {
|
||||||
try!(w.write_i32::<BigEndian>(inner_buf.len() as i32));
|
try!(w.write_i32::<BigEndian>(try!(downcast(inner_buf.len()))));
|
||||||
try!(w.write_all(&inner_buf));
|
try!(w.write_all(&inner_buf));
|
||||||
}
|
}
|
||||||
IsNull::Yes => try!(w.write_i32::<BigEndian>(-1)),
|
IsNull::Yes => try!(w.write_i32::<BigEndian>(-1)),
|
||||||
|
Loading…
Reference in New Issue
Block a user