1 #pragma once
2 
3 #include <cstdint>
4 #include <cstdlib>
5 #include <cstring>
6 #include <fuzzing/memory.hpp>
7 #include <vector>
8 #include <string>
9 
10 namespace fuzzing {
11 namespace types {
12 
13 template <typename CoreType, bool NullTerminated, bool UseMSAN = false>
14 class Container {
15     private:
16         CoreType* InvalidAddress = (CoreType*)0x12;
17 
18         CoreType* _data = InvalidAddress;
19         size_t _size = 0;
20 
21 #ifndef FUZZING_HEADERS_NO_IMPL
copy(const void * data,size_t size)22         void copy(const void* data, size_t size) {
23             if ( size > 0 ) {
24                 std::memcpy(_data, data, size);
25             }
26         }
27 
allocate(size_t size)28         void allocate(size_t size) {
29             if ( size > 0 ) {
30                 _data = static_cast<CoreType*>(malloc(size * sizeof(CoreType)));
31             } else {
32                 _data = InvalidAddress;
33             }
34         };
35 
allocate_and_copy(const void * data,size_t size)36         void allocate_and_copy(const void* data, size_t size) {
37             allocate(size);
38             copy(data, size);
39         }
40 
allocate_plus_1_and_copy(const void * data,size_t size)41         void allocate_plus_1_and_copy(const void* data, size_t size) {
42             allocate(size+1);
43             copy(data, size);
44         }
45 
access_hook(void) const46         void access_hook(void) const {
47             if ( UseMSAN == true ) {
48                 memory::memory_test_msan(_data, _size);
49             }
50         }
51 
free(void)52         void free(void) {
53             access_hook();
54 
55             if ( _data != InvalidAddress ) {
56                 std::free(_data);
57                 _data = InvalidAddress;
58                 _size = 0;
59             }
60         }
61 
62 #endif
63 
64     public:
65 #ifndef FUZZING_HEADERS_NO_IMPL
data(void)66         CoreType* data(void) {
67             access_hook();
68             return _data;
69         }
70 
size(void) const71         size_t size(void) const {
72             access_hook();
73             return _size;
74         }
75 #endif
76 
77         Container(void)
78 #ifndef FUZZING_HEADERS_NO_IMPL
79         = default
80 #endif
81         ;
82 
Container(const void * data,const size_t size)83         Container(const void* data, const size_t size)
84 #ifndef FUZZING_HEADERS_NO_IMPL
85         {
86             if ( NullTerminated == false ) {
87                 allocate_and_copy(data, size);
88             } else {
89                 allocate_plus_1_and_copy(data, size);
90                 _data[size] = 0;
91             }
92 
93             access_hook();
94         }
95 #endif
96         ;
97 
98         template<class T>
Container(const T & t)99         Container(const T& t)
100 #ifndef FUZZING_HEADERS_NO_IMPL
101         {
102             Container(t.data(), t.size());
103         }
104 #endif
105         ;
106 
~Container(void)107         ~Container(void)
108 #ifndef FUZZING_HEADERS_NO_IMPL
109         {
110             this->free();
111         }
112 #endif
113         ;
114 
115 
116 
117         // The copy constructor was not originally explicitly supplied
118         // so it must have been incorrectly just copying the pointers.
Container(const Container & c)119         Container(const Container &c) {
120           InvalidAddress = c.InvalidAddress;
121           allocate_and_copy(c._data, c._size);
122         }
123 
operator =(Container & c)124         Container& operator=(Container &c) {
125           InvalidAddress = c.InvalidAddress;
126           allocate_and_copy(c._data, c._size);
127         }
128 
129 };
130 
131 template <bool UseMSAN = false> using String = Container<char, true, UseMSAN>;
132 template <bool UseMSAN = false> using Data = Container<uint8_t, false, UseMSAN>;
133 
134 } /* namespace types */
135 } /* namespace fuzzing */
136