1 /*
2  * base.c  contributed by Mark Griffin
3  * Copyright (c) 2019-2021  K.Kosako
4  */
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <time.h>
13 #include "oniguruma.h"
14 
15 #define PARSE_DEPTH_LIMIT               8
16 #define MAX_SUBEXP_CALL_NEST_LEVEL      8
17 #define SUBEXP_CALL_LIMIT            1000
18 #define BASE_RETRY_LIMIT            20000
19 #define BASE_LENGTH                  2048
20 #define MATCH_STACK_LIMIT        10000000
21 #define MAX_REM_SIZE              1048576
22 #define MAX_SLOW_REM_SIZE            1024
23 #define MAX_SLOW_REM_SIZE2            100
24 #define SLOW_RETRY_LIMIT             2000
25 #define SLOW_SUBEXP_CALL_LIMIT        100
26 #define MAX_SLOW_BACKWARD_REM_SIZE    200
27 
28 //#define EXEC_PRINT_INTERVAL      500000
29 //#define DUMP_DATA_INTERVAL       100000
30 //#define STAT_PATH                "fuzzer.stat_log"
31 //#define PREV_CONTROL
32 
33 #ifdef PREV_CONTROL
34 #define OPTIONS_AT_COMPILE   (ONIG_OPTION_IGNORECASE | ONIG_OPTION_EXTEND | ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE | ONIG_OPTION_FIND_LONGEST | ONIG_OPTION_FIND_NOT_EMPTY | ONIG_OPTION_NEGATE_SINGLELINE | ONIG_OPTION_DONT_CAPTURE_GROUP | ONIG_OPTION_CAPTURE_GROUP | ONIG_OPTION_WORD_IS_ASCII | ONIG_OPTION_DIGIT_IS_ASCII | ONIG_OPTION_SPACE_IS_ASCII | ONIG_OPTION_POSIX_IS_ASCII | ONIG_OPTION_TEXT_SEGMENT_EXTENDED_GRAPHEME_CLUSTER | ONIG_OPTION_TEXT_SEGMENT_WORD)
35 #else
36 #define OPTIONS_AT_COMPILE   (ONIG_OPTION_IGNORECASE | ONIG_OPTION_EXTEND | ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE | ONIG_OPTION_FIND_LONGEST | ONIG_OPTION_FIND_NOT_EMPTY | ONIG_OPTION_NEGATE_SINGLELINE | ONIG_OPTION_DONT_CAPTURE_GROUP | ONIG_OPTION_CAPTURE_GROUP | ONIG_OPTION_WORD_IS_ASCII | ONIG_OPTION_DIGIT_IS_ASCII | ONIG_OPTION_SPACE_IS_ASCII | ONIG_OPTION_POSIX_IS_ASCII | ONIG_OPTION_TEXT_SEGMENT_EXTENDED_GRAPHEME_CLUSTER | ONIG_OPTION_TEXT_SEGMENT_WORD | ONIG_OPTION_IGNORECASE_IS_ASCII)
37 #endif
38 
39 #define OPTIONS_AT_RUNTIME   (ONIG_OPTION_NOTBOL | ONIG_OPTION_NOTEOL | ONIG_OPTION_CHECK_VALIDITY_OF_STRING | ONIG_OPTION_NOT_BEGIN_STRING | ONIG_OPTION_NOT_END_STRING | ONIG_OPTION_NOT_BEGIN_POSITION | ONIG_OPTION_CALLBACK_EACH_MATCH)
40 
41 
42 #define ADJUST_LEN(enc, len) do {\
43   int mlen = ONIGENC_MBC_MINLEN(enc);\
44   if (mlen != 1) { len -= len % mlen; }\
45 } while (0)
46 
47 typedef unsigned char uint8_t;
48 
49 
50 //#define TEST_PATTERN
51 
52 #ifdef TEST_PATTERN
53 
54 #if 1
55 unsigned char TestPattern[] = {
56 };
57 #endif
58 
59 #endif /* TEST_PATTERN */
60 
61 #ifdef STANDALONE
62 
63 static void
print_options(FILE * fp,OnigOptionType o)64 print_options(FILE* fp, OnigOptionType o)
65 {
66   if ((o & ONIG_OPTION_IGNORECASE) != 0)      fprintf(fp, " IGNORECASE");
67   if ((o & ONIG_OPTION_EXTEND) != 0)          fprintf(fp, " EXTEND");
68   if ((o & ONIG_OPTION_MULTILINE) != 0)       fprintf(fp, " MULTILINE");
69   if ((o & ONIG_OPTION_SINGLELINE) != 0)      fprintf(fp, " SINGLELINE");
70   if ((o & ONIG_OPTION_FIND_LONGEST) != 0)    fprintf(fp, " FIND_LONGEST");
71   if ((o & ONIG_OPTION_FIND_NOT_EMPTY) != 0)  fprintf(fp, " FIND_NOT_EMPTY");
72   if ((o & ONIG_OPTION_NEGATE_SINGLELINE) != 0)  fprintf(fp, " NEGATE_SINGLELINE");
73   if ((o & ONIG_OPTION_DONT_CAPTURE_GROUP) != 0) fprintf(fp, " DONT_CAPTURE_GROUP");
74   if ((o & ONIG_OPTION_CAPTURE_GROUP) != 0)   fprintf(fp, " CAPTURE_GROUP");
75   if ((o & ONIG_OPTION_NOTBOL) != 0)          fprintf(fp, " NOTBOL");
76   if ((o & ONIG_OPTION_NOTEOL) != 0)          fprintf(fp, " NOTEOL");
77   if ((o & ONIG_OPTION_POSIX_REGION) != 0)    fprintf(fp, " POSIX_REGION");
78   if ((o & ONIG_OPTION_CHECK_VALIDITY_OF_STRING) != 0) fprintf(fp, " CHECK_VALIDITY_OF_STRING");
79   if ((o & ONIG_OPTION_IGNORECASE_IS_ASCII) != 0) fprintf(fp, " IGNORECASE_IS_ASCII");
80   if ((o & ONIG_OPTION_WORD_IS_ASCII) != 0)   fprintf(fp, " WORD_IS_ASCII");
81   if ((o & ONIG_OPTION_DIGIT_IS_ASCII) != 0)  fprintf(fp, " DIGIT_IS_ASCII");
82   if ((o & ONIG_OPTION_SPACE_IS_ASCII) != 0)  fprintf(fp, " SPACE_IS_ASCII");
83   if ((o & ONIG_OPTION_POSIX_IS_ASCII) != 0)  fprintf(fp, " POSIX_IS_ASCII");
84   if ((o & ONIG_OPTION_TEXT_SEGMENT_EXTENDED_GRAPHEME_CLUSTER) != 0) fprintf(fp, " TEXT_SEGMENT_EXTENDED_GRAPHEME_CLUSTER");
85   if ((o & ONIG_OPTION_TEXT_SEGMENT_WORD) != 0) fprintf(fp, " TEXT_SEGMENT_WORD");
86   if ((o & ONIG_OPTION_NOT_BEGIN_STRING) != 0) fprintf(fp, " NOT_BIGIN_STRING");
87   if ((o & ONIG_OPTION_NOT_END_STRING) != 0)   fprintf(fp, " NOT_END_STRING");
88   if ((o & ONIG_OPTION_NOT_BEGIN_POSITION) != 0) fprintf(fp, " NOT_BEGIN_POSITION");
89   if ((o & ONIG_OPTION_CALLBACK_EACH_MATCH) != 0) fprintf(fp, " CALLBACK_EACH_MATCH");
90 }
91 
92 static void
to_binary(unsigned int v,char s[])93 to_binary(unsigned int v, char s[/* 33 */])
94 {
95   unsigned int mask;
96   int i;
97 
98   mask = 1 << (sizeof(v) * 8 - 1);
99   i = 0;
100   do {
101     s[i++] = (mask & v ? '1' : '0');
102   } while (mask >>= 1);
103   s[i] = 0;
104 }
105 #endif
106 
107 #ifdef DUMP_INPUT
108 static void
dump_input(unsigned char * data,size_t len)109 dump_input(unsigned char* data, size_t len)
110 {
111   static FILE* DumpFp;
112   static char end[] = { 'E', 'N', 'D' };
113 
114   if (DumpFp == 0)
115     DumpFp = fopen("dump-input", "w");
116 
117   fseek(DumpFp, 0, SEEK_SET);
118   fwrite(data, sizeof(unsigned char), len, DumpFp);
119   fwrite(end,  sizeof(char), sizeof(end), DumpFp);
120   fflush(DumpFp);
121 }
122 #endif
123 
124 #ifdef DUMP_DATA_INTERVAL
125 static void
dump_file(char * path,unsigned char * data,size_t len)126 dump_file(char* path, unsigned char* data, size_t len)
127 {
128   FILE* fp;
129 
130   fp = fopen(path, "w");
131   fwrite(data, sizeof(unsigned char), len, fp);
132   fclose(fp);
133 }
134 #endif
135 
136 #ifdef STANDALONE
137 #include <ctype.h>
138 
139 static void
dump_data(FILE * fp,unsigned char * data,int len)140 dump_data(FILE* fp, unsigned char* data, int len)
141 {
142   int i;
143 
144   fprintf(fp, "{\n");
145   for (i = 0; i < len; i++) {
146     unsigned char c = data[i];
147 
148     if (isprint((int )c)) {
149       if (c == '\\')
150         fprintf(fp, " '\\\\'");
151       else
152         fprintf(fp, " '%c'", c);
153     }
154     else {
155       fprintf(fp, "0x%02x", (int )c);
156     }
157 
158     if (i == len - 1) {
159       fprintf(fp, "\n");
160     }
161     else {
162       if (i % 8 == 7)
163         fprintf(fp, ",\n");
164       else
165         fprintf(fp, ", ");
166     }
167   }
168   fprintf(fp, "};\n");
169 }
170 
171 #else
172 
173 #ifdef EXEC_PRINT_INTERVAL
174 static void
output_current_time(FILE * fp)175 output_current_time(FILE* fp)
176 {
177   char d[64];
178   time_t t;
179 
180   t = time(NULL);
181   strftime(d, sizeof(d), "%m/%d %H:%M:%S", localtime(&t));
182 
183   fprintf(fp, "%s", d);
184 }
185 #endif
186 
187 #endif
188 
189 static int
progress_callout_func(OnigCalloutArgs * args,void * user_data)190 progress_callout_func(OnigCalloutArgs* args, void* user_data)
191 {
192   return ONIG_CALLOUT_SUCCESS;
193 }
194 
195 static int
each_match_callback_func(const UChar * str,const UChar * end,const UChar * match_start,OnigRegion * region,void * user_data)196 each_match_callback_func(const UChar* str, const UChar* end,
197   const UChar* match_start, OnigRegion* region, void* user_data)
198 {
199   return ONIG_NORMAL;
200 }
201 
202 static int
search(regex_t * reg,unsigned char * str,unsigned char * end,OnigOptionType options,int backward,int sl)203 search(regex_t* reg, unsigned char* str, unsigned char* end, OnigOptionType options, int backward, int sl)
204 {
205   int r;
206   unsigned char *start, *range;
207   OnigRegion *region;
208   unsigned int retry_limit;
209   size_t len;
210 
211   region = onig_region_new();
212 
213   len = (size_t )(end - str);
214   if (len < BASE_LENGTH) {
215     if (sl >= 2)
216       retry_limit = (unsigned int )SLOW_RETRY_LIMIT;
217     else
218       retry_limit = (unsigned int )BASE_RETRY_LIMIT;
219   }
220   else
221     retry_limit = (unsigned int )(BASE_RETRY_LIMIT * BASE_LENGTH / len);
222 
223 #ifdef STANDALONE
224   fprintf(stdout, "retry limit: %u\n", retry_limit);
225 #endif
226 
227   onig_set_retry_limit_in_search(retry_limit);
228   onig_set_match_stack_limit_size(MATCH_STACK_LIMIT);
229   if (sl >= 2)
230     onig_set_subexp_call_limit_in_search(SLOW_SUBEXP_CALL_LIMIT);
231   else
232     onig_set_subexp_call_limit_in_search(SUBEXP_CALL_LIMIT);
233 
234   if (backward != 0) {
235     start = end;
236     range = str;
237   }
238   else {
239     start = str;
240     range = end;
241   }
242 
243   r = onig_search(reg, str, end, start, range, region, (options & OPTIONS_AT_RUNTIME));
244   if (r >= 0) {
245 #ifdef STANDALONE
246     int i;
247 
248     fprintf(stdout, "match at %d  (%s)\n", r,
249             ONIGENC_NAME(onig_get_encoding(reg)));
250     for (i = 0; i < region->num_regs; i++) {
251       fprintf(stdout, "%d: (%d-%d)\n", i, region->beg[i], region->end[i]);
252     }
253 #endif
254   }
255   else if (r == ONIG_MISMATCH) {
256 #ifdef STANDALONE
257     fprintf(stdout, "search fail (%s)\n",
258             ONIGENC_NAME(onig_get_encoding(reg)));
259 #endif
260   }
261   else { /* error */
262 #ifdef STANDALONE
263     char s[ONIG_MAX_ERROR_MESSAGE_LEN];
264 
265     onig_error_code_to_str((UChar* )s, r);
266     fprintf(stdout, "ERROR: %s\n", s);
267     fprintf(stdout, "  (%s)\n", ONIGENC_NAME(onig_get_encoding(reg)));
268 #endif
269     onig_region_free(region, 1 /* 1:free self, 0:free contents only */);
270 
271     if (r == ONIGERR_STACK_BUG ||
272         r == ONIGERR_UNDEFINED_BYTECODE ||
273         r == ONIGERR_UNEXPECTED_BYTECODE)
274       return -2;
275 
276     return -1;
277   }
278 
279   onig_region_free(region, 1 /* 1:free self, 0:free contents only */);
280   return 0;
281 }
282 
283 static long INPUT_COUNT;
284 static long EXEC_COUNT;
285 static long EXEC_COUNT_INTERVAL;
286 static long REGEX_SUCCESS_COUNT;
287 static long VALID_STRING_COUNT;
288 
289 static int
exec(OnigEncoding enc,OnigOptionType options,OnigSyntaxType * syntax,char * apattern,char * apattern_end,char * astr,UChar * end,int backward,int sl)290 exec(OnigEncoding enc, OnigOptionType options, OnigSyntaxType* syntax,
291      char* apattern, char* apattern_end, char* astr, UChar* end, int backward,
292      int sl)
293 {
294   int r;
295   regex_t* reg;
296   OnigErrorInfo einfo;
297   UChar* pattern = (UChar* )apattern;
298   UChar* str     = (UChar* )astr;
299   UChar* pattern_end = (UChar* )apattern_end;
300 
301   EXEC_COUNT++;
302   EXEC_COUNT_INTERVAL++;
303 
304   onig_initialize(&enc, 1);
305   (void)onig_set_progress_callout(progress_callout_func);
306 #ifdef PARSE_DEPTH_LIMIT
307   onig_set_parse_depth_limit(PARSE_DEPTH_LIMIT);
308 #endif
309   onig_set_subexp_call_max_nest_level(MAX_SUBEXP_CALL_NEST_LEVEL);
310   onig_set_callback_each_match(each_match_callback_func);
311 
312   r = onig_new(&reg, pattern, pattern_end,
313                (options & OPTIONS_AT_COMPILE), enc, syntax, &einfo);
314   if (r != ONIG_NORMAL) {
315     char s[ONIG_MAX_ERROR_MESSAGE_LEN];
316     onig_error_code_to_str((UChar* )s, r, &einfo);
317 #ifdef STANDALONE
318     fprintf(stdout, "ERROR: %s\n", s);
319 #endif
320     onig_end();
321 
322     if (r == ONIGERR_PARSER_BUG ||
323         r == ONIGERR_STACK_BUG  ||
324         r == ONIGERR_UNDEFINED_BYTECODE ||
325         r == ONIGERR_UNEXPECTED_BYTECODE) {
326       return -2;
327     }
328     else
329       return -1;
330   }
331   REGEX_SUCCESS_COUNT++;
332 
333   r = search(reg, pattern, pattern_end, options, backward, sl);
334   if (r == -2) return -2;
335 
336   if (onigenc_is_valid_mbc_string(enc, str, end) != 0) {
337     VALID_STRING_COUNT++;
338     r = search(reg, str, end, options, backward, sl);
339     if (r == -2) return -2;
340   }
341 
342   onig_free(reg);
343   onig_end();
344   return 0;
345 }
346 
347 static int
alloc_exec(OnigEncoding enc,OnigOptionType options,OnigSyntaxType * syntax,int backward,int pattern_size,size_t rem_size,unsigned char * data)348 alloc_exec(OnigEncoding enc, OnigOptionType options, OnigSyntaxType* syntax,
349            int backward, int pattern_size, size_t rem_size, unsigned char *data)
350 {
351   extern int onig_detect_can_be_slow_pattern(const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax);
352 
353   int r;
354   int sl;
355   unsigned char *pattern;
356   unsigned char *pattern_end;
357   unsigned char *str_null_end;
358 
359 #ifdef TEST_PATTERN
360   pattern = (unsigned char *)malloc(sizeof(TestPattern));
361   memcpy(pattern, TestPattern, sizeof(TestPattern));
362   pattern_end = pattern + sizeof(TestPattern);
363 #else
364   pattern = (unsigned char *)malloc(pattern_size != 0 ? pattern_size : 1);
365   memcpy(pattern, data, pattern_size);
366   pattern_end = pattern + pattern_size;
367 #endif
368 
369   data += pattern_size;
370   rem_size -= pattern_size;
371 
372   if (rem_size > MAX_REM_SIZE) rem_size = MAX_REM_SIZE;
373 
374   sl = onig_detect_can_be_slow_pattern(pattern, pattern_end, options, enc, syntax);
375 #ifdef STANDALONE
376   fprintf(stdout, "sl: %d\n", sl);
377 #endif
378   if (sl > 0) {
379     if (sl >= 100) {
380       if (rem_size > MAX_SLOW_REM_SIZE2)
381         rem_size = MAX_SLOW_REM_SIZE2;
382     }
383     else {
384       if (rem_size > MAX_SLOW_REM_SIZE)
385         rem_size = MAX_SLOW_REM_SIZE;
386     }
387   }
388   if (backward != 0 && enc == ONIG_ENCODING_GB18030) {
389     if (rem_size > MAX_SLOW_BACKWARD_REM_SIZE)
390       rem_size = MAX_SLOW_BACKWARD_REM_SIZE;
391   }
392 
393   ADJUST_LEN(enc, rem_size);
394 #ifdef STANDALONE
395   fprintf(stdout, "rem_size: %ld\n", rem_size);
396 #endif
397 
398   unsigned char *str = (unsigned char*)malloc(rem_size != 0 ? rem_size : 1);
399   memcpy(str, data, rem_size);
400   str_null_end = str + rem_size;
401 
402   r = exec(enc, options, syntax,
403            (char *)pattern, (char *)pattern_end,
404            (char *)str, str_null_end, backward, sl);
405 
406   free(pattern);
407   free(str);
408   return r;
409 }
410 
411 #ifdef PREV_CONTROL
412 #ifdef SYNTAX_TEST
413 #define NUM_CONTROL_BYTES      7
414 #else
415 #define NUM_CONTROL_BYTES      6
416 #endif
417 #else
418 #ifdef SYNTAX_TEST
419 #define NUM_CONTROL_BYTES      8
420 #else
421 #define NUM_CONTROL_BYTES      7
422 #endif
423 #endif
424 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)425 int LLVMFuzzerTestOneInput(const uint8_t * Data, size_t Size)
426 {
427 #if !defined(UTF16_BE) && !defined(UTF16_LE)
428   static OnigEncoding encodings[] = {
429     ONIG_ENCODING_UTF8,
430     ONIG_ENCODING_UTF8,
431     ONIG_ENCODING_UTF8,
432     ONIG_ENCODING_UTF8,
433     ONIG_ENCODING_UTF8,
434     ONIG_ENCODING_UTF8,
435     ONIG_ENCODING_UTF8,
436     ONIG_ENCODING_UTF8,
437     ONIG_ENCODING_ASCII,
438     ONIG_ENCODING_EUC_JP,
439     ONIG_ENCODING_EUC_TW,
440     ONIG_ENCODING_EUC_KR,
441     ONIG_ENCODING_EUC_CN,
442     ONIG_ENCODING_SJIS,
443     ONIG_ENCODING_KOI8_R,
444     ONIG_ENCODING_CP1251,
445     ONIG_ENCODING_BIG5,
446     ONIG_ENCODING_GB18030,
447     ONIG_ENCODING_UTF16_BE,
448     ONIG_ENCODING_UTF16_LE,
449     ONIG_ENCODING_UTF16_BE,
450     ONIG_ENCODING_UTF16_LE,
451     ONIG_ENCODING_UTF32_BE,
452     ONIG_ENCODING_UTF32_LE,
453     ONIG_ENCODING_UTF32_BE,
454     ONIG_ENCODING_UTF32_LE,
455     ONIG_ENCODING_ISO_8859_1,
456     ONIG_ENCODING_ISO_8859_2,
457     ONIG_ENCODING_ISO_8859_3,
458     ONIG_ENCODING_ISO_8859_4,
459     ONIG_ENCODING_ISO_8859_5,
460     ONIG_ENCODING_ISO_8859_6,
461     ONIG_ENCODING_ISO_8859_7,
462     ONIG_ENCODING_ISO_8859_8,
463     ONIG_ENCODING_ISO_8859_9,
464     ONIG_ENCODING_ISO_8859_10,
465     ONIG_ENCODING_ISO_8859_11,
466     ONIG_ENCODING_ISO_8859_13,
467     ONIG_ENCODING_ISO_8859_14,
468     ONIG_ENCODING_ISO_8859_15,
469     ONIG_ENCODING_ISO_8859_16
470   };
471   unsigned char encoding_choice;
472 #endif
473 
474 #ifdef SYNTAX_TEST
475   static OnigSyntaxType* syntaxes[] = {
476     ONIG_SYNTAX_POSIX_EXTENDED,
477     ONIG_SYNTAX_EMACS,
478     ONIG_SYNTAX_GREP,
479     ONIG_SYNTAX_GNU_REGEX,
480     ONIG_SYNTAX_JAVA,
481     ONIG_SYNTAX_PERL_NG,
482     ONIG_SYNTAX_PYTHON,
483     ONIG_SYNTAX_ONIGURUMA
484   };
485 
486 #ifdef STANDALONE
487   static char* syntax_names[] = {
488     "Posix Extended",
489     "Emacs",
490     "Grep",
491     "GNU Regex",
492     "Java",
493     "Perl+NG",
494     "Python",
495     "Oniguruma"
496   };
497 #endif
498 
499   unsigned char syntax_choice;
500 #endif
501 
502   int r;
503   int backward;
504   int pattern_size;
505   size_t rem_size;
506   unsigned char *data;
507   unsigned char pattern_size_choice;
508   OnigOptionType  options;
509   OnigEncoding    enc;
510   OnigSyntaxType* syntax;
511 
512 #ifndef STANDALONE
513 #ifdef EXEC_PRINT_INTERVAL
514   static FILE* STAT_FP;
515 #endif
516 #endif
517 
518   INPUT_COUNT++;
519 
520 #ifdef DUMP_DATA_INTERVAL
521   if (INPUT_COUNT % DUMP_DATA_INTERVAL == 0) {
522     char path[20];
523     sprintf(path, "dump-%ld", INPUT_COUNT);
524     dump_file(path, (unsigned char* )Data, Size);
525   }
526 #endif
527 
528   if (Size < NUM_CONTROL_BYTES) return 0;
529 
530   rem_size = Size;
531   data = (unsigned char* )(Data);
532 
533 #ifdef UTF16_BE
534   enc = ONIG_ENCODING_UTF16_BE;
535 #else
536 #ifdef UTF16_LE
537   enc = ONIG_ENCODING_UTF16_LE;
538 #else
539   encoding_choice = data[0];
540   data++;
541   rem_size--;
542 
543   int num_encodings = sizeof(encodings)/sizeof(encodings[0]);
544   enc = encodings[encoding_choice % num_encodings];
545 #endif
546 #endif
547 
548 #ifdef SYNTAX_TEST
549   syntax_choice = data[0];
550   data++;
551   rem_size--;
552 
553   int num_syntaxes = sizeof(syntaxes)/sizeof(syntaxes[0]);
554   syntax = syntaxes[syntax_choice % num_syntaxes];
555 #else
556   syntax = ONIG_SYNTAX_DEFAULT;
557 #endif
558 
559 #ifdef PREV_CONTROL
560   if ((data[2] & 0xc0) == 0)
561     options = data[0] | (data[1] << 8) | (data[2] << 16);
562 #else
563   if ((data[3] & 0xc0) == 0)
564     options = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
565 #endif
566   else
567     options = data[0] & ONIG_OPTION_IGNORECASE;
568 
569   data++; rem_size--;
570   data++; rem_size--;
571   data++; rem_size--;
572 #ifndef PREV_CONTROL
573   data++; rem_size--;
574 #endif
575 
576   pattern_size_choice = data[0];
577   data++; rem_size--;
578 
579   backward = (data[0] == 0xbb);
580   data++; rem_size--;
581 
582   if (backward != 0) {
583     options = options & ~ONIG_OPTION_FIND_LONGEST;
584   }
585 
586   if (rem_size == 0)
587     pattern_size = 0;
588   else {
589     pattern_size = (int )pattern_size_choice % rem_size;
590     ADJUST_LEN(enc, pattern_size);
591   }
592 
593 #ifdef STANDALONE
594   {
595     char soptions[33];
596 
597     dump_data(stdout, data, pattern_size);
598     to_binary(options, soptions);
599 #ifdef SYNTAX_TEST
600     fprintf(stdout,
601             "enc: %s, syntax: %s, pattern_size: %d, back:%d\noptions: %s\n",
602             ONIGENC_NAME(enc),
603             syntax_names[syntax_choice % num_syntaxes],
604             pattern_size, backward, soptions);
605 #else
606     fprintf(stdout, "enc: %s, pattern_size: %d, back:%d\noptions: %s\n",
607             ONIGENC_NAME(enc), pattern_size, backward, soptions);
608 #endif
609 
610     print_options(stdout, options);
611     fprintf(stdout, "\n");
612   }
613 #endif
614 
615 #ifdef DUMP_INPUT
616   dump_input((unsigned char* )Data, Size);
617 #endif
618 
619   r = alloc_exec(enc, options, syntax, backward, pattern_size,
620                  rem_size, data);
621   if (r == -2) exit(-2);
622 
623 #ifndef STANDALONE
624 #ifdef EXEC_PRINT_INTERVAL
625   if (EXEC_COUNT_INTERVAL == EXEC_PRINT_INTERVAL) {
626     float fexec, freg, fvalid;
627 
628     if (STAT_FP == 0) {
629 #ifdef STAT_PATH
630       STAT_FP = fopen(STAT_PATH, "a");
631 #else
632       STAT_FP = stdout;
633 #endif
634     }
635 
636     output_current_time(STAT_FP);
637 
638     if (INPUT_COUNT != 0) { // overflow check
639       fexec  = (float )EXEC_COUNT / INPUT_COUNT;
640       freg   = (float )REGEX_SUCCESS_COUNT / INPUT_COUNT;
641       fvalid = (float )VALID_STRING_COUNT / INPUT_COUNT;
642 
643       fprintf(STAT_FP, ": %ld: EXEC:%.2f, REG:%.2f, VALID:%.2f\n",
644               EXEC_COUNT, fexec, freg, fvalid);
645       fflush(STAT_FP);
646     }
647     else {
648       fprintf(STAT_FP, ": ignore (input count overflow)\n");
649     }
650 
651     EXEC_COUNT_INTERVAL = 0;
652   }
653   else if (EXEC_COUNT == 1) {
654     output_current_time(stdout);
655     fprintf(stdout, ": ------------ START ------------\n");
656   }
657 #endif
658 #endif
659 
660   return r;
661 }
662 
663 #ifdef STANDALONE
664 
665 #define MAX_INPUT_DATA_SIZE  4194304
666 
main(int argc,char * argv[])667 extern int main(int argc, char* argv[])
668 {
669   size_t max_size;
670   size_t n;
671   uint8_t Data[MAX_INPUT_DATA_SIZE];
672 
673   if (argc > 1) {
674     max_size = (size_t )atoi(argv[1]);
675   }
676   else {
677     max_size = sizeof(Data);
678   }
679 
680   n = read(0, Data, max_size);
681   fprintf(stdout, "read size: %ld, max_size: %ld\n", n, max_size);
682 
683   LLVMFuzzerTestOneInput(Data, n);
684   return 0;
685 }
686 #endif /* STANDALONE */
687