/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * 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 . */ #include "interface/FramingIface.h" #include "crypto/random/Random.h" #include "memory/Allocator.h" #include "test/FuzzTest.h" #include "util/Identity.h" #define BUF_SZ 1024 struct Context { struct Iface iface; struct Iface* fi; struct Iface outer; int success; struct Allocator* alloc; int messageLen; struct Message* buf; uint8_t* bufPtr; Identity } ctx; static Iface_DEFUN ifaceRecvMsg(struct Message* message, struct Iface* thisInterface) { struct Context* ctx = Identity_containerOf(thisInterface, struct Context, iface); Assert_true(!ctx->success); Assert_true(Message_getLength(message) == ctx->messageLen); Assert_true(Message_getLength(ctx->buf) == 0); Assert_true(!Bits_memcmp(ctx->bufPtr, message->msgbytes, ctx->messageLen)); ctx->success = 1; return NULL; } void CJDNS_FUZZ_MAIN(void* vctx, struct Message* fuzz) { struct Context* ctx = Identity_check((struct Context*) vctx); if (Message_getLength(fuzz) <= 2) { return; } ctx->messageLen = Er_assert(Message_epop16be(fuzz)) % BUF_SZ; Er_assert(Message_truncate(ctx->buf, ctx->messageLen)); Er_assert(Message_epush32be(ctx->buf, ctx->messageLen)); for (int i = 0; ; i++) { uint8_t len = fuzz->msgbytes[i % Message_getLength(fuzz)] + 1; if (len > Message_getLength(ctx->buf)) { len = Message_getLength(ctx->buf); } struct Allocator* a = Allocator_child(ctx->alloc); struct Message* m = Message_new(len, 0, a); Er_assert(Message_epop(ctx->buf, m->msgbytes, len)); Iface_send(&ctx->outer, m); Allocator_free(a); if (ctx->success) { return; } } } void* CJDNS_FUZZ_INIT(struct Allocator* alloc, struct Random* rand) { struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1); ctx->iface.send = ifaceRecvMsg; ctx->fi = FramingIface_new(BUF_SZ, &ctx->outer, alloc); Iface_plumb(&ctx->iface, ctx->fi); ctx->alloc = alloc; ctx->buf = Message_new(BUF_SZ, 4, alloc); Random_bytes(rand, ctx->buf->msgbytes, BUF_SZ); ctx->bufPtr = ctx->buf->msgbytes; Identity_set(ctx); return ctx; }