md2html: Add undoc'ed debug option --replay-fuzz. This helps to reproduce issues found by oss-fuzz project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
diff --git a/md2html/md2html.c b/md2html/md2html.c
index cea82fd..467a9e3 100644
--- a/md2html/md2html.c
+++ b/md2html/md2html.c
@@ -43,6 +43,7 @@ static unsigned parser_flags = 0;
static int want_fullhtml = 0;
static int want_xhtml = 0;
static int want_stat = 0;
+static int want_replay_fuzz = 0;
static const char* html_title = NULL;
static const char* css_path = NULL;
@@ -115,13 +116,15 @@ process_output(const MD_CHAR* text, MD_SIZE size, void* userdata)
}
static int
-process_file(FILE* in, FILE* out)
+process_file(const char* in_path, FILE* in, FILE* out)
{
size_t n;
struct membuffer buf_in = {0};
struct membuffer buf_out = {0};
int ret = -1;
clock_t t0, t1;
+ unsigned p_flags = parser_flags;
+ unsigned r_flags = renderer_flags;
membuf_init(&buf_in, 32 * 1024);
@@ -140,12 +143,31 @@ process_file(FILE* in, FILE* out)
* deal with the HTML header/footer and tags. */
membuf_init(&buf_out, (MD_SIZE)(buf_in.size + buf_in.size/8 + 64));
+ /* Special mode for reproduce test case found with fuzzing a tool.
+ * We assume file format as produced by test/fuzzers/fuzz-mdhtml.c. */
+ if(want_replay_fuzz) {
+ if(buf_in.size < 2 * sizeof(unsigned)) {
+ fprintf(stderr, "File %s isn't valid fuzz test case.\n", in_path);
+ ret = -1;
+ goto out;
+ }
+
+ /* Override parser and renderer flags with those form the test case. */
+ p_flags = ((unsigned*)buf_in.data)[0];
+ r_flags = ((unsigned*)buf_in.data)[1];
+
+ /* And get rid of them from the text input to the parser. */
+ memmove(buf_in.data, buf_in.data + 2 * sizeof(unsigned),
+ buf_in.size - 2 * sizeof(unsigned));
+ buf_in.size -= 2 * sizeof(unsigned);
+ }
+
/* Parse the document. This shall call our callbacks provided via the
* md_renderer_t structure. */
t0 = clock();
- ret = md_html(buf_in.data, (MD_SIZE)buf_in.size, process_output, (void*) &buf_out,
- parser_flags, renderer_flags);
+ ret = md_html(buf_in.data, (MD_SIZE)buf_in.size, process_output,
+ (void*) &buf_out, p_flags, r_flags);
t1 = clock();
if(ret != 0) {
@@ -236,6 +258,9 @@ static const CMDLINE_OPTION cmdline_options[] = {
{ 0, "fno-html", 'H', 0 },
{ 0, "fno-indented-code", 'I', 0 },
+ /* Undocumented option for replaying test cases from fuzzers. */
+ { 0, "replay-fuzz", 'r', 0 },
+
{ 0, NULL, 0, 0 }
};
@@ -326,6 +351,7 @@ cmdline_callback(int opt, char const* value, void* data)
case 'f': want_fullhtml = 1; break;
case 'x': want_xhtml = 1; renderer_flags |= MD_HTML_FLAG_XHTML; break;
case 's': want_stat = 1; break;
+ case 'r': want_replay_fuzz = 1; break;
case 'h': usage(); exit(0); break;
case 'v': version(); exit(0); break;
@@ -391,7 +417,7 @@ main(int argc, char** argv)
}
}
- ret = process_file(in, out);
+ ret = process_file((input_path != NULL) ? input_path : "<stdin>", in, out);
if(in != stdin)
fclose(in);
if(out != stdout)