diff --git a/src/elf.rs b/src/elf.rs index fd76235a..b9150f60 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -1188,6 +1188,7 @@ mod test { // FIXME consts::{ELFCLASS32, ELFDATA2MSB, ET_REL}, consts::{ELFCLASS32, ELFDATA2MSB, ET_REL}, types::{Elf64Ehdr, Elf64Shdr}, + SECTION_NAME_LENGTH_MAXIMUM, }, error::ProgramResult, fuzz::fuzz, @@ -1966,4 +1967,17 @@ mod test { LittleEndian::write_i32(&mut elf_bytes[0x1064..0x1068], 5); ElfExecutable::load(&elf_bytes, loader()).expect("validation failed"); } + + #[test] + fn test_long_section_name() { + let elf_bytes = std::fs::read("tests/elfs/long_section_name.so").unwrap(); + assert_error!( + NewParser::parse(&elf_bytes), + "FailedToParse(\"Section or symbol name `{}` is longer than `{}` bytes\")", + ".bss.__rust_no_alloc_shim_is_unstable" + .get(0..SECTION_NAME_LENGTH_MAXIMUM) + .unwrap(), + SECTION_NAME_LENGTH_MAXIMUM + ); + } } diff --git a/src/elf_parser/mod.rs b/src/elf_parser/mod.rs index 7cafa4e3..bddcfeb4 100644 --- a/src/elf_parser/mod.rs +++ b/src/elf_parser/mod.rs @@ -8,7 +8,8 @@ use std::{fmt, mem, ops::Range, slice}; use crate::{ArithmeticOverflow, ErrCheckedArithmetic}; use {consts::*, types::*}; -const SECTION_NAME_LENGTH_MAXIMUM: usize = 16; +/// Maximum length of section name allowed. +pub const SECTION_NAME_LENGTH_MAXIMUM: usize = 16; const SYMBOL_NAME_LENGTH_MAXIMUM: usize = 64; /// Error definitions @@ -26,6 +27,9 @@ pub enum ElfParserError { /// Section or symbol name is not UTF8 or too long #[error("invalid string")] InvalidString, + /// Section or symbol name is too long + #[error("Section or symbol name `{0}` is longer than `{1}` bytes")] + StringTooLong(String, usize), /// An index or memory range does exeed its boundaries #[error("value out of bounds")] OutOfBounds, @@ -396,7 +400,12 @@ impl<'a> Elf64<'a> { .iter() .position(|byte| *byte == 0x00) .and_then(|string_length| unterminated_string_bytes.get(0..string_length)) - .ok_or(ElfParserError::InvalidString) + .ok_or_else(|| { + ElfParserError::StringTooLong( + String::from_utf8_lossy(unterminated_string_bytes).to_string(), + maximum_length, + ) + }) } /// Returns the string corresponding to the given `sh_name` diff --git a/src/elf_parser_glue.rs b/src/elf_parser_glue.rs index 687402cd..e04fe736 100644 --- a/src/elf_parser_glue.rs +++ b/src/elf_parser_glue.rs @@ -527,6 +527,7 @@ impl From for ElfError { match err { ElfParserError::InvalidSectionHeader | ElfParserError::InvalidString + | ElfParserError::StringTooLong(_, _) | ElfParserError::InvalidSize | ElfParserError::Overlap | ElfParserError::SectionNotInOrder diff --git a/tests/elfs/long_section_name.so b/tests/elfs/long_section_name.so new file mode 100755 index 00000000..76f4f141 Binary files /dev/null and b/tests/elfs/long_section_name.so differ