Skip to content

Commit

Permalink
GMLAS: avoid crash on a OSSFuzz generated xsd
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Aug 10, 2024
1 parent 2e99a88 commit 1e95085
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 15 deletions.
15 changes: 15 additions & 0 deletions autotest/ogr/data/gmlas/test_ossfuzz_70511.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<!-- matches string recognized in GMLASBaseEntityResolver::resolveEntity() -->
<xs:import namespace="http://foo" schemaLocation="foo/gml/3.2.1/gml.xsd"/>
<!-- matches string recognized in GMLASErrorHandler::handle() -->
<xs:import namespace="http://bar" schemaLocation="foo.http://www.opengis.net/gml/3.2:AbstractCRS' not found"/>
<xs:element name="foo">
<xs:complexType>
<xs:sequence>
<xs:element name="x"/>
</xs:sequence>
<xs:attribute name="y" type="invalid"/>
</xs:complexType>
</xs:element>
</xs:schema>
13 changes: 13 additions & 0 deletions autotest/ogr/ogr_gmlas.py
Original file line number Diff line number Diff line change
Expand Up @@ -3468,3 +3468,16 @@ def test_ogr_gmlas_bugfix_sf_2371():
ds = gdal.OpenEx("GMLAS:data/gmlas/citygml_empty_lod1.gml")
lyr = ds.GetLayerByName("address1")
assert lyr.GetFeatureCount() == 0


###############################################################################
# Test we don't crash on a OSSFuzz generated xsd


@gdaltest.enable_exceptions()
def test_ogr_gmlas_ossfuzz_70511():

with gdal.quiet_errors(), pytest.raises(
Exception, match="Cannot get type definition for attribute y"
):
gdal.OpenEx("GMLAS:", open_options=["XSD=data/gmlas/test_ossfuzz_70511.xsd"])
2 changes: 1 addition & 1 deletion ogr/ogrsf_frmts/gmlas/ogr_gmlas.h
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,7 @@ class GMLASSchemaAnalyzer
const XSModelGroup *poModelGroup2);
XSModelGroupDefinition *
GetGroupDefinition(const XSModelGroup *poModelGroup);
void SetFieldFromAttribute(GMLASField &oField, XSAttributeUse *poAttr,
bool SetFieldFromAttribute(GMLASField &oField, XSAttributeUse *poAttr,
const CPLString &osXPathPrefix,
const CPLString &osNamePrefix = CPLString());
void GetConcreteImplementationTypes(
Expand Down
50 changes: 36 additions & 14 deletions ogr/ogrsf_frmts/gmlas/ogrgmlasschemaanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1572,24 +1572,31 @@ static bool IsAnyType(XSComplexTypeDefinition *poType)
/* SetFieldFromAttribute() */
/************************************************************************/

void GMLASSchemaAnalyzer::SetFieldFromAttribute(GMLASField &oField,
bool GMLASSchemaAnalyzer::SetFieldFromAttribute(GMLASField &oField,
XSAttributeUse *poAttr,
const CPLString &osXPathPrefix,
const CPLString &osNamePrefix)
{
XSAttributeDeclaration *poAttrDecl = poAttr->getAttrDeclaration();
XSSimpleTypeDefinition *poAttrType = poAttrDecl->getTypeDefinition();

SetFieldTypeAndWidthFromDefinition(poAttrType, oField);

CPLString osNS(transcode(poAttrDecl->getNamespace()));
CPLString osName(transcode(poAttrDecl->getName()));
const XSAttributeDeclaration *poAttrDecl = poAttr->getAttrDeclaration();
const CPLString osNS(transcode(poAttrDecl->getNamespace()));
const CPLString osName(transcode(poAttrDecl->getName()));

if (osNamePrefix.empty())
oField.SetName(osName);
else
oField.SetName(osNamePrefix + "_" + osName);

XSSimpleTypeDefinition *poAttrType = poAttrDecl->getTypeDefinition();
if (!poAttrType)
{
CPLError(CE_Failure, CPLE_AppDefined,
"Cannot get type definition for attribute %s",
oField.GetName().c_str());
return false;
}

SetFieldTypeAndWidthFromDefinition(poAttrType, oField);

oField.SetXPath(osXPathPrefix + "/@" + MakeXPath(osNS, osName));
if (poAttr->getRequired())
{
Expand Down Expand Up @@ -1626,6 +1633,8 @@ void GMLASSchemaAnalyzer::SetFieldFromAttribute(GMLASField &oField,
}

oField.SetDocumentation(GetAnnotationDoc(poAttrDecl->getAnnotation()));

return true;
}

/************************************************************************/
Expand Down Expand Up @@ -2276,8 +2285,11 @@ bool GMLASSchemaAnalyzer::FindElementsWithMustBeToLevel(
XSAttributeUse *poAttr =
poAttrList->elementAt(j);
GMLASField oField;
SetFieldFromAttribute(oField, poAttr,
osFullXPath);
if (!SetFieldFromAttribute(oField, poAttr,
osFullXPath))
{
return false;
}
if (!IsIgnoredXPath(oField.GetXPath()) &&
oField.GetFixedValue().empty())
{
Expand Down Expand Up @@ -2343,7 +2355,11 @@ bool GMLASSchemaAnalyzer::FindElementsWithMustBeToLevel(
{
XSAttributeUse *poAttr = poAttrList->elementAt(j);
GMLASField oField;
SetFieldFromAttribute(oField, poAttr, osFullXPath);
if (!SetFieldFromAttribute(oField, poAttr,
osFullXPath))
{
return false;
}
if (!IsIgnoredXPath(oField.GetXPath()) &&
oField.GetFixedValue().empty())
{
Expand Down Expand Up @@ -2606,7 +2622,10 @@ bool GMLASSchemaAnalyzer::ExploreModelGroup(
{
GMLASField oField;
XSAttributeUse *poAttr = poMainAttrList->elementAt(j);
SetFieldFromAttribute(oField, poAttr, oClass.GetXPath());
if (!SetFieldFromAttribute(oField, poAttr, oClass.GetXPath()))
{
return false;
}

if (IsIgnoredXPath(oField.GetXPath()))
{
Expand Down Expand Up @@ -2989,8 +3008,11 @@ bool GMLASSchemaAnalyzer::ExploreModelGroup(
CPLString osNamePrefix(bMoveNestedClassToTop
? osPrefixedEltName
: CPLString());
SetFieldFromAttribute(oField, poAttr, osElementXPath,
osNamePrefix);
if (!SetFieldFromAttribute(oField, poAttr, osElementXPath,
osNamePrefix))
{
return false;
}
if (nMinOccurs == 0 || bIsChoice)
{
oField.SetMinOccurs(0);
Expand Down

0 comments on commit 1e95085

Please sign in to comment.