Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always panic if len of varlena exceeds the maximum #1894

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions pgrx/src/datum/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,12 @@ impl_into_datum_c_str!(&CStr);
impl<'a> IntoDatum for &'a [u8] {
/// # Panics
///
/// This function will panic if the string being converted to a datum is longer than a `u32`.
/// This function will panic if the string being converted to a datum
// is longer than 1 GiB including 4 bytes used for a header.
#[inline]
fn into_datum(self) -> Option<pg_sys::Datum> {
let len = pg_sys::VARHDRSZ + self.len();
let len = self.len().saturating_add(pg_sys::VARHDRSZ);
assert!(len < (u32::MAX as usize >> 2));
unsafe {
// SAFETY: palloc gives us a valid pointer and if there's not enough memory it'll raise an error
let varlena = pg_sys::palloc(len) as *mut pg_sys::varlena;
Expand All @@ -351,10 +353,9 @@ impl<'a> IntoDatum for &'a [u8] {
&mut varlena.cast::<pg_sys::varattrib_4b>().as_mut().unwrap_unchecked().va_4byte;

// This is the same as Postgres' `#define SET_VARSIZE_4B` (which have over in
// `pgrx/src/varlena.rs`), however we're asserting that the input string isn't too big
// for a Postgres varlena, since it's limited to 32bits -- in reality it's about half
// that length, but this is good enough
debug_assert!(len < (u32::MAX as usize >> 2));
// `pgrx/src/varlena.rs`), however we're asserting above that the input string
// isn't too big for a Postgres varlena, since it's limited to 32 bits and,
// in reality, it's a quarter that length, but this is good enough
set_varsize_4b(varlena, len as i32);

// SAFETY: src and dest pointers are valid, exactly `self.len()` bytes long,
Expand Down
2 changes: 1 addition & 1 deletion pgrx/src/varlena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use core::{ops::DerefMut, slice, str};
/// # Safety
///
/// The caller asserts the specified `ptr` really is a non-null, palloc'd [`pg_sys::varlena`] pointer
/// that is aligned to 4 bytes.
/// that is aligned to 4 bytes, and that the `len` is a half of [`i32::MAX`]
#[inline(always)]
pub unsafe fn set_varsize_4b(ptr: *mut pg_sys::varlena, len: i32) {
// #define SET_VARSIZE_4B(PTR,len) \
Expand Down
Loading