From 3df5fd9507215cf70a1147ea631cf061475c7b34 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 | 76 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 23 deletions(-) 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,43 @@ 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: + cfp.read(f) + except cfgparser.DuplicateSectionError as e: + printError( + pkg, 'desktopfile-duplicate-section', filename, + '[%s]' % e.section) + except cfgparser.DuplicateOptionError as e: + printError( + pkg, 'desktopfile-duplicate-option', filename, + '[%s]/%s' % (e.section, e.option)) + except cfgparser.MissingSectionHeaderError: + printError( + pkg, 'desktopfile-missing-header', filename) + except (cfgparser.ParsingError, UnicodeDecodeError) as e: + printWarning( + pkg, 'invalid-desktopfile', filename) + 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 +80,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 +95,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.''', )