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

read: fix endianness problems #458

Merged
merged 4 commits into from Aug 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 22 additions & 1 deletion .github/workflows/rust.yml
Expand Up @@ -44,14 +44,35 @@ jobs:
- run: cargo build --no-default-features --features read_core,wasm
- run: cargo build --no-default-features --features doc

cross:
strategy:
matrix:
target:
# A 32-bit target.
- "i686-unknown-linux-gnu"
# A big-endian target
- "mips64-unknown-linux-gnuabi64"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Install rust
run: |
rustup install stable
rustup default stable
- run: cargo install cross
- run: rustup target add ${{matrix.target}}
- run: cross test --target ${{matrix.target}} --features all

msrv-read:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Install rust
run: rustup update 1.42.0 && rustup default 1.42.0
run: rustup update 1.52.0 && rustup default 1.52.0
- name: Test
run: cargo test --verbose --no-default-features --features read,std

Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -39,7 +39,7 @@ See [`crates/examples`](crates/examples) for more examples.
Changes to MSRV are considered breaking changes. We are conservative about changing the MSRV,
but sometimes are required to due to dependencies. The MSRV is:

* 1.42.0 for the `read` feature and its dependencies.
* 1.52.0 for the `read` feature and its dependencies.
* 1.56.1 for the `write` feature and its dependencies.

## License
Expand Down
2 changes: 1 addition & 1 deletion crates/examples/src/readobj/elf.rs
Expand Up @@ -361,7 +361,7 @@ fn print_section_symbols<Elf: FileHeader>(
} else {
p.field("SectionIndex", shndx);
}
if let Some(shndx) = symbols.shndx(index) {
if let Some(shndx) = symbols.shndx(endian, index) {
p.field("ExtendedSectionIndex", shndx);
}
});
Expand Down
42 changes: 42 additions & 0 deletions crates/examples/testfiles/pe/resource.exe.readobj.0
@@ -0,0 +1,42 @@
ImageResourceDirectory {
Characteristics: 0
TimeDateStamp: 0
MajorVersion: 0
MinorVersion: 0
NumberOfNamedEntries: 0
NumberOfIdEntries: 1
ImageResourceDirectoryEntry {
NameOrId: RT_VERSION (0x10)
OffsetToDataOrDirectory: 0x80000018
ImageResourceDirectory {
Characteristics: 0
TimeDateStamp: 0
MajorVersion: 0
MinorVersion: 0
NumberOfNamedEntries: 1
NumberOfIdEntries: 0
ImageResourceDirectoryEntry {
NameOrId: "MY VERSION" (0x80000048)
OffsetToDataOrDirectory: 0x80000030
ImageResourceDirectory {
Characteristics: 0
TimeDateStamp: 0
MajorVersion: 0
MinorVersion: 0
NumberOfNamedEntries: 0
NumberOfIdEntries: 1
ImageResourceDirectoryEntry {
NameOrId: 1033
OffsetToDataOrDirectory: 0x60
ImageResourceDataEntry {
VirtualAddress: 0x10070
Size: 92
CodePage: 0
Reserved: 0x0
}
}
}
}
}
}
}
12 changes: 6 additions & 6 deletions src/read/elf/symbol.rs
Expand Up @@ -4,14 +4,14 @@ use core::fmt::Debug;
use core::slice;
use core::str;

use crate::elf;
use crate::endian::{self, Endianness};
use crate::pod::Pod;
use crate::read::util::StringTable;
use crate::read::{
self, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, SectionIndex, SymbolFlags,
SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection,
};
use crate::{elf, U32};

use super::{FileHeader, SectionHeader, SectionTable};

Expand All @@ -28,7 +28,7 @@ where
shndx_section: SectionIndex,
symbols: &'data [Elf::Sym],
strings: StringTable<'data, R>,
shndx: &'data [u32],
shndx: &'data [U32<Elf::Endian>],
}

impl<'data, Elf: FileHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Elf, R> {
Expand Down Expand Up @@ -145,8 +145,8 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> {

/// Return the extended section index for the given symbol if present.
#[inline]
pub fn shndx(&self, index: usize) -> Option<u32> {
self.shndx.get(index).copied()
pub fn shndx(&self, endian: Elf::Endian, index: usize) -> Option<u32> {
self.shndx.get(index).map(|x| x.get(endian))
}

/// Return the section index for the given symbol.
Expand All @@ -161,7 +161,7 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> {
match symbol.st_shndx(endian) {
elf::SHN_UNDEF => Ok(None),
elf::SHN_XINDEX => self
.shndx(index)
.shndx(endian, index)
.read_error("Missing ELF symbol extended index")
.map(|index| Some(SectionIndex(index as usize))),
shndx if shndx < elf::SHN_LORESERVE => Ok(Some(SectionIndex(shndx.into()))),
Expand Down Expand Up @@ -369,7 +369,7 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
}
}
elf::SHN_COMMON => SymbolSection::Common,
elf::SHN_XINDEX => match self.symbols.shndx(self.index.0) {
elf::SHN_XINDEX => match self.symbols.shndx(self.endian, self.index.0) {
Some(index) => SymbolSection::Section(SectionIndex(index as usize)),
None => SymbolSection::Unknown,
},
Expand Down
19 changes: 13 additions & 6 deletions src/read/pe/resource.rs
@@ -1,7 +1,8 @@
use alloc::string::String;
use core::char;

use crate::read::{ReadError, ReadRef, Result};
use crate::{pe, LittleEndian as LE, U16};
use crate::{pe, LittleEndian as LE, U16Bytes};

/// The `.rsrc` section of a PE file.
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -143,20 +144,26 @@ pub struct ResourceName {
impl ResourceName {
/// Converts to a `String`.
pub fn to_string_lossy(&self, directory: ResourceDirectory) -> Result<String> {
let d = self.data(directory)?;
Ok(String::from_utf16_lossy(d))
let d = self.data(directory)?.iter().map(|c| c.get(LE));

Ok(char::decode_utf16(d)
.map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
.collect::<String>())
}

/// Returns the string unicode buffer.
pub fn data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u16]> {
pub fn data<'data>(
&self,
directory: ResourceDirectory<'data>,
) -> Result<&'data [U16Bytes<LE>]> {
let mut offset = u64::from(self.offset);
let len = directory
.data
.read::<U16<LE>>(&mut offset)
.read::<U16Bytes<LE>>(&mut offset)
.read_error("Invalid resource name offset")?;
directory
.data
.read_slice::<u16>(&mut offset, len.get(LE).into())
.read_slice::<U16Bytes<LE>>(&mut offset, len.get(LE).into())
.read_error("Invalid resource name length")
}
}
Expand Down
2 changes: 1 addition & 1 deletion testfiles