File 0001-Improve-XDG-Menu-checks-stability.patch of Package rpmlint.17311

From 8de78fa8b0cd9a2fe4156b841429ac8d55b39909 Mon Sep 17 00:00:00 2001
From: Dirk Mueller <dirk@dmllr.de>
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,9 +8,9 @@
 
 import os
 try:
-    from ConfigParser import RawConfigParser
-except:
-    from configparser import RawConfigParser
+    import ConfigParser as cfgparser
+except ImportError:
+    import configparser as cfgparser
 
 import AbstractCheck
 from Filter import addDetails, printError, printWarning
@@ -25,7 +25,52 @@ class MenuXDGCheck(AbstractCheck.Abstrac
         # $ echo $XDG_DATA_DIRS/applications
         # /var/lib/menu-xdg:/usr/share
         AbstractCheck.AbstractFilesCheck.__init__(
-            self, "MenuXDGCheck", r"/usr/share/applications/.*\.desktop$")
+            self, "MenuXDGCheck", r'(?:/usr|/etc/opt|/opt/.*)/share/applications/.*\.desktop$')
+
+    def parse_desktop_file(self, pkg, root, f, filename):
+        cfp = cfgparser.RawConfigParser()
+        try:
+            with open(f, 'rb') 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()
@@ -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.''',
 )
openSUSE Build Service is sponsored by