Add a call to pcre2_dfa_match() to the fuzzer driver.

This commit is contained in:
Philip.Hazel 2017-05-20 14:28:11 +00:00
parent 62564c08fd
commit 72f0c742dd
1 changed files with 62 additions and 23 deletions

View File

@ -19,6 +19,8 @@ Written by Philip Hazel, October 2016
#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 @@ Written by Philip Hazel, October 2016
(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,9 +46,9 @@ static int callout_function(pcre2_callout_block *cb, void *callout_data)
*((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);
@ -59,12 +61,13 @@ uint32_t match_options;
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 @@ for (i = 0; i < 2; i++)
code = pcre2_compile((PCRE2_SPTR)data, (PCRE2_SIZE)size, compile_options,
&errorcode, &erroroffset, NULL);
/* Compilation succeeded */
if (code != NULL)
@ -169,8 +172,8 @@ for (i = 0; i < 2; i++)
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 */
@ -195,6 +198,42 @@ for (i = 0; i < 2; i++)
errorcode = pcre2_match(code, (PCRE2_SPTR)data, (PCRE2_SIZE)match_size, 0,
match_options, match_data, match_context);
#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 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
{
@ -210,7 +249,7 @@ for (i = 0; i < 2; i++)
match_options = save_match_options; /* Reset for the second compile */
pcre2_code_free(code);
}
/* Compilation failed */
else
@ -253,30 +292,30 @@ for (i = 1; i < argc; i++)
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)
{