/src/immer/extra/fuzzer/fuzzer_input.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // immer: immutable data structures for C++ |
3 | | // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente |
4 | | // |
5 | | // This software is distributed under the Boost Software License, Version 1.0. |
6 | | // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt |
7 | | // |
8 | | |
9 | | #pragma once |
10 | | |
11 | | #include <cstdint> |
12 | | #include <memory> |
13 | | #include <stdexcept> |
14 | | |
15 | | #if defined(__GNUC__) && (__GNUC__ == 9 || __GNUC__ == 8 || __GNUC__ == 10) |
16 | | #define IMMER_DISABLE_FUZZER_DUE_TO_GCC_BUG 1 |
17 | | #endif |
18 | | |
19 | | struct no_more_input : std::exception |
20 | | {}; |
21 | | |
22 | | constexpr auto fuzzer_input_max_size = 1 << 16; |
23 | | |
24 | | struct fuzzer_input |
25 | | { |
26 | | const std::uint8_t* data_; |
27 | | std::size_t size_; |
28 | | |
29 | | const std::uint8_t* next(std::size_t size) |
30 | 554k | { |
31 | 554k | if (size_ < size) |
32 | 0 | throw no_more_input{}; |
33 | 554k | auto r = data_; |
34 | 554k | data_ += size; |
35 | 554k | size_ -= size; |
36 | 554k | return r; |
37 | 554k | } |
38 | | |
39 | | const std::uint8_t* next(std::size_t size, std::size_t align) |
40 | 558k | { |
41 | 558k | auto& p = const_cast<void*&>(reinterpret_cast<const void*&>(data_)); |
42 | 558k | auto r = std::align(align, size, p, size_); |
43 | 558k | if (r == nullptr) |
44 | 4.29k | throw no_more_input{}; |
45 | 554k | return next(size); |
46 | 558k | } |
47 | | |
48 | | template <typename Fn> |
49 | | int run(Fn step) |
50 | 4.29k | { |
51 | 4.29k | if (size_ > fuzzer_input_max_size) |
52 | 1 | return 0; |
53 | 4.29k | try { |
54 | 120k | while (step(*this)) |
55 | 116k | continue; |
56 | 4.29k | } catch (const no_more_input&) { |
57 | 4.29k | }; |
58 | 4.29k | return 0; |
59 | 4.29k | } |
60 | | }; |
61 | | |
62 | | template <typename T> |
63 | | const T& read(fuzzer_input& fz) |
64 | 558k | { |
65 | 558k | return *reinterpret_cast<const T*>(fz.next(sizeof(T), alignof(T))); |
66 | 558k | } char const& read<char>(fuzzer_input&) Line | Count | Source | 64 | 470k | { | 65 | 470k | return *reinterpret_cast<const T*>(fz.next(sizeof(T), alignof(T))); | 66 | 470k | } |
unsigned long const& read<unsigned long>(fuzzer_input&) Line | Count | Source | 64 | 87.6k | { | 65 | 87.6k | return *reinterpret_cast<const T*>(fz.next(sizeof(T), alignof(T))); | 66 | 87.6k | } |
|
67 | | |
68 | | template <typename T, typename Cond> |
69 | | T read(fuzzer_input& fz, Cond cond) |
70 | 237k | { |
71 | 237k | auto x = read<T>(fz); |
72 | 354k | while (!cond(x)) |
73 | 116k | x = read<T>(fz); |
74 | 237k | return x; |
75 | 237k | } |