Skip to content
Open
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
30 changes: 30 additions & 0 deletions src/pe/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,34 @@ mod tests {
assert_eq!(binary.imports[0].rva, 0x21B8);
assert_eq!(binary.imports[0].size, 8);
}

#[test]
fn skip_import_parsing_when_disabled() {
let opts = crate::pe::options::ParseOptions::default().with_parse_imports(false);
let binary = crate::pe::PE::parse_with_opts(WELL_FORMED_IMPORT, &opts)
.expect("Unable to parse binary");
assert!(binary.import_data.is_none());
assert!(binary.imports.is_empty());
assert!(binary.libraries.is_empty());
assert!(binary.header.optional_header.is_some());
assert!(!binary.sections.is_empty());
}

#[test]
fn skip_imports_preserves_debug_data() {
// Use a binary with debug directories to verify that skipping imports
// does not affect debug data parsing.
const MSVC_BIN: &[u8] =
include_bytes!("../../tests/bins/pe/debug_directories-msvc.exe.bin");
let opts = crate::pe::options::ParseOptions::default().with_parse_imports(false);
let binary =
crate::pe::PE::parse_with_opts(MSVC_BIN, &opts).expect("Unable to parse binary");
assert!(binary.import_data.is_none());
assert!(binary.imports.is_empty());
let debug_data = binary
.debug_data
.as_ref()
.expect("debug_data should be present");
assert!(debug_data.codeview_pdb70_debug_info.is_some());
}
}
5 changes: 4 additions & 1 deletion src/pe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ impl<'a> PE<'a> {
}
}
debug!("exports: {:#?}", exports);
if let Some(&import_table) = optional_header.data_directories.get_import_table() {
if let (true, Some(&import_table)) = (
opts.parse_imports,
optional_header.data_directories.get_import_table(),
) {
let id = if is_64 {
import::ImportData::parse_with_opts::<u64>(
bytes,
Expand Down
11 changes: 11 additions & 0 deletions src/pe/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub struct ParseOptions {
pub parse_tls_data: bool,
/// Whether or not to end with an error in case of incorrect data or continue parsing if able. Default: ParseMode::Strict
pub parse_mode: ParseMode,
/// Whether or not to parse import tables. Set to false if you only need headers,
/// debug info, or exports. This can dramatically speed up parsing for PE files with
/// large or malformed import tables. Default: true
pub parse_imports: bool,
}

impl Default for ParseOptions {
Expand All @@ -24,6 +28,7 @@ impl Default for ParseOptions {
parse_attribute_certificates: true,
parse_tls_data: true,
parse_mode: ParseMode::Strict,
parse_imports: true,
}
}
}
Expand All @@ -36,11 +41,17 @@ impl ParseOptions {
parse_attribute_certificates: false,
parse_tls_data: true,
parse_mode: ParseMode::Strict,
parse_imports: true,
}
}

pub fn with_parse_mode(mut self, parse_mode: ParseMode) -> Self {
self.parse_mode = parse_mode;
self
}

pub fn with_parse_imports(mut self, parse_imports: bool) -> Self {
self.parse_imports = parse_imports;
self
}
}
Loading