[apparmor] [patch] Adjust type(x) == str checks in the rule classes for py2

Christian Boltz apparmor at cboltz.de
Sun Nov 29 21:19:02 UTC 2015


Hallo,

python 3 uses only the 'str' type, while python 2 also uses 'unicode'.
This patch adds a type_is_str() function to common.py - depending on the
python version, it checks for both. This helper function is used to keep
the complexity outside of the rule classes.

The rule classes get adjusted to use type_is_str() instead of checking
for type(x) == str, which means they support both python versions.

Finally, add test-common.py with some tests for type_is_str().

References: https://bugs.launchpad.net/apparmor/+bug/1513880


I propose this patch for trunk and 2.10 (except the rule/signal.py
change because 2.10 doesn't contain SignalRule yet)


[ 21-change-rule-classes-for-py2-str-type.diff ]

=== modified file ./utils/apparmor/common.py
--- utils/apparmor/common.py    2014-12-17 00:54:04.150444000 +0100
+++ utils/apparmor/common.py    2015-11-29 21:14:49.301661957 +0100
@@ -245,6 +245,15 @@
         return False
     return True
 
+def type_is_str(var):
+    ''' returns True if the given variable is a str (or unicode string when using python 2)'''
+    if type(var) == str:
+        return True
+    elif sys.version_info[0] < 3 and type(var) == unicode:  # python 2 sometimes uses the 'unicode' type
+        return True
+    else:
+        return False
+
 class DebugLogger(object):
     def __init__(self, module_name=__name__):
         self.debugging = False
=== modified file ./utils/apparmor/rule/capability.py
--- utils/apparmor/rule/capability.py   2015-07-17 00:19:58.515815472 +0200
+++ utils/apparmor/rule/capability.py   2015-11-29 21:15:57.373653618 +0100
@@ -14,7 +14,7 @@
 # ----------------------------------------------------------------------
 
 from apparmor.regex import RE_PROFILE_CAP
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
 import re
 
@@ -47,7 +47,7 @@
             self.all_caps = True
             self.capability = set()
         else:
-            if type(cap_list) == str:
+            if type_is_str(cap_list):
                 self.capability = {cap_list}
             elif type(cap_list) == list and len(cap_list) > 0:
                 self.capability = set(cap_list)
=== modified file ./utils/apparmor/rule/change_profile.py
--- utils/apparmor/rule/change_profile.py       2015-07-17 00:19:58.529814641 +0200
+++ utils/apparmor/rule/change_profile.py       2015-11-29 21:16:36.585638082 +0100
@@ -14,7 +14,7 @@
 # ----------------------------------------------------------------------
 
 from apparmor.regex import RE_PROFILE_CHANGE_PROFILE, strip_quotes
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, quote_if_needed
 
 # setup module translations
@@ -48,7 +48,7 @@
         self.all_execconds = False
         if execcond == ChangeProfileRule.ALL:
             self.all_execconds = True
-        elif type(execcond) == str:
+        elif type_is_str(execcond):
             if not execcond.strip():
                 raise AppArmorBug('Empty exec condition in change_profile rule')
             elif execcond.startswith('/') or execcond.startswith('@'):
@@ -62,7 +62,7 @@
         self.all_targetprofiles = False
         if targetprofile == ChangeProfileRule.ALL:
             self.all_targetprofiles = True
-        elif type(targetprofile) == str:
+        elif type_is_str(targetprofile):
             if targetprofile.strip():
                 self.targetprofile = targetprofile
             else:
=== modified file ./utils/apparmor/rule/network.py
--- utils/apparmor/rule/network.py      2015-08-24 21:32:50.122441922 +0200
+++ utils/apparmor/rule/network.py      2015-11-29 21:17:13.125616867 +0100
@@ -16,7 +16,7 @@
 import re
 
 from apparmor.regex import RE_PROFILE_NETWORK
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
 
 # setup module translations
@@ -66,7 +66,7 @@
         self.all_domains = False
         if domain == NetworkRule.ALL:
             self.all_domains = True
-        elif type(domain) == str:
+        elif type_is_str(domain):
             if domain in network_domain_keywords:
                 self.domain = domain
             else:
@@ -78,7 +78,7 @@
         self.all_type_or_protocols = False
         if type_or_protocol == NetworkRule.ALL:
             self.all_type_or_protocols = True
-        elif type(type_or_protocol) == str:
+        elif type_is_str(type_or_protocol):
             if type_or_protocol in network_protocol_keywords:
                 self.type_or_protocol = type_or_protocol
             elif type_or_protocol in network_type_keywords:
=== modified file ./utils/apparmor/rule/rlimit.py
--- utils/apparmor/rule/rlimit.py       2015-07-17 00:19:58.574811968 +0200
+++ utils/apparmor/rule/rlimit.py       2015-11-29 21:18:18.101563810 +0100
@@ -16,7 +16,7 @@
 import re
 
 from apparmor.regex import RE_PROFILE_RLIMIT, strip_quotes
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
 
 # setup module translations
@@ -57,7 +57,7 @@
         if audit or deny or allow_keyword:
             raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.')
 
-        if type(rlimit) == str:
+        if type_is_str(rlimit):
             if rlimit in rlimit_all:
                 self.rlimit = rlimit
             else:
@@ -70,7 +70,7 @@
         self.all_values = False
         if value == RlimitRule.ALL:
             self.all_values = True
-        elif type(value) == str:
+        elif type_is_str(value):
             if not value.strip():
                 raise AppArmorBug('Empty value in rlimit rule')
 
=== modified file ./utils/apparmor/rule/signal.py
--- utils/apparmor/rule/signal.py       2015-11-23 22:15:45.411432694 +0100
+++ utils/apparmor/rule/signal.py       2015-11-29 21:18:38.877542865 +0100
@@ -16,7 +16,7 @@
 
 from apparmor.aare import AARE
 from apparmor.regex import RE_PROFILE_SIGNAL, RE_PROFILE_NAME
-from apparmor.common import AppArmorBug, AppArmorException
+from apparmor.common import AppArmorBug, AppArmorException, type_is_str
 from apparmor.rule import BaseRule, BaseRuleset, check_and_split_list, parse_modifiers, quote_if_needed
 
 # setup module translations
@@ -96,7 +96,7 @@
         self.all_peers = False
         if peer == SignalRule.ALL:
             self.all_peers = True
-        elif type(peer) == str:
+        elif type_is_str(peer):
             if len(peer.strip()) == 0:
                 raise AppArmorBug('Passed empty peer to SignalRule: %s' % str(peer))
             self.peer = AARE(peer, False, log_event=log_event)
=== modified file ./utils/test/test-common.py
--- utils/test/test-common.py   2015-11-29 21:58:47.320305689 +0100
+++ utils/test/test-common.py   2015-11-29 21:13:39.121644329 +0100
@@ -0,0 +1,32 @@
+#! /usr/bin/env python
+# ------------------------------------------------------------------
+#
+#    Copyright (C) 2015 Christian Boltz <apparmor at cboltz.de>
+#
+#    This program is free software; you can redistribute it and/or
+#    modify it under the terms of version 2 of the GNU General Public
+#    License published by the Free Software Foundation.
+#
+# ------------------------------------------------------------------
+
+import unittest
+from common_test import AATest, setup_all_loops
+
+from apparmor.common import type_is_str
+
+class TestIs_str_type(AATest):
+    tests = [
+        ('foo',     True),
+        (u'foo',    True),
+        (42,        False),
+        (True,      False),
+        ([],        False),
+    ]
+
+    def _run_test(self, params, expected):
+        self.assertEqual(type_is_str(params), expected)
+
+
+setup_all_loops(__name__)
+if __name__ == '__main__':
+    unittest.main(verbosity=2)


Regards,

Christian Boltz
-- 
[BILD] Als langjährig tätiger Strafverteidiger (und Fan von Volker
Pispers) muß ich jedoch dringend davor warnen, stinkende tote Fische in
dieses Freiexemplar der sogenannten "Zeitung" einzuwickeln. Weil das ein
Strafverfahren wegen Beleidigung zulasten des Fisches nach sich ziehen
könnte.
[http://www.kanzlei-hoenig.de/2012/keine-stinkende-tote-fische-im-briefkasten/]




More information about the AppArmor mailing list