Consolidate seed corpus generation
Implement file handling in C to speed up corpus generation.
diff --git a/fuzz/.gitignore b/fuzz/.gitignore
index 92e2913..02c74b1 100644
--- a/fuzz/.gitignore
+++ b/fuzz/.gitignore
@@ -1,9 +1,8 @@
corpus/
+genSeed
html
-htmlSeed
regexp
schema
-schemaSeed
seed/html*
seed/schema*
seed/xml*
@@ -11,6 +10,4 @@
testFuzzer
uri
xml
-xmlSeed
xpath
-xpathSeed
diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am
index 7f0bcef..49b9554 100644
--- a/fuzz/Makefile.am
+++ b/fuzz/Makefile.am
@@ -1,6 +1,5 @@
AUTOMAKE_OPTIONS = -Wno-syntax
-EXTRA_PROGRAMS = html htmlSeed regexp uri schema schemaSeed xml xmlSeed \
- xpath xpathSeed
+EXTRA_PROGRAMS = genSeed html regexp schema uri xml xpath
check_PROGRAMS = testFuzzer
CLEANFILES = $(EXTRA_PROGRAMS)
AM_CPPFLAGS = -I$(top_srcdir)/include
@@ -8,16 +7,17 @@
LDADD = $(STATIC_BINARIES) $(top_builddir)/libxml2.la $(THREAD_LIBS) $(Z_LIBS) $(LZMA_LIBS) $(ICONV_LIBS) $(M_LIBS) $(WIN32_EXTRA_LIBADD)
XML_MAX_LEN = 80000
+# Single quotes to avoid wildcard expansion by the shell
XML_SEED_CORPUS_SRC = \
- $(top_srcdir)/test/* \
- $(top_srcdir)/test/errors/*.xml \
- $(top_srcdir)/test/errors10/*.xml \
- $(top_srcdir)/test/namespaces/* \
- $(top_srcdir)/test/valid/*.xml \
- $(top_srcdir)/test/VC/* \
- $(top_srcdir)/test/VCM/* \
- $(top_srcdir)/test/XInclude/docs/* \
- $(top_srcdir)/test/xmlid/*
+ '$(top_srcdir)/test/*' \
+ '$(top_srcdir)/test/errors/*.xml' \
+ '$(top_srcdir)/test/errors10/*.xml' \
+ '$(top_srcdir)/test/namespaces/*' \
+ '$(top_srcdir)/test/valid/*.xml' \
+ '$(top_srcdir)/test/VC/*' \
+ '$(top_srcdir)/test/VCM/*' \
+ '$(top_srcdir)/test/XInclude/docs/*' \
+ '$(top_srcdir)/test/xmlid/*'
testFuzzer_SOURCES = testFuzzer.c fuzz.c
@@ -35,25 +35,15 @@
rm -rf seed/xml.stamp seed/xml
rm -rf seed/xpath.stamp seed/xpath
+# Seed corpus
+
+genSeed_SOURCES = genSeed.c fuzz.c
+
# XML fuzzer
-xmlSeed_SOURCES = xmlSeed.c fuzz.c
-
-seed/xml.stamp: xmlSeed$(EXEEXT)
+seed/xml.stamp: genSeed$(EXEEXT)
@mkdir -p seed/xml
- @for i in $(XML_SEED_CORPUS_SRC); do \
- if [ -f $$i ]; then \
- echo Processing seed $$i; \
- base=$$(basename $$i) \
- outfile=$(abs_builddir)/seed/xml/$$base; \
- pushd $$(dirname $$i) >/dev/null; \
- $(abs_builddir)/xmlSeed$(EXEEXT) $$base > $$outfile; \
- popd >/dev/null; \
- if [ "$$(wc -c < $$outfile)" -gt $(XML_MAX_LEN) ]; then \
- rm $$outfile; \
- fi; \
- fi; \
- done
+ @./genSeed$(EXEEXT) xml $(XML_SEED_CORPUS_SRC)
@touch seed/xml.stamp
xml_SOURCES = xml.c fuzz.c
@@ -69,16 +59,9 @@
# HTML fuzzer
-htmlSeed_SOURCES = htmlSeed.c fuzz.c
-
-seed/html.stamp: htmlSeed$(EXEEXT)
+seed/html.stamp: genSeed$(EXEEXT)
@mkdir -p seed/html
- @for i in $(top_srcdir)/test/HTML/*; do \
- if [ -f $$i ]; then \
- echo Processing seed $$i; \
- ./htmlSeed$(EXEEXT) $$i > seed/html/$$(basename $$i); \
- fi; \
- done
+ @./genSeed$(EXEEXT) html '$(top_srcdir)/test/HTML/*'
@touch seed/html.stamp
html_SOURCES = html.c fuzz.c
@@ -119,20 +102,9 @@
# XML Schema fuzzer
-schemaSeed_SOURCES = schemaSeed.c fuzz.c
-
-seed/schema.stamp: schemaSeed$(EXEEXT)
+seed/schema.stamp: genSeed$(EXEEXT)
@mkdir -p seed/schema
- @for i in ../test/schemas/*.xsd; do \
- if [ -f $$i ]; then \
- echo Processing seed $$i; \
- base=$$(basename $$i) \
- outfile=$(abs_builddir)/seed/schema/$$base; \
- pushd $$(dirname $$i) >/dev/null; \
- $(abs_builddir)/schemaSeed$(EXEEXT) $$base > $$outfile; \
- popd >/dev/null; \
- fi; \
- done
+ @./genSeed$(EXEEXT) schema '$(top_srcdir)/test/schemas/*.xsd'
@touch seed/schema.stamp
schema_SOURCES = schema.c fuzz.c
@@ -148,11 +120,9 @@
# XPath fuzzer
-xpathSeed_SOURCES = xpathSeed.c fuzz.c
-
-seed/xpath.stamp: xpathSeed$(EXEEXT)
+seed/xpath.stamp: genSeed$(EXEEXT)
@mkdir -p seed/xpath
- @./xpathSeed$(EXEEXT) "$(top_builddir)/test/XPath"
+ @./genSeed$(EXEEXT) xpath "$(top_builddir)/test/XPath"
@touch seed/xpath.stamp
xpath_SOURCES = xpath.c fuzz.c
diff --git a/fuzz/fuzz.c b/fuzz/fuzz.c
index 543235c..b5dfa18 100644
--- a/fuzz/fuzz.c
+++ b/fuzz/fuzz.c
@@ -72,11 +72,6 @@
fuzzData.mainEntity = NULL;
}
-static void
-xmlFreeEntityEntry(void *value, const xmlChar *name) {
- xmlFree(value);
-}
-
/**
* xmlFuzzDataFree:
*
@@ -85,7 +80,7 @@
void
xmlFuzzDataCleanup(void) {
xmlFree(fuzzData.outBuf);
- xmlHashFree(fuzzData.entities, xmlFreeEntityEntry);
+ xmlHashFree(fuzzData.entities, xmlHashDefaultDeallocator);
}
/**
@@ -193,47 +188,6 @@
return(NULL);
}
-/*
- * A custom entity loader that writes all external DTDs or entities to a
- * single file in the format expected by xmlFuzzEntityLoader.
- */
-xmlParserInputPtr
-xmlFuzzEntityRecorder(const char *URL, const char *ID,
- xmlParserCtxtPtr ctxt) {
- xmlParserInputPtr in;
- static const int chunkSize = 16384;
- int len;
-
- in = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
- if (in == NULL)
- return(NULL);
-
- if (fuzzData.entities == NULL) {
- fuzzData.entities = xmlHashCreate(4);
- } else if (xmlHashLookup(fuzzData.entities,
- (const xmlChar *) URL) != NULL) {
- return(in);
- }
-
- do {
- len = xmlParserInputBufferGrow(in->buf, chunkSize);
- if (len < 0) {
- fprintf(stderr, "Error reading %s\n", URL);
- xmlFreeInputStream(in);
- return(NULL);
- }
- } while (len > 0);
-
- xmlFuzzWriteString(stdout, URL);
- xmlFuzzWriteString(stdout, (char *) xmlBufContent(in->buf->buffer));
-
- xmlFreeInputStream(in);
-
- xmlHashAddEntry(fuzzData.entities, (const xmlChar *) URL, NULL);
-
- return(xmlNoNetExternalEntityLoader(URL, ID, ctxt));
-}
-
/**
* xmlFuzzReadEntities:
*
diff --git a/fuzz/fuzz.h b/fuzz/fuzz.h
index c39fa65..8716af9 100644
--- a/fuzz/fuzz.h
+++ b/fuzz/fuzz.h
@@ -43,9 +43,6 @@
const char *
xmlFuzzReadString(size_t *size);
-xmlParserInputPtr
-xmlFuzzEntityRecorder(const char *URL, const char *ID, xmlParserCtxtPtr ctxt);
-
void
xmlFuzzReadEntities(void);
diff --git a/fuzz/genSeed.c b/fuzz/genSeed.c
new file mode 100644
index 0000000..68fb87a
--- /dev/null
+++ b/fuzz/genSeed.c
@@ -0,0 +1,407 @@
+/*
+ * xmlSeed.c: Generate the XML seed corpus for fuzzing.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <glob.h>
+#include <libgen.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xinclude.h>
+#include <libxml/xmlschemas.h>
+#include "fuzz.h"
+
+#define PATH_SIZE 500
+#define SEED_BUF_SIZE 16384
+#define EXPR_SIZE 4500
+
+typedef int
+(*fileFunc)(const char *base, FILE *out);
+
+typedef int
+(*mainFunc)(const char *arg);
+
+static struct {
+ FILE *out;
+ xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */
+ xmlExternalEntityLoader oldLoader;
+ fileFunc processFile;
+ const char *fuzzer;
+ int counter;
+ char cwd[PATH_SIZE];
+} globalData;
+
+/*
+ * A custom entity loader that writes all external DTDs or entities to a
+ * single file in the format expected by xmlFuzzEntityLoader.
+ */
+static xmlParserInputPtr
+fuzzEntityRecorder(const char *URL, const char *ID,
+ xmlParserCtxtPtr ctxt) {
+ xmlParserInputPtr in;
+ static const int chunkSize = 16384;
+ int len;
+
+ in = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+ if (in == NULL)
+ return(NULL);
+
+ if (globalData.entities == NULL) {
+ globalData.entities = xmlHashCreate(4);
+ } else if (xmlHashLookup(globalData.entities,
+ (const xmlChar *) URL) != NULL) {
+ return(in);
+ }
+
+ do {
+ len = xmlParserInputBufferGrow(in->buf, chunkSize);
+ if (len < 0) {
+ fprintf(stderr, "Error reading %s\n", URL);
+ xmlFreeInputStream(in);
+ return(NULL);
+ }
+ } while (len > 0);
+
+ xmlFuzzWriteString(globalData.out, URL);
+ xmlFuzzWriteString(globalData.out,
+ (char *) xmlBufContent(in->buf->buffer));
+
+ xmlFreeInputStream(in);
+
+ xmlHashAddEntry(globalData.entities, (const xmlChar *) URL, NULL);
+
+ return(xmlNoNetExternalEntityLoader(URL, ID, ctxt));
+}
+
+static void
+fuzzRecorderInit(FILE *out) {
+ globalData.out = out;
+ globalData.entities = xmlHashCreate(8);
+ globalData.oldLoader = xmlGetExternalEntityLoader();
+ xmlSetExternalEntityLoader(fuzzEntityRecorder);
+}
+
+static void
+fuzzRecorderCleanup() {
+ xmlSetExternalEntityLoader(globalData.oldLoader);
+ xmlHashFree(globalData.entities, xmlHashDefaultDeallocator);
+ globalData.out = NULL;
+ globalData.entities = NULL;
+ globalData.oldLoader = NULL;
+}
+
+static int
+processXml(const char *docFile, FILE *out) {
+ int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
+ xmlDocPtr doc;
+
+ fwrite(&opts, sizeof(opts), 1, out);
+
+ fuzzRecorderInit(out);
+
+ doc = xmlReadFile(docFile, NULL, opts);
+ xmlXIncludeProcessFlags(doc, opts);
+ xmlFreeDoc(doc);
+
+ fuzzRecorderCleanup();
+
+ return(0);
+}
+
+static int
+processHtml(const char *docFile, FILE *out) {
+ char buf[SEED_BUF_SIZE];
+ FILE *file;
+ size_t size;
+ int opts = 0;
+
+ fwrite(&opts, sizeof(opts), 1, out);
+
+ /* Copy file */
+ file = fopen(docFile, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "couldn't open %s\n", docFile);
+ return(0);
+ }
+ do {
+ size = fread(buf, 1, SEED_BUF_SIZE, file);
+ if (size > 0)
+ fwrite(buf, 1, size, out);
+ } while (size == SEED_BUF_SIZE);
+ fclose(file);
+
+ return(0);
+}
+
+static int
+processSchema(const char *docFile, FILE *out) {
+ xmlSchemaPtr schema;
+ xmlSchemaParserCtxtPtr pctxt;
+
+ fuzzRecorderInit(out);
+
+ pctxt = xmlSchemaNewParserCtxt(docFile);
+ xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
+ schema = xmlSchemaParse(pctxt);
+ xmlSchemaFreeParserCtxt(pctxt);
+ xmlSchemaFree(schema);
+
+ fuzzRecorderCleanup();
+
+ return(0);
+}
+
+static int
+processPattern(const char *pattern) {
+ glob_t globbuf;
+ int ret = 0;
+ int res, i;
+
+ res = glob(pattern, 0, NULL, &globbuf);
+ if (res == GLOB_NOMATCH)
+ return(0);
+ if (res != 0) {
+ fprintf(stderr, "couldn't match pattern %s\n", pattern);
+ return(-1);
+ }
+
+ for (i = 0; i < globbuf.gl_pathc; i++) {
+ struct stat statbuf;
+ char outPath[PATH_SIZE];
+ char *dirBuf = NULL;
+ char *baseBuf = NULL;
+ const char *path, *dir, *base;
+ FILE *out = NULL;
+ int dirChanged = 0;
+ size_t size;
+
+ path = globbuf.gl_pathv[i];
+
+ if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
+ continue;
+
+ dirBuf = (char *) xmlCharStrdup(path);
+ baseBuf = (char *) xmlCharStrdup(path);
+ if ((dirBuf == NULL) || (baseBuf == NULL)) {
+ fprintf(stderr, "memory allocation failed\n");
+ ret = -1;
+ goto error;
+ }
+ dir = dirname(dirBuf);
+ base = basename(baseBuf);
+
+ size = snprintf(outPath, sizeof(outPath), "seed/%s/%s",
+ globalData.fuzzer, base);
+ if (size >= PATH_SIZE) {
+ fprintf(stderr, "creating path failed\n");
+ ret = -1;
+ goto error;
+ }
+ out = fopen(outPath, "wb");
+ if (out == NULL) {
+ fprintf(stderr, "couldn't open %s for writing\n", outPath);
+ ret = -1;
+ goto error;
+ }
+ if (chdir(dir) != 0) {
+ fprintf(stderr, "couldn't chdir to %s\n", dir);
+ ret = -1;
+ goto error;
+ }
+ dirChanged = 1;
+ if (globalData.processFile(base, out) != 0)
+ ret = -1;
+
+error:
+ if (out != NULL)
+ fclose(out);
+ xmlFree(dirBuf);
+ xmlFree(baseBuf);
+ if ((dirChanged) && (chdir(globalData.cwd) != 0)) {
+ fprintf(stderr, "couldn't chdir to %s\n", globalData.cwd);
+ ret = -1;
+ break;
+ }
+ }
+
+ globfree(&globbuf);
+ return(ret);
+}
+
+static int
+processXPath(const char *testDir, const char *prefix, const char *name,
+ const char *data, const char *subdir, int xptr) {
+ char pattern[PATH_SIZE];
+ glob_t globbuf;
+ size_t i, size;
+ int ret = 0, res;
+
+ size = snprintf(pattern, sizeof(pattern), "%s/%s/%s*",
+ testDir, subdir, prefix);
+ if (size >= PATH_SIZE)
+ return(-1);
+ res = glob(pattern, 0, NULL, &globbuf);
+ if (res == GLOB_NOMATCH)
+ return(0);
+ if (res != 0) {
+ fprintf(stderr, "couldn't match pattern %s\n", pattern);
+ return(-1);
+ }
+
+ for (i = 0; i < globbuf.gl_pathc; i++) {
+ char *path = globbuf.gl_pathv[i];
+ struct stat statbuf;
+ FILE *in;
+ char expr[EXPR_SIZE];
+
+ if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
+ continue;
+
+ in = fopen(path, "rb");
+ if (in == NULL) {
+ ret = -1;
+ continue;
+ }
+
+ while (fgets(expr, EXPR_SIZE, in) > 0) {
+ char outPath[PATH_SIZE];
+ FILE *out;
+ int j;
+
+ for (j = 0; expr[j] != 0; j++)
+ if (expr[j] == '\r' || expr[j] == '\n')
+ break;
+ expr[j] = 0;
+
+ size = snprintf(outPath, sizeof(outPath), "seed/xpath/%s-%d",
+ name, globalData.counter);
+ if (size >= PATH_SIZE) {
+ ret = -1;
+ continue;
+ }
+ out = fopen(outPath, "wb");
+ if (out == NULL) {
+ ret = -1;
+ continue;
+ }
+
+ if (xptr) {
+ xmlFuzzWriteString(out, expr);
+ } else {
+ char xptrExpr[EXPR_SIZE+100];
+
+ /* Wrap XPath expressions as XPointer */
+ snprintf(xptrExpr, sizeof(xptrExpr), "xpointer(%s)", expr);
+ xmlFuzzWriteString(out, xptrExpr);
+ }
+
+ xmlFuzzWriteString(out, data);
+
+ fclose(out);
+ globalData.counter++;
+ }
+
+ fclose(in);
+ }
+
+ globfree(&globbuf);
+
+ return(ret);
+}
+
+int
+processXPathDir(const char *testDir) {
+ char pattern[PATH_SIZE];
+ glob_t globbuf;
+ size_t i, size;
+ int ret = 0;
+
+ globalData.counter = 1;
+ if (processXPath(testDir, "", "expr", "<d></d>", "expr", 0) != 0)
+ ret = -1;
+
+ size = snprintf(pattern, sizeof(pattern), "%s/docs/*", testDir);
+ if (size >= PATH_SIZE)
+ return(1);
+ if (glob(pattern, 0, NULL, &globbuf) != 0)
+ return(1);
+
+ for (i = 0; i < globbuf.gl_pathc; i++) {
+ char *path = globbuf.gl_pathv[i];
+ char *data;
+ const char *docFile;
+
+ data = xmlSlurpFile(path, NULL);
+ if (data == NULL) {
+ ret = -1;
+ continue;
+ }
+ docFile = basename(path);
+
+ globalData.counter = 1;
+ if (processXPath(testDir, docFile, docFile, data, "tests", 0) != 0)
+ ret = -1;
+ if (processXPath(testDir, docFile, docFile, data, "xptr", 1) != 0)
+ ret = -1;
+
+ xmlFree(data);
+ }
+
+ globfree(&globbuf);
+
+ return(ret);
+}
+
+int
+main(int argc, const char **argv) {
+ mainFunc processArg = processPattern;
+ const char *fuzzer;
+ int ret = 0;
+ int xpath = 0;
+ int i;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: seed [FUZZER] [PATTERN...]\n");
+ return(1);
+ }
+
+ xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+
+ fuzzer = argv[1];
+ if (strcmp(fuzzer, "html") == 0) {
+ globalData.processFile = processHtml;
+ } else if (strcmp(fuzzer, "schema") == 0) {
+ globalData.processFile = processSchema;
+ } else if (strcmp(fuzzer, "xml") == 0) {
+ globalData.processFile = processXml;
+ } else if (strcmp(fuzzer, "xpath") == 0) {
+ processArg = processXPathDir;
+ } else {
+ fprintf(stderr, "unknown fuzzer %s\n", fuzzer);
+ return(1);
+ }
+ globalData.fuzzer = fuzzer;
+
+ if (getcwd(globalData.cwd, PATH_SIZE) == NULL) {
+ fprintf(stderr, "couldn't get current directory\n");
+ return(1);
+ }
+
+ for (i = 2; i < argc; i++)
+ processArg(argv[i]);
+
+ return(ret);
+}
+
diff --git a/fuzz/htmlSeed.c b/fuzz/htmlSeed.c
deleted file mode 100644
index f3213e2..0000000
--- a/fuzz/htmlSeed.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * htmlSeed.c: Generate the HTML seed corpus for fuzzing.
- *
- * See Copyright for the status of this software.
- */
-
-#include <stdio.h>
-
-#define SEED_BUF_SIZE 16384
-
-int
-main(int argc, char **argv) {
- int opts = 0;
- FILE *file;
- char buf[SEED_BUF_SIZE];
- size_t size;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: htmlSeed [FILE]\n");
- return(1);
- }
-
- fwrite(&opts, sizeof(opts), 1, stdout);
-
- /* Copy file */
- file = fopen(argv[1], "rb");
- do {
- size = fread(buf, 1, SEED_BUF_SIZE, file);
- if (size > 0)
- fwrite(buf, 1, size, stdout);
- } while (size == SEED_BUF_SIZE);
- fclose(file);
-
- return(0);
-}
-
diff --git a/fuzz/schemaSeed.c b/fuzz/schemaSeed.c
deleted file mode 100644
index 4e2c6bc..0000000
--- a/fuzz/schemaSeed.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * xmlSeed.c: Generate the XML seed corpus for fuzzing.
- *
- * See Copyright for the status of this software.
- */
-
-#include <stdio.h>
-#include <libxml/xmlschemas.h>
-#include "fuzz.h"
-
-int
-main(int argc, char **argv) {
- xmlSchemaPtr schema;
- xmlSchemaParserCtxtPtr pctxt;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: schemaSeed [XSD]\n");
- return(1);
- }
-
- xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
- xmlSetExternalEntityLoader(xmlFuzzEntityRecorder);
-
- pctxt = xmlSchemaNewParserCtxt(argv[1]);
- xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
- schema = xmlSchemaParse(pctxt);
- xmlSchemaFreeParserCtxt(pctxt);
-
- xmlSchemaFree(schema);
- xmlFuzzDataCleanup();
-
- return(0);
-}
-
diff --git a/fuzz/xmlSeed.c b/fuzz/xmlSeed.c
deleted file mode 100644
index 8f164dd..0000000
--- a/fuzz/xmlSeed.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * xmlSeed.c: Generate the XML seed corpus for fuzzing.
- *
- * See Copyright for the status of this software.
- */
-
-#include <stdio.h>
-#include <libxml/xinclude.h>
-#include "fuzz.h"
-
-int
-main(int argc, char **argv) {
- int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
- xmlDocPtr doc;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: xmlSeed [FILE]\n");
- return(1);
- }
-
- fwrite(&opts, sizeof(opts), 1, stdout);
-
- xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
- xmlSetExternalEntityLoader(xmlFuzzEntityRecorder);
- doc = xmlReadFile(argv[1], NULL, opts);
- xmlXIncludeProcessFlags(doc, opts);
- xmlFreeDoc(doc);
- xmlFuzzDataCleanup();
-
- return(0);
-}
-
diff --git a/fuzz/xpathSeed.c b/fuzz/xpathSeed.c
deleted file mode 100644
index 1d2c8a4..0000000
--- a/fuzz/xpathSeed.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * xpathSeed.c: Generate the XPath and XPointer seed corpus for fuzzing.
- *
- * See Copyright for the status of this software.
- */
-
-#include <glob.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include "fuzz.h"
-
-#define PATH_SIZE 256
-#define EXPR_SIZE 4500
-
-typedef struct {
- const char *name;
- const char *prefix;
- char *data;
- int counter;
-} xpathTestXml;
-
-static int
-processXml(const char *testDir, xpathTestXml *xml, const char *subdir,
- int xptr);
-
-int
-main(int argc, char **argv) {
- xpathTestXml xml;
- char pattern[PATH_SIZE];
- glob_t globbuf;
- size_t i, size;
- int ret = 0;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: xpathSeed [TESTDIR]\n");
- return(1);
- }
-
- xml.name = "expr";
- xml.prefix = "";
- xml.data = "<d></d>";
- xml.counter = 1;
- if (processXml(argv[1], &xml, "expr", 0) != 0)
- ret = 1;
-
- size = snprintf(pattern, sizeof(pattern), "%s/docs/*", argv[1]);
- if (size >= PATH_SIZE)
- return(1);
- if (glob(pattern, 0, NULL, &globbuf) != 0)
- return(1);
-
- for (i = 0; i < globbuf.gl_pathc; i++) {
- char *path = globbuf.gl_pathv[i];
-
- xml.data = xmlSlurpFile(path, NULL);
- if (xml.data == NULL) {
- ret = 1;
- continue;
- }
- xml.name = basename(path);
- xml.prefix = xml.name;
- xml.counter = 1;
-
- if (processXml(argv[1], &xml, "tests", 0) != 0)
- ret = 1;
- if (processXml(argv[1], &xml, "xptr", 1) != 0)
- ret = 1;
-
- xmlFree(xml.data);
- }
-
- globfree(&globbuf);
-
- return(ret);
-}
-
-static int
-processXml(const char *testDir, xpathTestXml *xml, const char *subdir,
- int xptr) {
- char pattern[PATH_SIZE];
- glob_t globbuf;
- size_t i, size;
- int ret = 0, res;
-
- size = snprintf(pattern, sizeof(pattern), "%s/%s/%s*",
- testDir, subdir, xml->prefix);
- if (size >= PATH_SIZE)
- return(-1);
- res = glob(pattern, 0, NULL, &globbuf);
- if (res == GLOB_NOMATCH)
- return(0);
- if (res != 0)
- return(-1);
-
- for (i = 0; i < globbuf.gl_pathc; i++) {
- char *path = globbuf.gl_pathv[i];
- struct stat statbuf;
- FILE *in;
- char expr[EXPR_SIZE];
-
- if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
- continue;
-
- printf("## Processing %s\n", path);
- in = fopen(path, "rb");
- if (in == NULL) {
- ret = -1;
- continue;
- }
-
- while (fgets(expr, EXPR_SIZE, in) > 0) {
- char outPath[PATH_SIZE];
- FILE *out;
- int j;
-
- for (j = 0; expr[j] != 0; j++)
- if (expr[j] == '\r' || expr[j] == '\n')
- break;
- expr[j] = 0;
-
- size = snprintf(outPath, sizeof(outPath), "seed/xpath/%s-%d",
- xml->name, xml->counter);
- if (size >= PATH_SIZE) {
- ret = -1;
- continue;
- }
- out = fopen(outPath, "wb");
- if (out == NULL) {
- ret = -1;
- continue;
- }
-
- if (xptr) {
- xmlFuzzWriteString(out, expr);
- } else {
- char xptrExpr[EXPR_SIZE+100];
-
- /* Wrap XPath expressions as XPointer */
- snprintf(xptrExpr, sizeof(xptrExpr), "xpointer(%s)", expr);
- xmlFuzzWriteString(out, xptrExpr);
- }
-
- xmlFuzzWriteString(out, xml->data);
-
- fclose(out);
- xml->counter++;
- }
-
- fclose(in);
- }
-
- globfree(&globbuf);
-
- return(ret);
-}
-