#include "SkData.h"
#include "SkTRegistry.h"
#include "SkTypes.h"
-#include <stdlib.h>
class Fuzz : SkNoncopyable {
public:
uint32_t nextU();
float nextF();
+ void signalBug (); // Tell afl-fuzz these inputs found a bug.
+ void signalBoring(); // Tell afl-fuzz these inputs are not worth testing.
+
private:
+ template <typename T>
+ T nextT();
+
SkAutoTUnref<SkData> fBytes;
int fNextByte;
};
SkTRegistry<Fuzzable> register_##name({#name, fuzz_##name}); \
static void fuzz_##name(Fuzz* f)
-#define ASSERT(cond) do { if (!(cond)) abort(); } while(false)
-
#endif//Fuzz_DEFINED
*/
#include "Fuzz.h"
+#include <stdlib.h>
// This really is just an example Fuzz*.cpp file.
// It tests that two different ways of calculating the Paeth predictor function are equivalent.
auto a = fuzz->nextB(),
b = fuzz->nextB(),
c = fuzz->nextB();
- ASSERT(paeth_alt(a,b,c) == paeth_std(a,b,c));
+ SkDebugf("Paeth(%d,%d,%d)\n", a,b,c);
+
+ if (a == b && b == c) {
+ fuzz->signalBoring(); // Not really boring, just demoing signalBoring().
+ }
+
+ if (paeth_alt(a,b,c) != paeth_std(a,b,c)) {
+ fuzz->signalBug();
+ }
}
*/
#include "Fuzz.h"
+#include <stdlib.h>
+#include <signal.h>
int main(int argc, char** argv) {
- ASSERT(argc > 2);
+ if (argc < 3) {
+ SkDebugf("Usage: %s <fuzz name> <path/to/fuzzed.data>\n", argv[0]);
+ return 1;
+ }
const char* name = argv[1];
const char* path = argv[2];
for (auto r = SkTRegistry<Fuzzable>::Head(); r; r = r->next()) {
auto fuzzable = r->factory();
if (0 == strcmp(name, fuzzable.name)) {
+ SkDebugf("Running %s\n", fuzzable.name);
fuzzable.fn(&fuzz);
return 0;
}
Fuzz::Fuzz(SkData* bytes) : fBytes(SkSafeRef(bytes)), fNextByte(0) {}
+void Fuzz::signalBug () { raise(SIGSEGV); }
+void Fuzz::signalBoring() { exit(0); }
+
template <typename T>
-static T read(const SkData* data, int* next) {
- ASSERT(sizeof(T) <= data->size());
- if (*next + sizeof(T) > data->size()) {
- *next = 0;
+T Fuzz::nextT() {
+ if (fNextByte + sizeof(T) > fBytes->size()) {
+ this->signalBoring();
}
+
T val;
- memcpy(&val, data->bytes() + *next, sizeof(T));
- *next += sizeof(T);
+ memcpy(&val, fBytes->bytes() + fNextByte, sizeof(T));
+ fNextByte += sizeof(T);
return val;
}
-uint8_t Fuzz::nextB() { return read<uint8_t >(fBytes, &fNextByte); }
-uint32_t Fuzz::nextU() { return read<uint32_t>(fBytes, &fNextByte); }
-float Fuzz::nextF() { return read<float >(fBytes, &fNextByte); }
+uint8_t Fuzz::nextB() { return this->nextT<uint8_t >(); }
+uint32_t Fuzz::nextU() { return this->nextT<uint32_t>(); }
+float Fuzz::nextF() { return this->nextT<float >(); }