Skip to content

Commit

Permalink
fix: audit PgValueRef::get() and usage sites for bad casts
Browse files Browse the repository at this point in the history
  • Loading branch information
abonander committed Aug 16, 2024
1 parent 63349de commit dd92def
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 19 deletions.
13 changes: 7 additions & 6 deletions sqlx-postgres/src/types/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,21 +242,22 @@ where
// length of the array axis
let len = buf.get_i32();

let len = usize::try_from(len)
.map_err(|_| format!("overflow converting array len ({len}) to usize"))?;

// the lower bound, we only support arrays starting from "1"
let lower = buf.get_i32();

if lower != 1 {
return Err(format!("encountered an array with a lower bound of {lower} in the first dimension; only arrays starting at one are supported").into());
}

let mut elements = Vec::with_capacity(len as usize);
let mut elements = Vec::with_capacity(len);

for _ in 0..len {
elements.push(T::decode(PgValueRef::get(
&mut buf,
format,
element_type_info.clone(),
))?)
let value_ref = PgValueRef::get(&mut buf, format, element_type_info.clone())?;

elements.push(T::decode(value_ref)?);
}

Ok(elements)
Expand Down
4 changes: 2 additions & 2 deletions sqlx-postgres/src/types/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ where

if !flags.contains(RangeFlags::LB_INF) {
let value =
T::decode(PgValueRef::get(&mut buf, value.format, element_ty.clone()))?;
T::decode(PgValueRef::get(&mut buf, value.format, element_ty.clone())?)?;

start = if flags.contains(RangeFlags::LB_INC) {
Bound::Included(value)
Expand All @@ -361,7 +361,7 @@ where

if !flags.contains(RangeFlags::UB_INF) {
let value =
T::decode(PgValueRef::get(&mut buf, value.format, element_ty.clone()))?;
T::decode(PgValueRef::get(&mut buf, value.format, element_ty.clone())?)?;

end = if flags.contains(RangeFlags::UB_INC) {
Bound::Included(value)
Expand Down
2 changes: 1 addition & 1 deletion sqlx-postgres/src/types/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl<'r> PgRecordDecoder<'r> {

self.ind += 1;

T::decode(PgValueRef::get(&mut self.buf, self.fmt, element_type))
T::decode(PgValueRef::get(&mut self.buf, self.fmt, element_type)?)
}

PgValueFormat::Text => {
Expand Down
26 changes: 16 additions & 10 deletions sqlx-postgres/src/value.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::error::{BoxDynError, UnexpectedNullError};
use crate::{PgTypeInfo, Postgres};
use sqlx_core::bytes::{Buf, Bytes};
pub(crate) use sqlx_core::value::{Value, ValueRef};
use std::borrow::Cow;
use std::str::from_utf8;

pub(crate) use sqlx_core::value::{Value, ValueRef};

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
pub enum PgValueFormat {
Expand All @@ -31,24 +30,31 @@ pub struct PgValue {
}

impl<'r> PgValueRef<'r> {
pub(crate) fn get(buf: &mut &'r [u8], format: PgValueFormat, ty: PgTypeInfo) -> Self {
let mut element_len = buf.get_i32();
pub(crate) fn get(
buf: &mut &'r [u8],
format: PgValueFormat,
ty: PgTypeInfo,
) -> Result<Self, String> {
let element_len = buf.get_i32();

let element_val = if element_len == -1 {
element_len = 0;
None
} else {
Some(&buf[..(element_len as usize)])
};
let element_len: usize = element_len
.try_into()
.map_err(|_| format!("overflow converting element_len ({element_len}) to usize"))?;

buf.advance(element_len as usize);
let val = &buf[..element_len];
buf.advance(element_len);
Some(val)
};

PgValueRef {
Ok(PgValueRef {
value: element_val,
row: None,
type_info: ty,
format,
}
})
}

pub fn format(&self) -> PgValueFormat {
Expand Down

0 comments on commit dd92def

Please sign in to comment.