File: test_fuzzing_sdiv.cpp

package info (click to toggle)
gringo 5.8.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 32,128 kB
  • sloc: cpp: 210,867; ansic: 37,507; python: 11,271; yacc: 825; javascript: 627; sh: 368; xml: 364; makefile: 102
file content (170 lines) | stat: -rw-r--r-- 5,147 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
///////////////////////////////////////////////////////////////////////////////
//  Copyright Christopher Kormanyos 2024.
//  Distributed under the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt
//  or copy at http://www.boost.org/LICENSE_1_0.txt)
//

// cd /mnt/c/Users/ckorm/Documents/Ks/PC_Software/NumericalPrograms/ExtendedNumberTypes/wide_integer
// clang++ -std=c++20 -g -O2 -Wall -Wextra -fsanitize=fuzzer -I. -I/mnt/c/boost/boost_1_85_0 test/fuzzing/test_fuzzing_sdiv.cpp -o test_fuzzing_sdiv
// ./test_fuzzing_sdiv -max_total_time=300

#include <math/wide_integer/uintwide_t.h>

#include <boost/multiprecision/cpp_int.hpp>

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <random>
#include <sstream>
#include <vector>

namespace fuzzing
{
  auto pseudo_random_sign_bit() -> int
  {
    static unsigned seed_prescaler { };

    static std::mt19937 engine { };

    if((seed_prescaler++ % 0x10000U) == 0U)
    {
      std::random_device rd { };

      engine.seed(rd());
    }

    // Create a uniform distribution for the bit position (0 to 1).
    static std::uniform_int_distribution<int> bit_dist(0, 1);

    // Generate a pseudo-random sign bit.
    return bit_dist(engine);
  }

  using boost_uint_backend_type =
    boost::multiprecision::cpp_int_backend<static_cast<unsigned>(UINT32_C(256)),
                                           static_cast<unsigned>(UINT32_C(256)),
                                           boost::multiprecision::unsigned_magnitude>;

  using boost_uint_type = boost::multiprecision::number<boost_uint_backend_type,
                                                        boost::multiprecision::et_off>;

  using local_uint_type = ::math::wide_integer::uint256_t;

  using boost_sint_backend_type =
    boost::multiprecision::cpp_int_backend<static_cast<unsigned>(UINT32_C(256)),
                                           static_cast<unsigned>(UINT32_C(256)),
                                           boost::multiprecision::signed_magnitude>;

  using boost_sint_type = boost::multiprecision::number<boost_sint_backend_type,
                                                        boost::multiprecision::et_off>;

  using local_sint_type = ::math::wide_integer::int256_t;

  auto eval_op(const std::uint8_t* data, std::size_t size) -> bool;
}

auto fuzzing::eval_op(const std::uint8_t* data, std::size_t size) -> bool
{
  const std::size_t
    max_size
    {
      static_cast<std::size_t>
      (
        std::numeric_limits<fuzzing::local_uint_type>::digits / 8
      )
    };

  bool result_is_ok { true };

  if((size > std::size_t { UINT8_C(1) }) && (size <= std::size_t { max_size * 2U }))
  {
    local_uint_type a_local { 0U };
    local_uint_type b_local { 0U };

    // Import data into the uintwide_t values.
    import_bits
    (
      a_local,
      data,
      data + std::size_t { size / 2U },
      8U
    );

    import_bits
    (
      b_local,
      data + std::size_t { size / 2U },
      data + size,
      8U
    );

    if(a_local + 256U < b_local)
    {
      std::swap(a_local, b_local);
    }

    if(b_local != 0U)
    {
      local_sint_type a_signed_local { a_local };
      local_sint_type b_signed_local { b_local };

      const int
        sign_mixer
        {
          (pseudo_random_sign_bit() << 1U) | pseudo_random_sign_bit()
        };

      if     (sign_mixer == 0) { }
      else if(sign_mixer == 1) { a_signed_local = -a_signed_local; }
      else if(sign_mixer == 2) { b_signed_local = -b_signed_local; }
      else                     { a_signed_local = -a_signed_local; b_signed_local = -b_signed_local; }

      std::stringstream strm_a_local { };
      std::stringstream strm_b_local { };

      strm_a_local << a_signed_local;
      strm_b_local << b_signed_local;

      boost_sint_type a_signed_boost { strm_a_local.str() };
      boost_sint_type b_signed_boost { strm_b_local.str() };

      local_sint_type result_signed_local { a_signed_local / b_signed_local };
      boost_sint_type result_signed_boost { a_signed_boost / b_signed_boost };

      std::vector<std::uint8_t> result_signed_data_local(max_size, UINT8_C(0));
      std::vector<std::uint8_t> result_signed_data_boost(result_signed_data_local.size(), UINT8_C(0));

      export_bits(result_signed_local, result_signed_data_local.data(), 8U);
      export_bits(result_signed_boost, result_signed_data_boost.data(), 8U);

      // Verify that both uintwide_t as well as boost obtain the same result.
      const bool result_op_is_ok =
        std::equal
        (
          result_signed_data_local.cbegin(),
          result_signed_data_local.cend(),
          result_signed_data_boost.cbegin(),
          result_signed_data_boost.cend()
        );

      result_is_ok = (result_op_is_ok && result_is_ok);
    }
  }

  // Assert the correct result.
  assert(result_is_ok);

  return result_is_ok;
}

// The fuzzing entry point.
extern "C"
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
  const bool result_one_div_is_ok { fuzzing::eval_op(data, size) };

  return (result_one_div_is_ok ? 0 : -1);
}