File indexing completed on 2024-05-05 05:44:15

0001 /*
0002     SPDX-FileCopyrightText: 2021 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "suppressions.h"
0008 
0009 #include <cstring>
0010 #include <fstream>
0011 #include <iostream>
0012 
0013 #include <boost/algorithm/string/trim.hpp>
0014 
0015 namespace {
0016 std::vector<std::string> parseSuppressionsFile(std::istream& input)
0017 {
0018     std::vector<std::string> ret;
0019     std::string line;
0020     while (std::getline(input, line)) {
0021         auto suppression = parseSuppression(line);
0022         if (!suppression.empty()) {
0023             ret.push_back(std::move(suppression));
0024         }
0025     }
0026     return ret;
0027 }
0028 
0029 /**
0030  * This function is based on the TemplateMatch function found in
0031  *     llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp
0032  * The code was licensed under Apache License v2.0 with LLVM Exceptions
0033  */
0034 bool TemplateMatch(const char* templ, const char* str)
0035 {
0036     if ((!str) || str[0] == 0)
0037         return false;
0038     bool start = false;
0039     if (templ && templ[0] == '^') {
0040         start = true;
0041         templ++;
0042     }
0043     bool asterisk = false;
0044     while (templ && templ[0]) {
0045         if (templ[0] == '*') {
0046             templ++;
0047             start = false;
0048             asterisk = true;
0049             continue;
0050         }
0051         if (templ[0] == '$')
0052             return str[0] == 0 || asterisk;
0053         if (str[0] == 0)
0054             return false;
0055         char* tpos = (char*)strchr(templ, '*');
0056         char* tpos1 = (char*)strchr(templ, '$');
0057         if ((!tpos) || (tpos1 && tpos1 < tpos))
0058             tpos = tpos1;
0059         if (tpos)
0060             tpos[0] = 0;
0061         const char* str0 = str;
0062         const char* spos = strstr(str, templ);
0063         str = spos + strlen(templ);
0064         templ = tpos;
0065         if (tpos)
0066             tpos[0] = tpos == tpos1 ? '$' : '*';
0067         if (!spos)
0068             return false;
0069         if (start && spos != str0)
0070             return false;
0071         start = false;
0072         asterisk = false;
0073     }
0074     return true;
0075 }
0076 }
0077 
0078 std::string parseSuppression(std::string line)
0079 {
0080     boost::trim(line, std::locale::classic());
0081     if (line.empty() || line[0] == '#') {
0082         // comment
0083         return {};
0084     } else if (line.compare(0, 5, "leak:") == 0) {
0085         return line.substr(5);
0086     }
0087     std::cerr << "invalid suppression line: " << line << '\n';
0088     return {};
0089 }
0090 
0091 std::vector<std::string> parseSuppressions(const std::string& suppressionFile, bool* ok)
0092 {
0093     if (ok) {
0094         *ok = true;
0095     }
0096 
0097     if (suppressionFile.empty()) {
0098         return {};
0099     }
0100 
0101     auto stream = std::ifstream(suppressionFile);
0102     if (!stream.is_open()) {
0103         std::cerr << "failed to open suppression file: " << suppressionFile << '\n';
0104         if (ok) {
0105             *ok = false;
0106         }
0107         return {};
0108     }
0109 
0110     return parseSuppressionsFile(stream);
0111 }
0112 
0113 bool matchesSuppression(const std::string& suppression, const std::string& haystack)
0114 {
0115     return suppression == haystack || TemplateMatch(suppression.c_str(), haystack.c_str());
0116 }
0117 
0118 std::vector<Suppression> builtinSuppressions()
0119 {
0120     return {
0121         // libc
0122         {"__nss_module_allocate", 0, 0},
0123         {"__gconv_read_conf", 0, 0},
0124         {"__new_exitfn", 0, 0},
0125         {"tzset_internal", 0, 0},
0126         // dynamic linker
0127         {"dl_open_worker", 0, 0},
0128         // glib event loop
0129         {"g_main_context_new", 0, 0},
0130         {"g_main_context_new", 0, 0},
0131         {"g_thread_self", 0, 0},
0132     };
0133 }