diff options
author | TizenOpenSource <tizenopensrc@samsung.com> | 2023-12-27 18:11:19 +0900 |
---|---|---|
committer | TizenOpenSource <tizenopensrc@samsung.com> | 2023-12-27 18:11:19 +0900 |
commit | 727a4bfe21f594703093859adb151f67f0403a13 (patch) | |
tree | 90f3c63cafddcdc010091ead32a9d5e7d09e4cd2 /test/test_readelf_parser.py | |
parent | 95b3517edeace0e940b51d8ac5609c8f9326f6f4 (diff) | |
download | rpmlint-727a4bfe21f594703093859adb151f67f0403a13.tar.gz rpmlint-727a4bfe21f594703093859adb151f67f0403a13.tar.bz2 rpmlint-727a4bfe21f594703093859adb151f67f0403a13.zip |
Imported Upstream version 2.5.0upstream/2.5.0upstream
Diffstat (limited to 'test/test_readelf_parser.py')
-rw-r--r-- | test/test_readelf_parser.py | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/test/test_readelf_parser.py b/test/test_readelf_parser.py new file mode 100644 index 0000000..28df231 --- /dev/null +++ b/test/test_readelf_parser.py @@ -0,0 +1,292 @@ +from pathlib import Path +import re + +import pytest +from rpmlint.checks.BinariesCheck import BinariesCheck +from rpmlint.filter import Filter +from rpmlint.pkg import FakePkg, get_magic +from rpmlint.pkgfile import PkgFile +from rpmlint.readelfparser import ReadelfParser + +from Testing import CONFIG, get_tested_path, HAS_32BIT_GLIBC, IS_I686, IS_X86_64 + + +@pytest.fixture(scope='function', autouse=True) +def binariescheck(): + CONFIG.info = True + output = Filter(CONFIG) + test = BinariesCheck(CONFIG, output) + return output, test + + +def get_full_path(path): + return str(get_tested_path(Path('readelf', path))) + + +def readelfparser(path, system_path=None): + if system_path is None: + system_path = path + return ReadelfParser(get_full_path(path), system_path) + + +def run_elf_checks(test, pkg, pkgfile): + test._detect_attributes(get_magic(pkgfile.path)) + test.run_elf_checks(pkg, pkgfile) + + +def test_empty_archive(): + readelf = readelfparser('empty-archive.a') + assert len(readelf.section_info.elf_files) == 0 + assert len(readelf.symbol_table_info.functions) == 0 + + +def test_simple_archive(): + readelf = readelfparser('main.a') + assert readelf.is_archive + assert len(readelf.section_info.elf_files) == 1 + elf_file = readelf.section_info.elf_files[0] + assert len(elf_file) == 11 + assert elf_file[0].name == '.text' + assert elf_file[0].size == 21 + assert readelf.symbol_table_info.functions == {'main'} + assert len(list(readelf.symbol_table_info.get_functions_for_regex(re.compile('mai.')))) == 1 + + +def test_program_header_parsing(): + readelf = readelfparser('nested-function') + assert len(readelf.program_header_info.headers) == 11 + h0 = readelf.program_header_info.headers[0] + assert h0.name == 'PHDR' + assert h0.flags == 'R' + h9 = readelf.program_header_info.headers[9] + assert h9.name == 'GNU_STACK' + assert h9.flags == 'RWE' + + +def test_dynamic_section_parsing(): + readelf = readelfparser('libutil-2.29.so', '/lib64/libutil-2.29.so') + assert readelf.is_shlib + assert not readelf.is_archive + sections = readelf.dynamic_section_info.sections + assert len(sections) == 30 + assert sections[0].key == 'NEEDED' + assert sections[0].value == 'Shared library: [libc.so.6]' + assert readelf.dynamic_section_info['SYMTAB'] == ['0x4c8'] + assert readelf.dynamic_section_info['NULL'] == ['0x0'] + assert readelf.dynamic_section_info.soname == 'libutil.so.1' + assert len(readelf.dynamic_section_info.needed) == 1 + assert readelf.dynamic_section_info.needed[0] == 'libc.so.6' + + +def test_rpath(): + readelf = readelfparser('rpath-lib.so', '/lib64/rpath-lib.so') + assert readelf.is_shlib + assert not readelf.is_archive + assert len(readelf.dynamic_section_info.runpaths) == 1 + assert '/tmp/termcap.so.4' in readelf.dynamic_section_info.runpaths + + +def test_lto_bytecode(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('lto-object.o'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + assert not test.readelf_parser.parsing_failed_reason() + out = output.print_results(output.results) + assert 'lto-bytecode' in out + + +def test_lto_archive_text(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('stripped-lto.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'E: lto-no-text-in-archive' in out + assert 'E: static-library-without-debuginfo' in out + + +def test_stripped_archive(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('stripped-archive.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'E: static-library-without-symtab' in out + + +def test_lto_archive_text_function_sections(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('function-sections.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + assert 'E: lto-no-text-in-archive' not in output.print_results(output.results) + + +def test_lto_archive_init_array(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('libbsd-ctor.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + assert 'E: lto-no-text-in-archive' not in output.print_results(output.results) + + +def test_lto_archive_preinit_array(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('libclang_rt.asan-preinit-x86_64.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + assert 'E: lto-no-text-in-archive' not in output.print_results(output.results) + + +def test_lto_archive_with_only_data(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('only-data.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + assert 'E: lto-no-text-in-archive' not in output.print_results(output.results) + + +def test_archive_with_debuginfo(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('archive-with-debuginfo.a'), 'x.a') + run_elf_checks(test, pkg, pkgfile) + assert 'E: static-library-without-debuginfo' not in output.print_results(output.results) + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_executable_stack(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('executable-stack'), '/lib64/my/a.out') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + + if 'ldd-failed' in out: + pytest.skip("ldd failed, maybe it's a different architecture") + + assert 'E: executable-stack /lib64/my/a.out' in out + + +def test_readelf_failure(): + readelf = readelfparser('not-existing-file') + assert 'No such file' in readelf.parsing_failed_reason() + + +def test_readelf_failure_in_package(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('not-existing.so'), '/lib64/not-existing.so') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'readelf-failed /lib64/not-existing.so' in out + + +def test_readelf_single_error_message(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('small_archive.a'), '/lib64/small_archive.a') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + filtered = [line for line in out.splitlines() if 'Not an ELF file' in line] + assert len(filtered) == 1 + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_no_soname(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('no-soname.so'), '/lib64/no-soname.so') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'no-soname /lib64/no-soname.so' in out + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_invalid_soname(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('invalid-soname.so'), '/lib64/invalid-soname.so') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'invalid-soname /lib64/invalid-soname.so' in out + assert 'E: shlib-with-non-pic-code /lib64/invalid-soname.so' not in out + + +@pytest.mark.skipif(not IS_I686 and (not IS_X86_64 or not HAS_32BIT_GLIBC), reason='i686 glibc only') +def test_non_pic_code_library(binariescheck): + output, test = binariescheck + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('non-pic-shared-m32.so'), '/usr/lib/non-pic-shared-m32.so') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'E: shlib-with-non-pic-code' in out + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_no_ldconfig_symlink(binariescheck): + output, test = binariescheck + + with FakePkg('libfake') as pkg: + pkgfile = pkg.add_file(get_full_path('libutil-2.29.so'), '/lib64/libutil-2.29.so') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'no-ldconfig-symlink /lib64/libutil-2.29.so' in out + assert 'E: shlib-policy-name-error SONAME: libutil.so.1 (/lib64/libutil-2.29.so), expected package suffix: 1' in out + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_call_mktemp(binariescheck): + output, test = binariescheck + + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('call-mktemp'), '/bin/call-mktemp') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'E: call-to-mktemp /bin/call-mktemp' in out + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_call_setgroups(binariescheck): + output, test = binariescheck + + with FakePkg('fake') as pkg: + pkgfile = PkgFile('/bin/call-setgroups') + pkgfile.path = get_full_path('call-setgroups') + pkg.files[pkgfile.name] = pkgfile + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'E: missing-call-to-setgroups-before-setuid /bin/call-setgroups' in out + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_call_gethostbyname(binariescheck): + output, test = binariescheck + + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('hostname'), '/usr/bin/hostname') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'W: binary-or-shlib-calls-gethostbyname' in out + + +def test_bca_files(binariescheck): + output, test = binariescheck + + with FakePkg('fake') as pkg: + pkgfile = pkg.add_file(get_full_path('libkleeRuntimeFreeStanding.bca'), '/usr/lib64/klee/runtime/libkleeRuntimeFreeStanding.bca') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'E: ' not in out + + +@pytest.mark.skipif(not IS_X86_64, reason='x86-64 only') +def test_shlib_policy_name_error(binariescheck): + output, test = binariescheck + + with FakePkg('libgame') as pkg: + pkgfile = pkg.add_file(get_full_path('libgame.so'), '/lib64/libgame.so') + run_elf_checks(test, pkg, pkgfile) + out = output.print_results(output.results) + assert 'libgame: E: shlib-policy-name-error SONAME: libgame2-1.9.so.10.0.0 (/lib64/libgame.so), expected package suffix: 1_9-10_0_0' in out |