diff --git a/src/elf_parser/mod.rs b/src/elf_parser/mod.rs index 7cafa4e3..25672776 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/symbol name size `{0}` longer than `{1}` bytes.")] + InvalidStringTooLong(String, usize), /// An index or memory range does exeed its boundaries #[error("value out of bounds")] OutOfBounds, @@ -396,7 +400,14 @@ 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(|| { + let string_bytes_unparsed = + match String::from_utf8(unterminated_string_bytes.to_vec()) { + Ok(x) => x, + Err(_) => ElfParserError::InvalidString.to_string(), + }; + ElfParserError::InvalidStringTooLong(string_bytes_unparsed, 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..e7502bd6 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::InvalidStringTooLong(_, _) | 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 diff --git a/tests/execution.rs b/tests/execution.rs index ddc30ab8..e8d78d55 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -2208,6 +2208,26 @@ fn test_relative_call() { ); } +#[test] +#[should_panic( + expected = r#"called `Result::unwrap()` on an `Err` value: ElfError(FailedToParse("Section/symbol name size `.bss.__rust_no_a` longer than `16` bytes."))"# +)] +fn test_long_section_name() { + test_interpreter_and_jit_elf!( + "tests/elfs/long_section_name.so", + [1], + (), + TestContextObject::new(18), + ProgramResult::Err(EbpfError::ElfError( + solana_rbpf::elf_parser::ElfParserError::InvalidStringTooLong( + ".bss.__rust_no_a".to_string(), + solana_rbpf::elf_parser::SECTION_NAME_LENGTH_MAXIMUM + ) + .into() + )), + ); +} + #[test] fn test_bpf_to_bpf_scratch_registers() { test_interpreter_and_jit_asm!(