From e2f28db985e8d66702e0dbea7d24ac2cca0935c4 Mon Sep 17 00:00:00 2001 From: firewave Date: Tue, 17 Dec 2024 18:40:14 +0100 Subject: [PATCH] fixed #13440 - do not crash when whole program analysis addon execution fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel Marjamäki --- lib/cppcheck.cpp | 18 +++++++------ test/cli/other_test.py | 57 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 5a270d938ca..36498e4a3d1 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1682,8 +1682,15 @@ void CppCheck::executeAddons(const std::vector& files, const std::s if (isCtuInfo && addonInfo.name != "misra" && !addonInfo.ctu) continue; - const std::vector results = - executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mSettings.premiumArgs, mExecuteCommand); + std::vector results; + + try { + results = executeAddon(addonInfo, mSettings.addonPython, fileList.empty() ? files[0] : fileList, mSettings.premiumArgs, mExecuteCommand); + } catch (const InternalError& e) { + const std::string ctx = isCtuInfo ? "Whole program analysis" : "Checking file"; + const ErrorMessage errmsg = ErrorMessage::fromInternalError(e, nullptr, file0, "Bailing out from analysis: " + ctx + " failed"); + mErrorLogger.reportErr(errmsg); + } const bool misraC2023 = mSettings.premiumArgs.find("--misra-c-2023") != std::string::npos; @@ -1779,12 +1786,7 @@ void CppCheck::executeAddonsWholeProgram(const std::list &files ctuInfoFiles.push_back(getCtuInfoFileName(dumpFileName)); } - try { - executeAddons(ctuInfoFiles, ""); - } catch (const InternalError& e) { - const ErrorMessage errmsg = ErrorMessage::fromInternalError(e, nullptr, "", "Bailing out from analysis: Whole program analysis failed"); - mErrorLogger.reportErr(errmsg); - } + executeAddons(ctuInfoFiles, ""); } Settings &CppCheck::settings() diff --git a/test/cli/other_test.py b/test/cli/other_test.py index b5fbe73f9e9..2a7b0b6cd85 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -197,7 +197,7 @@ def test_progress_j(tmpdir): assert stderr == "" -def test_execute_addon_failure(tmpdir): +def test_execute_addon_failure_py_auto(tmpdir): test_file = os.path.join(tmpdir, 'test.cpp') with open(test_file, 'wt') as f: f.write(""" @@ -212,14 +212,14 @@ def test_execute_addon_failure(tmpdir): assert stderr == '{}:0:0: error: Bailing out from analysis: Checking file failed: Failed to auto detect python [internalError]\n\n^\n'.format(test_file) -def test_execute_addon_failure_2(tmpdir): +def test_execute_addon_failure_py_notexist(tmpdir): test_file = os.path.join(tmpdir, 'test.cpp') with open(test_file, 'wt') as f: f.write(""" void f(); """) - # specify non-existent python executbale so execution of addon fails + # specify non-existent python executable so execution of addon fails args = ['--addon=naming', '--addon-python=python5.x', test_file] _, _, stderr = cppcheck(args) @@ -227,6 +227,57 @@ def test_execute_addon_failure_2(tmpdir): assert stderr == "{}:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon 'naming' - exitcode is {} [internalError]\n\n^\n".format(test_file, ec) +def test_execute_addon_failure_json_notexist(tmpdir): + # specify non-existent python executable so execution of addon fails + addon_json = os.path.join(tmpdir, 'addon.json') + with open(addon_json, 'wt') as f: + f.write(json.dumps({'executable': 'notexist'})) + + test_file = os.path.join(tmpdir, 'test.cpp') + with open(test_file, 'wt') as f: + f.write(""" + void f(); + """) + + args = [ + '--addon={}'.format(addon_json), + test_file + ] + + _, _, stderr = cppcheck(args) + ec = 1 if os.name == 'nt' else 127 + assert stderr == "{}:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon 'addon.json' - exitcode is {} [internalError]\n\n^\n".format(test_file, ec) + + +def test_execute_addon_failure_json_ctu_notexist(tmpdir): + # specify non-existent python executable so execution of addon fails + addon_json = os.path.join(tmpdir, 'addon.json') + with open(addon_json, 'wt') as f: + f.write(json.dumps({ + 'executable': 'notexist', + 'ctu': True + })) + + test_file = os.path.join(tmpdir, 'test.cpp') + with open(test_file, 'wt') as f: + f.write(""" + void f(); """) + + args = [ + '--template=simple', + '--addon={}'.format(addon_json), + test_file + ] + + _, _, stderr = cppcheck(args) + ec = 1 if os.name == 'nt' else 127 + print(stderr) + assert stderr.splitlines() == [ + "{}:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon 'addon.json' - exitcode is {} [internalError]".format(test_file, ec), + ":0:0: error: Bailing out from analysis: Whole program analysis failed: Failed to execute addon 'addon.json' - exitcode is {} [internalError]".format(ec) + ] + + def test_execute_addon_file0(tmpdir): test_file = os.path.join(tmpdir, 'test.c') with open(test_file, 'wt') as f: