23 #include <sys/resource.h>
25 #define STACK_SIZE_MB 256
26 #define JIT_SIZE_LIMIT (200 * 1024)
28 #ifndef PCRE2_CODE_UNIT_WIDTH
29 #define PCRE2_CODE_UNIT_WIDTH 8
36 #define MAX_MATCH_SIZE 1000
38 #define DFA_WORKSPACE_COUNT 100
43 #define ALLOWED_COMPILE_OPTIONS \
44 (PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \
45 PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \
46 PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_ENDANCHORED|PCRE2_EXTENDED| \
47 PCRE2_EXTENDED_MORE|PCRE2_FIRSTLINE| \
48 PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \
49 PCRE2_NO_AUTO_CAPTURE| \
50 PCRE2_NO_AUTO_POSSESS|PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_NO_START_OPTIMIZE| \
51 PCRE2_UCP|PCRE2_UNGREEDY|PCRE2_USE_OFFSET_LIMIT| \
54 #define ALLOWED_MATCH_OPTIONS \
55 (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
56 PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_HARD| \
59 #define BASE_MATCH_OPTIONS \
60 (PCRE2_NO_JIT|PCRE2_DISABLE_RECURSELOOP_CHECK)
63 #if defined(SUPPORT_DIFF_FUZZ) || defined(STANDALONE)
64 static void print_compile_options(FILE *stream,
uint32_t compile_options)
66 fprintf(stream,
"Compile options %s%.8x =",
70 fprintf(stream,
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
95 ((compile_options &
PCRE2_UCP) != 0)?
" ucp" :
"",
98 ((compile_options &
PCRE2_UTF) != 0)?
" utf" :
"");
101 static void print_match_options(FILE *stream,
uint32_t match_options)
103 fprintf(stream,
"Match options %s%.8x =",
106 fprintf(stream,
"%s%s%s%s%s%s%s%s%s%s%s\n",
123 static void print_error(FILE *
f,
int errorcode,
const char *
text, ...)
129 vfprintf(
f,
text, ap);
132 while (*p != 0) fprintf(
f,
"%c", *p++);
139 #ifdef SUPPORT_DIFF_FUZZ
144 for (
int index = 0; index <
count; index++)
154 fprintf(stream,
"Match %d (hex encoded): ", index);
157 fprintf(stream,
"%02x", bufferptr[
i]);
159 fprintf(stream,
"\n");
163 print_error(stream, errorcode,
"Match %d failed: ", index);
170 static void describe_failure(
172 const unsigned char *
data,
184 fprintf(stderr,
"Encountered failure while performing %s; context:\n", task);
186 fprintf(stderr,
"Pattern/sample string (hex encoded): ");
187 for (
size_t i = 0;
i <
size;
i++)
189 fprintf(stderr,
"%02x",
data[
i]);
191 fprintf(stderr,
"\n");
193 print_compile_options(stderr, compile_options);
194 print_match_options(stderr, match_options);
198 print_error(stderr, errorcode,
"Non-JIT'd operation emitted an error: ");
203 fprintf(stderr,
"Non-JIT'd operation did not emit an error.\n");
206 fprintf(stderr,
"%d matches discovered by non-JIT'd regex:\n", matches);
208 fprintf(stderr,
"\n");
212 if (errorcode_jit < 0)
214 print_error(stderr, errorcode_jit,
"JIT'd operation emitted error %d:",
218 if (matches_jit >= 0)
220 fprintf(stderr,
"JIT'd operation did not emit an error.\n");
221 if (match_data_jit !=
NULL)
223 fprintf(stderr,
"%d matches discovered by JIT'd regex:\n", matches_jit);
224 dump_matches(stderr, matches_jit, match_data_jit);
225 fprintf(stderr,
"\n");
256 getrlimit(RLIMIT_STACK, &rlim);
258 if (rlim.rlim_cur > rlim.rlim_max)
260 fprintf(stderr,
"Hard stack size limit is too small (needed 8MiB)!\n");
263 rc = setrlimit(RLIMIT_STACK, &rlim);
266 fprintf(stderr,
"Failed to expand stack size\n");
293 if (
size <
sizeof(random_options))
return -1;
296 data +=
sizeof(random_options);
298 size -=
sizeof(random_options);
322 for (
size_t i = 1;
i <
size - 2;
i++)
326 if ((wdata[
i] !=
')' && wdata[
i] !=
']') || wdata[
i-1] ==
'\\' ||
334 for (
int ii = 0; ii < 2; ii++)
338 if (
i >=
size - 1)
goto END_QSCAN;
342 while (wdata[
i+1] ==
' ' || wdata[
i+1] ==
'\t')
345 if (
i >=
size - 1)
goto END_QSCAN;
351 for (j =
i + 1; j <
size && j <
i + 7; j++)
353 if (wdata[j] ==
' ' || wdata[j] ==
'\t')
356 while (j <
size && (wdata[j] ==
' ' || wdata[j] ==
'\t')) j++;
357 if (j >=
size)
goto OUTERLOOP;
358 if (wdata[j] !=
'}' && wdata[j] !=
',')
goto OUTERLOOP;
360 if (wdata[j] ==
'}' || (ii == 0 && wdata[j] ==
','))
break;
361 if (wdata[j] <
'0' || wdata[j] >
'9')
366 q = q * 10 + wdata[j] -
'0';
369 if (j >=
size)
goto END_QSCAN;
374 if (j >=
i + 7 || q > 65535)
goto OUTERLOOP;
381 printf(
"Reduced quantifier value %d to 10.\n", q);
383 for (
size_t k =
i + 1; k < j; k++) wdata[k] =
'0';
391 if (wdata[
i] ==
'}')
break;
415 fprintf(stderr,
"** Failed to create compile context block\n");
441 for (
int i = 0;
i < 2;
i++)
447 #ifdef SUPPORT_DIFF_FUZZ
457 print_compile_options(stdout, compile_options);
468 uint32_t save_match_options = match_options;
477 printf(
"Compile succeeded; calling JIT compile\n");
481 if (jit_ret < 0) printf(
"JIT compile error %d\n", jit_ret);
487 printf(
"Not calling JIT: compiled pattern is too long "
488 "(%ld bytes; limit=%d)\n",
509 fprintf(stderr,
"** Failed to create match data block\n");
521 fprintf(stderr,
"** Failed to create match context block\n");
535 for (j = 0; j < 2; j++)
538 print_match_options(stdout, match_options);
546 if (errorcode >= 0) printf(
"Match returned %d\n", errorcode);
else
547 print_error(stdout, errorcode,
"Match failed: error %d: ", errorcode);
557 printf(
"Matching with JIT\n");
564 if (errorcode_jit >= 0)
565 printf(
"Match returned %d\n", errorcode_jit);
567 print_error(stdout, errorcode_jit,
"JIT match failed: error %d: ",
575 #ifdef SUPPORT_DIFF_FUZZ
577 matches_jit = errorcode_jit;
579 if (errorcode_jit != errorcode)
581 if (!(errorcode < 0 && errorcode_jit < 0) &&
585 describe_failure(
"match errorcode comparison", wdata,
size, compile_options, match_options, errorcode, errorcode_jit, matches, matches_jit,
match_data, match_data_jit);
590 for (
int index = 0; index < errorcode; index++)
595 bufferptr = bufferptr_jit =
NULL;
596 bufflen = bufflen_jit = 0;
601 if (errorcode != errorcode_jit)
603 describe_failure(
"match entry errorcode comparison", wdata,
size,
604 compile_options, match_options, errorcode, errorcode_jit,
605 matches, matches_jit,
match_data, match_data_jit);
610 if (bufflen != bufflen_jit)
612 describe_failure(
"match entry length comparison", wdata,
size,
613 compile_options, match_options, errorcode, errorcode_jit,
614 matches, matches_jit,
match_data, match_data_jit);
617 if (memcmp(bufferptr, bufferptr_jit, bufflen) != 0)
619 describe_failure(
"match entry content comparison", wdata,
size,
620 compile_options, match_options, errorcode, errorcode_jit,
621 matches, matches_jit,
match_data, match_data_jit);
646 for (j = 0; j < 2; j++)
649 printf(
"DFA match options %.8x =", match_options);
650 printf(
"%s%s%s%s%s%s%s%s%s\n",
669 printf(
"Match returned %d\n", errorcode);
671 print_error(stdout, errorcode,
"DFA match failed: error %d: ", errorcode);
674 if (match_options == 0)
break;
678 match_options = save_match_options;
687 print_error(stdout, errorcode,
"Error %d at offset %lu: ", errorcode,
714 int main(
int argc,
char **argv)
720 printf(
"** No arguments given\n");
724 for (
int i = 1;
i < argc;
i++)
734 if (argv[
i][0] ==
'=')
736 readsize = strlen(argv[
i]) - 1;
737 printf(
"------ <Literal> ------\n");
738 printf(
"Length = %lu\n", readsize);
739 printf(
"%.*s\n", (
int)readsize, argv[
i]+1);
742 printf(
"** Failed to allocate %lu bytes of memory\n", readsize);
745 memcpy(
buffer, argv[
i]+1, readsize);
754 f = fopen(argv[
i],
"rb");
757 printf(
"** Failed to open %s: %s\n", argv[
i],
strerror(errno));
761 printf(
"------ %s ------\n", argv[
i]);
770 printf(
"** Failed to allocate %lu bytes of memory\n", filelen);
775 readsize = fread(
buffer, 1, filelen,
f);
778 if (readsize != filelen)
779 printf(
"** File size is %lu but fread() returned %lu\n", filelen, readsize);
782 printf(
"Length = %lu\n", filelen);
int main(int argc, const char *argv[])
static void text(MDB_val *v)
const struct ncbi::grid::netcache::search::fields::SIZE size
#define PCRE2_ALLOW_EMPTY_CLASS
#define PCRE2_DOLLAR_ENDONLY
#define PCRE2_NOTEMPTY_ATSTART
#define PCRE2_ENDANCHORED
#define PCRE2_ALT_VERBNAMES
#define PCRE2_AUTO_CALLOUT
#define PCRE2_ERROR_INTERNAL
#define PCRE2_NO_AUTO_POSSESS
#define PCRE2_EXTENDED_MORE
#define PCRE2_MATCH_UNSET_BACKREF
#define PCRE2_PARTIAL_SOFT
#define PCRE2_NO_DOTSTAR_ANCHOR
#define PCRE2_PARTIAL_HARD
#define pcre2_match_context
#define PCRE2_ERROR_JIT_STACKLIMIT
#define PCRE2_USE_OFFSET_LIMIT
#define PCRE2_ERROR_MATCHLIMIT
#define PCRE2_ERROR_CALLOUT
#define PCRE2_ALT_CIRCUMFLEX
#define PCRE2_JIT_COMPLETE
#define PCRE2_NO_AUTO_CAPTURE
#define PCRE2_NEVER_BACKSLASH_C
#define PCRE2_NO_UTF_CHECK
#define PCRE2_NO_START_OPTIMIZE
#define pcre2_callout_block
#define pcre2_compile_context
#define PCRE2_DISABLE_RECURSELOOP_CHECK
PCRE2_EXPORT pcre2_code *PCRE2_CALL_CONVENTION pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options, int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext)
PCRE2_EXPORT void PCRE2_CALL_CONVENTION pcre2_code_free(pcre2_code *code)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_set_max_pattern_compiled_length(pcre2_compile_context *ccontext, PCRE2_SIZE length)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_set_depth_limit(pcre2_match_context *mcontext, uint32_t limit)
PCRE2_EXPORT void PCRE2_CALL_CONVENTION pcre2_match_context_free(pcre2_match_context *mcontext)
PCRE2_EXPORT pcre2_match_context *PCRE2_CALL_CONVENTION pcre2_match_context_create(pcre2_general_context *gcontext)
PCRE2_EXPORT pcre2_compile_context *PCRE2_CALL_CONVENTION pcre2_compile_context_create(pcre2_general_context *gcontext)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_set_match_limit(pcre2_match_context *mcontext, uint32_t limit)
PCRE2_EXPORT void PCRE2_CALL_CONVENTION pcre2_compile_context_free(pcre2_compile_context *ccontext)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_set_callout(pcre2_match_context *mcontext, int(*callout)(pcre2_callout_block *, void *), void *callout_data)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data, pcre2_match_context *mcontext, int *workspace, PCRE2_SIZE wscount)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_get_error_message(int enumber, PCRE2_UCHAR *buffer, PCRE2_SIZE size)
#define ALLOWED_MATCH_OPTIONS
static int callout_function(pcre2_callout_block *cb, void *callout_data)
#define DFA_WORKSPACE_COUNT
int LLVMFuzzerInitialize(int *, char ***)
int LLVMFuzzerTestOneInput(unsigned char *, size_t)
#define ALLOWED_COMPILE_OPTIONS
#define BASE_MATCH_OPTIONS
#define PCRE2_CODE_UNIT_WIDTH
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_jit_compile(pcre2_code *code, uint32_t options)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data, pcre2_match_context *mcontext)
PCRE2_EXPORT pcre2_match_data *PCRE2_CALL_CONVENTION pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext)
PCRE2_EXPORT void PCRE2_CALL_CONVENTION pcre2_match_data_free(pcre2_match_data *match_data)
PCRE2_EXPORT int PCRE2_CALL_CONVENTION pcre2_substring_get_bynumber(pcre2_match_data *match_data, uint32_t stringnumber, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)
PCRE2_EXPORT void PCRE2_CALL_CONVENTION pcre2_substring_free(PCRE2_UCHAR *string)
static pcre2_match_context * match_context
static pcre2_match_data * match_data
static pcre2_compile_context * compile_context
static uint32_t callout_count
static int * dfa_workspace