Skip to content
This repository was archived by the owner on Jan 10, 2025. It is now read-only.

Commit e1fd3c8

Browse files
committed
Adds tests.
1 parent 692f63c commit e1fd3c8

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

src/elf.rs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ mod test {
13691369
elf_parser::{
13701370
// FIXME consts::{ELFCLASS32, ELFDATA2MSB, ET_REL},
13711371
consts::{ELFCLASS32, ELFDATA2MSB, ET_REL},
1372-
types::{Elf64Ehdr, Elf64Shdr},
1372+
types::{Elf64Ehdr, Elf64Shdr, Elf64Sym},
13731373
SECTION_NAME_LENGTH_MAXIMUM,
13741374
},
13751375
error::ProgramResult,
@@ -1398,6 +1398,99 @@ mod test {
13981398
))
13991399
}
14001400

1401+
#[test]
1402+
fn test_strict_header() {
1403+
let elf_bytes =
1404+
std::fs::read("tests/elfs/strict_header.so").expect("failed to read elf file");
1405+
let loader = loader();
1406+
1407+
// Check that the unmodified file can be parsed
1408+
ElfExecutable::load(&elf_bytes, loader.clone()).unwrap();
1409+
1410+
// Check that an empty file fails
1411+
let err = ElfExecutable::load_with_strict_parser(&[], loader.clone()).unwrap_err();
1412+
assert_eq!(err, ElfParserError::OutOfBounds);
1413+
1414+
// Break the file header one byte at a time
1415+
let expected_results = std::iter::repeat(&Err(ElfParserError::InvalidFileHeader))
1416+
.take(40)
1417+
.chain(std::iter::repeat(&Ok(())).take(12))
1418+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidFileHeader)).take(4))
1419+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader)).take(1))
1420+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidFileHeader)).take(3))
1421+
.chain(std::iter::repeat(&Ok(())).take(2))
1422+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidFileHeader)).take(2));
1423+
for (offset, expected) in (0..std::mem::size_of::<Elf64Ehdr>()).zip(expected_results) {
1424+
let mut elf_bytes = elf_bytes.clone();
1425+
elf_bytes[offset] = 0xAF;
1426+
let result =
1427+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).map(|_| ());
1428+
assert_eq!(&result, expected);
1429+
}
1430+
1431+
// Break the program header table one byte at a time
1432+
let expected_results_readonly =
1433+
std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader))
1434+
.take(48)
1435+
.chain(std::iter::repeat(&Ok(())).take(8))
1436+
.collect::<Vec<_>>();
1437+
let expected_results_writable =
1438+
std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader))
1439+
.take(40)
1440+
.chain(std::iter::repeat(&Ok(())).take(4))
1441+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader)).take(4))
1442+
.chain(std::iter::repeat(&Ok(())).take(8))
1443+
.collect::<Vec<_>>();
1444+
let expected_results = vec![
1445+
expected_results_readonly.iter(),
1446+
expected_results_readonly.iter(),
1447+
expected_results_writable.iter(),
1448+
expected_results_writable.iter(),
1449+
expected_results_readonly.iter(),
1450+
];
1451+
for (header_index, expected_results) in expected_results.into_iter().enumerate() {
1452+
for (offset, expected) in (std::mem::size_of::<Elf64Ehdr>()
1453+
+ std::mem::size_of::<Elf64Phdr>() * header_index
1454+
..std::mem::size_of::<Elf64Ehdr>()
1455+
+ std::mem::size_of::<Elf64Phdr>() * (header_index + 1))
1456+
.zip(expected_results)
1457+
{
1458+
let mut elf_bytes = elf_bytes.clone();
1459+
elf_bytes[offset] = 0xAF;
1460+
let result =
1461+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).map(|_| ());
1462+
assert_eq!(&&result, expected);
1463+
}
1464+
}
1465+
1466+
// Break the dynamic symbol table one byte at a time
1467+
for index in 1..3 {
1468+
let expected_results = std::iter::repeat(&Ok(()))
1469+
.take(8)
1470+
.chain(std::iter::repeat(&Err(ElfParserError::OutOfBounds)).take(8))
1471+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidSize)).take(1))
1472+
.chain(std::iter::repeat(&Err(ElfParserError::OutOfBounds)).take(7));
1473+
for (offset, expected) in (0x3000 + std::mem::size_of::<Elf64Sym>() * index
1474+
..0x3000 + std::mem::size_of::<Elf64Sym>() * (index + 1))
1475+
.zip(expected_results)
1476+
{
1477+
let mut elf_bytes = elf_bytes.clone();
1478+
elf_bytes[offset] = 0xAF;
1479+
let result =
1480+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).map(|_| ());
1481+
assert_eq!(&result, expected);
1482+
}
1483+
}
1484+
1485+
// Check that an empty function symbol fails
1486+
let mut elf_bytes = elf_bytes.clone();
1487+
elf_bytes[0x3040] = 0x00;
1488+
assert_eq!(
1489+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).unwrap_err(),
1490+
ElfParserError::InvalidSize
1491+
);
1492+
}
1493+
14011494
#[test]
14021495
fn test_validate() {
14031496
let elf_bytes = std::fs::read("tests/elfs/relative_call_sbpfv1.so").unwrap();

tests/execution.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3186,6 +3186,17 @@ fn test_struct_func_pointer() {
31863186
);
31873187
}
31883188

3189+
#[test]
3190+
fn test_strict_header() {
3191+
test_interpreter_and_jit_elf!(
3192+
"tests/elfs/strict_header.so",
3193+
[],
3194+
(),
3195+
TestContextObject::new(6),
3196+
ProgramResult::Ok(42),
3197+
);
3198+
}
3199+
31893200
// Programs
31903201

31913202
#[test]

0 commit comments

Comments
 (0)