From 617b7a39cd3af10f477db55689617b53da94e360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 8 Nov 2023 15:23:50 +0100 Subject: [PATCH] Fix #12163 (misra.py: crashes when ctu-info line does not have certain attributes) (#5638) --- addons/misra.py | 22 +++++++++++++++++----- addons/test/test-misra.py | 34 +++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/addons/misra.py b/addons/misra.py index 192147db5..b09c2ff8a 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -4618,6 +4618,19 @@ class MisraChecker: self.executeCheck(2209, self.misra_22_9, cfg) self.executeCheck(2210, self.misra_22_10, cfg) + def read_ctu_info_line(self, line): + if not line.startswith('{'): + return None + try: + ctu_info = json.loads(line) + except json.decoder.JSONDecodeError: + return None + if 'summary' not in ctu_info: + return None + if 'data' not in ctu_info: + return None + return ctu_info + def analyse_ctu_info(self, ctu_info_files): all_typedef_info = {} all_tagname_info = {} @@ -4639,12 +4652,11 @@ class MisraChecker: try: for filename in ctu_info_files: for line in open(filename, 'rt'): - if not line.startswith('{'): + s = self.read_ctu_info_line(line) + if s is None: continue - - s = json.loads(line) - summary_type = s['summary'] - summary_data = s['data'] + summary_type = s.get('summary', '') + summary_data = s.get('data', None) if summary_type == 'MisraTypedefInfo': for new_typedef_info in summary_data: diff --git a/addons/test/test-misra.py b/addons/test/test-misra.py index debd4f2a6..3ae6380b8 100644 --- a/addons/test/test-misra.py +++ b/addons/test/test-misra.py @@ -7,9 +7,11 @@ # Command in cppcheck directory: # PYTHONPATH=./addons python3 -m pytest addons/test/test-misra.py +import os import pytest import re import sys +import tempfile from .util import dump_create, dump_remove, convert_json_output @@ -25,16 +27,6 @@ def remove_misra_config(s:str): return ret -def setup_module(module): - for f in TEST_SOURCE_FILES: - dump_create(f) - - -def teardown_module(module): - for f in TEST_SOURCE_FILES: - dump_remove(f) - - @pytest.fixture(scope="function") def checker(): from addons.misra import MisraChecker, MisraSettings, get_args_parser @@ -44,6 +36,15 @@ def checker(): return MisraChecker(settings) +@pytest.fixture +def test_files(): + for f in TEST_SOURCE_FILES: + dump_create(f) + yield + for f in TEST_SOURCE_FILES: + dump_remove(f) + + def test_loadRuleTexts_structure(checker): checker.loadRuleTexts("./addons/test/misra/misra_rules_structure.txt") assert(checker.ruleTexts.get(101, None) is None) @@ -83,7 +84,7 @@ def test_rules_misra_severity(checker): assert(checker.ruleTexts[2104].misra_severity == '') -def test_json_out(checker, capsys): +def test_json_out(checker, capsys, test_files): sys.argv.append("--cli") checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") checker.parseDump("./addons/test/misra/misra-test.c.dump") @@ -96,7 +97,7 @@ def test_json_out(checker, capsys): assert("Advisory" in json_output['c2012-20.1'][0]['extra']) -def test_rules_cppcheck_severity(checker, capsys): +def test_rules_cppcheck_severity(checker, capsys, test_files): checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") checker.parseDump("./addons/test/misra/misra-test.c.dump") captured = capsys.readouterr().err @@ -104,7 +105,7 @@ def test_rules_cppcheck_severity(checker, capsys): assert("(warning)" not in captured) assert("(style)" in captured) -def test_rules_cppcheck_severity_custom(checker, capsys): +def test_rules_cppcheck_severity_custom(checker, capsys, test_files): checker.loadRuleTexts("./addons/test/misra/misra_rules_dummy.txt") checker.setSeverity("custom-severity") checker.parseDump("./addons/test/misra/misra-test.c.dump") @@ -167,3 +168,10 @@ def test_arguments_regression(): sys.argv.remove(arg) finally: sys.argv = sys_argv_old + + +def test_read_ctu_info_line(checker): + assert checker.read_ctu_info_line('{') is None + assert checker.read_ctu_info_line('{"summary":"123"}') is None + assert checker.read_ctu_info_line('{"data":123}') is None + assert checker.read_ctu_info_line('{"summary":"123","data":123}') is not None