pelite\pe64/
file.rs

1/*!
2PE file.
3*/
4
5use std::prelude::v1::*;
6
7use crate::Result;
8
9use super::pe::validate_headers;
10use super::{Align, Pe, PeObject};
11
12/// View into an unmapped PE file.
13#[derive(Copy, Clone)]
14pub struct PeFile<'a> {
15	image: &'a [u8],
16}
17
18impl<'a> PeFile<'a> {
19	/// Constructs a file view from a byte slice.
20	///
21	/// # Errors
22	///
23	/// * [`Bounds`](../enum.Error.html#variant.Bounds):
24	///   The byte slice is too small to fit the PE headers.
25	///
26	/// * [`Misaligned`](../enum.Error.html#variant.Misaligned):
27	///   The minimum alignment of 4 is not satisfied.
28	///
29	/// * [`BadMagic`](../enum.Error.html#variant.BadMagic):
30	///   This is not a PE file.
31	///
32	/// * [`PeMagic`](../enum.Error.html#variant.PeMagic):
33	///   Trying to parse a PE32 file with the PE32+ parser and vice versa.
34	///
35	/// * [`Insanity`](../enum.Error.html#variant.Insanity):
36	///   Reasonable limits on `e_lfanew`, `SizeOfHeaders` or `NumberOfSections` are exceeded.
37	pub fn from_bytes<T: AsRef<[u8]> + ?Sized>(image: &'a T) -> Result<PeFile<'a>> {
38		let image = image.as_ref();
39		let _ = validate_headers(image)?;
40		Ok(PeFile { image })
41	}
42	/// Converts the file to section alignment.
43	pub fn to_view(self) -> Vec<u8> {
44		let (sizeof_headers, sizeof_image) = {
45			let optional_header = self.optional_header();
46			(optional_header.SizeOfHeaders, optional_header.SizeOfImage)
47		};
48
49		// Zero fill the underlying image
50		let mut vec = vec![0u8; sizeof_image as usize];
51
52		// Start by copying the headers
53		let image = self.image();
54		unsafe {
55			// Validated by constructor
56			let dest_headers = vec.get_unchecked_mut(..sizeof_headers as usize);
57			let src_headers = image.get_unchecked(..sizeof_headers as usize);
58			dest_headers.copy_from_slice(src_headers);
59		}
60
61		// Copy the section file data
62		for section in self.section_headers() {
63			let dest = vec.get_mut(section.VirtualAddress as usize..u32::wrapping_add(section.VirtualAddress, section.VirtualSize) as usize);
64			let src = image.get(section.PointerToRawData as usize..u32::wrapping_add(section.PointerToRawData, section.SizeOfRawData) as usize);
65			// Skip invalid sections...
66			if let (Some(dest), Some(src)) = (dest, src) {
67				dest.copy_from_slice(src);
68			}
69		}
70
71		vec
72	}
73}
74
75//----------------------------------------------------------------
76
77unsafe impl<'a> Pe<'a> for PeFile<'a> {}
78
79unsafe impl<'a> PeObject<'a> for PeFile<'a> {
80	fn image(&self) -> &'a [u8] {
81		self.image
82	}
83	fn align(&self) -> Align {
84		Align::File
85	}
86	#[cfg(feature = "serde")]
87	fn serde_name(&self) -> &'static str {
88		"PeFile"
89	}
90}
91
92//----------------------------------------------------------------
93
94#[cfg(feature = "serde")]
95impl<'a> serde::Serialize for PeFile<'a> {
96	fn serialize<S: serde::Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
97		super::pe::serialize_pe(*self, serializer)
98	}
99}
100
101//----------------------------------------------------------------
102
103#[test]
104fn from_byte_slice() {
105	assert!(match PeFile::from_bytes(&[]) { Err(crate::Error::Bounds) => true, _ => false });
106}