Ejemplo n.º 1
0
 def check_summary(self, pkg, lang, ignored_words):
     summary = pkg.langtag(rpm.RPMTAG_SUMMARY, lang)
     if use_utf8:
         if not Pkg.is_utf8_bytestr(summary):
             printError(pkg, 'tag-not-utf8', 'Summary', lang)
         summary = Pkg.to_unicode(summary)
     else:
         summary = Pkg.b2s(summary)
     self._unexpanded_macros(pkg, 'Summary(%s)' % lang, summary)
     spell_check(pkg, summary, 'Summary(%s)', lang, ignored_words)
     if '\n' in summary:
         printError(pkg, 'summary-on-multiple-lines', lang)
     if (summary[0] != summary[0].upper()
             and summary.partition(' ')[0] not in CAPITALIZED_IGNORE_LIST):
         printWarning(pkg, 'summary-not-capitalized', lang, summary)
     if summary[-1] == '.':
         printWarning(pkg, 'summary-ended-with-dot', lang, summary)
     if len(summary) > max_line_len:
         printError(pkg, 'summary-too-long', lang, summary)
     if leading_space_regex.search(summary):
         printError(pkg, 'summary-has-leading-spaces', lang, summary)
     res = forbidden_words_regex.search(summary)
     if res and Config.getOption('ForbiddenWords'):
         printWarning(pkg, 'summary-use-invalid-word', lang, res.group(1))
     if pkg.name:
         sepchars = r'[\s%s]' % punct
         res = re.search(
             r'(?:^|\s)(%s)(?:%s|$)' % (re.escape(pkg.name), sepchars),
             summary, re.IGNORECASE | re.UNICODE)
         if res:
             printWarning(pkg, 'name-repeated-in-summary', lang,
                          res.group(1))
Ejemplo n.º 2
0
    def __comparePRCOs(self, old, new, name):
        try:
            oldflags = old[name[:-1] + 'FLAGS']
        except ValueError:
            # assume tag not supported, e.g. Recommends with older rpm
            return
        newflags = new[name[:-1] + 'FLAGS']
        # fix buggy rpm binding not returning list for single entries
        if not isinstance(oldflags, list):
            oldflags = [oldflags]
        if not isinstance(newflags, list):
            newflags = [newflags]

        o = zip(old[name], oldflags, old[name[:-1] + 'VERSION'])
        if not isinstance(o, list):
            o = list(o)
        n = zip(new[name], newflags, new[name[:-1] + 'VERSION'])
        if not isinstance(n, list):
            n = list(n)

        # filter self provides, TODO: self %name(%_isa) as well
        if name == 'PROVIDES':
            oldE = old['epoch'] is not None and str(old['epoch']) + ":" or ""
            oldV = "%s%s" % (oldE, old.format("%{VERSION}-%{RELEASE}"))
            oldNV = (old['name'], rpm.RPMSENSE_EQUAL, oldV.encode())
            newE = new['epoch'] is not None and str(new['epoch']) + ":" or ""
            newV = "%s%s" % (newE, new.format("%{VERSION}-%{RELEASE}"))
            newNV = (new['name'], rpm.RPMSENSE_EQUAL, newV.encode())
            o = [entry for entry in o if entry != oldNV]
            n = [entry for entry in n if entry != newNV]

        for oldentry in o:
            if oldentry not in n:
                namestr = name
                if namestr == 'REQUIRES':
                    namestr = self.req2str(oldentry[1])
                self.__add(self.DEPFORMAT,
                           (self.REMOVED, namestr, Pkg.b2s(oldentry[0]),
                            self.sense2str(oldentry[1]), Pkg.b2s(oldentry[2])))
        for newentry in n:
            if newentry not in o:
                namestr = name
                if namestr == 'REQUIRES':
                    namestr = self.req2str(newentry[1])
                self.__add(self.DEPFORMAT,
                           (self.ADDED, namestr, Pkg.b2s(newentry[0]),
                            self.sense2str(newentry[1]), Pkg.b2s(newentry[2])))
Ejemplo n.º 3
0
    def check(self, pkg):
        for fname, pkgfile in pkg.files().items():
            path = pkgfile.path
            if zip_regex.search(fname) and os.path.exists(path) and \
               stat.S_ISREG(os.lstat(path)[stat.ST_MODE]) and \
               zipfile.is_zipfile(path):
                z = None  # TODO ZipFile is context manager in 2.7+
                try:
                    z = zipfile.ZipFile(path, 'r')
                    badcrc = z.testzip()
                    if badcrc:
                        printError(pkg, 'bad-crc-in-zip', badcrc, fname)
                except zipfile.error:
                    printWarning(pkg, 'unable-to-read-zip',
                                 '%s: %s' % (fname, sys.exc_info()[1]))
                else:
                    compressed = False
                    for zinfo in z.infolist():
                        if zinfo.compress_type != zipfile.ZIP_STORED:
                            compressed = True
                            break
                    if not compressed:
                        printWarning(pkg, 'uncompressed-zip', fname)

                    # additional jar checks
                    if jar_regex.search(fname):
                        try:
                            mf = Pkg.b2s(z.read('META-INF/MANIFEST.MF'))
                            if classpath_regex.search(mf):
                                printWarning(pkg, 'class-path-in-manifest',
                                             fname)
                        except KeyError:
                            # META-INF/* are optional:
                            # http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html
                            pass
                        try:
                            zinfo = z.getinfo('META-INF/INDEX.LIST')
                            if not want_indexed_jars:
                                printWarning(pkg, 'jar-indexed', fname)
                        except KeyError:
                            if want_indexed_jars:
                                printWarning(pkg, 'jar-not-indexed', fname)
                            pass

                z and z.close()
Ejemplo n.º 4
0
 def check_description(self, pkg, lang, ignored_words):
     description = pkg.langtag(rpm.RPMTAG_DESCRIPTION, lang)
     if use_utf8:
         if not Pkg.is_utf8_bytestr(description):
             printError(pkg, 'tag-not-utf8', '%description', lang)
         description = Pkg.to_unicode(description)
     else:
         description = Pkg.b2s(description)
     self._unexpanded_macros(pkg, '%%description -l %s' % lang, description)
     spell_check(pkg, description, '%%description -l %s', lang,
                 ignored_words)
     for l in description.splitlines():
         if len(l) > max_line_len:
             printError(pkg, 'description-line-too-long', lang, l)
         res = forbidden_words_regex.search(l)
         if res and Config.getOption('ForbiddenWords'):
             printWarning(pkg, 'description-use-invalid-word', lang,
                          res.group(1))
         res = tag_regex.search(l)
         if res:
             printWarning(pkg, 'tag-in-description', lang, res.group(1))
Ejemplo n.º 5
0
    def __init__(self, pkg, path, fname, is_ar, is_shlib):
        self.readelf_error = False
        self.needed = []
        self.rpath = []
        self.undef = []
        self.unused = []
        self.comment = False
        self.soname = False
        self.non_pic = True
        self.stack = False
        self.exec_stack = False
        self.exit_calls = []
        self.forbidden_calls = []
        fork_called = False
        self.tail = ''

        self.setgid = False
        self.setuid = False
        self.setgroups = False
        self.chroot = False
        self.chdir = False
        self.chroot_near_chdir = False
        self.mktemp = False
        self.forbidden_functions = Config.getOption("WarnOnFunction")
        if self.forbidden_functions:
            for name, func in self.forbidden_functions.items():
                # precompile regexps
                f_name = func['f_name']
                func['f_regex'] = create_nonlibc_regexp_call(f_name)
                if 'good_param' in func:
                    func['waiver_regex'] = re.compile(func['good_param'])
                # register descriptions
                addDetails(name, func['description'])

        is_debug = path.endswith('.debug')
        # Currently this implementation works only on specific
        # architectures due to reliance on arch specific assembly.
        if (pkg.arch.startswith('armv') or pkg.arch == 'aarch64'):
            # 10450:   ebffffec        bl      10408 <chroot@plt>
            self.objdump_call_regex = re.compile(br'\sbl\s+(.*)')
        elif (pkg.arch.endswith('86') or pkg.arch == 'x86_64'):
            # 401eb8:   e8 c3 f0 ff ff          callq  400f80 <chdir@plt>
            self.objdump_call_regex = re.compile(br'callq?\s(.*)')
        else:
            self.objdump_call_regex = None

        res = Pkg.getstatusoutput(
            ('readelf', '-W', '-S', '-l', '-d', '-s', path))
        if not res[0]:
            lines = res[1].splitlines()
            for line in lines:
                r = self.needed_regex.search(line)
                if r:
                    self.needed.append(r.group(1))
                    continue

                r = self.rpath_regex.search(line)
                if r:
                    for p in r.group(1).split(':'):
                        self.rpath.append(p)
                    continue

                if self.comment_regex.search(line):
                    self.comment = True
                    continue

                if self.pic_regex.search(line):
                    self.non_pic = False
                    continue

                r = self.soname_regex.search(line)
                if r:
                    self.soname = r.group(1)
                    continue

                r = self.stack_regex.search(line)
                if r:
                    self.stack = True
                    flags = r.group(1)
                    if flags and self.stack_exec_regex.search(flags):
                        self.exec_stack = True
                    continue

                if line.startswith("Symbol table"):
                    break

            for line in lines:
                r = self.call_regex.search(line)
                if not r:
                    continue
                line = r.group(1)

                if self.mktemp_call_regex.search(line):
                    self.mktemp = True

                if self.setgid_call_regex.search(line):
                    self.setgid = True

                if self.setuid_call_regex.search(line):
                    self.setuid = True

                if self.setgroups_call_regex.search(line):
                    self.setgroups = True

                if self.chdir_call_regex.search(line):
                    self.chdir = True

                if self.chroot_call_regex.search(line):
                    self.chroot = True

                if self.forbidden_functions:
                    for r_name, func in self.forbidden_functions.items():
                        ret = func['f_regex'].search(line)
                        if ret:
                            self.forbidden_calls.append(r_name)

                if is_shlib:
                    r = self.exit_call_regex.search(line)
                    if r:
                        self.exit_calls.append(r.group(1))
                        continue
                    r = self.fork_call_regex.search(line)
                    if r:
                        fork_called = True
                        continue

            # check if we don't have a string that will automatically
            # waive the presence of a forbidden call
            if self.forbidden_calls:
                res = Pkg.getstatusoutput(('strings', path))
                if not res[0]:
                    for line in res[1].splitlines():
                        # as we need to remove elements, iterate backwards
                        for i in range(len(self.forbidden_calls) - 1, -1, -1):
                            func = self.forbidden_calls[i]
                            f = self.forbidden_functions[func]
                            if 'waiver_regex' not in f:
                                continue
                            r = f['waiver_regex'].search(line)
                            if r:
                                del self.forbidden_calls[i]

            if self.non_pic:
                self.non_pic = 'TEXTREL' in res[1]

            # Ignore all exit() calls if fork() is being called.
            # Does not have any context at all but without this kludge, the
            # number of false positives would probably be intolerable.
            if fork_called:
                self.exit_calls = []

            # check if chroot is near chdir (since otherwise, chroot is called
            # without chdir)
            if not self.objdump_call_regex and self.chroot and self.chdir:
                # On some architectures, e.g. PPC, it is to difficult to
                # find the actual invocations of chroot/chdir, if both
                # exist assume chroot is fine
                self.chroot_near_chdir = True

            elif self.chroot and self.chdir:
                p = subprocess.Popen(('objdump', '-d', path),
                                     stdout=subprocess.PIPE, bufsize=-1,
                                     env=dict(os.environ, LC_ALL="C"))
                with p.stdout:
                    index = 0
                    chroot_index = -99
                    chdir_index = -99
                    for line in p.stdout:
                        res = self.objdump_call_regex.search(line)
                        if not res:
                            continue
                        if b'@plt' not in res.group(1):
                            pass
                        elif b'chroot@plt' in res.group(1):
                            chroot_index = index
                            if abs(chroot_index - chdir_index) <= 2:
                                self.chroot_near_chdir = True
                                break
                        elif b'chdir@plt' in res.group(1):
                            chdir_index = index
                            if abs(chroot_index - chdir_index) <= 2:
                                self.chroot_near_chdir = True
                                break
                        index += 1
                if p.wait() and not self.chroot_near_chdir:
                    printWarning(pkg, 'binaryinfo-objdump-failed', fname)
                    self.chroot_near_chdir = True  # avoid false positive
                elif chroot_index == -99 and chdir_index == -99:
                    self.chroot_near_chdir = True  # avoid false positive

        else:
            self.readelf_error = True
            # Go and others are producing ar archives that don't have ELF
            # headers, so don't complain about it
            if not is_ar:
                printWarning(pkg, 'binaryinfo-readelf-failed',
                             fname, re.sub('\n.*', '', res[1]))

        try:
            with open(path, 'rb') as fobj:
                fobj.seek(-12, os.SEEK_END)
                self.tail = Pkg.b2s(fobj.read())
        except Exception as e:
            printWarning(pkg, 'binaryinfo-tail-failed %s: %s' % (fname, e))

        # Undefined symbol and unused direct dependency checks make sense only
        # for installed packages.
        # skip debuginfo: https://bugzilla.redhat.com/190599
        if not is_ar and not is_debug and isinstance(pkg, Pkg.InstalledPkg):
            # We could do this with objdump, but it's _much_ simpler with ldd.
            res = Pkg.getstatusoutput(('ldd', '-d', '-r', path))
            if not res[0]:
                for line in res[1].splitlines():
                    undef = self.undef_regex.search(line)
                    if undef:
                        self.undef.append(undef.group(1))
                if self.undef:
                    try:
                        res = Pkg.getstatusoutput(['c++filt'] + self.undef)
                        if not res[0]:
                            self.undef = res[1].splitlines()
                    except OSError:
                        pass
            else:
                printWarning(pkg, 'ldd-failed', fname)
            res = Pkg.getstatusoutput(('ldd', '-r', '-u', path))
            if res[0]:
                # Either ldd doesn't grok -u (added in glibc 2.3.4) or we have
                # unused direct dependencies
                in_unused = False
                for line in res[1].splitlines():
                    if not line.rstrip():
                        pass
                    elif line.startswith('Unused direct dependencies'):
                        in_unused = True
                    elif in_unused:
                        unused = self.unused_regex.search(line)
                        if unused:
                            self.unused.append(unused.group(1))
                        else:
                            in_unused = False
Ejemplo n.º 6
0
    def check(self, pkg):

        packager = pkg[rpm.RPMTAG_PACKAGER]
        if packager:
            self._unexpanded_macros(pkg, 'Packager', packager)
            if Config.getOption('Packager') and \
               not packager_regex.search(packager):
                printWarning(pkg, 'invalid-packager', packager)
        else:
            printError(pkg, 'no-packager-tag')

        version = pkg[rpm.RPMTAG_VERSION]
        if version:
            self._unexpanded_macros(pkg, 'Version', version)
            res = invalid_version_regex.search(version)
            if res:
                printError(pkg, 'invalid-version', version)
        else:
            printError(pkg, 'no-version-tag')

        release = pkg[rpm.RPMTAG_RELEASE]
        if release:
            self._unexpanded_macros(pkg, 'Release', release)
            if release_ext and not extension_regex.search(release):
                printWarning(pkg, 'not-standard-release-extension', release)
        else:
            printError(pkg, 'no-release-tag')

        epoch = pkg[rpm.RPMTAG_EPOCH]
        if epoch is None:
            if use_epoch:
                printError(pkg, 'no-epoch-tag')
        else:
            if epoch > 99:
                printWarning(pkg, 'unreasonable-epoch', epoch)
            epoch = str(epoch)

        if use_epoch:
            for tag in ("obsoletes", "conflicts", "provides", "recommends",
                        "suggests", "enhances", "supplements"):
                for x in (x for x in getattr(pkg, tag)()
                          if x[1] and x[2][0] is None):
                    printWarning(pkg, 'no-epoch-in-%s' % tag,
                                 Pkg.formatRequire(*x))

        name = pkg.name
        deps = pkg.requires() + pkg.prereq()
        devel_depend = False
        is_devel = FilesCheck.devel_regex.search(name)
        is_source = pkg.isSource()
        for d in deps:
            value = Pkg.formatRequire(*d)
            if use_epoch and d[1] and d[2][0] is None and \
                    not d[0].startswith('rpmlib('):
                printWarning(pkg, 'no-epoch-in-dependency', value)
            for r in INVALID_REQUIRES:
                if r.search(d[0]):
                    printError(pkg, 'invalid-dependency', d[0])

            if d[0].startswith('/usr/local/'):
                printError(pkg, 'invalid-dependency', d[0])

            if is_source:
                if lib_devel_number_regex.search(d[0]):
                    printError(pkg, 'invalid-build-requires', d[0])
            elif not is_devel:
                if not devel_depend and FilesCheck.devel_regex.search(d[0]):
                    printError(pkg, 'devel-dependency', d[0])
                    devel_depend = True
                if not d[1]:
                    res = lib_package_regex.search(d[0])
                    if res and not res.group(1):
                        printError(pkg, 'explicit-lib-dependency', d[0])

            if d[1] == rpm.RPMSENSE_EQUAL and d[2][2] is not None:
                printWarning(pkg, 'requires-on-release', value)
            self._unexpanded_macros(pkg, 'dependency %s' % (value, ), value)

        self._unexpanded_macros(pkg, 'Name', name)
        if not name:
            printError(pkg, 'no-name-tag')
        else:
            if is_devel and not is_source:
                base = is_devel.group(1)
                dep = None
                has_so = False
                for fname in pkg.files():
                    if fname.endswith('.so'):
                        has_so = True
                        break
                if has_so:
                    base_or_libs = base + '/' + base + '-libs/lib' + base
                    # try to match *%_isa as well (e.g. "(x86-64)", "(x86-32)")
                    base_or_libs_re = re.compile(
                        r'^(lib)?%s(-libs)?(\(\w+-\d+\))?$' % re.escape(base))
                    for d in deps:
                        if base_or_libs_re.match(d[0]):
                            dep = d
                            break
                    if not dep:
                        printWarning(pkg, 'no-dependency-on', base_or_libs)
                    elif version:
                        exp = (epoch, version, None)
                        sexp = Pkg.versionToString(exp)
                        if not dep[1]:
                            printWarning(pkg, 'no-version-dependency-on',
                                         base_or_libs, sexp)
                        elif dep[2][:2] != exp[:2]:
                            printWarning(
                                pkg, 'incoherent-version-dependency-on',
                                base_or_libs,
                                Pkg.versionToString(
                                    (dep[2][0], dep[2][1], None)), sexp)
                    res = devel_number_regex.search(name)
                    if not res:
                        printWarning(pkg, 'no-major-in-name', name)
                    else:
                        if res.group(3):
                            prov = res.group(1) + res.group(2) + '-devel'
                        else:
                            prov = res.group(1) + '-devel'

                        if prov not in (x[0] for x in pkg.provides()):
                            printWarning(pkg, 'no-provides', prov)

        # List of words to ignore in spell check
        ignored_words = set()
        for pf in pkg.files():
            ignored_words.update(pf.split('/'))
        ignored_words.update((x[0] for x in pkg.provides()))
        ignored_words.update((x[0] for x in pkg.requires()))
        ignored_words.update((x[0] for x in pkg.conflicts()))
        ignored_words.update((x[0] for x in pkg.obsoletes()))

        langs = pkg[rpm.RPMTAG_HEADERI18NTABLE]

        summary = pkg[rpm.RPMTAG_SUMMARY]
        if summary:
            if not langs:
                self._unexpanded_macros(pkg, 'Summary', Pkg.b2s(summary))
            else:
                for lang in langs:
                    self.check_summary(pkg, lang, ignored_words)
        else:
            printError(pkg, 'no-summary-tag')

        description = pkg[rpm.RPMTAG_DESCRIPTION]
        if description:
            if not langs:
                self._unexpanded_macros(pkg, '%description',
                                        Pkg.b2s(description))
            else:
                for lang in langs:
                    self.check_description(pkg, lang, ignored_words)

            if len(Pkg.b2s(description)) < len(pkg[rpm.RPMTAG_SUMMARY]):
                printWarning(pkg, 'description-shorter-than-summary')
        else:
            printError(pkg, 'no-description-tag')

        group = pkg[rpm.RPMTAG_GROUP]
        self._unexpanded_macros(pkg, 'Group', group)
        if not group:
            printError(pkg, 'no-group-tag')
        elif VALID_GROUPS and group not in VALID_GROUPS:
            printWarning(pkg, 'non-standard-group', group)

        buildhost = pkg[rpm.RPMTAG_BUILDHOST]
        self._unexpanded_macros(pkg, 'BuildHost', buildhost)
        if not buildhost:
            printError(pkg, 'no-buildhost-tag')
        elif Config.getOption('ValidBuildHost') and \
                not valid_buildhost_regex.search(buildhost):
            printWarning(pkg, 'invalid-buildhost', buildhost)

        changelog = pkg[rpm.RPMTAG_CHANGELOGNAME]
        if not changelog:
            printError(pkg, 'no-changelogname-tag')
        else:
            clt = pkg[rpm.RPMTAG_CHANGELOGTEXT]
            if use_version_in_changelog:
                ret = changelog_version_regex.search(Pkg.b2s(changelog[0]))
                if not ret and clt:
                    # we also allow the version specified as the first
                    # thing on the first line of the text
                    ret = changelog_text_version_regex.search(Pkg.b2s(clt[0]))
                if not ret:
                    printWarning(pkg, 'no-version-in-last-changelog')
                elif version and release:
                    srpm = pkg[rpm.RPMTAG_SOURCERPM] or ''
                    # only check when source name correspond to name
                    if srpm[0:-8] == '%s-%s-%s' % (name, version, release):
                        expected = [version + '-' + release]
                        if epoch is not None:  # regardless of use_epoch
                            expected[0] = str(epoch) + ':' + expected[0]
                        # Allow EVR in changelog without release extension,
                        # the extension is often a macro or otherwise dynamic.
                        if release_ext:
                            expected.append(
                                extension_regex.sub('', expected[0]))
                        if ret.group(1) not in expected:
                            if len(expected) == 1:
                                expected = expected[0]
                            printWarning(pkg,
                                         'incoherent-version-in-changelog',
                                         ret.group(1), expected)

            if use_utf8:
                if clt:
                    changelog = changelog + clt
                for s in changelog:
                    if not Pkg.is_utf8_bytestr(s):
                        printError(pkg, 'tag-not-utf8', '%changelog')
                        break

            clt = pkg[rpm.RPMTAG_CHANGELOGTIME][0]
            if clt:
                clt -= clt % (24 * 3600)  # roll back to 00:00:00, see #246
                if clt < oldest_changelog_timestamp:
                    printWarning(pkg, 'changelog-time-overflow',
                                 time.strftime("%Y-%m-%d", time.gmtime(clt)))
                elif clt > time.time():
                    printError(pkg, 'changelog-time-in-future',
                               time.strftime("%Y-%m-%d", time.gmtime(clt)))

#         for provide_name in (x[0] for x in pkg.provides()):
#             if name == provide_name:
#                 printWarning(pkg, 'package-provides-itself')
#                 break

        def split_license(license):
            return (x.strip()
                    for x in (l for l in license_regex.split(license) if l))

        rpm_license = pkg[rpm.RPMTAG_LICENSE]
        if not rpm_license:
            printError(pkg, 'no-license')
        else:
            valid_license = True
            if rpm_license not in VALID_LICENSES:
                for l1 in split_license(rpm_license):
                    if l1 in VALID_LICENSES:
                        continue
                    for l2 in split_license(l1):
                        if l2 not in VALID_LICENSES:
                            printWarning(pkg, 'invalid-license', l2)
                            valid_license = False
            if not valid_license:
                self._unexpanded_macros(pkg, 'License', rpm_license)

        for tag in ('URL', 'DistURL', 'BugURL'):
            if hasattr(rpm, 'RPMTAG_%s' % tag.upper()):
                url = Pkg.b2s(pkg[getattr(rpm, 'RPMTAG_%s' % tag.upper())])
                self._unexpanded_macros(pkg, tag, url, is_url=True)
                if url:
                    (scheme, netloc) = urlparse(url)[0:2]
                    if not scheme or not netloc or "." not in netloc or \
                            scheme not in ('http', 'https', 'ftp') or \
                            (Config.getOption('InvalidURL') and
                             invalid_url_regex.search(url)):
                        printWarning(pkg, 'invalid-url', tag, url)
                    else:
                        self.check_url(pkg, tag, url)
                elif tag == 'URL':
                    printWarning(pkg, 'no-url-tag')

        obs_names = [x[0] for x in pkg.obsoletes()]
        prov_names = [x[0] for x in pkg.provides()]

        for o in (x for x in obs_names if x not in prov_names):
            printWarning(pkg, 'obsolete-not-provided', o)
        for o in pkg.obsoletes():
            value = Pkg.formatRequire(*o)
            self._unexpanded_macros(pkg, 'Obsoletes %s' % (value, ), value)

        # TODO: should take versions, <, <=, =, >=, > into account here
        #       https://bugzilla.redhat.com/460872
        useless_provides = set()
        for p in prov_names:
            if (prov_names.count(p) != 1 and not p.startswith('debuginfo(')
                    and p not in useless_provides):
                useless_provides.add(p)
        for p in sorted(useless_provides):
            printError(pkg, 'useless-provides', p)

        for tagname, items in (('Provides', pkg.provides()), ('Conflicts',
                                                              pkg.conflicts()),
                               ('Obsoletes', pkg.obsoletes()),
                               ('Supplements', pkg.supplements()),
                               ('Suggests', pkg.suggests()), ('Enhances',
                                                              pkg.enhances()),
                               ('Recommends', pkg.recommends())):
            for p in items:
                value = Pkg.formatRequire(*p)
                self._unexpanded_macros(pkg, '%s %s' % (tagname, value), value)

        obss = pkg.obsoletes()
        if obss:
            provs = pkg.provides()
            for prov in provs:
                for obs in obss:
                    if Pkg.rangeCompare(obs, prov):
                        printWarning(
                            pkg, 'self-obsoletion',
                            '%s obsoletes %s' % (Pkg.formatRequire(*obs),
                                                 Pkg.formatRequire(*prov)))

        expfmt = rpm.expandMacro("%{_build_name_fmt}")
        if pkg.isSource():
            # _build_name_fmt often (always?) ends up not outputting src/nosrc
            # as arch for source packages, do it ourselves
            expfmt = re.sub(r'(?i)%\{?ARCH\b\}?', pkg.arch, expfmt)
        expected = pkg.header.sprintf(expfmt).split("/")[-1]
        basename = os.path.basename(pkg.filename)
        if basename != expected:
            printWarning(pkg, 'non-coherent-filename', basename, expected)

        for tag in ('Distribution', 'DistTag', 'ExcludeArch', 'ExcludeOS',
                    'Vendor'):
            if hasattr(rpm, 'RPMTAG_%s' % tag.upper()):
                res = Pkg.b2s(pkg[getattr(rpm, 'RPMTAG_%s' % tag.upper())])
                self._unexpanded_macros(pkg, tag, res)

        for path in private_so_paths:
            for fname, pkgfile in pkg.files().items():
                if fname.startswith(path):
                    for prov in pkgfile.provides:
                        if so_dep_regex.search(prov[0]):
                            printWarning(pkg, "private-shared-object-provides",
                                         fname, Pkg.formatRequire(*prov))
Ejemplo n.º 7
0
    def check_aux(self, pkg, files, prog, script, tag, prereq):
        if script:
            script_str = Pkg.b2s(script)
            if prog:
                if prog not in valid_shells:
                    printError(pkg, 'invalid-shell-in-' + tag, prog)
                if prog in empty_shells:
                    printError(pkg, 'non-empty-' + tag, prog)
            if prog in syntaxcheck_shells or prog == '/usr/bin/perl':
                if percent_regex.search(script_str):
                    printWarning(pkg, 'percent-in-' + tag)
                if bracket_regex.search(script_str):
                    printWarning(pkg, 'spurious-bracket-in-' + tag)
                res = dangerous_command_regex.search(script_str)
                if res:
                    printWarning(pkg, 'dangerous-command-in-' + tag,
                                 res.group(2))
                res = selinux_regex.search(script_str)
                if res:
                    printError(pkg, 'forbidden-selinux-command-in-' + tag,
                               res.group(2))

                if 'update-menus' in script_str:
                    menu_error = True
                    for f in files:
                        if menu_regex.search(f):
                            menu_error = False
                            break
                    if menu_error:
                        printError(pkg,
                                   'update-menus-without-menu-file-in-' + tag)
                if tmp_regex.search(script_str):
                    printError(pkg, 'use-tmp-in-' + tag)
                for c in prereq_assoc:
                    if c[0].search(script_str):
                        found = False
                        for p in c[1]:
                            if p in prereq or p in files:
                                found = True
                                break
                        if not found:
                            printError(pkg, 'no-prereq-on', c[1][0])

            if prog in syntaxcheck_shells:
                if incorrect_shell_script(prog, script):
                    printError(pkg, 'shell-syntax-error-in-' + tag)
                if home_regex.search(script_str):
                    printError(pkg, 'use-of-home-in-' + tag)
                res = bogus_var_regex.search(script_str)
                if res:
                    printWarning(pkg, 'bogus-variable-use-in-' + tag,
                                 res.group(1))

            if prog == '/usr/bin/perl':
                if incorrect_perl_script(prog, script):
                    printError(pkg, 'perl-syntax-error-in-' + tag)
            elif prog.endswith('sh'):
                res = single_command_regex.search(script_str)
                if res:
                    printWarning(pkg, 'one-line-command-in-' + tag,
                                 res.group(1))

        elif prog not in empty_shells and prog in valid_shells:
            printWarning(pkg, 'empty-' + tag)
Ejemplo n.º 8
0
def test_b2s():
    for thing in ("foo", ["foo"], None, []):
        assert thing == Pkg.b2s(thing)
    assert "foo" == Pkg.b2s(b"foo")
    assert ["foo"] == Pkg.b2s([b"foo"])