From 714c1836d214cb0d02bc5168fd3641646a3d5728 Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Nov 21 2019 15:56:14 +0000 Subject: [PATCH 1/3] Add a sanity check on remotely opened RPMs This should catch issues with downloading RPMs early, so as to not break the build in unknown ways. Fixes: #290 Signed-off-by: Patrick Uiterwijk --- diff --git a/koji/__init__.py b/koji/__init__.py index e44ea59..ac86c5e 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -1677,6 +1677,15 @@ def openRemoteFile(relpath, topurl=None, topdir=None, tempdir=None): fo = open(fn) else: raise GenericError("No access method for remote file: %s" % relpath) + if relpath.endswith('.rpm'): + # Do a initial sanity check on any RPM we opened. + # This is basically to detect issues with RPMs before they break builds + # in unknown ways. + # Note that this does not always catch every possible issue, but it + # will at least catch issues like when an RPM is only partly downloaded + # (see issue #290). + rpm.TransactionSet().hdrCheck(fo.read()) + fo.seek(0) return fo From dea2497c940199bc36006340b7cb594b7ea4bbe1 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Nov 21 2019 15:56:46 +0000 Subject: [PATCH 2/3] refactor --- diff --git a/builder/kojid b/builder/kojid index 186f4ec..9ce8a79 100755 --- a/builder/kojid +++ b/builder/kojid @@ -1101,6 +1101,7 @@ class BuildTask(BaseTaskHandler): opts = dict([(k, getattr(self.options, k)) for k in ('topurl','topdir')]) opts['tempdir'] = self.workdir with koji.openRemoteFile(relpath, **opts) as fo: + koji.check_rpm_file(fo) h = koji.get_rpm_header(fo) if not koji.get_header_field(h, 'sourcepackage'): raise koji.BuildError("%s is not a source package" % srpm) diff --git a/koji/__init__.py b/koji/__init__.py index ac86c5e..ebb26f8 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -1677,18 +1677,32 @@ def openRemoteFile(relpath, topurl=None, topdir=None, tempdir=None): fo = open(fn) else: raise GenericError("No access method for remote file: %s" % relpath) - if relpath.endswith('.rpm'): - # Do a initial sanity check on any RPM we opened. - # This is basically to detect issues with RPMs before they break builds - # in unknown ways. - # Note that this does not always catch every possible issue, but it - # will at least catch issues like when an RPM is only partly downloaded - # (see issue #290). - rpm.TransactionSet().hdrCheck(fo.read()) - fo.seek(0) return fo +def check_rpm_file(rpmfile): + "Do a initial sanity check on an RPM + + rpmfile can either be a file name or a file object + + This check is used to detect issues with RPMs before they break builds + See: https://pagure.io/koji/issue/290 + " + if isinstance(rpmfile, basestring): + with open(rpmfile, 'rb') as fo: + return _check_rpm_file(fo) + else: + return _check_rpm_file(rpmfile) + + +def _check_rpm_file(fo): + """Check that the open file appears to be an rpm""" + # TODO: trap exception and raise something with more infomation + rpm.TransactionSet().hdrCheck(fo.read()) + fo.seek(0) + + + def config_directory_contents(dir_name, strict=False): configs = [] try: From 8e83612297b231ade23abd7d20dcfda736d8bd11 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Nov 22 2019 07:38:50 +0000 Subject: [PATCH 3/3] added koji exceptions Fixes: https://pagure.io/koji/issue/290 --- diff --git a/koji/__init__.py b/koji/__init__.py index ebb26f8..9216eae 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -1681,14 +1681,14 @@ def openRemoteFile(relpath, topurl=None, topdir=None, tempdir=None): def check_rpm_file(rpmfile): - "Do a initial sanity check on an RPM + """Do a initial sanity check on an RPM rpmfile can either be a file name or a file object This check is used to detect issues with RPMs before they break builds See: https://pagure.io/koji/issue/290 - " - if isinstance(rpmfile, basestring): + """ + if isinstance(rpmfile, six.string_types): with open(rpmfile, 'rb') as fo: return _check_rpm_file(fo) else: @@ -1698,11 +1698,20 @@ def check_rpm_file(rpmfile): def _check_rpm_file(fo): """Check that the open file appears to be an rpm""" # TODO: trap exception and raise something with more infomation - rpm.TransactionSet().hdrCheck(fo.read()) + ts = rpm.TransactionSet() + try: + hdr = ts.hdrFromFdno(fo.fileno()) + except rpm.error as ex: + raise GenericError("rpm's header can't be extracted: %s (rpm error: %s)" % \ + (fo.name, ', '.join(ex.args))) + try: + rpm.TransactionSet().hdrCheck(hdr.unload()) + except rpm.error as ex: + raise GenericError("rpm's header can't be checked: %s (rpm error: %s)" % \ + (fo.name, ', '.join(ex.args))) fo.seek(0) - def config_directory_contents(dir_name, strict=False): configs = [] try: