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
|