From 06e22d7929f36d9dd9cc556560450fbdbbc821d0 Mon Sep 17 00:00:00 2001 From: asolana <110843012+ksolana@users.noreply.github.com> Date: Fri, 6 Oct 2023 07:43:05 -0700 Subject: [PATCH] Add error message when elf_parser fails on long section names (#537) Addresses: #532 Co-authored-by: Aditya K <1894981+hiraditya@users.noreply.github.com> --- src/elf.rs | 14 ++++++++++++++ src/elf_parser/mod.rs | 13 +++++++++++-- src/elf_parser_glue.rs | 1 + tests/elfs/long_section_name.so | Bin 0 -> 36352 bytes 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100755 tests/elfs/long_section_name.so 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 0000000000000000000000000000000000000000..76f4f14173c6999468bde4b3da50a4ba2afb5e90 GIT binary patch literal 36352 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 literal 0 HcmV?d00001