From e6594808fdf6c1fcb4175c523582ab7c358839f0 Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Fri, 29 Sep 2017 09:12:33 +0200 Subject: [PATCH] Improve XDG Menu checks stability Running RawConfigParser on untrusted input can cause a lot of exceptions. Handle them gracefully and raise appropriate rpmlint errors. Also separate the code a little and cleaning it up. --- MenuXDGCheck.py | 84 ++++++++++++++++++++++++++---------- test/binary/menuxdg1-0-0.noarch.rpm | Bin 0 -> 6555 bytes test/test_menuxdg.py | 17 ++++++++ 3 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 test/binary/menuxdg1-0-0.noarch.rpm create mode 100644 test/test_menuxdg.py Index: rpmlint-rpmlint-1.10/MenuXDGCheck.py =================================================================== --- rpmlint-rpmlint-1.10.orig/MenuXDGCheck.py +++ rpmlint-rpmlint-1.10/MenuXDGCheck.py @@ -8,15 +8,15 @@ import os try: - from ConfigParser import RawConfigParser + import ConfigParser as cfgparser except: - from configparser import RawConfigParser + import configparser as cfgparser import AbstractCheck from Filter import addDetails, printError, printWarning from Pkg import getstatusoutput, is_utf8 -STANDARD_BIN_DIRS = ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'] +STANDARD_BIN_DIRS = ('/bin', '/sbin', '/usr/bin', '/usr/sbin') class MenuXDGCheck(AbstractCheck.AbstractFilesCheck): @@ -27,6 +27,51 @@ class MenuXDGCheck(AbstractCheck.Abstrac AbstractCheck.AbstractFilesCheck.__init__( self, "MenuXDGCheck", r"(?:/usr/share|/etc/opt/.*/share|/opt/.*)/applications/.*\.desktop$") + def parse_desktop_file(self, pkg, root, f, filename): + cfp = cfgparser.RawConfigParser() + try: + with open(f) as inputf: + cfp.readfp(inputf, filename) + except cfgparser.DuplicateSectionError as e: + printError( + pkg, 'desktopfile-duplicate-section', filename, + '[%s]' % e.section) + except cfgparser.MissingSectionHeaderError: + printError( + pkg, 'desktopfile-missing-header', filename) + except cfgparser.Error as e: + # Only in Python >= 3.2 + if (hasattr(cfgparser, 'DuplicateOptionError') and + isinstance(e, cfgparser.DuplicateOptionError)): + printError( + pkg, 'desktopfile-duplicate-option', filename, + '[%s]/%s' % (e.section, e.option)) + else: + printWarning( + pkg, 'invalid-desktopfile', filename, + e.message.partition(':')[0]) + except UnicodeDecodeError as e: + printWarning( + pkg, 'invalid-desktopfile', filename, 'No valid Unicode') + else: + binary = None + if cfp.has_option('Desktop Entry', 'Exec'): + binary = cfp.get('Desktop Entry', 'Exec').partition(' ')[0] + if binary: + found = False + if binary.startswith('/'): + found = os.path.exists(root + binary) + else: + for i in STANDARD_BIN_DIRS: + if os.path.exists(root + i + '/' + binary): + # no need to check if the binary is +x, rpmlint does it + # in another place + found = True + break + if not found: + printWarning( + pkg, 'desktopfile-without-binary', filename, binary) + def check_file(self, pkg, filename): root = pkg.dirName() f = root + filename @@ -43,25 +88,7 @@ class MenuXDGCheck(AbstractCheck.Abstrac if not is_utf8(f): printError(pkg, 'non-utf8-desktopfile', filename) - cfp = RawConfigParser() - cfp.read(f) - binary = None - if cfp.has_option('Desktop Entry', 'Exec'): - binary = cfp.get('Desktop Entry', 'Exec').split(' ', 1)[0] - if binary: - found = False - if binary.startswith('/'): - found = os.path.exists(root + binary) - else: - for i in STANDARD_BIN_DIRS: - if os.path.exists(root + i + binary): - # no need to check if the binary is +x, rpmlint does it - # in another place - found = True - break - if not found: - printWarning(pkg, 'desktopfile-without-binary', filename, - binary) + self.parse_desktop_file(pkg, root, f, filename) check = MenuXDGCheck() @@ -76,4 +103,15 @@ addDetails( 'desktopfile-without-binary', '''the .desktop file is for a file not present in the package. You should check the requires or see if this is not a error''', + +'desktopfile-duplicate-section', +'''The .desktop file contains the mentioned section name twice, which +can trigger parsing ambiguities. Remove the duplicate.''', + +'desktopfile-duplicate-option', +'''The .desktop file contains the mentioned option key twice, +which can trigger parsing ambiguities. Remove the duplicate.''', + +'desktopfile-missing-header', +'''The .desktop file should start with a section header.''', )