-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathStorageModule.hpp
More file actions
311 lines (281 loc) · 12 KB
/
Copy pathStorageModule.hpp
File metadata and controls
311 lines (281 loc) · 12 KB
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/* =============================================================================
* Vader Modular Fuzzer (VMF)
* Copyright (c) 2021-2025 The Charles Stark Draper Laboratory, Inc.
* <vmf@draper.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 (only) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @license GPL-2.0-only <https://spdx.org/licenses/GPL-2.0-only.html>
* ===========================================================================*/
#pragma once
#include "Module.hpp"
#include "StorageEntry.hpp"
#include "StorageEntryListener.hpp"
#include "Iterator.hpp"
#include <memory>
namespace vmf
{
/**
* @brief Base class for VMF Storage Modules
*
* Storage modules provide for storage of test cases and their associated data. Support
* for global metadata variables is provided as well.
*
* Implementors of this base class must also implement all methods in StorageEntryLister.
* Note that the StorageEntryListener methods, init(), and configure(), are not intended to be used
* by other modules. clearNewAndLocalEntries() should only be called by Controller modules.
*
*/
class StorageModule : public Module, public StorageEntryListener {
public:
/** Destructor */
virtual ~StorageModule() {};
//-----------------Used by the VMF Application-----------------------
virtual void init(ConfigInterface& config) = 0;
/**
* @brief Configure storage
*
* This method should only be called by the VMF application, and must be
* called before anything is read or written to storage.
*
* @param registry the fields and tags that must be maintained by storage
* @param metadata the field maintained in the metadata (tags are not supported)
*/
virtual void configure(StorageRegistry* registry, StorageRegistry* metadata) = 0;
//-----------------Used by the VMF Controller-----------------------
/**
* @brief Clear the list of new entries
*
* This method should only be called by the controller module. After calling this,
* getNewEntries and getNewEntriesByTag will not return any elements until createNewEntry
* is called again.
*/
virtual void clearNewAndLocalEntries() = 0;
//-----------------Used by VMF modules-----------------
/**
* @brief Create a New Entry object
*
* New entries are not sorted, and need not neccesarily have yet defined the sort by fields.
* New entries will be cleared on each call to clearNewAndLocalEntries unless saveEntry() is called,
* indicating that the entry should be saved in long term storage.
*
* @return StorageEntry* a pointer to the newly created entry
*/
virtual StorageEntry* createNewEntry() = 0;
/**
* @brief Create a local Storage Entry object
*
* Local entries are to be used only as temporary, local variables. They are only
* accessible to the module that created them, and to any submodules that that module
* passes them to. Local entries will not persist on the next call to the fuzzing loop
* (they are cleared on each call to clearNewAndLocalEntries). Local entries cannot be saved,
* and will not be returned by any of the other methods in storage.
*
* @return StorageEntry* a pointer to the newly created local entry
*/
virtual StorageEntry* createLocalEntry() = 0;
/**
* @brief Manually remove a local Storage Entry object (the value of the provided pointer will be null after this call)
*
* This method does not have to called, as local entries are automatically freed on every call
* to clearNewAndLocalEntries. However, if a module wants to create a large number of local StorageEntries
* it may be useful to be able to free them to avoid using massive amounts of memory within storage.
*
* @param entry the entry to delete
* @throws RuntimeException if this method is called on a non-local entry (one that was created with createLocalEntry)
*/
virtual void removeLocalEntry(StorageEntry*& entry) = 0;
/**
* @brief Get all the new entries
*
* Returns an iterator that will step through all of the new entries. The entries will
* be ordered in the order in which they were created (with the entry that was created
* first returned first from the iterator).
*
* @return std::unique_ptr<Iterator> the iterator
*/
virtual std::unique_ptr<Iterator> getNewEntries() = 0;
/**
* @brief Get all the new entries that have the provided tag
*
* Returns an iterator that will step through all of the new entries that have the provided tag.
* The entries will be ordered in the order in which they were tagged (with the entry that was tagged
* first returned first from the iterator).
*
* @return std::unique_ptr<Iterator> the iterator
*/
virtual std::unique_ptr<Iterator> getNewEntriesByTag(int tagId) = 0;
/**
* @brief Get the New Entries That Will Be Saved
*
* Returns an interator that will step through of the entries that were saved since the last
* call to clearNewAndLocalEntries();
*
* @return std::unique_ptr<Iterator> the iterator
*/
virtual std::unique_ptr<Iterator> getNewEntriesThatWillBeSaved() = 0;
/**
* @brief Save the entry to long term storage
*
* Note that long term storage is sorted by the sort by key (configured in StorageRegistry), so the
* sort by key's value must be written to the entry prior to calling this method.
*
* @param e
*/
virtual void saveEntry(StorageEntry* e) = 0;
/**
* @brief Removes a previously saved entry
*
* Only use this method to remove entries that have been saved to long term storage.
*
* @param e the entry to remove
*/
virtual void removeEntry(StorageEntry* e) = 0;
/**
* @brief Get all the tag handles that storage is tracking
* This returns the list of all registered tag handles in storage.
* Modules that want to generically handle all tags should use this
* method sometime after initialization to retrieve all of the relevant tags.
*
* @return std::vector<int> the list of tag handles
*/
virtual std::vector<int> getListOfTagHandles() = 0;
/**
* @brief Convert a tag handle to the registered tag name
* Modules may use this method to convert a tag handle to the associated
* tag name. This is useful for modules that generically support handling
* all tags in the system.
*
* @param tagId the tag handle
* @return std::string the name associated with the tag
*/
virtual std::string tagHandleToString(int tagId) = 0;
/**
* @brief Get all the metadata key handles that storage is tracking
* This returns the list of all registered metadata handles in storage.
* Modules that want to generically handle all metadata keys should use this
* method sometime after initialization to retrieve all of the relevant keys.
*
* @return std::vector<int> the list of key handles
*/
virtual std::vector<int> getListOfMetadataKeyHandles(StorageRegistry::storageTypes type) = 0;
/**
* @brief Convert a metadata key handle to the registered key name
* Modules may use this method to convert a metadata key handle to the associated
* key name. This is useful for modules that generically support handling
* all metadata in the system.
*
* @param handle the key handle
* @return std::string the name associated with the key
*/
virtual std::string metadataKeyHandleToString(int handle) = 0;
/**
* @brief Get all the saved entries that have been previously tagged with the provided tag.
*
* Returns an iterator that can be used to step through all of the tagged entries.
* Entries are sorted using the sort by fields that were configured in the StorageRegistry.
*
* @param tagId the tag handle (as returned from a call to StoragRegistry.registerTag)
* @return std::unique_ptr<Iterator> the iterator
*/
virtual std::unique_ptr<Iterator> getSavedEntriesByTag(int tagId) = 0;
/**
* @brief Get all the entries in long term storage (regardless of whether or not they have been tagged)
*
* Returns an iterator that can be used to step through all of the entries in long term storage.
* Entries are sorted using the sort by fields that were configured in the StorageRegistry.
*
* @return std::unique_ptr<Iterator> the iterator
*/
virtual std::unique_ptr<Iterator> getSavedEntries() = 0;
/**
* @brief Retrieves a saved storage entry by it's unique ID
*
* This can be used for modules that need to keep track of a complex data structure
* that cannot be maintained within storage.
*
* @param id the id to retrieve
* @return StorageEntry* or a nullptr if no such entry is found
*/
virtual StorageEntry* getSavedEntryByID(unsigned long id) = 0;
/**
* @brief Retrieves a saved storage entry with a particular tag by it's unique ID
*
* This can be used for modules that need to keep track of a complex data structure
* that cannot be maintained within storage. This version of the method constrains
* the lookup to entries that also have the specified tag. In some implementations of
* storage this will be faster than the version of getSavedEntryByID that does not take a tag.
*
* @param id the id to retrieve
* @param tagId the tag handle (as returned from a call to StoragRegistry.registerTag)
* @return StorageEntry* or a nullptr if no such entry is found
*/
virtual StorageEntry* getSavedEntryByID(unsigned long id, int tagId) = 0;
/**
* @brief Returns the metadata object
*
* This special storage entry is for global data that is used to store metadata that is
* shared between modules, but are not specific to an individual entry.
*
* @return StorageEntry& the metadata object
*/
virtual StorageEntry& getMetadata() = 0;
/**
* @brief Convenience method to determine if a module is actually a storage module
*
* @param module
* @return true if this module has a module type=STORAGE
* @return false
*/
static bool isAnInstance(Module* module)
{
ModuleTypeEnum type = module->getModuleType();
return (ModuleTypeEnum::STORAGE == type);
}
/**
* @brief Convenience method to cast Module* to StorageModule*
*
* Call isAnInstance first to check the type in order to avoid an exception.
*
* @param module
* @return StorageModule*
* @throws RuntimeException if the underlying Module* is not a decendant of StorageModule
*/
static StorageModule* castTo(Module* module)
{
StorageModule* storage;
if(nullptr != module)
{
storage = dynamic_cast<StorageModule*>(module);
if(nullptr == storage)
{
throw RuntimeException("Failed attempt to cast module to StorageModule",
RuntimeException::USAGE_ERROR);
}
}
else
{
throw RuntimeException("Attempt to cast nullptr to StorageModule",
RuntimeException::UNEXPECTED_ERROR);
}
return storage;
}
protected:
/**
* @brief Construct a new Storage Module object
*
* @param name the name of the module
*/
StorageModule(std::string name) : Module(name, ModuleTypeEnum::STORAGE) {};
};
}