8000 Use fallible Vec allocation when the capacity comes from input data. by afranchuk · Pull Request #246 · rust-minidump/minidump-writer · GitHub
[go: up one dir, main page]

Skip to content
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
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub mod module_reader;
pub mod process_reader;

mod serializers;
mod vec_extension;

/// Re-export of crash-context
pub use ::crash_context;
5 changes: 4 additions & 1 deletion src/linux/process_inspection/process_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::{
maps_reader::{MappingInfo, MapsReaderError},
};
use crate::module_reader::ProcessModuleMemoryReader;
use crate::vec_extension::*;

use plain::Plain;

Expand Down Expand Up @@ -105,7 +106,7 @@ impl<'a> ProcessReader<'a> {
mut address: usize,
count: usize,
) -> Result<Vec<T>, CopyFromProcessError> {
let mut v = Vec::with_capacity(count);
let mut v = vec_with_capacity(count)?;
for _ in 0..count {
v.push(self.read_pod(address)?);
address += std::mem::size_of::<T>();
Expand Down Expand Up @@ -182,6 +183,8 @@ pub enum CopyFromProcessError {
Backend(Error),
#[error("an invalid argument was passed")]
InvalidArgument,
#[error("failed to pre-allocate memory")]
CapacityError(#[from] TryReserveError),
}

#[derive(Debug, thiserror::Error, serde::Serialize)]
Expand Down
7 changes: 5 additions & 2 deletions src/mac/module_reader.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::module_reader::{ModuleMemoryReadError, ProcessModuleMemoryReader};
use crate::serializers::*;
use crate::vec_extension::*;
use goblin::container::{Container, Ctx, Endian};
use goblin::mach::{
self,
Expand Down Expand Up @@ -34,6 +35,8 @@ pub enum ModuleReaderError {
),
#[error("failed to derive parsing context from MachO memory")]
MissingCtx,
#[error("failed to pre-allocate memory")]
AllocError(#[from] TryReserveError),
}

macro_rules! read_scroll {
Expand All @@ -47,7 +50,7 @@ macro_rules! read_scroll {
macro_rules! read_scroll_array {
( $T:ty , $mem:expr , $offset:expr , $count:expr , $ctx:expr ) => {{
let bytes = $mem.read($offset, (<$T>::size_with(&$ctx) * $count) as u64)?;
let mut vals = Vec::with_capacity($count);
let mut vals = vec_with_capacity($count)?;
let mut offset = 0;
for _ in 0..$count {
let (value, bytes_read) = <$T>::try_from_ctx(&bytes[offset..], $ctx)?;
Expand Down Expand Up @@ -79,7 +82,7 @@ impl ProcessModuleMemoryReader<'_> {
Error: From<ModuleMemoryReadError>,
{
let bytes = self.read(offset, (T::size_with(&ctx) * count) as u64)?;
let mut vals = Vec::with_capacity(count);
let mut vals = vec_with_capacity(count)?;
let mut offset = 0;
for _ in 0..count {
let (value, bytes_read) = match T::try_from_ctx(&bytes[offset..], ctx) {
Expand Down
20 changes: 12 additions & 8 deletions src/mac/process_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use {
crate::module_reader::ProcessModuleMemoryReader,
crate::{module_reader::ProcessModuleMemoryReader, vec_extension::TryReserveError},
mach2::{
kern_return::KERN_SUCCESS,
task::task_info,
Expand Down Expand Up @@ -57,12 +57,16 @@ struct ImageInfo {
}

#[derive(Debug, thiserror::Error, serde::Serialize)]
#[error("Copy from process {child} failed (source {src}, length: {length})")]
pub struct CopyFromProcessError {
pub child: ProcessHandle,
pub src: usize,
pub length: usize,
pub kern_return: mach2::kern_return::kern_return_t,
pub enum CopyFromProcessError {
#[error("Copy from process {child} failed (source {src}, length: {length})")]
ReadError {
child: ProcessHandle,
src: usize,
length: usize,
kern_return: mach2::kern_return::kern_return_t,
},
#[error("failed to pre-allocate memory")]
AllocError(#[from] TryReserveError),
}

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -100,7 +104,7 @@ impl ProcessReader<'_> {
if res == KERN_SUCCESS {
Ok(size as usize)
} else {
Err(CopyFromProcessError {
Err(CopyFromProcessError::ReadError {
child: self.process,
src,
length: dst.len(),
Expand Down
3 changes: 2 additions & 1 deletion src/process_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub use crate::windows::process_reader::*;
#[cfg(target_os = "macos")]
pub use crate::mac::process_reader::*;

use crate::vec_extension::vec_with_capacity;
use std::{ffi::CString, mem::MaybeUninit};

impl ProcessReader<'_> {
Expand Down Expand Up @@ -123,7 +124,7 @@ impl ProcessReader<'_> {
src: usize,
num: usize,
) -> Result<Vec<MaybeUninit<T>>, CopyFromProcessError> {
let mut v = Vec::with_capacity(num);
let mut v = vec_with_capacity(num)?;
for _ in 0..num {
v.push(MaybeUninit::<T>::uninit());
}
Expand Down
18 changes: 18 additions & 0 deletions src/vec_extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! Vec extension functions/methods.

/// We need a TryReserveError that is serializable, so we create one here.
#[derive(Debug, thiserror::Error, serde::Serialize)]
#[error("{}", .0)]
pub struct TryReserveError(String);

impl From<std::collections::TryReserveError> for TryReserveError {
fn from(value: std::collections::TryReserveError) -> Self {
Self(value.to_string())
}
}

pub fn vec_with_capacity<T>(capacity: usize) -> Result<Vec<T>, TryReserveError> {
let mut v = Vec::new();
v.try_reserve_exact(capacity)?;
Ok(v)
}
25 changes: 16 additions & 9 deletions src/windows/process_reader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use {
super::ffi::{self, HMODULE},
crate::{module_reader::ProcessModuleMemoryReader, serializers::serialize_io_error},
crate::{
module_reader::ProcessModuleMemoryReader, serializers::serialize_io_error,
vec_extension::TryReserveError,
},
std::{
convert::TryInto,
ffi::OsString,
AD4E Expand All @@ -18,13 +21,17 @@ pub struct ProcessReader<'a> {
}

#[derive(Debug, thiserror::Error, serde::Serialize)]
#[error("Copy from process {child} failed (source {src}, length: {length})")]
pub struct CopyFromProcessError {
pub child: ProcessHandle,
pub src: usize,
pub length: usize,
#[serde(serialize_with = "serialize_io_error")]
pub error: std::io::Error,
pub enum CopyFromProcessError {
#[error("Copy from process {child} failed (source {src}, length: {length})")]
ReadError {
child: ProcessHandle,
src: usize,
length: usize,
#[serde(serialize_with = "serialize_io_error")]
error: std::io::Error,
},
#[error("failed to pre-allocate memory")]
AllocError(#[from] TryReserveError),
}

#[derive(Debug, thiserror::Error, serde::Serialize)]
Expand Down Expand Up @@ -60,7 +67,7 @@ impl ProcessReader<'_> {
if res != ffi::FALSE {
Ok(size)
} else {
Err(CopyFromProcessError {
Err(CopyFromProcessError::ReadError {
child: self.process,
src,
length: dst.len(),
Expand Down
Loading
0