From 4ce280dab7a155fab0185c7313bd985156ca8b1a Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Tue, 4 Jun 2013 06:20:56 +0200 Subject: [PATCH] Add a test for overlinking (unused shared libraries) Based on the rpath code. --- Namcap/rules/__init__.py | 3 +- Namcap/rules/unusedsodepends.py | 76 ++++++++++++++++++++++++++++ Namcap/tests/package/test_unusedsodepends.py | 66 ++++++++++++++++++++++++ namcap-tags | 1 + 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 Namcap/rules/unusedsodepends.py create mode 100644 Namcap/tests/package/test_unusedsodepends.py diff --git a/Namcap/rules/__init__.py b/Namcap/rules/__init__.py index f7780d2..a1b6775 100644 --- a/Namcap/rules/__init__.py +++ b/Namcap/rules/__init__.py @@ -46,7 +46,8 @@ from . import ( scrollkeeper, shebangdepends, sodepends, - symlink + symlink, + unusedsodepends ) # PKGBUILD and metadata rules diff --git a/Namcap/rules/unusedsodepends.py b/Namcap/rules/unusedsodepends.py new file mode 100644 index 0000000..4d6a5be --- /dev/null +++ b/Namcap/rules/unusedsodepends.py @@ -0,0 +1,76 @@ +# +# namcap rules - unusedsodepends +# Copyright (C) 2009 Abhishek Dasgupta +# Copyright (C) 2013 Jan Alexander Steffens +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import os, subprocess, re +import tempfile +from Namcap.util import is_elf, clean_filename +from Namcap.ruleclass import * + +libre = re.compile('^\t(/.*)') +lddfail = re.compile('^\tnot a dynamic executable') + +def get_unused_sodepends(filename): + p = subprocess.Popen(["ldd", "-r", "-u", filename], + env={'LANG': 'C'}, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + var = p.communicate() + if p.returncode == 0: + return + else: + for j in var[0].decode('ascii').splitlines(): + # Don't raise an error, as the executable might be a valid ELF file, + # just not a dynamically linked one + n = lddfail.search(j) + if n is not None: + return + + n = libre.search(j) + if n is not None: + yield n.group(1) + +class package(TarballRule): + name = "unusedsodepends" + description = "Checks for unused dependencies caused by linked shared libraries" + def analyze(self, pkginfo, tar): + for entry in tar: + if not entry.isfile(): + continue + + # is it an ELF file ? + f = tar.extractfile(entry) + elf = f.read() + f.close() + if elf[:4] != b"\x7fELF": + continue # not an ELF file + + # write it to a temporary file + f = tempfile.NamedTemporaryFile(delete = False) + f.write(elf) + f.close() + + os.chmod(f.name, 0o755) + + for lib in get_unused_sodepends(f.name): + self.warnings.append(("unused-sodepend %s %s", (lib, entry.name))) + + os.unlink(f.name) + +# vim: set ts=4 sw=4 noet: diff --git a/Namcap/tests/package/test_unusedsodepends.py b/Namcap/tests/package/test_unusedsodepends.py new file mode 100644 index 0000000..b2002f7 --- /dev/null +++ b/Namcap/tests/package/test_unusedsodepends.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# +# namcap tests - unusedsodepends +# Copyright (C) 2011 Rémy Oudompheng +# Copyright (C) 2013 Jan Alexander Steffens +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# + +import os +from Namcap.tests.makepkg import MakepkgTest +import Namcap.rules.unusedsodepends + +class UnusedSodependsTest(MakepkgTest): + pkgbuild = """ +pkgname=__namcap_test_unusedsodepends +pkgver=1.0 +pkgrel=1 +pkgdesc="A package" +arch=('i686' 'x86_64') +url="http://www.example.com/" +license=('GPL') +depends=('glibc') +source=() +options=(!purge !zipman) +build() { + cd "${srcdir}" + echo "int main() { return 0; }" > main.c + /usr/bin/gcc -o main main.c -lm +} +package() { + install -D -m 755 "$srcdir/main" "$pkgdir/usr/bin/evilprogram" +} +""" + def test_unusedsodepends_files(self): + "Package with binaries linking to unused shared libraries" + pkgfile = "__namcap_test_unusedsodepends-1.0-1-%(arch)s.pkg.tar" % { "arch": self.arch } + with open(os.path.join(self.tmpdir, "PKGBUILD"), "w") as f: + f.write(self.pkgbuild) + self.run_makepkg() + pkg, r = self.run_rule_on_tarball( + os.path.join(self.tmpdir, pkgfile), + Namcap.rules.unusedsodepends.package + ) + self.assertEqual(r.errors, []) + self.assertEqual(r.warnings, [ + ("unused-sodepend %s %s", + ("/usr/lib/libm.so.6", "usr/bin/evilprogram")) + ]) + self.assertEqual(r.infos, []) + +# vim: set ts=4 sw=4 noet: + diff --git a/namcap-tags b/namcap-tags index 818c7a5..dd8ca24 100644 --- a/namcap-tags +++ b/namcap-tags @@ -73,6 +73,7 @@ specific-host-type-used %s :: Reference to %s should be changed to $CARCH specific-sourceforge-mirror :: Attempting to use specific sourceforge mirror, use downloads.sourceforge.net instead symlink-found %s points to %s :: Symlink (%s) found that points to %s too-many-checksums %s %i needed :: Too many %s: %i needed +unused-sodepend %s %s :: Unused shared library '%s' by file ('%s') use-pkgdir :: Use $pkgdir instead of $startdir/pkg use-srcdir :: Use $srcdir instead of $startdir/src using-dl-sourceforge :: Attempting to use dl sourceforge domain, use downloads.sourceforge.net instead -- 1.8.3