Use dict instead of OrderedDict
authorAlexander Popov <alex.popov@linux.com>
Mon, 13 May 2024 16:03:19 +0000 (19:03 +0300)
committerAlexander Popov <alex.popov@linux.com>
Mon, 13 May 2024 16:44:21 +0000 (19:44 +0300)
Changed in Python version 3.7:
Dictionary order is guaranteed to be insertion order.

This makes the code simpler and faster.

kernel_hardening_checker/__init__.py
kernel_hardening_checker/engine.py
kernel_hardening_checker/test_engine.py

index 601619ea9ac321c568fe85c8311c1a5257e58bf6..182f76fd7fdf67083747ac340279b26d130408d6 100644 (file)
@@ -13,8 +13,7 @@ This module performs input/output.
 import gzip
 import sys
 from argparse import ArgumentParser
-from collections import OrderedDict
-from typing import List, Tuple, OrderedDict, TextIO
+from typing import List, Tuple, Dict, TextIO
 import re
 import json
 from .__about__ import __version__
@@ -132,7 +131,7 @@ def print_checklist(mode: StrOrNone, checklist: List[ChecklistObjType], with_res
         print(f'[+] Config check is finished: \'OK\' - {ok_count}{ok_suppressed} / \'FAIL\' - {fail_count}{fail_suppressed}')
 
 
-def parse_kconfig_file(_mode: StrOrNone, parsed_options: OrderedDict[str, str], fname: str) -> None:
+def parse_kconfig_file(_mode: StrOrNone, parsed_options: Dict[str, str], fname: str) -> None:
     with _open(fname, 'rt', encoding='utf-8') as f:
         opt_is_on = re.compile(r"CONFIG_[a-zA-Z0-9_]+=.+$")
         opt_is_off = re.compile(r"# CONFIG_[a-zA-Z0-9_]+ is not set$")
@@ -161,7 +160,7 @@ def parse_kconfig_file(_mode: StrOrNone, parsed_options: OrderedDict[str, str],
                 parsed_options[option] = value
 
 
-def parse_cmdline_file(mode: StrOrNone, parsed_options: OrderedDict[str, str], fname: str) -> None:
+def parse_cmdline_file(mode: StrOrNone, parsed_options: Dict[str, str], fname: str) -> None:
     with open(fname, 'r', encoding='utf-8') as f:
         line = f.readline()
         opts = line.split()
@@ -183,7 +182,7 @@ def parse_cmdline_file(mode: StrOrNone, parsed_options: OrderedDict[str, str], f
             parsed_options[name] = value
 
 
-def parse_sysctl_file(mode: StrOrNone, parsed_options: OrderedDict[str, str], fname: str) -> None:
+def parse_sysctl_file(mode: StrOrNone, parsed_options: Dict[str, str], fname: str) -> None:
     with open(fname, 'r', encoding='utf-8') as f:
         sysctl_pattern = re.compile(r"[a-zA-Z0-9/\._-]+ =.*$")
         for line in f.readlines():
@@ -290,7 +289,7 @@ def main() -> None:
             add_sysctl_checks(config_checklist, arch)
 
         # populate the checklist with the parsed Kconfig data
-        parsed_kconfig_options = OrderedDict() # type: OrderedDict[str, str]
+        parsed_kconfig_options = {} # type: Dict[str, str]
         parse_kconfig_file(mode, parsed_kconfig_options, args.config)
         populate_with_data(config_checklist, parsed_kconfig_options, 'kconfig')
 
@@ -299,13 +298,13 @@ def main() -> None:
 
         if args.cmdline:
             # populate the checklist with the parsed cmdline data
-            parsed_cmdline_options = OrderedDict() # type: OrderedDict[str, str]
+            parsed_cmdline_options = {} # type: Dict[str, str]
             parse_cmdline_file(mode, parsed_cmdline_options, args.cmdline)
             populate_with_data(config_checklist, parsed_cmdline_options, 'cmdline')
 
         if args.sysctl:
             # populate the checklist with the parsed sysctl data
-            parsed_sysctl_options = OrderedDict() # type: OrderedDict[str, str]
+            parsed_sysctl_options = {} # type: Dict[str, str]
             parse_sysctl_file(mode, parsed_sysctl_options, args.sysctl)
             populate_with_data(config_checklist, parsed_sysctl_options, 'sysctl')
 
@@ -350,7 +349,7 @@ def main() -> None:
         add_sysctl_checks(config_checklist, None)
 
         # populate the checklist with the parsed sysctl data
-        parsed_sysctl_options = OrderedDict()
+        parsed_sysctl_options = {}
         parse_sysctl_file(mode, parsed_sysctl_options, args.sysctl)
         populate_with_data(config_checklist, parsed_sysctl_options, 'sysctl')
 
index a816c2911a16e74fbff6aa5612267cd8864980ab..7195bc01e8050e96a8c7218f048f368f5e9568ed 100644 (file)
@@ -14,10 +14,10 @@ This module is the engine of checks.
 from __future__ import annotations
 import sys
 
-from typing import Union, Optional, List, Dict, OrderedDict, Tuple
+from typing import Union, Optional, List, Dict, Tuple
 StrOrNone = Optional[str]
 TupleOrNone = Optional[Tuple]
-TupleOrOrderedDict = Union[Tuple, OrderedDict[str, str]]
+DictOrTuple = Union[Dict[str, str], Tuple]
 StrOrBool = Union[str, bool]
 
 GREEN_COLOR = '\x1b[32m'
@@ -338,7 +338,7 @@ ChecklistObjType = Union[KconfigCheck, CmdlineCheck, SysctlCheck, OR, AND]
 AnyOptCheckType = Union[KconfigCheck, CmdlineCheck, SysctlCheck, VersionCheck, OR, AND]
 
 
-def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: TupleOrOrderedDict, data_type: str) -> None:
+def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: DictOrTuple, data_type: str) -> None:
     assert(opt.opt_type != 'complex'), f'unexpected opt_type "{opt.opt_type}" for {opt}'
     assert(opt.opt_type in SIMPLE_OPTION_TYPES), f'invalid opt_type "{opt.opt_type}"'
     assert(data_type in SIMPLE_OPTION_TYPES), f'invalid data_type "{data_type}"'
@@ -348,7 +348,7 @@ def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: TupleOrOrderedD
         return
 
     if data_type in ('kconfig', 'cmdline', 'sysctl'):
-        assert(isinstance(data, OrderedDict)), \
+        assert(isinstance(data, dict)), \
                f'unexpected data with data_type {data_type}'
         assert(isinstance(opt, SimpleNamedOptCheckTypes)), \
                f'unexpected VersionCheck with opt_type "{opt.opt_type}"'
@@ -361,7 +361,7 @@ def populate_simple_opt_with_data(opt: SimpleOptCheckType, data: TupleOrOrderedD
         opt.set_state(data)
 
 
-def populate_opt_with_data(opt: AnyOptCheckType, data: TupleOrOrderedDict, data_type: str) -> None:
+def populate_opt_with_data(opt: AnyOptCheckType, data: DictOrTuple, data_type: str) -> None:
     assert(opt.opt_type != 'version'), 'a single VersionCheck is useless'
     if opt.opt_type != 'complex':
         assert(isinstance(opt, SimpleOptCheckTypes)), \
@@ -380,7 +380,7 @@ def populate_opt_with_data(opt: AnyOptCheckType, data: TupleOrOrderedDict, data_
                 populate_opt_with_data(o, data, data_type)
 
 
-def populate_with_data(checklist: List[ChecklistObjType], data: TupleOrOrderedDict, data_type: str) -> None:
+def populate_with_data(checklist: List[ChecklistObjType], data: DictOrTuple, data_type: str) -> None:
     for opt in checklist:
         populate_opt_with_data(opt, data, data_type)
 
@@ -398,7 +398,7 @@ def perform_checks(checklist: List[ChecklistObjType]) -> None:
         opt.check()
 
 
-def print_unknown_options(checklist: List[ChecklistObjType], parsed_options: OrderedDict[str, str], opt_type: str) -> None:
+def print_unknown_options(checklist: List[ChecklistObjType], parsed_options: Dict[str, str], opt_type: str) -> None:
     known_options = []
 
     for o1 in checklist:
index 3e5e60cf6c0ebf431344c59c94f4145af3ce9b21..d1745b3c9190ac5ba9d7bf709e7da57144c62c4c 100644 (file)
@@ -13,10 +13,9 @@ This module performs unit-testing of the kernel-hardening-checker engine.
 import unittest
 import io
 import sys
-from collections import OrderedDict
 import json
 import inspect
-from typing import Optional, List, OrderedDict, Tuple
+from typing import Optional, List, Dict, Tuple
 from .engine import ChecklistObjType, KconfigCheck, CmdlineCheck, SysctlCheck, VersionCheck, OR, AND, populate_with_data, perform_checks, override_expected_value
 
 
@@ -31,15 +30,15 @@ class TestEngine(unittest.TestCase):
         config_checklist += [SysctlCheck('reason_3', 'decision_3', 'sysctl_name', 'expected_3')]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_KCONFIG_NAME'] = 'UNexpected_1'
 
         # 3. prepare the parsed cmdline options
-        parsed_cmdline_options = OrderedDict()
+        parsed_cmdline_options  = {}
         parsed_cmdline_options['cmdline_name'] = 'expected_2'
 
         # 4. prepare the parsed sysctl options
-        parsed_sysctl_options = OrderedDict()
+        parsed_sysctl_options  = {}
         parsed_sysctl_options['sysctl_name'] = 'expected_3'
 
         # 5. prepare the kernel version
@@ -58,9 +57,9 @@ class TestEngine(unittest.TestCase):
 
     @staticmethod
     def run_engine(checklist: List[ChecklistObjType],
-                   parsed_kconfig_options: Optional[OrderedDict],
-                   parsed_cmdline_options: Optional[OrderedDict],
-                   parsed_sysctl_options: Optional[OrderedDict],
+                   parsed_kconfig_options: Optional[Dict],
+                   parsed_cmdline_options: Optional[Dict],
+                   parsed_sysctl_options: Optional[Dict],
                    kernel_version: Optional[Tuple]) -> None:
         # populate the checklist with data
         if parsed_kconfig_options:
@@ -126,7 +125,7 @@ class TestEngine(unittest.TestCase):
         config_checklist += [KconfigCheck('reason_10', 'decision_10', 'NAME_10', 'is not off')]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_1'] = 'expected_1'
         parsed_kconfig_options['CONFIG_NAME_2'] = 'UNexpected_2'
         parsed_kconfig_options['CONFIG_NAME_5'] = 'UNexpected_5'
@@ -169,7 +168,7 @@ class TestEngine(unittest.TestCase):
         config_checklist += [CmdlineCheck('reason_10', 'decision_10', 'name_10', 'is not off')]
 
         # 2. prepare the parsed cmdline options
-        parsed_cmdline_options = OrderedDict()
+        parsed_cmdline_options  = {}
         parsed_cmdline_options['name_1'] = 'expected_1'
         parsed_cmdline_options['name_2'] = 'UNexpected_2'
         parsed_cmdline_options['name_5'] = ''
@@ -212,7 +211,7 @@ class TestEngine(unittest.TestCase):
         config_checklist += [SysctlCheck('reason_10', 'decision_10', 'name_10', 'is not off')]
 
         # 2. prepare the parsed sysctl options
-        parsed_sysctl_options = OrderedDict()
+        parsed_sysctl_options  = {}
         parsed_sysctl_options['name_1'] = 'expected_1'
         parsed_sysctl_options['name_2'] = 'UNexpected_2'
         parsed_sysctl_options['name_5'] = ''
@@ -257,7 +256,7 @@ class TestEngine(unittest.TestCase):
                                 KconfigCheck('reason_12', 'decision_12', 'NAME_12', 'is not off'))]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_1'] = 'expected_1'
         parsed_kconfig_options['CONFIG_NAME_2'] = 'UNexpected_2'
         parsed_kconfig_options['CONFIG_NAME_3'] = 'UNexpected_3'
@@ -300,7 +299,7 @@ class TestEngine(unittest.TestCase):
                                  KconfigCheck('reason_12', 'decision_12', 'NAME_12', 'is not off'))]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_1'] = 'expected_1'
         parsed_kconfig_options['CONFIG_NAME_2'] = 'expected_2'
         parsed_kconfig_options['CONFIG_NAME_3'] = 'expected_3'
@@ -345,7 +344,7 @@ class TestEngine(unittest.TestCase):
                                      KconfigCheck('reason_12', 'decision_12', 'NAME_12', 'expected_12')))]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_1'] = 'expected_1'
         parsed_kconfig_options['CONFIG_NAME_2'] = 'UNexpected_2'
         parsed_kconfig_options['CONFIG_NAME_3'] = 'expected_3'
@@ -390,7 +389,7 @@ class TestEngine(unittest.TestCase):
                                  VersionCheck((42, 43, 45)))]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_2'] = 'expected_2'
         parsed_kconfig_options['CONFIG_NAME_4'] = 'expected_4'
         parsed_kconfig_options['CONFIG_NAME_6'] = 'expected_6'
@@ -425,16 +424,16 @@ class TestEngine(unittest.TestCase):
                                  SysctlCheck('reason_6', 'decision_6', 'name_6', 'expected_6'))]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_1'] = 'UNexpected_1'
 
         # 3. prepare the parsed cmdline options
-        parsed_cmdline_options = OrderedDict()
+        parsed_cmdline_options  = {}
         parsed_cmdline_options['name_2'] = 'expected_2'
         parsed_cmdline_options['name_5'] = 'UNexpected_5'
 
         # 4. prepare the parsed sysctl options
-        parsed_sysctl_options = OrderedDict()
+        parsed_sysctl_options  = {}
         parsed_sysctl_options['name_6'] = 'expected_6'
 
         # 5. run the engine
@@ -487,15 +486,15 @@ name_6                                  |sysctl | expected_6 |decision_6|     re
         config_checklist += [SysctlCheck('reason_3', 'decision_3', 'name_3', 'expected_3')]
 
         # 2. prepare the parsed kconfig options
-        parsed_kconfig_options = OrderedDict()
+        parsed_kconfig_options  = {}
         parsed_kconfig_options['CONFIG_NAME_1'] = 'expected_1_new'
 
         # 3. prepare the parsed cmdline options
-        parsed_cmdline_options = OrderedDict()
+        parsed_cmdline_options  = {}
         parsed_cmdline_options['name_2'] = 'expected_2_new'
 
         # 4. prepare the parsed sysctl options
-        parsed_sysctl_options = OrderedDict()
+        parsed_sysctl_options  = {}
         parsed_sysctl_options['name_3'] = 'expected_3_new'
 
         # 5. run the engine