Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "include/skiplist.h"
#include <fstream>
#include <sstream>
namespace QtFuzz {
static bool tagMatchesCurrentPlatform(const std::string &tag)
{
if (tag == "All")
return true;
#if defined(_WIN32) || defined(_WIN64)
return tag == "Windows" || tag == "Windows11";
#elif defined(__APPLE__)
return tag == "macOS" || tag == "mac";
#elif defined(__ANDROID__)
return tag == "Android";
#elif defined(__EMSCRIPTEN__)
return tag == "WASM";
#elif defined(__linux__)
return tag == "Linux";
#else
return false;
#endif
}
static void parseInto(const fs::path &path, std::unordered_set<std::string> &skippedClasses,
std::unordered_set<std::string> &skippedFunctions,
std::unordered_set<std::string> &crashFunctions)
{
if (path.empty())
return;
std::ifstream file(path);
if (!file)
return;
bool sectionSeen = false;
bool applies = false;
std::string line;
while (std::getline(file, line)) {
const auto commentPos = line.find('#');
if (commentPos != std::string::npos)
line.resize(commentPos);
const auto first = line.find_first_not_of(" \t\r\n");
if (first == std::string::npos)
continue;
const auto last = line.find_last_not_of(" \t\r\n");
line = line.substr(first, last - first + 1);
if (line.empty())
continue;
if (line.front() == '[' && line.back() == ']') {
std::string tag = line.substr(1, line.size() - 2);
const auto tf = tag.find_first_not_of(" \t");
if (tf == std::string::npos) {
sectionSeen = false;
applies = false;
} else {
const auto tl = tag.find_last_not_of(" \t");
tag = tag.substr(tf, tl - tf + 1);
sectionSeen = true;
applies = tagMatchesCurrentPlatform(tag);
}
continue;
}
if (!sectionSeen || !applies)
continue;
std::string target, action;
std::istringstream ss(line);
if (!(ss >> target >> action))
continue;
const bool isFunction = target.find("::") != std::string::npos;
if (action == "skip") {
if (isFunction)
skippedFunctions.insert(target);
else
skippedClasses.insert(target);
} else if (action == "expectCrash") {
if (isFunction)
crashFunctions.insert(target);
}
}
}
SkipList::SkipList(const fs::path &path)
{
parseInto(path, m_skippedClasses, m_skippedFunctions, m_crashFunctions);
}
void SkipList::load(const fs::path &path)
{
parseInto(path, m_skippedClasses, m_skippedFunctions, m_crashFunctions);
}
bool SkipList::isClassSkipped(const std::string &className) const
{
return m_skippedClasses.count(className) > 0;
}
bool SkipList::isFunctionSkipped(const std::string &className,
const std::string &functionName) const
{
return m_skippedFunctions.count(className + "::" + functionName) > 0;
}
bool SkipList::expectsCrash(const std::string &className, const std::string &functionName) const
{
return m_crashFunctions.count(className + "::" + functionName) > 0;
}
} // namespace QtFuzz