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

Commit 4c761be

Browse files
committed
Adds tests.
1 parent 2bdb30c commit 4c761be

File tree

2 files changed

+143
-1
lines changed

2 files changed

+143
-1
lines changed

src/elf.rs

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,7 @@ mod test {
13801380
elf_parser::{
13811381
// FIXME consts::{ELFCLASS32, ELFDATA2MSB, ET_REL},
13821382
consts::{ELFCLASS32, ELFDATA2MSB, ET_REL},
1383-
types::{Elf64Ehdr, Elf64Shdr},
1383+
types::{Elf64Ehdr, Elf64Shdr, Elf64Sym},
13841384
SECTION_NAME_LENGTH_MAXIMUM,
13851385
},
13861386
error::ProgramResult,
@@ -1409,6 +1409,137 @@ mod test {
14091409
))
14101410
}
14111411

1412+
#[test]
1413+
fn test_strict_header() {
1414+
let elf_bytes =
1415+
std::fs::read("tests/elfs/strict_header.so").expect("failed to read elf file");
1416+
let loader = loader();
1417+
1418+
// Check that the unmodified file can be parsed
1419+
{
1420+
let loader = Arc::new(BuiltinProgram::new_loader(
1421+
Config {
1422+
enable_symbol_and_section_labels: true,
1423+
..Config::default()
1424+
},
1425+
FunctionRegistry::<BuiltinFunction<TestContextObject>>::default(),
1426+
));
1427+
let executable = ElfExecutable::load(&elf_bytes, loader.clone()).unwrap();
1428+
let (name, _pc) = executable.get_function_registry().lookup_by_key(4).unwrap();
1429+
assert_eq!(name, b"entrypoint");
1430+
}
1431+
1432+
// Check that using a reserved SBPF version fails
1433+
{
1434+
let mut elf_bytes = elf_bytes.clone();
1435+
elf_bytes[0x0030] = 0xFF;
1436+
let err = ElfExecutable::load(&elf_bytes, loader.clone()).unwrap_err();
1437+
assert_eq!(err, ElfError::UnsupportedSBPFVersion);
1438+
}
1439+
1440+
// Check that an empty file fails
1441+
let err = ElfExecutable::load_with_strict_parser(&[], loader.clone()).unwrap_err();
1442+
assert_eq!(err, ElfParserError::OutOfBounds);
1443+
1444+
// Break the file header one byte at a time
1445+
let expected_results = std::iter::repeat(&Err(ElfParserError::InvalidFileHeader))
1446+
.take(40)
1447+
.chain(std::iter::repeat(&Ok(())).take(12))
1448+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidFileHeader)).take(4))
1449+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader)).take(1))
1450+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidFileHeader)).take(3))
1451+
.chain(std::iter::repeat(&Ok(())).take(2))
1452+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidFileHeader)).take(2));
1453+
for (offset, expected) in (0..std::mem::size_of::<Elf64Ehdr>()).zip(expected_results) {
1454+
let mut elf_bytes = elf_bytes.clone();
1455+
elf_bytes[offset] = 0xAF;
1456+
let result =
1457+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).map(|_| ());
1458+
assert_eq!(&result, expected);
1459+
}
1460+
1461+
// Break the program header table one byte at a time
1462+
let expected_results_readonly =
1463+
std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader))
1464+
.take(48)
1465+
.chain(std::iter::repeat(&Ok(())).take(8))
1466+
.collect::<Vec<_>>();
1467+
let expected_results_writable =
1468+
std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader))
1469+
.take(40)
1470+
.chain(std::iter::repeat(&Ok(())).take(4))
1471+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidProgramHeader)).take(4))
1472+
.chain(std::iter::repeat(&Ok(())).take(8))
1473+
.collect::<Vec<_>>();
1474+
let expected_results = vec![
1475+
expected_results_readonly.iter(),
1476+
expected_results_readonly.iter(),
1477+
expected_results_writable.iter(),
1478+
expected_results_writable.iter(),
1479+
expected_results_readonly.iter(),
1480+
];
1481+
for (header_index, expected_results) in expected_results.into_iter().enumerate() {
1482+
for (offset, expected) in (std::mem::size_of::<Elf64Ehdr>()
1483+
+ std::mem::size_of::<Elf64Phdr>() * header_index
1484+
..std::mem::size_of::<Elf64Ehdr>()
1485+
+ std::mem::size_of::<Elf64Phdr>() * (header_index + 1))
1486+
.zip(expected_results)
1487+
{
1488+
let mut elf_bytes = elf_bytes.clone();
1489+
elf_bytes[offset] = 0xAF;
1490+
let result =
1491+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).map(|_| ());
1492+
assert_eq!(&&result, expected);
1493+
}
1494+
}
1495+
1496+
// Break the dynamic symbol table one byte at a time
1497+
for index in 1..3 {
1498+
let expected_results = std::iter::repeat(&Ok(()))
1499+
.take(8)
1500+
.chain(std::iter::repeat(&Err(ElfParserError::OutOfBounds)).take(8))
1501+
.chain(std::iter::repeat(&Err(ElfParserError::InvalidSize)).take(1))
1502+
.chain(std::iter::repeat(&Err(ElfParserError::OutOfBounds)).take(7));
1503+
for (offset, expected) in (0x3000 + std::mem::size_of::<Elf64Sym>() * index
1504+
..0x3000 + std::mem::size_of::<Elf64Sym>() * (index + 1))
1505+
.zip(expected_results)
1506+
{
1507+
let mut elf_bytes = elf_bytes.clone();
1508+
elf_bytes[offset] = 0xAF;
1509+
let result =
1510+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).map(|_| ());
1511+
assert_eq!(&result, expected);
1512+
}
1513+
}
1514+
1515+
// Check that an empty function symbol fails
1516+
{
1517+
let mut elf_bytes = elf_bytes.clone();
1518+
elf_bytes[0x3040] = 0x00;
1519+
let err =
1520+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).unwrap_err();
1521+
assert_eq!(err, ElfParserError::InvalidSize);
1522+
}
1523+
1524+
// Check that bytecode not covered by function symbols fails
1525+
{
1526+
let mut elf_bytes = elf_bytes.clone();
1527+
elf_bytes[0x3040] = 0x08;
1528+
let err =
1529+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).unwrap_err();
1530+
assert_eq!(err, ElfParserError::OutOfBounds);
1531+
}
1532+
1533+
// Check that an entrypoint not covered by function symbols fails
1534+
{
1535+
let mut elf_bytes = elf_bytes.clone();
1536+
elf_bytes[0x0018] = 0x10;
1537+
let err =
1538+
ElfExecutable::load_with_strict_parser(&elf_bytes, loader.clone()).unwrap_err();
1539+
assert_eq!(err, ElfParserError::InvalidFileHeader);
1540+
}
1541+
}
1542+
14121543
#[test]
14131544
fn test_validate() {
14141545
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
@@ -3187,6 +3187,17 @@ fn test_struct_func_pointer() {
31873187
);
31883188
}
31893189

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

31923203
#[test]

0 commit comments

Comments
 (0)