fix crash in loading ooo57731-1.odt

This fixes bugs in the following commits, where
we need to also process unknown elements, in order to
maintain compatibility with the preceding code.

    commit 0c48c46d3e
    Date:   Thu Nov 19 13:16:17 2020 +0200
    fastparser in DomBuilderContext

    commit bb124fe673
    Author: Noel <noelgrandin@gmail.com>
    Date:   Thu Nov 19 11:52:50 2020 +0200
    fastparser in DomBuilderContext

    commit cf13e985a6
    Date:   Thu Nov 19 14:17:54 2020 +0200
    fastparser in TokenContext

    commit 39d8ee8f91
    Date:   Thu Nov 19 13:51:21 2020 +0200
    fastparser in TokenContext

Change-Id: I9e4eddfedc6d13db72066f0d5bf436fc237bf3e5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106490
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel
2020-11-24 11:03:25 +02:00
committed by Noel Grandin
parent d84deb9536
commit f981f756e1
12 changed files with 214 additions and 38 deletions

View File

@@ -45,16 +45,24 @@ class DomBuilderContext final : public SvXMLImportContext
{
css::uno::Reference<css::xml::dom::XNode> mxNode;
void HandleAttributes(const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs);
public:
/** default constructor: create new DOM tree */
DomBuilderContext( SvXMLImport& rImport,
sal_Int32 nElement );
DomBuilderContext( SvXMLImport& rImport,
const OUString & Namespace, const OUString & Name );
/** constructor: create DOM subtree under the given node */
DomBuilderContext( SvXMLImport& rImport,
sal_Int32 nElement,
css::uno::Reference<css::xml::dom::XNode> const & );
/** constructor: create DOM subtree under the given node */
DomBuilderContext( SvXMLImport& rImport,
const OUString & Namespace, const OUString & Name,
css::uno::Reference<css::xml::dom::XNode> const & );
virtual ~DomBuilderContext() override;
@@ -70,10 +78,15 @@ public:
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext(
const OUString& Namespace, const OUString& Name,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs ) override;
virtual void SAL_CALL startFastElement(
sal_Int32 nElement,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
virtual void SAL_CALL startUnknownElement(const OUString & Namespace, const OUString & Name,
const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override;
virtual void SAL_CALL characters( const OUString& rChars ) override;
};

View File

@@ -57,7 +57,9 @@ static Reference<XNode> lcl_createDomInstance();
static Reference<XNode> lcl_createElement( SvXMLImport& rImport,
sal_Int32 nElement,
const Reference<XNode>& xParent);
static Reference<XNode> lcl_createElement(
const OUString & rNamespace, const OUString & rName,
const Reference<XNode>& xParent);
DomBuilderContext::DomBuilderContext( SvXMLImport& rImport,
sal_Int32 nElement ) :
@@ -70,6 +72,17 @@ DomBuilderContext::DomBuilderContext( SvXMLImport& rImport,
SAL_WARN_IF( mxNode->getNodeType() != NodeType_ELEMENT_NODE, "xmloff", "need element" );
}
DomBuilderContext::DomBuilderContext( SvXMLImport& rImport,
const OUString & rNamespace, const OUString & rName ) :
SvXMLImportContext( rImport ),
mxNode( lcl_createElement( rNamespace, rName,
lcl_createDomInstance() ) )
{
SAL_WARN_IF( !mxNode.is(), "xmloff", "empty XNode not allowed" );
SAL_WARN_IF( !Reference<XElement>( mxNode, UNO_QUERY ).is(), "xmloff", "need element" );
SAL_WARN_IF( mxNode->getNodeType() != NodeType_ELEMENT_NODE, "xmloff", "need element" );
}
DomBuilderContext::DomBuilderContext( SvXMLImport& rImport,
sal_Int32 nElement,
Reference<XNode> const & xParent ) :
@@ -81,6 +94,17 @@ DomBuilderContext::DomBuilderContext( SvXMLImport& rImport,
SAL_WARN_IF( mxNode->getNodeType() != NodeType_ELEMENT_NODE, "xmloff", "need element" );
}
DomBuilderContext::DomBuilderContext( SvXMLImport& rImport,
const OUString & rNamespace, const OUString & rName,
Reference<XNode> const & xParent ) :
SvXMLImportContext( rImport ),
mxNode( lcl_createElement( rNamespace, rName, xParent ) )
{
SAL_WARN_IF( !mxNode.is(), "xmloff", "empty XNode not allowed" );
SAL_WARN_IF( !Reference<XElement>( mxNode, UNO_QUERY ).is(), "xmloff", "need element" );
SAL_WARN_IF( mxNode->getNodeType() != NodeType_ELEMENT_NODE, "xmloff", "need element" );
}
DomBuilderContext::~DomBuilderContext()
{
}
@@ -98,14 +122,35 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > DomBuilderContext::cre
return new DomBuilderContext( GetImport(), nElement, mxNode );
}
css::uno::Reference< css::xml::sax::XFastContextHandler > DomBuilderContext::createUnknownChildContext(
const OUString & rNamespace, const OUString &rName, const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
{
// create DomBuilder for subtree
return new DomBuilderContext( GetImport(), rNamespace, rName, mxNode );
}
void SAL_CALL DomBuilderContext::startFastElement(
sal_Int32 nElement,
sal_Int32 /*nElement*/,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
{
SAL_WARN_IF( !mxNode.is(), "xmloff", "empty XNode not allowed" );
SAL_WARN_IF( !mxNode->getOwnerDocument().is(), "xmloff", "XNode must have XDocument" );
HandleAttributes(xAttrList);
}
void SAL_CALL DomBuilderContext::startUnknownElement(
const OUString & /*rNamespace*/, const OUString & /*rName*/,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
{
SAL_WARN_IF( !mxNode.is(), "xmloff", "empty XNode not allowed" );
SAL_WARN_IF( !mxNode->getOwnerDocument().is(), "xmloff", "XNode must have XDocument" );
HandleAttributes(xAttrList);
}
void DomBuilderContext::HandleAttributes(
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
{
// add attribute nodes to new node
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
{
@@ -141,13 +186,34 @@ void SAL_CALL DomBuilderContext::startFastElement(
default:
{
// a real and proper namespace: create namespaced attribute
OUString namespaceURI = SvXMLImport::getNamespaceURIFromToken(nElement);
OUString namespaceURI = SvXMLImport::getNamespaceURIFromToken(aIter.getToken());
OUString qualifiedName = rPrefix.isEmpty() ? rLocalName : rPrefix + SvXMLImport::aNamespaceSeparator + rLocalName;
xElement->setAttributeNS( namespaceURI, qualifiedName, aValue );
}
break;
}
}
const css::uno::Sequence< css::xml::Attribute > unknownAttribs = xAttrList->getUnknownAttributes();
for ( const auto& rUnknownAttrib : unknownAttribs )
{
// create attribute node and set value
Reference<XElement> xElement( mxNode, UNO_QUERY_THROW );
if (!rUnknownAttrib.NamespaceURL.isEmpty())
{
// unknown namespace: illegal input. Raise Warning.
Sequence<OUString> aSeq(2);
aSeq[0] = rUnknownAttrib.Name;
aSeq[1] = rUnknownAttrib.Value;
GetImport().SetError(
XMLERROR_FLAG_WARNING | XMLERROR_NAMESPACE_TROUBLE, aSeq );
}
else
{
// no namespace: create a non-namespaced attribute
xElement->setAttribute( rUnknownAttrib.Name, rUnknownAttrib.Value );
}
}
}
void DomBuilderContext::characters( const OUString& rCharacters )
@@ -229,4 +295,33 @@ static Reference<XNode> lcl_createElement( SvXMLImport& rImport,
return xElement;
}
static Reference<XNode> lcl_createElement(
const OUString & rNamespace, const OUString & rName,
const Reference<XNode>& xParent)
{
SAL_WARN_IF( !xParent.is(), "xmloff", "need parent node" );
Reference<XDocument> xDocument = xParent->getOwnerDocument();
SAL_WARN_IF( !xDocument.is(), "xmloff", "no XDocument found!" );
// TODO: come up with proper way of handling namespaces; re-creating the
// namespace from the key is NOT a good idea, and will not work for
// multiple prefixes for the same namespace. Fortunately, those are rare.
Reference<XElement> xElement;
if (rNamespace.isEmpty())
{
// no namespace: use local name
xElement = xDocument->createElement( rName );
}
else
{
xElement = xDocument->createElementNS(rNamespace, rName);
}
// add new element to parent and return
xParent->appendChild( xElement );
return xElement;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -26,6 +26,7 @@
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmltkmap.hxx>
#include <xmloff/xmlimp.hxx>
#include <sal/log.hxx>
#include <com/sun/star/xforms/XDataTypeRepository.hpp>
@@ -55,6 +56,8 @@ SvXMLImportContext* SchemaContext::HandleChild(
{
if ( nElementToken == XML_ELEMENT(XSD, XML_SIMPLETYPE) )
return new SchemaSimpleTypeContext( GetImport(), mxRepository );
else
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElementToken);
return nullptr;
}

View File

@@ -94,9 +94,11 @@ void SchemaRestrictionContext::HandleAttribute(
sal_Int32 nAttributeToken,
const OUString& rValue )
{
if( nAttributeToken == XML_ELEMENT(NONE, XML_BASE) )
switch (nAttributeToken & TOKEN_MASK)
{
msBaseName = rValue;
case XML_BASE:
msBaseName = rValue;
break;
}
}
@@ -244,7 +246,7 @@ SvXMLImportContext* SchemaRestrictionContext::HandleChild(
// converter is only type dependent.
// first, attribute-dependent prefix
switch( nElementToken )
switch( nElementToken & TOKEN_MASK )
{
case XML_MININCLUSIVE:
sPropertyName = "MinInclusive";

View File

@@ -28,6 +28,7 @@
#include <xmloff/xmlimp.hxx>
#include <osl/diagnose.h>
#include <sal/log.hxx>
using com::sun::star::uno::Reference;
using com::sun::star::xml::sax::XFastAttributeList;
@@ -47,9 +48,11 @@ void SchemaSimpleTypeContext::HandleAttribute(
sal_Int32 nAttributeToken,
const OUString& rValue )
{
if( nAttributeToken == XML_ELEMENT(NONE, XML_NAME) )
switch (nAttributeToken & TOKEN_MASK)
{
msTypeName = rValue;
case XML_NAME:
msTypeName = rValue;
break;
}
}
@@ -63,6 +66,8 @@ SvXMLImportContext* SchemaSimpleTypeContext::HandleChild(
return new SchemaRestrictionContext( GetImport(),
mxRepository, msTypeName );
break;
default:
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElementToken);
}
return nullptr;

View File

@@ -61,6 +61,13 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > TokenContext::createFa
return pContext;
}
css::uno::Reference< css::xml::sax::XFastContextHandler > TokenContext::createUnknownChildContext(
const OUString& Namespace, const OUString& Name, const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
{
GetImport().SetError( XMLERROR_UNKNOWN_ELEMENT, Namespace + " " + Name );
return nullptr;
}
static bool lcl_IsWhiteSpace( sal_Unicode c )
{
return c == ' '

View File

@@ -52,6 +52,10 @@ public:
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext(
const OUString& Namespace, const OUString& Name,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs ) override;
/** Create a warning for all non-namespace character
* content. Classes that wish to deal with character content have
* to override this method anyway, and will thus get rid of the

View File

@@ -92,7 +92,7 @@ void XFormsBindContext::HandleAttribute( sal_Int32 nAttributeToken,
rValue ) ) );
break;
default:
OSL_FAIL( "should not happen" );
assert( false && "should not happen" );
break;
}
}
@@ -119,7 +119,7 @@ SvXMLImportContext* XFormsBindContext::HandleChild(
sal_Int32,
const Reference<XFastAttributeList>& )
{
OSL_FAIL( "no children supported" );
assert( false && "no children supported" );
return nullptr;
}

View File

@@ -81,6 +81,31 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > XFormsInstanceContext:
}
css::uno::Reference< css::xml::sax::XFastContextHandler > XFormsInstanceContext::createUnknownChildContext(
const OUString & rNamespace, const OUString &rName, const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*Attribs*/)
{
SvXMLImportContext* pContext = nullptr;
// only the first element child of an xforms:instance element
// is used as an instance. The other children remainder must be
// ignored.
if( mxInstance.is() )
{
GetImport().SetError( XMLERROR_XFORMS_ONLY_ONE_INSTANCE_ELEMENT, rName );
}
else
{
// create new DomBuilderContext. Save reference to tree in Model.
DomBuilderContext* pInstance = new DomBuilderContext( GetImport(), rNamespace, rName );
mxInstance = pInstance->getTree();
pContext = pInstance;
}
SAL_WARN_IF( pContext == nullptr, "xmloff", "no context!" );
return pContext;
}
void XFormsInstanceContext::endFastElement(sal_Int32 )
{
Sequence<PropertyValue> aSequence( 3 );
@@ -95,21 +120,35 @@ void XFormsInstanceContext::endFastElement(sal_Int32 )
mxModel->getInstances()->insert( makeAny( aSequence ) );
}
void XFormsInstanceContext::endUnknownElement(const OUString & /*Namespace*/, const OUString & /*Name*/)
{
Sequence<PropertyValue> aSequence( 3 );
PropertyValue* pSequence = aSequence.getArray();
pSequence[0].Name = "Instance";
pSequence[0].Value <<= mxInstance;
pSequence[1].Name = "ID";
pSequence[1].Value <<= msId;
pSequence[2].Name = "URL";
pSequence[2].Value <<= msURL;
mxModel->getInstances()->insert( makeAny( aSequence ) );
}
void XFormsInstanceContext::HandleAttribute(
sal_Int32 nAttributeToken,
const OUString& rValue )
{
switch( nAttributeToken )
switch( nAttributeToken & TOKEN_MASK )
{
case XML_ELEMENT(NONE, XML_SRC):
case XML_SRC:
msURL = rValue;
break;
case XML_ELEMENT(NONE, XML_ID):
case XML_ID:
msId = rValue;
break;
default:
OSL_FAIL( "should not happen" );
XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttributeToken, rValue);
assert( false && "this should not happen" );
break;
}
}
@@ -118,7 +157,7 @@ SvXMLImportContext* XFormsInstanceContext::HandleChild(
sal_Int32,
const Reference<css::xml::sax::XFastAttributeList>& )
{
OSL_FAIL( "to be handled by CreateChildContext" );
assert( false && "to be handled by CreateChildContext" );
return nullptr;
}

View File

@@ -52,8 +52,12 @@ public:
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext(
const OUString& Namespace, const OUString& Name,
const css::uno::Reference< css::xml::sax::XFastAttributeList >& Attribs ) override;
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
virtual void SAL_CALL endUnknownElement(const OUString & Namespace, const OUString & Name) override;
protected:
virtual void HandleAttribute(

View File

@@ -33,6 +33,7 @@
#include <xmloff/xmlerror.hxx>
#include <osl/diagnose.h>
#include <sal/log.hxx>
#include <com/sun/star/util/XUpdatable.hpp>
#include <com/sun/star/xforms/XModel2.hpp>
@@ -53,16 +54,17 @@ void XFormsModelContext::HandleAttribute(
sal_Int32 nAttributeToken,
const OUString& rValue )
{
switch( nAttributeToken )
switch( nAttributeToken & TOKEN_MASK)
{
case XML_ELEMENT(NONE, XML_ID):
case XML_ID:
mxModel->setPropertyValue( "ID", makeAny( rValue ) );
break;
case XML_ELEMENT(NONE, XML_SCHEMA):
case XML_SCHEMA:
GetImport().SetError( XMLERROR_XFORMS_NO_SCHEMA_SUPPORT );
break;
default:
OSL_FAIL( "this should not happen" );
XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttributeToken, rValue);
assert( false && "this should not happen" );
break;
}
}
@@ -88,7 +90,8 @@ SvXMLImportContext* XFormsModelContext::HandleChild(
pContext = new SchemaContext( GetImport(), mxModel->getDataTypeRepository() );
break;
default:
OSL_FAIL( "Boooo!" );
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElementToken);
assert( false && "Boooo!" );
break;
}

View File

@@ -72,56 +72,57 @@ Any toBool( const OUString& rValue )
void XFormsSubmissionContext::HandleAttribute( sal_Int32 nAttributeToken,
const OUString& rValue )
{
switch( nAttributeToken )
switch( nAttributeToken & TOKEN_MASK )
{
case XML_ELEMENT(NONE, XML_ID):
case XML_ID:
xforms_setValue( mxSubmission, "ID", rValue );
break;
case XML_ELEMENT(NONE, XML_BIND):
case XML_BIND:
xforms_setValue( mxSubmission, "Bind", rValue );
break;
case XML_ELEMENT(NONE, XML_REF):
case XML_REF:
xforms_setValue( mxSubmission, "Ref", rValue );
break;
case XML_ELEMENT(NONE, XML_ACTION):
case XML_ACTION:
xforms_setValue( mxSubmission, "Action", rValue );
break;
case XML_ELEMENT(NONE, XML_METHOD):
case XML_METHOD:
xforms_setValue( mxSubmission, "Method", rValue );
break;
case XML_ELEMENT(NONE, XML_VERSION):
case XML_VERSION:
xforms_setValue( mxSubmission, "Version", rValue );
break;
case XML_ELEMENT(NONE, XML_INDENT):
case XML_INDENT:
xforms_setValue( mxSubmission, "Indent", toBool( rValue ) );
break;
case XML_ELEMENT(NONE, XML_MEDIATYPE):
case XML_MEDIATYPE:
xforms_setValue( mxSubmission, "MediaType", rValue );
break;
case XML_ELEMENT(NONE, XML_ENCODING):
case XML_ENCODING:
xforms_setValue( mxSubmission, "Encoding", rValue );
break;
case XML_ELEMENT(NONE, XML_OMIT_XML_DECLARATION):
case XML_OMIT_XML_DECLARATION:
xforms_setValue( mxSubmission, "OmitXmlDeclaration",
toBool( rValue ) );
break;
case XML_ELEMENT(NONE, XML_STANDALONE):
case XML_STANDALONE:
xforms_setValue( mxSubmission, "Standalone", toBool( rValue ) );
break;
case XML_ELEMENT(NONE, XML_CDATA_SECTION_ELEMENTS):
case XML_CDATA_SECTION_ELEMENTS:
xforms_setValue( mxSubmission, "CDataSectionElement", rValue );
break;
case XML_ELEMENT(NONE, XML_REPLACE):
case XML_REPLACE:
xforms_setValue( mxSubmission, "Replace", rValue );
break;
case XML_ELEMENT(NONE, XML_SEPARATOR):
case XML_SEPARATOR:
xforms_setValue( mxSubmission, "Separator", rValue );
break;
case XML_ELEMENT(NONE, XML_INCLUDENAMESPACEPREFIXES):
case XML_INCLUDENAMESPACEPREFIXES:
xforms_setValue( mxSubmission, "IncludeNamespacePrefixes", rValue );
break;
default:
OSL_FAIL( "unknown attribute" );
XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttributeToken, rValue);
assert( false && "unknown attribute" );
break;
}
}
@@ -131,7 +132,7 @@ SvXMLImportContext* XFormsSubmissionContext::HandleChild(
sal_Int32,
const Reference<css::xml::sax::XFastAttributeList>& )
{
OSL_FAIL( "no children supported" );
assert( false && "no children supported" );
return nullptr;
}