From 122aa6ae54cad704ba28f0d6e117e7d709dfb771 Mon Sep 17 00:00:00 2001 From: Samat Tamerlan Date: Tue, 13 Aug 2024 15:15:05 +0200 Subject: [PATCH] fixed compile error and license file added --- .../analyzers/infer/LICENSE.txt | 24 +++++++++ .../analyzers/infer/analyzer.py | 53 ++++++++++--------- .../analyzers/infer/config_handler.py | 1 - .../analyzers/infer/result_handler.py | 2 +- .../analyze_and_parse/test_files/Makefile | 2 +- .../test_files/infer_simple.c | 16 ++++++ .../test_files/infer_simple.cpp | 9 ---- .../test_files/infer_simple.output | 28 +++++----- 8 files changed, 83 insertions(+), 52 deletions(-) create mode 100644 analyzer/codechecker_analyzer/analyzers/infer/LICENSE.txt create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.c delete mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.cpp diff --git a/analyzer/codechecker_analyzer/analyzers/infer/LICENSE.txt b/analyzer/codechecker_analyzer/analyzers/infer/LICENSE.txt new file mode 100644 index 0000000000..264eac1052 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/infer/LICENSE.txt @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +The following license is valid for descriptions.json file located in the +current directory (codechecker/analyzer/codechecker_analyzer/analyzers/infer/) \ No newline at end of file diff --git a/analyzer/codechecker_analyzer/analyzers/infer/analyzer.py b/analyzer/codechecker_analyzer/analyzers/infer/analyzer.py index 1546166046..1bd81b14b1 100644 --- a/analyzer/codechecker_analyzer/analyzers/infer/analyzer.py +++ b/analyzer/codechecker_analyzer/analyzers/infer/analyzer.py @@ -6,6 +6,7 @@ # # ------------------------------------------------------------------------- """ +Module for Facebook Infer analyzer related methods """ from collections import defaultdict # TODO distutils will be removed in python3.12 @@ -25,6 +26,7 @@ from .config_handler import InferConfigHandler from .result_handler import InferResultHandler +from codechecker_analyzer.buildlog.log_parser import IGNORED_OPTIONS_GCC LOG = get_logger('analyzer.infer') @@ -45,7 +47,6 @@ def add_checker_config(self, checker_cfg): # TODO pass - @classmethod def get_analyzer_mentioned_files(self, output): """ This is mostly used for CTU. @@ -61,7 +62,7 @@ def construct_analyzer_cmd(self, result_handler): # unforeseen exceptions where a general catch is justified? config = self.config_handler - analyzer_cmd = [Infer.analyzer_binary(), 'run'] + analyzer_cmd = [Infer.analyzer_binary(), 'run', '--keep-going'] for checker_name, value in config.checks().items(): filtered_name = checker_name.replace("infer-", "") @@ -69,8 +70,6 @@ def construct_analyzer_cmd(self, result_handler): filtered_name = filtered_name.upper() if value[0] == CheckerState.disabled: - # TODO python3.9 removeprefix method would be nicer - # than startswith and a hardcoded slicing analyzer_cmd.extend(['--disable-issue-type', filtered_name]) else: analyzer_cmd.extend(['--enable-issue-type', filtered_name]) @@ -78,35 +77,41 @@ def construct_analyzer_cmd(self, result_handler): output_dir = Path(result_handler.workspace, "infer", result_handler.buildaction_hash) output_dir.mkdir(exist_ok=True, parents=True) - analyzer_cmd.extend(['-o', str(output_dir)]) + analyzer_cmd.append('--') - compile_lang = self.buildaction.lang - analyzer_cmd.extend(['--', compile_lang, '-c', self.source_file]) + cmd_filtered = [] + for cmd in shlex.split(self.buildaction.original_command): + if IGNORED_OPTIONS_GCC.match(cmd) and \ + self.buildaction.lang in ['c', 'c++']: + continue + cmd_filtered.append(cmd) - # analyzer_cmd.append(self.source_file) + if self.buildaction.lang == 'c++': + cmd_filtered.append('-stdlib=libc++') + analyzer_cmd.extend(cmd_filtered) LOG.debug_analyzer("Running analysis command " f"'{shlex.join(analyzer_cmd)}'") return analyzer_cmd @classmethod - def get_analyzer_checkers(self): + def get_analyzer_checkers(cls): """ Return the list of the supported checkers. """ - command = [self.analyzer_binary(), "help", "--list-issue-types"] - - desc = json.load(open(Path(__file__).parent / "descriptions.json")) - + command = [cls.analyzer_binary(), "help", "--list-issue-types"] + desc = json.load( + open(Path(__file__).parent / "descriptions.json", + "r", encoding="utf-8")) checker_list = [] try: output = subprocess.check_output(command, stderr=subprocess.DEVNULL) for entry in output.decode().split('\n'): data = entry.strip().split(":") - if (len(data) < 7): + if len(data) < 7: continue entry_id = data[0].lower() @@ -119,7 +124,6 @@ def get_analyzer_checkers(self): entry_id = entry_id.replace("_", "-") checker_list.append((f"infer-{entry_id}", description)) - return checker_list except (subprocess.CalledProcessError) as e: LOG.error(e.stderr) @@ -141,7 +145,7 @@ def get_checker_config(cls): """ return [] - def analyze(self, analyzer_cmd, res_handler, proc_callback=None): + def analyze(self, analyzer_cmd, res_handler, proc_callback=None, env=None): env = None original_env_file = os.environ.get( @@ -156,40 +160,37 @@ def post_analyze(self, result_handler: InferResultHandler): """ Post process the results after the analysis. """ - pass @classmethod - def resolve_missing_binary(cls, configured_binary, env): + def resolve_missing_binary(cls, configured_binary, environ): """ In case of the configured binary for the analyzer is not found in the PATH, this method is used to find a callable binary. """ - pass @classmethod - def get_binary_version(self, environ, details=False) -> str: + def get_binary_version(cls, environ, details=False) -> str: """ Return the analyzer version. """ # No need to LOG here, we will emit a warning later anyway. - if not self.analyzer_binary(): + if not cls.analyzer_binary(): return None if details: - version = [self.analyzer_binary(), '--version'] + version = [cls.analyzer_binary(), '--version'] else: - # version = [self.analyzer_binary(), '-dumpfullversion'] - version = [self.analyzer_binary(), '--version'] + version = [cls.analyzer_binary(), '--version'] try: output = subprocess.check_output(version, env=environ, encoding="utf-8", errors="ignore") - return output.split('\n')[0].strip().split(" ")[-1][1:] + output = output.split('\n', maxsplit=1)[0] + return output.strip().split(" ")[-1][1:] except (subprocess.CalledProcessError, OSError) as oerr: LOG.warning("Failed to get analyzer version: %s", ' '.join(version)) LOG.warning(oerr) - return None @classmethod diff --git a/analyzer/codechecker_analyzer/analyzers/infer/config_handler.py b/analyzer/codechecker_analyzer/analyzers/infer/config_handler.py index 313e7d0b19..757ed19dc4 100644 --- a/analyzer/codechecker_analyzer/analyzers/infer/config_handler.py +++ b/analyzer/codechecker_analyzer/analyzers/infer/config_handler.py @@ -15,4 +15,3 @@ class InferConfigHandler(config_handler.AnalyzerConfigHandler): """ Configuration handler for Infer analyzer. """ - pass diff --git a/analyzer/codechecker_analyzer/analyzers/infer/result_handler.py b/analyzer/codechecker_analyzer/analyzers/infer/result_handler.py index 2ba0b885f9..d0fd59877c 100644 --- a/analyzer/codechecker_analyzer/analyzers/infer/result_handler.py +++ b/analyzer/codechecker_analyzer/analyzers/infer/result_handler.py @@ -36,7 +36,7 @@ def __init__(self, *args, **kwargs): self.analyzer_info = AnalyzerInfo(name=AnalyzerResult.TOOL_NAME) self.infer_analyzer_result = AnalyzerResult() - super(InferResultHandler, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def postprocess_result( self, diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/Makefile b/analyzer/tests/functional/analyze_and_parse/test_files/Makefile index 3588216c4d..e949927faf 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_files/Makefile +++ b/analyzer/tests/functional/analyze_and_parse/test_files/Makefile @@ -54,4 +54,4 @@ cppcheck_undef_include: gcc_simple: $(CXX) -w gcc_simple.cpp -o /dev/null -c infer_simple: - $(CXX) -w infer_simple.cpp -o /dev/null -c \ No newline at end of file + $(CXX) -w infer_simple.c -o /dev/null -c \ No newline at end of file diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.c b/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.c new file mode 100644 index 0000000000..eb5cd308c9 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.c @@ -0,0 +1,16 @@ +#include + +typedef struct p { + int age; + char *name; +} Person; + +int main() { + Person *p = (Person*)malloc(sizeof(Person)); + p->age = 10; + p->name = "John"; + free(p); + + p->age = 20; // Null Dereference + return 0; +} \ No newline at end of file diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.cpp b/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.cpp deleted file mode 100644 index 8e02d20e4b..0000000000 --- a/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include -using namespace std; - -int main() -{ - int n = 123; - int m = n + 456; - return 0; -} \ No newline at end of file diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.output b/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.output index 045d8ebaf9..e0b902f4b5 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.output +++ b/analyzer/tests/functional/analyze_and_parse/test_files/infer_simple.output @@ -1,5 +1,5 @@ NORMAL#CodeChecker log --output $LOGFILE$ --build "make infer_simple" --quiet -NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers infer --enable=infer-dead-store +NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers infer --enable=infer-null-dereference NORMAL#CodeChecker parse $OUTPUT$ CHECK#CodeChecker check --build "make infer_simple" --output $OUTPUT$ --quiet --analyzers infer --enable=infer-dead-store ----------------------------------------------- @@ -18,11 +18,11 @@ CHECK#CodeChecker check --build "make infer_simple" --output $OUTPUT$ --quiet -- [] - To store results use the "CodeChecker store" command. [] - See --help and the user guide for further options about parsing and storing the reports. [] - ----=================---- -[HIGH] infer_simple.cpp:7:5: The value written to &m (type int) is never used. [infer-dead-store] - int m = n + 456; +[HIGH] infer_simple.c:10:5: pointer `p` last assigned on line 9 could be null and is dereferenced at line 10, column 5. [infer-null-dereference] + p->age = 10; ^ -Found 1 defect(s) in infer_simple.cpp +Found 1 defect(s) in infer_simple.c ----==== Severity Statistics ====---- @@ -34,19 +34,19 @@ HIGH | 1 ----=================---- ----==== Checker Statistics ====---- ------------------------------------------------ -Checker name | Severity | Number of reports ------------------------------------------------ -infer-dead-store | HIGH | 1 ------------------------------------------------ +----------------------------------------------------- +Checker name | Severity | Number of reports +----------------------------------------------------- +infer-null-dereference | HIGH | 1 +----------------------------------------------------- ----=================---- ----==== File Statistics ====---- ------------------------------------- -File name | Number of reports ------------------------------------- -infer_simple.cpp | 1 ------------------------------------- +---------------------------------- +File name | Number of reports +---------------------------------- +infer_simple.c | 1 +---------------------------------- ----=================---- ----======== Summary ========----