-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add sequence which supports fuzzing (#2)
- Loading branch information
Showing
11 changed files
with
298 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
find_package(OpenCV REQUIRED) | ||
|
||
set(FUZZ_RUNTIME | ||
1 | ||
CACHE STRING "Number of seconds to run fuzz tests during ctest run") | ||
|
||
|
||
add_executable(Example_Fuzzer | ||
main.cpp | ||
) | ||
|
||
target_include_directories(Example_Fuzzer PUBLIC ${OpenCV_INCLUDE_DIRS} ) | ||
target_link_libraries(Example_Fuzzer PRIVATE FairyCam) | ||
|
||
target_compile_features(Example_Fuzzer PUBLIC cxx_std_20) | ||
|
||
target_link_libraries(Example_Fuzzer PRIVATE -coverage -fsanitize=fuzzer) | ||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") | ||
target_compile_options(Example_Fuzzer PRIVATE -fsanitize=fuzzer) | ||
target_link_libraries(Example_Fuzzer PUBLIC -fsanitize=address,undefined) | ||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") | ||
target_compile_options(Example_Fuzzer PRIVATE /fsanitize=fuzzer) | ||
target_compile_definitions(Example_Fuzzer PRIVATE "-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS") | ||
endif() | ||
|
||
add_test(NAME Example_Fuzzer COMMAND Example_Fuzzer -max_total_time=${FUZZ_RUNTIME} -timeout=${FUZZ_RUNTIME}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include <cstdint> | ||
#include <span> | ||
|
||
#include <AnyCamera.hpp> | ||
#include <MemoryCamera.hpp> | ||
#include <chaos/BinaryBlobSequence.hpp> | ||
#include <chaos/ChaosCamera.hpp> | ||
|
||
void my_system(FairyCam::IsAnyCamera auto cam) | ||
{ | ||
while (true) | ||
{ | ||
try | ||
{ | ||
if (!cam.isOpened()) | ||
cam.open(0, 0, {}); | ||
cv::Mat m; | ||
cam.read(m); | ||
} | ||
catch (const std::exception &) | ||
{ | ||
// custom error handling | ||
} | ||
} | ||
} | ||
|
||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | ||
{ | ||
FairyCam::MemoryCamera cam( | ||
{.images = {cv::Mat(1, 1, CV_8UC1)}, .circular = true}); | ||
|
||
auto span = std::span(data, data + size); | ||
auto chaosCam = FairyCam::ChaosCamera(std::move(cam), | ||
FairyCam::BinaryBlobSequence(span)); | ||
try | ||
{ | ||
my_system(std::move(chaosCam)); | ||
} | ||
catch (FairyCam::SequenceEndException) | ||
{ | ||
// this exception indicated, that the program should stop | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#pragma once | ||
|
||
#include <cassert> | ||
#include <concepts> | ||
#include <cstdint> | ||
#include <functional> | ||
#include <span> | ||
#include <vector> | ||
|
||
#include "Exceptions.hpp" | ||
#include "Sequence.hpp" | ||
|
||
namespace FairyCam | ||
{ | ||
|
||
class BinaryBlobSequence : public Sequence | ||
{ | ||
std::span<const uint8_t> m_data; | ||
std::span<const uint8_t>::iterator m_iter; | ||
|
||
struct FailException | ||
{ | ||
std::vector<std::function<void()>> exceptions; | ||
}; | ||
|
||
FailException m_open; | ||
FailException m_grab; | ||
FailException m_retrieve; | ||
|
||
void check(const FailException &exp) | ||
{ | ||
if (m_iter == m_data.end()) | ||
throw SequenceEndException{}; | ||
uint8_t val = *m_iter; | ||
++m_iter; | ||
if (val == 0) | ||
return; | ||
std::invoke(exp.exceptions[val % exp.exceptions.size()]); | ||
} | ||
|
||
public: | ||
class Fail | ||
{ | ||
std::vector<std::function<void()>> exceptions; | ||
friend BinaryBlobSequence; | ||
|
||
public: | ||
template <std::default_initializable ExceptionT> Fail &with() | ||
{ | ||
exceptions.push_back([]() { throw ExceptionT{}; }); | ||
return *this; | ||
} | ||
}; | ||
|
||
struct Options | ||
{ | ||
Fail isOpen = Fail().with<NotOpenException>(); | ||
Fail grab = Fail().with<GrabException>(); | ||
Fail retrieve = Fail().with<RetrieveException>(); | ||
}; | ||
|
||
BinaryBlobSequence(std::span<const uint8_t> data, Options opts) | ||
: m_data(data), m_iter(m_data.begin()), | ||
m_open{std::move(opts.isOpen.exceptions)}, | ||
m_grab{std::move(opts.grab.exceptions)}, | ||
m_retrieve{std::move(opts.retrieve.exceptions)} | ||
{ | ||
} | ||
|
||
BinaryBlobSequence(std::span<const uint8_t> data) | ||
: BinaryBlobSequence(data, Options()) | ||
{ | ||
} | ||
|
||
void checkIsOpen() override { check(m_open); } | ||
void checkRetrieve() override { check(m_retrieve); } | ||
void checkGrab() override { check(m_grab); } | ||
}; | ||
|
||
} // namespace FairyCam |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#pragma once | ||
|
||
#include "Sequence.hpp" | ||
|
||
namespace FairyCam | ||
{ | ||
|
||
class NoErrorSequence : public Sequence | ||
{ | ||
virtual void checkIsOpen(){}; | ||
virtual void checkRetrieve(){}; | ||
virtual void checkGrab(){}; | ||
}; | ||
} // namespace FairyCam |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#include <array> | ||
#include <concepts> | ||
#include <doctest.h> | ||
#include <span> | ||
#include <vector> | ||
|
||
#include <chaos/BinaryBlobSequence.hpp> | ||
|
||
using namespace FairyCam; | ||
|
||
TEST_SUITE("BinaryBlobSequence") | ||
{ | ||
TEST_CASE("always or never") | ||
{ | ||
// for (auto [failIsOpen, failGrab, failRetrieve] : | ||
// std::views::cartesian_product( | ||
// std::array{0,1}, std::array{0,1}, std::array{0,1})) | ||
for (auto [failIsOpen, failGrab, failRetrieve] : std::vector{ | ||
std::array{0, 0, 0}, std::array{0, 0, 1}, std::array{0, 1, 0}, | ||
std::array{0, 1, 1}, std::array{1, 0, 0}, std::array{1, 0, 1}, | ||
std::array{1, 1, 0}, std::array{1, 1, 1}}) | ||
{ | ||
CAPTURE(failIsOpen); | ||
CAPTURE(failGrab); | ||
CAPTURE(failRetrieve); | ||
|
||
std::array blob = {static_cast<uint8_t>(failIsOpen * 255), | ||
static_cast<uint8_t>(failGrab * 255), | ||
static_cast<uint8_t>(failRetrieve * 255)}; | ||
|
||
BinaryBlobSequence s(std::span(blob.data(), blob.size())); | ||
|
||
if (failIsOpen) | ||
REQUIRE_THROWS_AS(s.checkIsOpen(), NotOpenException); | ||
else | ||
s.checkIsOpen(); | ||
|
||
if (failGrab) | ||
REQUIRE_THROWS_AS(s.checkGrab(), GrabException); | ||
else | ||
s.checkGrab(); | ||
|
||
if (failRetrieve) | ||
REQUIRE_THROWS_AS(s.checkRetrieve(), RetrieveException); | ||
else | ||
s.checkRetrieve(); | ||
|
||
REQUIRE_THROWS_AS(s.checkRetrieve(), SequenceEndException); | ||
REQUIRE_THROWS_AS(s.checkGrab(), SequenceEndException); | ||
REQUIRE_THROWS_AS(s.checkIsOpen(), SequenceEndException); | ||
} | ||
} | ||
|
||
TEST_CASE("custom exceptions") | ||
{ | ||
struct CustomException1 | ||
{ | ||
}; | ||
|
||
struct CustomException2 | ||
{ | ||
}; | ||
|
||
// for (auto [failIsOpen, failGrab, failRetrieve] : | ||
// std::views::cartesian_product( | ||
// std::array{0,1}, std::array{0,1}, std::array{0,1})) | ||
|
||
for (auto [failIsOpen, failGrab, failRetrieve] : std::vector{ | ||
std::array{0, 0, 0}, std::array{0, 0, 1}, std::array{0, 1, 0}, | ||
std::array{0, 1, 1}, std::array{1, 0, 0}, std::array{1, 0, 1}, | ||
std::array{1, 1, 0}, std::array{1, 1, 1}}) | ||
{ | ||
CAPTURE(failIsOpen); | ||
CAPTURE(failGrab); | ||
CAPTURE(failRetrieve); | ||
|
||
std::array blob = {static_cast<uint8_t>(failIsOpen * 255), | ||
static_cast<uint8_t>(failGrab * 255), | ||
static_cast<uint8_t>(failRetrieve * 254), | ||
static_cast<uint8_t>(failRetrieve * 255)}; | ||
|
||
BinaryBlobSequence s( | ||
std::span(blob.data(), blob.size()), | ||
{.isOpen = BinaryBlobSequence::Fail().with<CustomException1>(), | ||
.grab = BinaryBlobSequence::Fail().with<CustomException2>(), | ||
.retrieve = BinaryBlobSequence::Fail() | ||
.with<CustomException1>() | ||
.with<CustomException2>()}); | ||
|
||
if (failIsOpen) | ||
REQUIRE_THROWS_AS(s.checkIsOpen(), CustomException1); | ||
else | ||
s.checkIsOpen(); | ||
|
||
if (failGrab) | ||
REQUIRE_THROWS_AS(s.checkGrab(), CustomException2); | ||
else | ||
s.checkGrab(); | ||
|
||
if (failRetrieve) | ||
{ | ||
REQUIRE_THROWS_AS(s.checkRetrieve(), CustomException1); | ||
REQUIRE_THROWS_AS(s.checkRetrieve(), CustomException2); | ||
} | ||
else | ||
{ | ||
s.checkRetrieve(); | ||
s.checkRetrieve(); | ||
} | ||
|
||
REQUIRE_THROWS_AS(s.checkRetrieve(), SequenceEndException); | ||
REQUIRE_THROWS_AS(s.checkGrab(), SequenceEndException); | ||
REQUIRE_THROWS_AS(s.checkIsOpen(), SequenceEndException); | ||
} | ||
} | ||
} |