-
Notifications
You must be signed in to change notification settings - Fork 240
/
test_elffile.py
100 lines (83 loc) · 3.09 KB
/
test_elffile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import io
import pathlib
import struct
import pytest
from packaging._elffile import EIClass, EIData, ELFFile, ELFInvalid, EMachine
DIR_MANYLINUX = pathlib.Path(__file__, "..", "manylinux").resolve()
DIR_MUSLLINUX = pathlib.Path(__file__, "..", "musllinux").resolve()
BIN_MUSL_X86_64 = DIR_MUSLLINUX.joinpath("musl-x86_64").read_bytes()
@pytest.mark.parametrize(
"name, capacity, encoding, machine",
[
("x86_64-x32", EIClass.C32, EIData.Lsb, EMachine.X8664),
("x86_64-i386", EIClass.C32, EIData.Lsb, EMachine.I386),
("x86_64-amd64", EIClass.C64, EIData.Lsb, EMachine.X8664),
("armv7l-armel", EIClass.C32, EIData.Lsb, EMachine.Arm),
("armv7l-armhf", EIClass.C32, EIData.Lsb, EMachine.Arm),
("s390x-s390x", EIClass.C64, EIData.Msb, EMachine.S390),
],
)
def test_elffile_glibc(name, capacity, encoding, machine):
path = DIR_MANYLINUX.joinpath(f"hello-world-{name}")
with path.open("rb") as f:
ef = ELFFile(f)
assert ef.capacity == capacity
assert ef.encoding == encoding
assert ef.machine == machine
assert ef.flags is not None
@pytest.mark.parametrize(
"name, capacity, encoding, machine, interpreter",
[
(
"aarch64",
EIClass.C64,
EIData.Lsb,
EMachine.AArc64,
"aarch64",
),
("i386", EIClass.C32, EIData.Lsb, EMachine.I386, "i386"),
("x86_64", EIClass.C64, EIData.Lsb, EMachine.X8664, "x86_64"),
],
)
def test_elffile_musl(name, capacity, encoding, machine, interpreter):
path = DIR_MUSLLINUX.joinpath(f"musl-{name}")
with path.open("rb") as f:
ef = ELFFile(f)
assert ef.capacity == capacity
assert ef.encoding == encoding
assert ef.machine == machine
assert ef.interpreter == f"/lib/ld-musl-{interpreter}.so.1"
@pytest.mark.parametrize(
"data",
[
# Too short for magic.
b"\0",
# Enough for magic, but not ELF.
b"#!/bin/bash" + b"\0" * 16,
# ELF, but unknown byte declaration.
b"\x7fELF\3" + b"\0" * 16,
],
ids=["no-magic", "wrong-magic", "unknown-format"],
)
def test_elffile_bad_ident(data):
with pytest.raises(ELFInvalid):
ELFFile(io.BytesIO(data))
def test_elffile_no_section():
"""Enough for magic, but not the section definitions."""
data = BIN_MUSL_X86_64[:25]
with pytest.raises(ELFInvalid):
ELFFile(io.BytesIO(data))
def test_elffile_invalid_section():
"""Enough for section definitions, but not the actual sections."""
data = BIN_MUSL_X86_64[:58]
assert ELFFile(io.BytesIO(data)).interpreter is None
def test_elffle_no_interpreter_section():
ef = ELFFile(io.BytesIO(BIN_MUSL_X86_64))
# Change all sections to *not* PT_INTERP.
data = BIN_MUSL_X86_64
for i in range(ef._e_phnum + 1):
sb = ef._e_phoff + ef._e_phentsize * i
se = sb + ef._e_phentsize
section = struct.unpack(ef._p_fmt, data[sb:se])
data = data[:sb] + struct.pack(ef._p_fmt, 0, *section[1:]) + data[se:]
assert ELFFile(io.BytesIO(data)).interpreter is None