Skip to content

Commit 9650d64

Browse files
authored
pod: add slice_from_all_bytes{_mut} (#672)
Also convert some code to use it.
1 parent 9398058 commit 9650d64

File tree

4 files changed

+63
-42
lines changed

4 files changed

+63
-42
lines changed

Diff for: src/pod.rs

+46-6
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ type Result<T> = result::Result<T, ()>;
2121
/// - have no padding
2222
pub unsafe trait Pod: Copy + 'static {}
2323

24-
/// Cast a byte slice to a `Pod` type.
24+
/// Cast the head of a byte slice to a `Pod` type.
2525
///
26-
/// Returns the type and the tail of the slice.
26+
/// Returns the type and the tail of the byte slice.
27+
///
28+
/// Returns an error if the byte slice is too short or the alignment is invalid.
2729
#[inline]
2830
pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> {
2931
let size = mem::size_of::<T>();
@@ -39,9 +41,11 @@ pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> {
3941
Ok((val, tail))
4042
}
4143

42-
/// Cast a mutable byte slice to a `Pod` type.
44+
/// Cast the head of a mutable byte slice to a `Pod` type.
45+
///
46+
/// Returns the type and the tail of the byte slice.
4347
///
44-
/// Returns the type and the tail of the slice.
48+
/// Returns an error if the byte slice is too short or the alignment is invalid.
4549
#[inline]
4650
pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> {
4751
let size = mem::size_of::<T>();
@@ -60,9 +64,11 @@ pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> {
6064
Ok((val, tail))
6165
}
6266

63-
/// Cast a byte slice to a slice of a `Pod` type.
67+
/// Cast the head of a byte slice to a slice of a `Pod` type.
6468
///
6569
/// Returns the type slice and the tail of the byte slice.
70+
///
71+
/// Returns an error if the byte slice is too short or the alignment is invalid.
6672
#[inline]
6773
pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> {
6874
let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
@@ -78,9 +84,11 @@ pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8
7884
Ok((slice, tail))
7985
}
8086

81-
/// Cast a mutable byte slice to a slice of a `Pod` type.
87+
/// Cast the head of a mutable byte slice to a slice of a `Pod` type.
8288
///
8389
/// Returns the type slice and the tail of the byte slice.
90+
///
91+
/// Returns an error if the byte slice is too short or the alignment is invalid.
8492
#[inline]
8593
pub fn slice_from_bytes_mut<T: Pod>(
8694
data: &mut [u8],
@@ -102,6 +110,38 @@ pub fn slice_from_bytes_mut<T: Pod>(
102110
Ok((slice, tail))
103111
}
104112

113+
/// Cast all of a byte slice to a slice of a `Pod` type.
114+
///
115+
/// Returns the type slice.
116+
///
117+
/// Returns an error if the size of the byte slice is not an exact multiple
118+
/// of the type size, or the alignment is invalid.
119+
#[inline]
120+
pub fn slice_from_all_bytes<T: Pod>(data: &[u8]) -> Result<&[T]> {
121+
let count = data.len() / mem::size_of::<T>();
122+
let (slice, tail) = slice_from_bytes(data, count)?;
123+
if !tail.is_empty() {
124+
return Err(());
125+
}
126+
Ok(slice)
127+
}
128+
129+
/// Cast all of a byte slice to a slice of a `Pod` type.
130+
///
131+
/// Returns the type slice.
132+
///
133+
/// Returns an error if the size of the byte slice is not an exact multiple
134+
/// of the type size, or the alignment is invalid.
135+
#[inline]
136+
pub fn slice_from_all_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<&mut [T]> {
137+
let count = data.len() / mem::size_of::<T>();
138+
let (slice, tail) = slice_from_bytes_mut(data, count)?;
139+
if !tail.is_empty() {
140+
return Err(());
141+
}
142+
Ok(slice)
143+
}
144+
105145
/// Cast a `Pod` type to a byte slice.
106146
#[inline]
107147
pub fn bytes_of<T: Pod>(val: &T) -> &[u8] {

Diff for: src/read/elf/section.rs

+10-19
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use core::fmt::Debug;
2-
use core::{iter, mem, slice, str};
2+
use core::{iter, slice, str};
33

44
use crate::elf;
55
use crate::endian::{self, Endianness, U32Bytes};
6-
use crate::pod::Pod;
6+
use crate::pod::{self, Pod};
77
use crate::read::{
8-
self, Bytes, CompressedData, CompressedFileRange, CompressionFormat, Error, ObjectSection,
9-
ReadError, ReadRef, RelocationMap, SectionFlags, SectionIndex, SectionKind, StringTable,
8+
self, CompressedData, CompressedFileRange, CompressionFormat, Error, ObjectSection, ReadError,
9+
ReadRef, RelocationMap, SectionFlags, SectionIndex, SectionKind, StringTable,
1010
};
1111

1212
use super::{
@@ -671,8 +671,7 @@ pub trait SectionHeader: Debug + Pod {
671671
endian: Self::Endian,
672672
data: R,
673673
) -> read::Result<&'data [T]> {
674-
let mut data = self.data(endian, data).map(Bytes)?;
675-
data.read_slice(data.len() / mem::size_of::<T>())
674+
pod::slice_from_all_bytes(self.data(endian, data)?)
676675
.read_error("Invalid ELF section size or offset")
677676
}
678677

@@ -816,19 +815,11 @@ pub trait SectionHeader: Debug + Pod {
816815
if self.sh_type(endian) != elf::SHT_GROUP {
817816
return Ok(None);
818817
}
819-
let mut data = self
820-
.data(endian, data)
821-
.read_error("Invalid ELF group section offset or size")
822-
.map(Bytes)?;
823-
let flag = data
824-
.read::<U32Bytes<_>>()
825-
.read_error("Invalid ELF group section offset or size")?
826-
.get(endian);
827-
let count = data.len() / mem::size_of::<U32Bytes<Self::Endian>>();
828-
let sections = data
829-
.read_slice(count)
830-
.read_error("Invalid ELF group section offset or size")?;
831-
Ok(Some((flag, sections)))
818+
let msg = "Invalid ELF group section offset or size";
819+
let data = self.data(endian, data).read_error(msg)?;
820+
let (flag, data) = pod::from_bytes::<U32Bytes<_>>(data).read_error(msg)?;
821+
let sections = pod::slice_from_all_bytes(data).read_error(msg)?;
822+
Ok(Some((flag.get(endian), sections)))
832823
}
833824

834825
/// Return the header of a SysV hash section.

Diff for: src/read/elf/segment.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use core::fmt::Debug;
2-
use core::{mem, slice, str};
2+
use core::{slice, str};
33

44
use crate::elf;
55
use crate::endian::{self, Endianness};
6-
use crate::pod::Pod;
7-
use crate::read::{self, Bytes, ObjectSegment, ReadError, ReadRef, SegmentFlags};
6+
use crate::pod::{self, Pod};
7+
use crate::read::{self, ObjectSegment, ReadError, ReadRef, SegmentFlags};
88

99
use super::{ElfFile, FileHeader, NoteIterator};
1010

@@ -180,8 +180,7 @@ pub trait ProgramHeader: Debug + Pod {
180180
endian: Self::Endian,
181181
data: R,
182182
) -> Result<&'data [T], ()> {
183-
let mut data = self.data(endian, data).map(Bytes)?;
184-
data.read_slice(data.len() / mem::size_of::<T>())
183+
pod::slice_from_all_bytes(self.data(endian, data)?)
185184
}
186185

187186
/// Return the segment data in the given virtual address range

Diff for: src/read/pe/file.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use core::convert::TryInto;
66

77
use crate::endian::{LittleEndian as LE, U32};
88
use crate::pe;
9-
use crate::pod::Pod;
9+
use crate::pod::{self, Pod};
1010
use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable};
1111
use crate::read::{
1212
self, Architecture, ByteString, Bytes, CodeView, ComdatKind, Error, Export, FileFlags, Import,
@@ -317,17 +317,8 @@ where
317317
Some(data_dir) => data_dir,
318318
None => return Ok(None),
319319
};
320-
let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
321-
let debug_data_size = data_dir.size.get(LE) as usize;
322-
323-
let count = debug_data_size / mem::size_of::<pe::ImageDebugDirectory>();
324-
let rem = debug_data_size % mem::size_of::<pe::ImageDebugDirectory>();
325-
if rem != 0 || count < 1 {
326-
return Err(Error("Invalid PE debug dir size"));
327-
}
328-
329-
let debug_dirs = debug_data
330-
.read_slice_at::<pe::ImageDebugDirectory>(0, count)
320+
let debug_data = data_dir.data(self.data, &self.common.sections)?;
321+
let debug_dirs = pod::slice_from_all_bytes::<pe::ImageDebugDirectory>(debug_data)
331322
.read_error("Invalid PE debug dir size")?;
332323

333324
for debug_dir in debug_dirs {

0 commit comments

Comments
 (0)