blob: 17fd80a907bade2f537eb508669510eabccd627a [file] [log] [blame]
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <ctype.h>
#include "DNSCommon.h"
#ifdef FUZZING_MDNS_SNPRINTF
void hexdump(const void* Data, ssize_t Length) {
const uint8_t* bytes = (const uint8_t*) Data;
dprintf(2, "[%4d] ", Length);
for(ssize_t i = 0; i < Length; i++) {
dprintf(2, "%02x", bytes[i]);
}
dprintf(2, "\n");
}
// Large enough to be a uint64_t
const size_t numBuffers = 32;
const size_t bufferSize = 16; // Large enough to hold an IPv6 address
char **buffers[numBuffers];
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
size_t LLVMFuzzerCustomMutator(char *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
Size = LLVMFuzzerMutate((uint8_t*) Data, Size, MaxSize);
// Ensure there is a NULL terminator somewhere in the buffer
Data[MaxSize-3] = '\0';
Size = strlen(Data) + 1;
// Input values for the format buffer will be ASCII printable
for(size_t i = 0; i < Size; i++) {
Data[i] = Data[i] & 0x7f;
}
// Only have up to numBuffers format specifiers
// XXX: Can actually only have half that amount, because e.g. %.*s consumes two values
char* percent = Data;
size_t i = 0;
for(i = 0; percent && i < numBuffers / 2; i++) {
percent = strchr(percent, '%');
if(percent) {
percent++;
}
}
if(percent) {
*percent = '\0';
}
Size = strlen(Data) + 1;
// XXX: Due to rdar://68121985
Data[Size++] = 0;
return Size;
}
int LLVMFuzzerInitialize(int *argc, char ***argv) {
static int initialized = 0;
if(initialized) {
return 0;
}
for(size_t i = 0; i < numBuffers; i++) {
buffers[i] = malloc(bufferSize);
}
initialized = 1;
return 0;
}
void setup() {
for(size_t i = 0; i < numBuffers; i++) {
memset(&buffers[i][0], 0, bufferSize);
memset(&buffers[i][0], 'A' + i, bufferSize-1);
}
}
int LLVMFuzzerTestOneInput(const char* Data, const size_t Size)
{
// For some reason, the Release build doesn't call LLVMFuzzerInitialize so
// we do it manually here.
LLVMFuzzerInitialize(0, NULL);
// Skip short inputs
if(Size < 1 || !memchr(Data, 0, Size)) {
return 0;
}
// Require that there is a NULL terminator somewhere in the buffer
// char *copy = malloc(Size);
// memcpy(copy, Data, Size);
// Setup printed buffers
setup();
// Output buffer and run snprintf
size_t printBufferSize = 128;
// char printBuffer[printBufferSize]; // Repro
char* printBuffer = malloc(printBufferSize); // No repro
mDNS_snprintf(printBuffer, printBufferSize, Data,
buffers[000], buffers[001], buffers[002], buffers[003], buffers[004], buffers[005], buffers[006], buffers[007],
buffers[010], buffers[011], buffers[012], buffers[013], buffers[014], buffers[015], buffers[016], buffers[017],
buffers[020], buffers[021], buffers[022], buffers[023], buffers[024], buffers[025], buffers[026], buffers[027],
buffers[030], buffers[031], buffers[032], buffers[033], buffers[034], buffers[035], buffers[036], buffers[037]);
free(printBuffer);
return 0;
}
#endif