From a31ca8d75375a196bb4a2393db9f9d2307416d8f Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Tue, 11 Dec 2018 13:29:30 +0100
Subject: [PATCH] stringmatchlen() fuzz test added.

Verified to be able to trigger at least #5632. Does not report other
issues.
---
 src/debug.c |  5 +++++
 src/util.c  | 16 ++++++++++++++++
 src/util.h  |  1 +
 3 files changed, 22 insertions(+)

diff --git a/src/debug.c b/src/debug.c
index e7d6a5cb..1ec7c497 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -322,6 +322,7 @@ void debugCommand(client *c) {
 "SLEEP <seconds> -- Stop the server for <seconds>. Decimals allowed.",
 "STRUCTSIZE -- Return the size of different Redis core C structures.",
 "ZIPLIST <key> -- Show low level info about the ziplist encoding.",
+"STRINGMATCH-TEST -- Run a fuzz tester against the stringmatchlen() function.",
 NULL
         };
         addReplyHelp(c, help);
@@ -619,6 +620,10 @@ NULL
         changeReplicationId();
         clearReplicationId2();
         addReply(c,shared.ok);
+    } else if (!strcasecmp(c->argv[1]->ptr,"stringmatch-test") && c->argc == 2)
+    {
+        stringmatchlen_fuzz_test();
+        addReplyStatus(c,"Apparently Redis did not crash: test passed");
     } else {
         addReplySubcommandSyntaxError(c);
         return;
diff --git a/src/util.c b/src/util.c
index 1dc8dd87..66d59919 100644
--- a/src/util.c
+++ b/src/util.c
@@ -171,6 +171,22 @@ int stringmatch(const char *pattern, const char *string, int nocase) {
     return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);
 }
 
+/* Fuzz stringmatchlen() trying to crash it with bad input. */
+int stringmatchlen_fuzz_test(void) {
+    char str[32];
+    char pat[32];
+    int cycles = 10000000;
+    int total_matches = 0;
+    while(cycles--) {
+        int strlen = rand() % sizeof(str);
+        int patlen = rand() % sizeof(pat);
+        for (int j = 0; j < strlen; j++) str[j] = rand() % 128;
+        for (int j = 0; j < patlen; j++) pat[j] = rand() % 128;
+        total_matches += stringmatchlen(pat, patlen, str, strlen, 0);
+    }
+    return total_matches;
+}
+
 /* Convert a string representing an amount of memory into the number of
  * bytes, so for instance memtoll("1Gb") will return 1073741824 that is
  * (1024*1024*1024).
diff --git a/src/util.h b/src/util.h
index cc154d96..b6c01aa5 100644
--- a/src/util.h
+++ b/src/util.h
@@ -40,6 +40,7 @@
 
 int stringmatchlen(const char *p, int plen, const char *s, int slen, int nocase);
 int stringmatch(const char *p, const char *s, int nocase);
+int stringmatchlen_fuzz_test(void);
 long long memtoll(const char *p, int *err);
 uint32_t digits10(uint64_t v);
 uint32_t sdigits10(int64_t v);