CI: add fuzzing and sanitizing (#5)

This commit is contained in:
Vaxry 2023-12-31 16:51:50 +01:00 committed by GitHub
parent bf6300d316
commit 1db2a12767
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 153 additions and 23 deletions

View file

@ -19,22 +19,102 @@ jobs:
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy gcc base-devel cmake clang
- name: Build with gcc
- name: Build hyprlang with gcc
run: |
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cp ./build/libhyprlang.so /usr/lib
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target hyprlang -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install ./build
- name: Build with clang
- name: Build tests with clang
run: |
rm -rf ./build
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
rm ./build/libhyprlang.so
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --build ./build --config Release --target tests -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
- name: Run tests
run: |
cd ./tests && ../build/hyprlang_test
cd ./build && ctest --output-on-failure
asan:
name: "gcc build / ASan tests"
runs-on: ubuntu-latest
container:
image: archlinux
steps:
- name: Checkout repository actions
uses: actions/checkout@v4
with:
sparse-checkout: .github/actions
- name: Get required pkgs
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy gcc base-devel cmake clang
- name: Build with gcc
run: |
CXXFLAGS="-fsanitize=address" CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CXXFLAGS="-fsanitize=address" CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install ./build
- name: Run tests
run: |
cd ./build && ctest --output-on-failure
ubsan:
name: "gcc build / UBSan tests"
runs-on: ubuntu-latest
container:
image: archlinux
steps:
- name: Checkout repository actions
uses: actions/checkout@v4
with:
sparse-checkout: .github/actions
- name: Get required pkgs
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy gcc base-devel cmake clang
- name: Build with gcc
run: |
CXXFLAGS="-fsanitize=undefined" CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CXXFLAGS="-fsanitize=undefined" CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install ./build
- name: Run tests
run: |
cd ./build && ctest --output-on-failure
msan:
name: "gcc build / MSan tests"
runs-on: ubuntu-latest
container:
image: archlinux
steps:
- name: Checkout repository actions
uses: actions/checkout@v4
with:
sparse-checkout: .github/actions
- name: Get required pkgs
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy gcc base-devel cmake clang
- name: Build with gcc
run: |
CXXFLAGS="-fsanitize=leak" CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CXXFLAGS="-fsanitize=leak" CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install ./build
- name: Run tests
run: |
cd ./build && ctest --output-on-failure
clang:
name: "clang build / gcc test"
@ -53,22 +133,21 @@ jobs:
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy gcc base-devel cmake clang
- name: Build with clang
- name: Build hyprlang with clang
run: |
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cp ./build/libhyprlang.so /usr/lib
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CC="/usr/bin/clang" CXX="/usr/bin/clang++" cmake --build ./build --config Release --target hyprlang -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install ./build
- name: Build with gcc
- name: Build tests with gcc
run: |
rm -rf ./build
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
rm ./build/libhyprlang.so
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
CC="/usr/bin/gcc" CXX="/usr/bin/g++" cmake --build ./build --config Release --target tests -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
- name: Run tests
run: |
cd ./tests && ../build/hyprlang_test
cd ./build && ctest --output-on-failure
doxygen:
name: "Deploy docs"

View file

@ -25,9 +25,18 @@ set_target_properties(hyprlang PROPERTIES PUBLIC_HEADER include/hyprlang.hpp)
install(TARGETS hyprlang)
add_executable(hyprlang_test "tests/main.cpp")
# tests
add_custom_target(tests)
add_executable(hyprlang_test "tests/parse/main.cpp")
target_link_libraries(hyprlang_test PRIVATE hyprlang)
add_test(NAME "Parsing" WORKING_DIRECTORY "../tests/" COMMAND hyprlang_test "parse")
add_dependencies(tests hyprlang_test)
add_executable(hyprlang_fuzz "tests/fuzz/main.cpp")
target_link_libraries(hyprlang_fuzz PRIVATE hyprlang)
add_test(NAME "Fuzz" WORKING_DIRECTORY "../tests/" COMMAND hyprlang_fuzz "fuzz")
add_dependencies(tests hyprlang_fuzz)
# Installation
install(TARGETS hyprlang

View file

@ -92,7 +92,7 @@ void CConfigValue::defaultFrom(SConfigDefaultValue& ref) {
break;
}
case CONFIGDATATYPE_STR: {
if (!m_pData)
if (m_pData)
free(m_pData);
std::string str = std::any_cast<std::string>(ref.data);
m_pData = calloc(1, str.length() + 1);
@ -131,7 +131,8 @@ void CConfigValue::setFrom(std::any value) {
break;
}
case CONFIGDATATYPE_STR: {
free(m_pData);
if (m_pData)
free(m_pData);
std::string str = std::any_cast<std::string>(value);
m_pData = calloc(1, str.length() + 1);
strncpy((char*)m_pData, str.c_str(), str.length());

View file

@ -351,11 +351,10 @@ CParseResult CConfig::parseVariable(const std::string& lhs, const std::string& r
else {
impl->variables.push_back({lhs.substr(1), rhs});
std::sort(impl->variables.begin(), impl->variables.end(), [](const auto& lhs, const auto& rhs) { return lhs.name.length() > rhs.name.length(); });
IT = std::find_if(impl->variables.begin(), impl->variables.end(), [&](const auto& v) { return v.name == lhs.substr(1); });
}
if (dynamic) {
if (IT == impl->variables.end())
IT = std::find_if(impl->variables.begin(), impl->variables.end(), [&](const auto& v) { return v.name == lhs.substr(1); });
for (auto& l : IT->linesContainingVar) {
parseLine(l, true);
}

42
tests/fuzz/main.cpp Normal file
View file

@ -0,0 +1,42 @@
#include <iostream>
#include <hyprlang.hpp>
#define FUZZ_ITERS 1337
std::string garbage() {
srand(time(nullptr));
int len = rand() % 10000;
std::string chars;
for (int i = 0; i < len; ++i) {
chars += rand() % 254 + 1;
}
return chars;
}
int main(int argc, char** argv, char** envp) {
Hyprlang::CConfig config("./eeeeeeeUnused", {.allowMissingConfig = true});
config.addConfigValue("test", {0L});
config.parseDynamic("");
config.parseDynamic("", "");
config.parseDynamic("}");
for (size_t i = 0; i < FUZZ_ITERS; ++i) {
config.parseDynamic(garbage().c_str(), garbage().c_str());
config.parseDynamic((garbage() + "=" + garbage()).c_str());
config.parseDynamic(garbage().c_str());
config.parseDynamic((garbage() + " {").c_str());
config.parseDynamic((std::string{"test = "} + garbage()).c_str());
config.parseDynamic((std::string{"$"} + garbage()).c_str());
config.parseDynamic((std::string{"$VAR = "} + garbage()).c_str());
}
config.parseDynamic("}");
std::cout << "Success, no fuzzing errors\n";
return 0;
}