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 <appar...@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/] -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor