Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more strict about multiple indexes found in an archive #175

Merged
merged 3 commits into from
Jul 13, 2019
Merged
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
53 changes: 40 additions & 13 deletions src/archive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,21 @@ impl<'a> NameIndex<'a> {
}
}

#[derive(Debug, PartialEq)]
/// The type of symbol index can be present in an archive. Can serve as an indication of the
/// archive format.
pub enum IndexType {
/// No symbol index present.
None,
/// SystemV/GNU style symbol index, used on Windows as well.
SysV,
/// Windows specific extension of SysV symbol index, so called Second Linker Member. Has the
/// same member name as SysV symbol index but different structure.
Windows,
/// BSD style symbol index.
BSD,
}

// TODO: add pretty printer fmt::Display with number of members, and names of members, along with
// the values of the index symbols once implemented
#[derive(Debug)]
Expand All @@ -364,12 +379,15 @@ pub struct Archive<'a> {
member_array: Vec<Member<'a>>,
members: BTreeMap<&'a str, usize>,
// symbol -> member
symbol_index: BTreeMap<&'a str, usize>
symbol_index: BTreeMap<&'a str, usize>,
/// Type of the symbol index that was found in the archive.
index_type: IndexType,
}


impl<'a> Archive<'a> {
pub fn parse(buffer: &'a [u8]) -> Result<Archive<'a>> {

let mut magic = [0u8; SIZEOF_MAGIC];
let offset = &mut 0usize;
buffer.gread_inout(offset, &mut magic)?;
Expand All @@ -378,8 +396,8 @@ impl<'a> Archive<'a> {
}
let mut member_array = Vec::new();
let mut index = Index::default();
let mut index_type = IndexType::None;
let mut sysv_name_index = NameIndex::default();
let mut sysv_symbol_index_seen = false;
while *offset + 1 < buffer.len() {
// realign the cursor to a word boundary, if it's not on one already
if *offset & 1 == 1 {
Expand All @@ -394,15 +412,25 @@ impl<'a> Archive<'a> {
let name = member.raw_name();
if name == INDEX_NAME {
let data: &[u8] = buffer.pread_with(member.offset as usize, member.size())?;
index = if sysv_symbol_index_seen {
// Second symbol index is Microsoft's extension of SysV format
Index::parse_windows_linker_member(data)?
} else {
sysv_symbol_index_seen = true;
Index::parse_sysv_index(data)?
};
index = match index_type {
IndexType::None => {
index_type = IndexType::SysV;
Index::parse_sysv_index(data)?
},
IndexType::SysV => {
index_type = IndexType::Windows;
// second symbol index is Microsoft's extension of SysV format
Index::parse_windows_linker_member(data)?
},
IndexType::BSD => return Err(Error::Malformed("SysV index occurs after BSD index".into())),
IndexType::Windows => return Err(Error::Malformed("More than two Windows Linker members".into())),
}
raindev marked this conversation as resolved.
Show resolved Hide resolved

} else if member.bsd_name == Some(BSD_SYMDEF_NAME) || member.bsd_name == Some(BSD_SYMDEF_SORTED_NAME) {
if index_type != IndexType::None {
return Err(Error::Malformed("BSD index occurs after SysV index".into()));
}
index_type = IndexType::BSD;
let data: &[u8] = buffer.pread_with(member.offset as usize, member.size())?;
index = Index::parse_bsd_symdef(data)?;

Expand Down Expand Up @@ -440,15 +468,14 @@ impl<'a> Archive<'a> {
symbol_index.insert(&name, member_index);
}

let archive = Archive {
Ok(Archive {
index,
member_array,
sysv_name_index,
members,
symbol_index,
};

Ok(archive)
index_type,
})
}

/// Get the member named `member` in this archive, if any
Expand Down