Skip to content

Commit a75bd2a

Browse files
committed
rust: parse archive files and validate object files within
Previously, we weren't validating the content of static libraries because we weren't descending into archive files. This commit implements support for doing that.
1 parent 2d531b0 commit a75bd2a

File tree

1 file changed

+74
-34
lines changed

1 file changed

+74
-34
lines changed

src/main.rs

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,54 @@ fn validate_pe(path: &Path, pe: &goblin::pe::PE) -> Result<Vec<String>> {
552552
Ok(errors)
553553
}
554554

555+
/// Attempt to parse data as an object file and validate it.
556+
fn validate_possible_object_file(
557+
python_major_minor: &str,
558+
triple: &str,
559+
path: &Path,
560+
data: &[u8],
561+
) -> Result<(Vec<String>, BTreeSet<String>)> {
562+
let mut errors = vec![];
563+
let mut seen_dylibs = BTreeSet::new();
564+
565+
if let Ok(object) = goblin::Object::parse(&data) {
566+
match object {
567+
goblin::Object::Elf(elf) => {
568+
errors.extend(validate_elf(
569+
triple,
570+
python_major_minor,
571+
path.as_ref(),
572+
&elf,
573+
&data,
574+
)?);
575+
}
576+
goblin::Object::Mach(mach) => match mach {
577+
goblin::mach::Mach::Binary(macho) => {
578+
let (local_errors, local_seen_dylibs) =
579+
validate_macho(triple, path.as_ref(), &macho, &data)?;
580+
581+
errors.extend(local_errors);
582+
seen_dylibs.extend(local_seen_dylibs);
583+
}
584+
goblin::mach::Mach::Fat(_) => {
585+
if path.to_string_lossy() != "python/build/lib/libclang_rt.osx.a" {
586+
errors.push(format!("unexpected fat mach-o binary: {}", path.display()));
587+
}
588+
}
589+
},
590+
goblin::Object::PE(pe) => {
591+
// We don't care about the wininst-*.exe distutils executables.
592+
if !path.to_string_lossy().contains("wininst-") {
593+
errors.extend(validate_pe(path.as_ref(), &pe)?);
594+
}
595+
}
596+
_ => {}
597+
}
598+
}
599+
600+
Ok((errors, seen_dylibs))
601+
}
602+
555603
fn validate_json(json: &PythonJsonMain, triple: &str) -> Result<Vec<String>> {
556604
let mut errors = vec![];
557605

@@ -633,41 +681,33 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
633681
let mut data = Vec::new();
634682
entry.read_to_end(&mut data)?;
635683

636-
if let Ok(object) = goblin::Object::parse(&data) {
637-
match object {
638-
goblin::Object::Elf(elf) => {
639-
errors.extend(validate_elf(
640-
triple,
641-
python_major_minor,
642-
path.as_ref(),
643-
&elf,
644-
&data,
645-
)?);
646-
}
647-
goblin::Object::Mach(mach) => match mach {
648-
goblin::mach::Mach::Binary(macho) => {
649-
let (local_errors, local_seen_dylibs) =
650-
validate_macho(triple, path.as_ref(), &macho, &data)?;
651-
652-
errors.extend(local_errors);
653-
seen_dylibs.extend(local_seen_dylibs);
654-
}
655-
goblin::mach::Mach::Fat(_) => {
656-
if path.to_string_lossy() != "python/build/lib/libclang_rt.osx.a" {
657-
errors
658-
.push(format!("unexpected fat mach-o binary: {}", path.display()));
659-
}
660-
}
661-
},
662-
goblin::Object::PE(pe) => {
663-
// We don't care about the wininst-*.exe distutils executables.
664-
if path.to_string_lossy().contains("wininst-") {
665-
continue;
666-
}
684+
let (local_errors, local_seen_dylibs) =
685+
validate_possible_object_file(python_major_minor, &triple, &path, &data)?;
686+
errors.extend(local_errors);
687+
seen_dylibs.extend(local_seen_dylibs);
688+
689+
// Descend into archive files (static libraries are archive files and members
690+
// are usually object files).
691+
if let Ok(archive) = goblin::archive::Archive::parse(&data) {
692+
for member in archive.members() {
693+
let member_data = archive
694+
.extract(member, &data)
695+
.with_context(|| format!("extracting {} from {}", member, path.display()))?;
696+
697+
let member_path = path.with_file_name(format!(
698+
"{}:{}",
699+
path.file_name().unwrap().to_string_lossy(),
700+
member
701+
));
667702

668-
errors.extend(validate_pe(path.as_ref(), &pe)?);
669-
}
670-
_ => {}
703+
let (local_errors, local_seen_dylibs) = validate_possible_object_file(
704+
python_major_minor,
705+
&triple,
706+
&member_path,
707+
&member_data,
708+
)?;
709+
errors.extend(local_errors);
710+
seen_dylibs.extend(local_seen_dylibs);
671711
}
672712
}
673713

0 commit comments

Comments
 (0)