shithub: libtags

Download patch

ref: 013e83940de00cb4ee983ec2970946e8df5bc620
parent: 47f5e687278fa34f97363add03a741f01545ecf7
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Wed Mar 6 13:54:11 EST 2024

add a harness target, leave readtags example alone

--- a/examples/readtags.c
+++ b/examples/readtags.c
@@ -62,6 +62,7 @@
 int
 main(int argc, char **argv)
 {
+	int i;
 	char buf[256];
 	Aux aux;
 	Tagctx ctx = {
@@ -79,16 +80,6 @@
 		return 1;
 	}
 
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-	// this block is for fuzzing only, ignore
-	while(__AFL_LOOP(10000)){
-		if((aux.fd = open(argv[1], O_RDONLY)) >= 0){
-			tagsget(&ctx);
-			close(aux.fd);
-		}
-	}
-#else
-	int i;
 	for(i = 1; i < argc; i++){
 		printf("*** %s\n", argv[i]);
 		if((aux.fd = open(argv[i], O_RDONLY)) < 0)
@@ -110,6 +101,6 @@
 		}
 		printf("\n");
 	}
-#endif
+
 	return 0;
 }
--- /dev/null
+++ b/harness.c
@@ -1,0 +1,104 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "tags.h"
+
+typedef struct Aux Aux;
+
+struct Aux {
+	const uint8_t *in;
+	int sz;
+	int off;
+};
+
+#define USED(x) (void)x
+
+#ifndef __AFL_FUZZ_TESTCASE_LEN
+  ssize_t fuzz_len;
+  #define __AFL_FUZZ_TESTCASE_LEN fuzz_len
+  unsigned char fuzz_buf[1024000];
+  #define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
+  #define __AFL_FUZZ_INIT() void sync(void);
+  #define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0)
+  #define __AFL_INIT() sync()
+#endif
+
+__AFL_FUZZ_INIT()
+
+static void
+tag(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f)
+{
+	USED(ctx); USED(t);  USED(k); USED(v); USED(offset); USED(size); USED(f);
+}
+
+static void
+toc(Tagctx *ctx, int ms, int offset)
+{
+	USED(ctx); USED(ms); USED(offset);
+}
+
+static int
+ctxread(Tagctx *ctx, void *buf, int cnt)
+{
+	Aux *aux = ctx->aux;
+	int max = aux->sz - aux->off;
+	if(cnt < 0)
+		cnt = 0;
+	else if(cnt > max)
+		cnt = max;
+	memcpy(buf, aux->in, cnt);
+	aux->off += cnt;
+	return cnt;
+}
+
+static int
+ctxseek(Tagctx *ctx, int offset, int whence)
+{
+	Aux *aux = ctx->aux;
+	if(whence == 0)
+		aux->off = offset;
+	else if(whence == 1)
+		aux->off += offset;
+	else if(whence == 2)
+		aux->off = aux->sz + offset;
+	if(aux->off < 0)
+		aux->off = 0;
+	else if(aux->off > aux->sz)
+		aux->off = aux->sz;
+	return aux->off;
+}
+
+int
+main(int argc, char **argv)
+{
+	char buf[256];
+	Aux aux;
+	Tagctx ctx = {
+		.read = ctxread,
+		.seek = ctxseek,
+		.tag = tag,
+		.toc = toc,
+		.buf = buf,
+		.bufsz = sizeof(buf),
+		.aux = &aux,
+	};
+
+	USED(argc); USED(argv);
+
+	#ifdef __AFL_HAVE_MANUAL_CONTROL
+	__AFL_INIT();
+	#endif
+
+	aux.in = __AFL_FUZZ_TESTCASE_BUF;
+	while(__AFL_LOOP(10000)){
+		aux.sz = __AFL_FUZZ_TESTCASE_LEN;
+		if(aux.sz < 8)
+			continue;
+		aux.off = 0;
+		tagsget(&ctx);
+	}
+
+	return 0;
+}
--- a/meson.build
+++ b/meson.build
@@ -47,6 +47,13 @@
 	'examples/readtags.c',
 ]
 
+
+if(get_option('fuzz'))
+	if(cc.has_argument('-Wno-gnu-statement-expression-from-macro-expansion'))
+		add_project_arguments('-Wno-gnu-statement-expression-from-macro-expansion', language: 'c')
+	endif
+endif
+
 lib = static_library(
 	'tags',
 	sources: src_lib,
@@ -67,3 +74,12 @@
 	dependencies: [ libtags ],
 	install: false,
 )
+
+if(get_option('fuzz'))
+	executable(
+		'harness',
+		sources: [ 'harness.c' ],
+		dependencies: [ libtags ],
+		install: false,
+	)
+endif
--- /dev/null
+++ b/meson.options
@@ -1,0 +1,1 @@
+option('fuzz', type: 'boolean', value: false, description: 'Build fuzzing target')