mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-31 21:50:33 +03:00
fuzz: Start to fuzz XML Schema validator
This commit is contained in:
31
fuzz/fuzz.c
31
fuzz/fuzz.c
@@ -40,6 +40,8 @@ static struct {
|
|||||||
/* The first entity is the main entity. */
|
/* The first entity is the main entity. */
|
||||||
const char *mainUrl;
|
const char *mainUrl;
|
||||||
xmlFuzzEntityInfo *mainEntity;
|
xmlFuzzEntityInfo *mainEntity;
|
||||||
|
const char *secondaryUrl;
|
||||||
|
xmlFuzzEntityInfo *secondaryEntity;
|
||||||
} fuzzData;
|
} fuzzData;
|
||||||
|
|
||||||
size_t fuzzNumAttempts;
|
size_t fuzzNumAttempts;
|
||||||
@@ -195,6 +197,8 @@ xmlFuzzDataInit(const char *data, size_t size) {
|
|||||||
fuzzData.entities = xmlHashCreate(8);
|
fuzzData.entities = xmlHashCreate(8);
|
||||||
fuzzData.mainUrl = NULL;
|
fuzzData.mainUrl = NULL;
|
||||||
fuzzData.mainEntity = NULL;
|
fuzzData.mainEntity = NULL;
|
||||||
|
fuzzData.secondaryUrl = NULL;
|
||||||
|
fuzzData.secondaryEntity = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,6 +394,9 @@ xmlFuzzReadEntities(void) {
|
|||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
fuzzData.mainUrl = url;
|
fuzzData.mainUrl = url;
|
||||||
fuzzData.mainEntity = entityInfo;
|
fuzzData.mainEntity = entityInfo;
|
||||||
|
} else if (num == 1) {
|
||||||
|
fuzzData.secondaryUrl = url;
|
||||||
|
fuzzData.secondaryEntity = entityInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
num++;
|
num++;
|
||||||
@@ -421,6 +428,30 @@ xmlFuzzMainEntity(size_t *size) {
|
|||||||
return(fuzzData.mainEntity->data);
|
return(fuzzData.mainEntity->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlFuzzSecondaryUrl:
|
||||||
|
*
|
||||||
|
* Returns the secondary URL.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
xmlFuzzSecondaryUrl(void) {
|
||||||
|
return(fuzzData.secondaryUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlFuzzSecondaryEntity:
|
||||||
|
* @size: size of the secondary entity in bytes
|
||||||
|
*
|
||||||
|
* Returns the secondary entity.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
xmlFuzzSecondaryEntity(size_t *size) {
|
||||||
|
if (fuzzData.secondaryEntity == NULL)
|
||||||
|
return(NULL);
|
||||||
|
*size = fuzzData.secondaryEntity->size;
|
||||||
|
return(fuzzData.secondaryEntity->data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlFuzzResourceLoader:
|
* xmlFuzzResourceLoader:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -112,6 +112,12 @@ xmlFuzzMainUrl(void);
|
|||||||
const char *
|
const char *
|
||||||
xmlFuzzMainEntity(size_t *size);
|
xmlFuzzMainEntity(size_t *size);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
xmlFuzzSecondaryUrl(void);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
xmlFuzzSecondaryEntity(size_t *size);
|
||||||
|
|
||||||
int
|
int
|
||||||
xmlFuzzResourceLoader(void *data, const char *URL, const char *ID,
|
xmlFuzzResourceLoader(void *data, const char *URL, const char *ID,
|
||||||
xmlResourceType type, int flags, xmlParserInputPtr *out);
|
xmlResourceType type, int flags, xmlParserInputPtr *out);
|
||||||
|
|||||||
227
fuzz/genSeed.c
227
fuzz/genSeed.c
@@ -86,14 +86,16 @@ fuzzResourceRecorder(void *data ATTRIBUTE_UNUSED, const char *URL,
|
|||||||
}
|
}
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
|
|
||||||
xmlFuzzWriteString(globalData.out, URL);
|
data = xmlStrdup(xmlBufContent(in->buf->buffer));
|
||||||
xmlFuzzWriteString(globalData.out,
|
if (data == NULL) {
|
||||||
(char *) xmlBufContent(in->buf->buffer));
|
fprintf(stderr, "Error allocating entity data\n");
|
||||||
|
xmlFreeInputStream(in);
|
||||||
|
return(XML_ERR_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
xmlFreeInputStream(in);
|
xmlFreeInputStream(in);
|
||||||
|
|
||||||
xmlHashAddEntry(globalData.entities, (const xmlChar *) URL,
|
xmlHashAddEntry(globalData.entities, (const xmlChar *) URL, data);
|
||||||
globalData.entities);
|
|
||||||
|
|
||||||
return(xmlNewInputFromUrl(URL, flags, out));
|
return(xmlNewInputFromUrl(URL, flags, out));
|
||||||
}
|
}
|
||||||
@@ -105,9 +107,24 @@ fuzzRecorderInit(FILE *out) {
|
|||||||
globalData.oldLoader = xmlGetExternalEntityLoader();
|
globalData.oldLoader = xmlGetExternalEntityLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fuzzRecorderWriteAndFree(void *entry, const xmlChar *file) {
|
||||||
|
char *data = entry;
|
||||||
|
xmlFuzzWriteString(globalData.out, (const char *) file);
|
||||||
|
xmlFuzzWriteString(globalData.out, data);
|
||||||
|
xmlFree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fuzzRecorderWrite(const char *file) {
|
||||||
|
xmlHashRemoveEntry(globalData.entities, (const xmlChar *) file,
|
||||||
|
fuzzRecorderWriteAndFree);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fuzzRecorderCleanup(void) {
|
fuzzRecorderCleanup(void) {
|
||||||
xmlHashFree(globalData.entities, NULL);
|
/* Write remaining entities (in random order). */
|
||||||
|
xmlHashFree(globalData.entities, fuzzRecorderWriteAndFree);
|
||||||
globalData.out = NULL;
|
globalData.out = NULL;
|
||||||
globalData.entities = NULL;
|
globalData.entities = NULL;
|
||||||
globalData.oldLoader = NULL;
|
globalData.oldLoader = NULL;
|
||||||
@@ -174,6 +191,7 @@ processXml(const char *docFile, FILE *out) {
|
|||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
xmlFreeParserCtxt(ctxt);
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
|
||||||
|
fuzzRecorderWrite(docFile);
|
||||||
fuzzRecorderCleanup();
|
fuzzRecorderCleanup();
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
@@ -209,32 +227,7 @@ processHtml(const char *docFile, FILE *out) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SCHEMA_FUZZER
|
|
||||||
static int
|
|
||||||
processSchema(const char *docFile, FILE *out) {
|
|
||||||
xmlSchemaPtr schema;
|
|
||||||
xmlSchemaParserCtxtPtr pctxt;
|
|
||||||
|
|
||||||
/* Max allocations. */
|
|
||||||
xmlFuzzWriteInt(out, 0, 4);
|
|
||||||
|
|
||||||
fuzzRecorderInit(out);
|
|
||||||
|
|
||||||
pctxt = xmlSchemaNewParserCtxt(docFile);
|
|
||||||
xmlSchemaSetParserStructuredErrors(pctxt, xmlFuzzSErrorFunc, NULL);
|
|
||||||
xmlSchemaSetResourceLoader(pctxt, fuzzResourceRecorder, NULL);
|
|
||||||
schema = xmlSchemaParse(pctxt);
|
|
||||||
xmlSchemaFreeParserCtxt(pctxt);
|
|
||||||
xmlSchemaFree(schema);
|
|
||||||
|
|
||||||
fuzzRecorderCleanup();
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAVE_HTML_FUZZER) || \
|
#if defined(HAVE_HTML_FUZZER) || \
|
||||||
defined(HAVE_SCHEMA_FUZZER) || \
|
|
||||||
defined(HAVE_XML_FUZZER)
|
defined(HAVE_XML_FUZZER)
|
||||||
static int
|
static int
|
||||||
processPattern(const char *pattern) {
|
processPattern(const char *pattern) {
|
||||||
@@ -315,6 +308,175 @@ error:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SCHEMA_FUZZER)
|
||||||
|
static int
|
||||||
|
processSchema(const char *xsdFile, const char *xmlFile, FILE *out) {
|
||||||
|
xmlSchemaPtr schema;
|
||||||
|
xmlSchemaParserCtxtPtr pctxt;
|
||||||
|
|
||||||
|
/* Max allocations. */
|
||||||
|
xmlFuzzWriteInt(out, 0, 4);
|
||||||
|
|
||||||
|
fuzzRecorderInit(out);
|
||||||
|
|
||||||
|
pctxt = xmlSchemaNewParserCtxt(xsdFile);
|
||||||
|
xmlSchemaSetParserStructuredErrors(pctxt, xmlFuzzSErrorFunc, NULL);
|
||||||
|
xmlSchemaSetResourceLoader(pctxt, fuzzResourceRecorder, NULL);
|
||||||
|
schema = xmlSchemaParse(pctxt);
|
||||||
|
xmlSchemaFreeParserCtxt(pctxt);
|
||||||
|
|
||||||
|
if (schema != NULL) {
|
||||||
|
xmlSchemaValidCtxtPtr vctxt;
|
||||||
|
xmlParserCtxtPtr ctxt;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
ctxt = xmlNewParserCtxt();
|
||||||
|
xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
|
||||||
|
xmlCtxtSetResourceLoader(ctxt, fuzzResourceRecorder, NULL);
|
||||||
|
doc = xmlCtxtReadFile(ctxt, xmlFile, NULL, XML_PARSE_NOENT);
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
|
||||||
|
vctxt = xmlSchemaNewValidCtxt(schema);
|
||||||
|
xmlSchemaSetValidStructuredErrors(vctxt, xmlFuzzSErrorFunc, NULL);
|
||||||
|
xmlSchemaValidateDoc(vctxt, doc);
|
||||||
|
xmlSchemaFreeValidCtxt(vctxt);
|
||||||
|
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
xmlSchemaFree(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzzRecorderWrite(xsdFile);
|
||||||
|
fuzzRecorderWrite(xmlFile);
|
||||||
|
fuzzRecorderCleanup();
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
processSchemaPattern(const char *pattern) {
|
||||||
|
glob_t globbuf;
|
||||||
|
int ret = 0;
|
||||||
|
int res;
|
||||||
|
size_t 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++) {
|
||||||
|
glob_t globbuf2;
|
||||||
|
struct stat statbuf;
|
||||||
|
char xmlPattern[PATH_SIZE];
|
||||||
|
char *dirBuf = NULL;
|
||||||
|
char *baseBuf = NULL;
|
||||||
|
const char *path, *dir, *base;
|
||||||
|
size_t size, dirLen, baseLen, len, j;
|
||||||
|
|
||||||
|
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);
|
||||||
|
dirLen = strlen(dir);
|
||||||
|
base = basename(baseBuf);
|
||||||
|
baseLen = strlen(base);
|
||||||
|
|
||||||
|
len = strlen(path);
|
||||||
|
if (len <= 5)
|
||||||
|
continue;
|
||||||
|
/* Strip .xsl or _0.xsd suffix */
|
||||||
|
if (len > 6 && path[len - 6] == '_')
|
||||||
|
len -= 6;
|
||||||
|
else
|
||||||
|
len -= 4;
|
||||||
|
size = snprintf(xmlPattern, sizeof(xmlPattern), "%.*s_*.xml",
|
||||||
|
(int) len, path);
|
||||||
|
if (size >= PATH_SIZE) {
|
||||||
|
fprintf(stderr, "creating path failed\n");
|
||||||
|
ret = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = glob(xmlPattern, 0, NULL, &globbuf2);
|
||||||
|
if (res == GLOB_NOMATCH)
|
||||||
|
goto error;
|
||||||
|
if (res != 0) {
|
||||||
|
fprintf(stderr, "couldn't match pattern %s\n", xmlPattern);
|
||||||
|
ret = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < globbuf2.gl_pathc; j++) {
|
||||||
|
char outPath[PATH_SIZE];
|
||||||
|
const char *xmlFile;
|
||||||
|
FILE *out = NULL;
|
||||||
|
|
||||||
|
xmlFile = globbuf2.gl_pathv[j];
|
||||||
|
|
||||||
|
len = strlen(xmlFile);
|
||||||
|
if (len < dirLen + 7)
|
||||||
|
continue;
|
||||||
|
if (len >= 6 && xmlFile[len - 6] == '_')
|
||||||
|
size = snprintf(outPath, sizeof(outPath), "seed/%s/%.*s_%c",
|
||||||
|
globalData.fuzzer, (int) baseLen - 4, base,
|
||||||
|
xmlFile[len - 5]);
|
||||||
|
else
|
||||||
|
size = snprintf(outPath, sizeof(outPath), "seed/%s/%.*s",
|
||||||
|
globalData.fuzzer, (int) baseLen - 4, base);
|
||||||
|
|
||||||
|
if (size >= PATH_SIZE) {
|
||||||
|
fprintf(stderr, "creating path failed\n");
|
||||||
|
ret = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out = fopen(outPath, "wb");
|
||||||
|
if (out == NULL) {
|
||||||
|
fprintf(stderr, "couldn't open %s for writing\n", outPath);
|
||||||
|
ret = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chdir(dir) != 0) {
|
||||||
|
fprintf(stderr, "couldn't chdir to %s\n", dir);
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
if (processSchema(base, xmlFile + dirLen + 1, out) != 0)
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(out);
|
||||||
|
|
||||||
|
if (chdir(globalData.cwd) != 0) {
|
||||||
|
fprintf(stderr, "couldn't chdir to %s\n", globalData.cwd);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globfree(&globbuf2);
|
||||||
|
|
||||||
|
error:
|
||||||
|
xmlFree(dirBuf);
|
||||||
|
xmlFree(baseBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
globfree(&globbuf);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_XPATH_FUZZER
|
#ifdef HAVE_XPATH_FUZZER
|
||||||
static int
|
static int
|
||||||
processXPath(const char *testDir, const char *prefix, const char *name,
|
processXPath(const char *testDir, const char *prefix, const char *name,
|
||||||
@@ -479,8 +641,7 @@ main(int argc, const char **argv) {
|
|||||||
#endif
|
#endif
|
||||||
} else if (strcmp(fuzzer, "schema") == 0) {
|
} else if (strcmp(fuzzer, "schema") == 0) {
|
||||||
#ifdef HAVE_SCHEMA_FUZZER
|
#ifdef HAVE_SCHEMA_FUZZER
|
||||||
processArg = processPattern;
|
processArg = processSchemaPattern;
|
||||||
globalData.processFile = processSchema;
|
|
||||||
#endif
|
#endif
|
||||||
} else if (strcmp(fuzzer, "valid") == 0) {
|
} else if (strcmp(fuzzer, "valid") == 0) {
|
||||||
#ifdef HAVE_VALID_FUZZER
|
#ifdef HAVE_VALID_FUZZER
|
||||||
|
|||||||
@@ -24,9 +24,10 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
|||||||
int
|
int
|
||||||
LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||||
xmlSchemaParserCtxtPtr pctxt;
|
xmlSchemaParserCtxtPtr pctxt;
|
||||||
|
xmlSchemaPtr schema;
|
||||||
size_t failurePos;
|
size_t failurePos;
|
||||||
|
|
||||||
if (size > 50000)
|
if (size > 200000)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
failurePos = xmlFuzzReadInt(4) % (size + 100);
|
failurePos = xmlFuzzReadInt(4) % (size + 100);
|
||||||
@@ -38,9 +39,30 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
|||||||
pctxt = xmlSchemaNewParserCtxt(xmlFuzzMainUrl());
|
pctxt = xmlSchemaNewParserCtxt(xmlFuzzMainUrl());
|
||||||
xmlSchemaSetParserStructuredErrors(pctxt, xmlFuzzSErrorFunc, NULL);
|
xmlSchemaSetParserStructuredErrors(pctxt, xmlFuzzSErrorFunc, NULL);
|
||||||
xmlSchemaSetResourceLoader(pctxt, xmlFuzzResourceLoader, NULL);
|
xmlSchemaSetResourceLoader(pctxt, xmlFuzzResourceLoader, NULL);
|
||||||
xmlSchemaFree(xmlSchemaParse(pctxt));
|
schema = xmlSchemaParse(pctxt);
|
||||||
xmlSchemaFreeParserCtxt(pctxt);
|
xmlSchemaFreeParserCtxt(pctxt);
|
||||||
|
|
||||||
|
if (schema != NULL) {
|
||||||
|
xmlSchemaValidCtxtPtr vctxt;
|
||||||
|
xmlParserCtxtPtr ctxt;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
ctxt = xmlNewParserCtxt();
|
||||||
|
xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
|
||||||
|
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||||
|
doc = xmlCtxtReadFile(ctxt, xmlFuzzSecondaryUrl(), NULL,
|
||||||
|
XML_PARSE_NOENT);
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
|
||||||
|
vctxt = xmlSchemaNewValidCtxt(schema);
|
||||||
|
xmlSchemaSetValidStructuredErrors(vctxt, xmlFuzzSErrorFunc, NULL);
|
||||||
|
xmlSchemaValidateDoc(vctxt, doc);
|
||||||
|
xmlSchemaFreeValidCtxt(vctxt);
|
||||||
|
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
xmlSchemaFree(schema);
|
||||||
|
}
|
||||||
|
|
||||||
xmlFuzzInjectFailure(0);
|
xmlFuzzInjectFailure(0);
|
||||||
xmlFuzzDataCleanup();
|
xmlFuzzDataCleanup();
|
||||||
xmlResetLastError();
|
xmlResetLastError();
|
||||||
|
|||||||
@@ -158,13 +158,26 @@ testEntityLoader(void) {
|
|||||||
"<!ENTITY ent SYSTEM \"ent.txt\">\\\n"
|
"<!ENTITY ent SYSTEM \"ent.txt\">\\\n"
|
||||||
"ent.txt\\\n"
|
"ent.txt\\\n"
|
||||||
"Hello, world!\\\n";
|
"Hello, world!\\\n";
|
||||||
const char *docBuffer;
|
const char *docBuffer, *url;
|
||||||
size_t docSize;
|
size_t docSize;
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
xmlFuzzDataInit(data, sizeof(data) - 1);
|
xmlFuzzDataInit(data, sizeof(data) - 1);
|
||||||
xmlFuzzReadEntities();
|
xmlFuzzReadEntities();
|
||||||
|
|
||||||
|
url = xmlFuzzMainUrl();
|
||||||
|
if (strcmp(url, "doc.xml") != 0) {
|
||||||
|
fprintf(stderr, "unexpected main url: %s\n", url);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = xmlFuzzSecondaryUrl();
|
||||||
|
if (strcmp(url, "doc.dtd") != 0) {
|
||||||
|
fprintf(stderr, "unexpected secondary url: %s\n", url);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
docBuffer = xmlFuzzMainEntity(&docSize);
|
docBuffer = xmlFuzzMainEntity(&docSize);
|
||||||
ctxt = xmlNewParserCtxt();
|
ctxt = xmlNewParserCtxt();
|
||||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user