Revision: 793
http://www.exim.org/viewvc/pcre2?view=rev&revision=793
Author: ph10
Date: 2017-05-20 15:28:11 +0100 (Sat, 20 May 2017)
Log Message:
-----------
Add a call to pcre2_dfa_match() to the fuzzer driver.
Modified Paths:
--------------
code/trunk/src/pcre2_fuzzsupport.c
Modified: code/trunk/src/pcre2_fuzzsupport.c
===================================================================
--- code/trunk/src/pcre2_fuzzsupport.c 2017-05-20 11:40:12 UTC (rev 792)
+++ code/trunk/src/pcre2_fuzzsupport.c 2017-05-20 14:28:11 UTC (rev 793)
@@ -19,6 +19,8 @@
#define MAX_MATCH_SIZE 1000
+#define DFA_WORKSPACE_COUNT 100
+
#define ALLOWED_COMPILE_OPTIONS \
(PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \
PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \
@@ -33,9 +35,9 @@
(PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_HARD| \
PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT)
-
-/* This is the callout function. Its only purpose is to halt matching if there
-are more than 100 callouts, as one way of stopping too much time being spent on
+
+/* This is the callout function. Its only purpose is to halt matching if there
+are more than 100 callouts, as one way of stopping too much time being spent on
fruitless matches. The callout data is a pointer to the counter. */
static int callout_function(pcre2_callout_block *cb, void *callout_data)
@@ -44,10 +46,10 @@
*((uint32_t *)callout_data) += 1;
return (*((uint32_t *)callout_data) > 100)? PCRE2_ERROR_CALLOUT : 0;
}
-
-/* Putting in this apparently unnecessary prototype prevents gcc from giving a
-"no previous prototype" warning when compiling at high warning level. */
+/* Putting in this apparently unnecessary prototype prevents gcc from giving a
+"no previous prototype" warning when compiling at high warning level. */
+
int LLVMFuzzerTestOneInput(const unsigned char *, size_t);
/* Here's the driving function. */
@@ -59,12 +61,13 @@
pcre2_match_data *match_data = NULL;
pcre2_match_context *match_context = NULL;
size_t match_size;
+int dfa_workspace[DFA_WORKSPACE_COUNT];
int r1, r2;
int i;
if (size < 1) return 0;
-/* Limiting the length of the subject for matching stops fruitless searches
+/* Limiting the length of the subject for matching stops fruitless searches
in large trees taking too much time. */
match_size = (size > MAX_MATCH_SIZE)? MAX_MATCH_SIZE : size;
@@ -134,7 +137,7 @@
code = pcre2_compile((PCRE2_SPTR)data, (PCRE2_SIZE)size, compile_options,
&errorcode, &erroroffset, NULL);
-
+
/* Compilation succeeded */
if (code != NULL)
@@ -169,8 +172,8 @@
return 0;
}
(void)pcre2_set_match_limit(match_context, 100);
- (void)pcre2_set_depth_limit(match_context, 100);
- (void)pcre2_set_callout(match_context, callout_function, &callout_count);
+ (void)pcre2_set_depth_limit(match_context, 100);
+ (void)pcre2_set_callout(match_context, callout_function, &callout_count);
}
/* Match twice, with and without options */
@@ -207,10 +210,46 @@
match_options = 0; /* For second time */
}
+ /* Match with DFA twice, with and without options */
+
+ match_options = save_match_options & ~PCRE2_NO_JIT;
+ for (j = 0; j < 2; j++)
+ {
+#ifdef STANDALONE
+ printf("DFA match options %.8x", match_options);
+ printf("%s%s%s%s%s%s%s%s%s\n",
+ ((match_options & PCRE2_ANCHORED) != 0)? ",anchored" : "",
+ ((match_options & PCRE2_ENDANCHORED) != 0)? ",endanchored" : "",
+ ((match_options & PCRE2_NO_UTF_CHECK) != 0)? ",no_utf_check" : "",
+ ((match_options & PCRE2_NOTBOL) != 0)? ",notbol" : "",
+ ((match_options & PCRE2_NOTEMPTY) != 0)? ",notempty" : "",
+ ((match_options & PCRE2_NOTEMPTY_ATSTART) != 0)? ",notempty_atstart" : "",
+ ((match_options & PCRE2_NOTEOL) != 0)? ",noteol" : "",
+ ((match_options & PCRE2_PARTIAL_HARD) != 0)? ",partial_hard" : "",
+ ((match_options & PCRE2_PARTIAL_SOFT) != 0)? ",partial_soft" : "");
+#endif
+
+ callout_count = 0;
+ errorcode = pcre2_dfa_match(code, (PCRE2_SPTR)data,
+ (PCRE2_SIZE)match_size, 0, match_options, match_data, match_context,
+ dfa_workspace, DFA_WORKSPACE_COUNT);
+
+#ifdef STANDALONE
+ if (errorcode >= 0) printf("Match returned %d\n", errorcode); else
+ {
+ unsigned char buffer[256];
+ pcre2_get_error_message(errorcode, buffer, 256);
+ printf("Match failed: error %d: %s\n", errorcode, buffer);
+ }
+#endif
+
+ match_options = 0; /* For second time */
+ }
+
match_options = save_match_options; /* Reset for the second compile */
pcre2_code_free(code);
}
-
+
/* Compilation failed */
else
@@ -253,30 +292,30 @@
size_t readsize;
unsigned char *buffer;
FILE *f;
-
- /* Handle a literal string. Copy to an exact size buffer so that checks for
+
+ /* Handle a literal string. Copy to an exact size buffer so that checks for
overrunning work. */
-
+
if (argv[i][0] == '=')
- {
+ {
readsize = strlen(argv[i]) - 1;
- printf("------ <Literal> ------\n");
+ printf("------ <Literal> ------\n");
printf("Length = %lu\n", readsize);
- printf("%.*s\n", (int)readsize, argv[i]+1);
+ printf("%.*s\n", (int)readsize, argv[i]+1);
buffer = (unsigned char *)malloc(readsize);
if (buffer == NULL)
printf("** Failed to allocate %lu bytes of memory\n", readsize);
else
- {
- memcpy(buffer, argv[i]+1, readsize);
+ {
+ memcpy(buffer, argv[i]+1, readsize);
LLVMFuzzerTestOneInput(buffer, readsize);
- free(buffer);
- }
+ free(buffer);
+ }
continue;
- }
+ }
/* Handle a string given in a file */
-
+
f = fopen(argv[i], "rb");
if (f == NULL)
{