diff --git a/circle.yml b/circle.yml index bb6210ac..e6fe6f6e 100644 --- a/circle.yml +++ b/circle.yml @@ -124,13 +124,13 @@ scan_build_run: &scan_build_run - *fedora_install - run: name: Install clang and find - command: dnf install -y clang-analyzer findutils + command: dnf install -y clang-analyzer findutils python3-beautifulsoup4 - checkout - *ninja_scan_build - *export_logs - run: name: Check scan-build results - command: test ! -d ~/libratbag/build/meson-logs/scanbuild || test $(find ~/libratbag/build/meson-logs/scanbuild -maxdepth 0 ! -empty -exec echo "not empty" \; | wc -l) -eq 0 || (echo "Check scan-build results" && false) + command: python3 ~/libratbag/tools/check_scan_build.py ~/libratbag/build/meson-logs/scanbuild doc_build: &doc_build <<: *default_settings diff --git a/src/hidpp20.c b/src/hidpp20.c index 0c3382a6..d3996e33 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -2362,7 +2362,7 @@ hidpp20_onboard_profiles_parse(struct hidpp20_device *device, profiles->sector_size, data); if (rc < 0) - return rc; + return rc; // ignore_clang_sa_mem_leak crc_valid = hidpp20_onboard_profiles_is_sector_valid(device, profiles->sector_size, diff --git a/src/libratbag-data.c b/src/libratbag-data.c index 7ae4bb67..1de4f252 100644 --- a/src/libratbag-data.c +++ b/src/libratbag-data.c @@ -388,7 +388,7 @@ file_data_matches(struct ratbag *ratbag, data->refcount = 1; data->name = g_key_file_get_string(keyfile, GROUP_DEVICE, "Name", NULL); if (!data->name) { - return false; + return false; // ignore_clang_sa_mem_leak } data->driver = g_key_file_get_string(keyfile, GROUP_DEVICE, "Driver", NULL); diff --git a/tools/check_scan_build.py b/tools/check_scan_build.py new file mode 100755 index 00000000..c5d13f72 --- /dev/null +++ b/tools/check_scan_build.py @@ -0,0 +1,99 @@ +#!/bin/env python3 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +import bs4 +import os +import re +import sys + + +class Bug(object): + def __init__(self): + self.line_number = None + self.cfile = None + self.sa_type = None + self.sa_descr = None + + +def main(argv): + if len(argv) < 2: + print(f'usage {argv[0]} PATH') + sys.exit(1) + + scanbuild_path = argv[1] + + ignored = [] + bugs = [] + + line_re = re.compile(r'line (\d+), column (\d+)') + + for root, dirs, files in os.walk(scanbuild_path): + for filename in files: + if not filename.startswith('report'): + continue + + with open(os.path.join(root, filename)) as f: + soup = bs4.BeautifulSoup(f, 'html.parser') + + # the first table is the summary + summary = soup.table + bug = Bug() + + # iterate over the table + for tr in summary('tr'): + if 'File:' in tr.contents[0].string: + bug.cfile = os.path.abspath(tr.contents[1].string) + else: + bug.sa_type = tr.contents[0].string.rstrip(':').lower() + for s in tr.contents[1].strings: + # retrieve the line number and the description + m = line_re.match(s) + if m is None: + bug.sa_descr = s + else: + bug.line_number = int(m.group(1)) + + # retrieve the html line corresponding to the code + code = soup.find('td', id=f'LN{bug.line_number}').parent + + # fetching any comments in this line + try: + comments = code.find('span', class_='comment').string + except AttributeError: + # no comments on the line + bugs.append(bug) + else: + if 'ignore_clang_sa_' in comments: + ignored.append(bug) + else: + bugs.append(bug) + + if len(ignored) > 0: + print(f'{len(ignored)} bugs are ignored:') + for b in ignored: + print(f' {b.sa_type}: {b.sa_descr} at {b.cfile}:{b.line_number}') + + if len(bugs) > 0: + print() + + if len(bugs) > 0: + print(f'ERROR: {len(bugs)} bugs found:') + for b in bugs: + print(f' * {b.sa_type.upper()}: {b.sa_descr} at {b.cfile}:{b.line_number}') + sys.exit(1) + + sys.exit(0) + + +if __name__ == '__main__': + main(sys.argv)