Subject: [PATCH v2] fuzz: add new oss-fuzz fuzzer for date.c / date.h

From: "Arthur Chan via GitGitGadget" <[email-masked]>
Date: Mon, 13 Nov 2023 16:22:48 +0000

From: Arthur Chan <[email-masked]>

Signed-off-by: Arthur Chan <[email-masked]>
---
    fuzz: add new oss-fuzz fuzzer for date.c / date.h
    
    This patch is aimed to add a new oss-fuzz fuzzer to the oss-fuzz
    directory for fuzzing date.c / date.h in the base directory.
    
    The .gitignore of the oss-fuzz directory and the Makefile have been
    modified to accommodate the new fuzzer fuzz-date.c.
    
    Fixed the objects order in .gitignore and Makefiles and fixed some of
    the logic and formatting for the fuzz-date.c fuzzer in v2.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1612%2Farthurscchan%2Fnew-fuzzer-date-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1612/arthurscchan/new-fuzzer-date-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1612

Range-diff vs v1:

 1:  d43724c19d0 ! 1:  2928e2b858d fuzz: add new oss-fuzz fuzzer for date.c / date.h
     @@ Commit message
          Signed-off-by: Arthur Chan <[email-masked]>
      
       ## Makefile ##
     -@@ Makefile: ETAGS_TARGET = TAGS
     +@@ Makefile: SCRIPTS = $(SCRIPT_SH_GEN) \
     + ETAGS_TARGET = TAGS
     + 
       FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
     ++FUZZ_OBJS += oss-fuzz/fuzz-date.o
       FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
       FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
     -+FUZZ_OBJS += oss-fuzz/fuzz-date.o
       .PHONY: fuzz-objs
     - fuzz-objs: $(FUZZ_OBJS)
     - 
      
       ## oss-fuzz/.gitignore ##
      @@
       fuzz-commit-graph
     ++fuzz-date
       fuzz-pack-headers
       fuzz-pack-idx
     -+fuzz-date
      
       ## oss-fuzz/fuzz-date.c (new) ##
      @@
     @@ oss-fuzz/fuzz-date.c (new)
      +
      +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
      +{
     -+	int type;
     -+	int time;
     ++	int local;
      +	int num;
     ++	uint16_t tz;
      +	char *str;
      +	timestamp_t ts;
      +	enum date_mode_type dmtype;
      +	struct date_mode *dm;
      +
     -+	if (size <= 8)
     -+	{
     ++	if (size <= 4)
     ++		/*
     ++		 * we use the first byte to fuzz dmtype and local,
     ++		 * then the next three bytes to fuzz tz	offset,
     ++		 * and the remainder (at least one byte) is fed
     ++		 * as end-user input to approxidate_careful().
     ++		 */
      +		return 0;
     -+	}
      +
     -+	type = (*((int *)data)) % 8;
     -+	data += 4;
     -+	size -= 4;
     ++	local = !!(*data & 0x10);
     ++	dmtype = (enum date_mode_type)(*data % DATE_UNIX);
     ++	if (dmtype == DATE_STRFTIME)
     ++		/*
     ++		 * Currently DATE_STRFTIME is not supported.
     ++		 */
     ++		return 0;
     ++	data++;
     ++	size--;
      +
     -+	time = abs(*((int *)data));
     -+	data += 4;
     -+	size -= 4;
     ++	tz = *data++;
     ++	tz = (tz << 8) | *data++;
     ++	tz = (tz << 8) | *data++;
     ++	size -= 3;
      +
     -+	str = (char *)malloc(size+1);
     ++	str = (char *)malloc(size + 1);
      +	if (!str)
     -+	{
      +		return 0;
     -+	}
      +	memcpy(str, data, size);
      +	str[size] = '\0';
      +
      +	ts = approxidate_careful(str, &num);
      +	free(str);
      +
     -+	switch(type)
     -+	{
     -+		case 0: default:
     -+			dmtype = DATE_NORMAL;
     -+			break;
     -+		case 1:
     -+			dmtype = DATE_HUMAN;
     -+			break;
     -+		case 2:
     -+			dmtype = DATE_SHORT;
     -+			break;
     -+		case 3:
     -+			dmtype = DATE_ISO8601;
     -+			break;
     -+		case 4:
     -+			dmtype = DATE_ISO8601_STRICT;
     -+			break;
     -+		case 5:
     -+			dmtype = DATE_RFC2822;
     -+			break;
     -+		case 6:
     -+			dmtype = DATE_RAW;
     -+			break;
     -+		case 7:
     -+			dmtype = DATE_UNIX;
     -+			break;
     -+	}
     -+
      +	dm = date_mode_from_type(dmtype);
     -+	dm->local = 1;
     -+	show_date(ts, time, dm);
     ++	dm->local = local;
     ++	show_date(ts, (int16_t)tz, dm);
      +
      +	date_mode_release(dm);
      +

 Makefile             |  1 +
 oss-fuzz/.gitignore  |  1 +
 oss-fuzz/fuzz-date.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 oss-fuzz/fuzz-date.c

diff --git a/Makefile b/Makefile
index 03adcb5a480..4b875ef6ce1 100644
--- a/Makefile
+++ b/Makefile
@@ -750,6 +750,7 @@ SCRIPTS = $(SCRIPT_SH_GEN) \
 ETAGS_TARGET = TAGS
 
 FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
+FUZZ_OBJS += oss-fuzz/fuzz-date.o
 FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
 FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
 .PHONY: fuzz-objs
diff --git a/oss-fuzz/.gitignore b/oss-fuzz/.gitignore
index 9acb74412ef..5b954088254 100644
--- a/oss-fuzz/.gitignore
+++ b/oss-fuzz/.gitignore
@@ -1,3 +1,4 @@
 fuzz-commit-graph
+fuzz-date
 fuzz-pack-headers
 fuzz-pack-idx
diff --git a/oss-fuzz/fuzz-date.c b/oss-fuzz/fuzz-date.c
new file mode 100644
index 00000000000..a5c887bf11c
--- /dev/null
+++ b/oss-fuzz/fuzz-date.c
@@ -0,0 +1,56 @@
+#include "git-compat-util.h"
+#include "date.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+	int local;
+	int num;
+	uint16_t tz;
+	char *str;
+	timestamp_t ts;
+	enum date_mode_type dmtype;
+	struct date_mode *dm;
+
+	if (size <= 4)
+		/*
+		 * we use the first byte to fuzz dmtype and local,
+		 * then the next three bytes to fuzz tz	offset,
+		 * and the remainder (at least one byte) is fed
+		 * as end-user input to approxidate_careful().
+		 */
+		return 0;
+
+	local = !!(*data & 0x10);
+	dmtype = (enum date_mode_type)(*data % DATE_UNIX);
+	if (dmtype == DATE_STRFTIME)
+		/*
+		 * Currently DATE_STRFTIME is not supported.
+		 */
+		return 0;
+	data++;
+	size--;
+
+	tz = *data++;
+	tz = (tz << 8) | *data++;
+	tz = (tz << 8) | *data++;
+	size -= 3;
+
+	str = (char *)malloc(size + 1);
+	if (!str)
+		return 0;
+	memcpy(str, data, size);
+	str[size] = '\0';
+
+	ts = approxidate_careful(str, &num);
+	free(str);
+
+	dm = date_mode_from_type(dmtype);
+	dm->local = local;
+	show_date(ts, (int16_t)tz, dm);
+
+	date_mode_release(dm);
+
+	return 0;
+}

base-commit: dadef801b365989099a9929e995589e455c51fed
-- 
gitgitgadget