From 504a0f88febd83b0a9eb161a10f9972fd3f60032 Mon Sep 17 00:00:00 2001
From: Sergey Bronnikov <sergeyb@tarantool.org>
Date: Thu, 23 Mar 2023 19:29:01 +0300
Subject: [PATCH] test/fuzz: fix datetime_strptime fuzzing test

Function `datetime_strptime` decodes string with datetime according to
specified format, it accepts a datetime struct, buffer with datetime and
string with format in arguments. Fuzzing test used static string
"iso8601" as a format and it blocked fuzzing test to cover functions
used by datetime_strptime under the hood. Fuzz introspector shows that
code coveraged by a test is quite low.

Patch updates the test to make it more effective: buffer with datetime
and format string are generated using FDP (Fuzzing Data Provider).

Test file extension was changed to .cc, because FuzzingDataProvider is
used and we need building it by C++ compiler.

Function `tnt_strptime` uses assert, that triggered by fuzzing tests.
Therefore it was replaced with to if..then.

1. https://storage.googleapis.com/oss-fuzz-introspector/tarantool/

Fixes #8490

NO_CHANGELOG=fuzzing test
NO_DOC=fuzzing test
NO_TEST=fuzzing test

(cherry picked from commit a1bd6e0b799ab4b2cbe070917f6556f6239681f6)
---
 src/lib/tzcode/strptime.c             |  3 ++-
 test/fuzz/CMakeLists.txt              |  2 +-
 test/fuzz/datetime_strptime_fuzzer.c  | 22 ----------------------
 test/fuzz/datetime_strptime_fuzzer.cc | 21 +++++++++++++++++++++
 4 files changed, 24 insertions(+), 24 deletions(-)
 delete mode 100644 test/fuzz/datetime_strptime_fuzzer.c
 create mode 100644 test/fuzz/datetime_strptime_fuzzer.cc

diff --git a/src/lib/tzcode/strptime.c b/src/lib/tzcode/strptime.c
index 4cc4351fc9..6d1b7f24d1 100644
--- a/src/lib/tzcode/strptime.c
+++ b/src/lib/tzcode/strptime.c
@@ -262,7 +262,8 @@ tnt_strptime(const char *__restrict buf, const char *__restrict fmt,
 				;
 
 			c = *ptr++;
-			assert(c == 'f');
+			if (c != 'f')
+				return NULL;
 			/* fallthru */
 		case 'f':
 			if (!is_digit((u_char)*buf))
diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt
index a082b735af..183b676e76 100644
--- a/test/fuzz/CMakeLists.txt
+++ b/test/fuzz/CMakeLists.txt
@@ -84,7 +84,7 @@ create_fuzz_test(PREFIX datetime_parse_full
 )
 
 create_fuzz_test(PREFIX datetime_strptime
-                 SOURCES datetime_strptime_fuzzer.c
+                 SOURCES datetime_strptime_fuzzer.cc
                  LIBRARIES core fuzzer_config
 )
 
diff --git a/test/fuzz/datetime_strptime_fuzzer.c b/test/fuzz/datetime_strptime_fuzzer.c
deleted file mode 100644
index 0d00903e0e..0000000000
--- a/test/fuzz/datetime_strptime_fuzzer.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include "datetime.h"
-#include "trivia/util.h"
-
-void
-cord_on_yield(void) {}
-
-int
-LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
-{
-	char *buf = xcalloc(size + 1, sizeof(char));
-	if (buf == NULL)
-		return 0;
-	memcpy(buf, data, size);
-	buf[size] = '\0';
-	struct datetime date_expected;
-	datetime_strptime(&date_expected, buf, "iso8601");
-	free(buf);
-
-	return 0;
-}
diff --git a/test/fuzz/datetime_strptime_fuzzer.cc b/test/fuzz/datetime_strptime_fuzzer.cc
new file mode 100644
index 0000000000..f644f38025
--- /dev/null
+++ b/test/fuzz/datetime_strptime_fuzzer.cc
@@ -0,0 +1,21 @@
+#include <fuzzer/FuzzedDataProvider.h>
+#include <stddef.h>
+
+#include "datetime.h"
+
+extern "C" void
+cord_on_yield(void) {}
+
+extern "C" int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+	FuzzedDataProvider fdp(data, size);
+
+	auto buf = fdp.ConsumeRandomLengthString();
+	auto fmt = fdp.ConsumeRandomLengthString();
+
+	struct datetime date_expected;
+	datetime_strptime(&date_expected, buf.c_str(), fmt.c_str());
+
+	return 0;
+}
-- 
GitLab