1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 12:25:09 +03:00

Fuzz target for XML Schemas

This only tests the schema parser for now.
This commit is contained in:
Nick Wellnhofer 2020-06-21 14:42:00 +02:00
parent ffd31dbefd
commit eac1c7e2e5
9 changed files with 172 additions and 1 deletions

3
fuzz/.gitignore vendored
View File

@ -1,7 +1,10 @@
corpus/
html
regexp
schema
schemaSeed
seed/xml*
seed/schema*
testFuzzer
uri
xml

View File

@ -1,4 +1,4 @@
EXTRA_PROGRAMS = html regexp uri xml xmlSeed
EXTRA_PROGRAMS = html regexp uri schema schemaSeed xml xmlSeed
check_PROGRAMS = testFuzzer
CLEANFILES = $(EXTRA_PROGRAMS)
AM_CPPFLAGS = -I$(top_srcdir)/include
@ -84,3 +84,30 @@ fuzz-uri: uri$(EXEEXT)
-timeout=2 \
corpus/uri $(srcdir)/seed/uri
schemaSeed_SOURCES = schemaSeed.c fuzz.c
seed/schema.stamp: schemaSeed$(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
@touch seed/schema.stamp
schema_SOURCES = schema.c fuzz.c
schema_LDFLAGS = -fsanitize=fuzzer
fuzz-schema: schema$(EXEEXT) seed/schema.stamp
@mkdir -p corpus/schema
./schema$(EXEEXT) \
-dict=schema.dict \
-max_len=$(PARSER_FUZZER_MAX_LEN) \
-timeout=20 \
corpus/schema seed/schema

View File

@ -265,6 +265,16 @@ xmlFuzzReadEntities(void) {
}
}
/**
* xmlFuzzMainUrl:
*
* Returns the main URL.
*/
const char *
xmlFuzzMainUrl(void) {
return(fuzzData.mainUrl);
}
/**
* xmlFuzzMainEntity:
* @size: size of the main entity in bytes

View File

@ -42,6 +42,9 @@ xmlFuzzEntityRecorder(const char *URL, const char *ID, xmlParserCtxtPtr ctxt);
void
xmlFuzzReadEntities(void);
const char *
xmlFuzzMainUrl(void);
const char *
xmlFuzzMainEntity(size_t *size);

36
fuzz/schema.c Normal file
View File

@ -0,0 +1,36 @@
/*
* schema.c: a libFuzzer target to test the XML Schema processor.
*
* See Copyright for the status of this software.
*/
#include <libxml/xmlschemas.h>
#include "fuzz.h"
int
LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
char ***argv ATTRIBUTE_UNUSED) {
xmlInitParser();
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
return 0;
}
int
LLVMFuzzerTestOneInput(const char *data, size_t size) {
xmlSchemaParserCtxtPtr pctxt;
xmlFuzzDataInit(data, size);
xmlFuzzReadEntities();
pctxt = xmlSchemaNewParserCtxt(xmlFuzzMainUrl());
xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
xmlSchemaFree(xmlSchemaParse(pctxt));
xmlSchemaFreeParserCtxt(pctxt);
xmlFuzzDataCleanup();
return(0);
}

55
fuzz/schema.dict Normal file
View File

@ -0,0 +1,55 @@
# TODO: Add more language elements
xs_annotation="<xs:annotation></xs:annotation>"
xs_attribute="<xs:attribute name='a'></xs:attribute>"
xs_attribute_required="<xs:attribute name='a' use='required'></xs:attribute>"
xs_element="<xs:element name='e'></xs:element>"
# Primitive datatypes
type_string=" type='xs:string'"
type_boolean=" type='xs:boolean'"
type_decimal=" type='xs:decimal'"
type_float=" type='xs:float'"
type_double=" type='xs:double'"
type_date_time=" type='xs:dateTime'"
type_time=" type='xs:time'"
type_date=" type='xs:date'"
type_g_year_month=" type='xs:gYearMonth'"
type_g_year=" type='xs:gYear'"
type_g_month_day=" type='xs:gMonthDay'"
type_g_day=" type='xs:gDay'"
type_g_month=" type='xs:gMonth'"
type_hex_binary=" type='xs:hexBinary'"
type_base64_binary=" type='xs:base64Binary'"
type_any_uri=" type='xs:anyURI'"
type_qname=" type='xs:QName'"
type_notation=" type='xs:NOTATION'"
# Occurs
occurs_min=" minOccurs='1'"
occurs_max=" maxOccurs='9'"
occurs_max_unbounded=" maxOccurs='unbounded'"
# Simple type
xs_restriction_integer="<xs:simpleType><xs:restriction base='xs:integer'></xs:restriction></xs:simpleType>"
xs_restriction_string="<xs:simpleType><xs:restriction base='xs:string'></xs:restriction></xs:simpleType>"
xs_list="<xs:simpleType><xs:list></xs:list></xs:simpleType>"
xs_union="<xs:simpleType><xs:union></xs:union></xs:simpleType>"
# Restrictions
xs_min_exclusive="<xs:minExclusive value='0'/>"
xs_min_inclusive="<xs:minInclusive value='0'/>"
xs_max_exclusive="<xs:maxExclusive value='9'/>"
xs_max_inclusive="<xs:maxInclusive value='9'/>"
xs_total_digits="<xs:totalDigits value='3'/>"
xs_fraction_digits="<xs:fractionDigits value='3'/>"
xs_length="<xs:length value='3'/>"
xs_min_length="<xs:minLength value='3'/>"
xs_max_length="<xs:maxLength value='3'/>"
xs_enumeration="<xs:enumeration value='a'/>"
xs_white_space_collapse="<xs:whiteSpace value='collapse'/>"
xs_white_space_preserve="<xs:whiteSpace value='preserve'/>"
xs_white_space_replace="<xs:whiteSpace value='replace'/>"
xs_pattern="<xs:pattern value='a'/>"

2
fuzz/schema.options Normal file
View File

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 80000

34
fuzz/schemaSeed.c Normal file
View File

@ -0,0 +1,34 @@
/*
* 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);
}

View File

@ -13,6 +13,7 @@ main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: xmlSeed [FILE]\n");
return(1);
}
fwrite(&opts, sizeof(opts), 1, stdout);