Skip to content

Commit 50fa096

Browse files
authoredJan 5, 2025··
pe: add strict option to parse config; fix fail on malformed certificate table parsing (#417)
* pe.cert_table: ignore malformed * parse_options: added ParseMode * pe.options: added te(), fixes
1 parent 1a999cc commit 50fa096

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed
 

‎src/pe/mod.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::container;
3333
use crate::error;
3434
use crate::pe::utils::pad;
3535
use crate::strtab;
36+
use options::ParseMode;
3637

3738
use scroll::{ctx, Pwrite};
3839

@@ -264,11 +265,19 @@ impl<'a> PE<'a> {
264265
if let Some(&certificate_table) =
265266
optional_header.data_directories.get_certificate_table()
266267
{
267-
certificates = certificate_table::enumerate_certificates(
268+
let certificates_result = certificate_table::enumerate_certificates(
268269
bytes,
269270
certificate_table.virtual_address,
270271
certificate_table.size,
271-
)?;
272+
);
273+
274+
certificates = match opts.parse_mode {
275+
ParseMode::Strict => certificates_result?,
276+
ParseMode::Permissive => certificates_result.unwrap_or_else(|err| {
277+
warn!("Cannot parse CertificateTable: {:?}", err);
278+
Default::default()
279+
}),
280+
};
272281

273282
certificate_table.size as usize
274283
} else {
@@ -522,10 +531,7 @@ pub struct TE<'a> {
522531
impl<'a> TE<'a> {
523532
/// Reads a TE binary from the underlying `bytes`
524533
pub fn parse(bytes: &'a [u8]) -> error::Result<Self> {
525-
let opts = &options::ParseOptions {
526-
resolve_rva: false,
527-
parse_attribute_certificates: false,
528-
};
534+
let opts = &options::ParseOptions::te();
529535

530536
let mut offset = 0;
531537

‎src/pe/options.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/// Parsing Options structure for the PE parser
2+
#[non_exhaustive]
23
#[derive(Debug, Copy, Clone)]
34
pub struct ParseOptions {
45
/// Wether the parser should resolve rvas or not. Default: true
@@ -8,14 +9,35 @@ pub struct ParseOptions {
89
/// memory](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#other-contents-of-the-file).
910
/// For on-disk representations, leave as true. Default: true
1011
pub parse_attribute_certificates: bool,
12+
/// Whether or not to end with an error in case of incorrect data or continue parsing if able. Default: ParseMode::Strict
13+
pub parse_mode: ParseMode,
1114
}
1215

13-
impl ParseOptions {
16+
#[derive(Debug, Copy, Clone)]
17+
pub enum ParseMode {
18+
/// Always end with error on incorrect data
19+
Strict,
20+
/// Incorrect data will not cause to end with error if possible
21+
Permissive,
22+
}
23+
24+
impl Default for ParseOptions {
1425
/// Returns a parse options structure with default values
15-
pub fn default() -> Self {
26+
fn default() -> Self {
1627
ParseOptions {
1728
resolve_rva: true,
1829
parse_attribute_certificates: true,
30+
parse_mode: ParseMode::Strict,
31+
}
32+
}
33+
}
34+
35+
impl ParseOptions {
36+
pub(crate) fn te() -> Self {
37+
Self {
38+
resolve_rva: false,
39+
parse_attribute_certificates: false,
40+
parse_mode: ParseMode::Strict,
1941
}
2042
}
2143
}

0 commit comments

Comments
 (0)
Please sign in to comment.