Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-90612

Typecasting in QtXmlPatterns

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P4: Low
    • None
    • 5.15.2
    • XML: QtXmlPatterns
    • None
    • Mint Linux 20.1
      Clang 12
    • Linux/X11

    Description

      There are multiple typecasting issues in files:

      • qtxmlpatterns/src/xmlpatterns/schema/qxsdschemachecker.cpp
      • qtxmlpatterns/src/xmlpatterns/schema/qxsdschemaresolver.cpp
      • qtxmlpatterns/src/xmlpatterns/type/qtypechecker.cpp

      The issues are the same: ambiguities between XSD schema parser types and base types referenced by inherited ::Ptr pointer type. The issues are easily detected by Clang 12.

      As a workaround for these issues the following patch could be used:

      diff --git a/schema/qxsdschemachecker.cpp b/schema/qxsdschemachecker.cpp
      index 9f7c6a25..2daac434 100644
      --- a/schema/qxsdschemachecker.cpp
      +++ b/schema/qxsdschemachecker.cpp
      @@ -127,15 +127,15 @@ static bool matchesType(const SchemaType::Ptr &myType, const SchemaType::Ptr &ot
                   const XsdSimpleType::Ptr simpleType = otherType;
                   if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
                       // for atomic type we use the same test as in SchemaType::wxsTypeMatches
      -                retval = (myType == simpleType ? true : matchesType(myType, simpleType->wxsSuperType(), visitedTypes));
      +                retval = (myType == static_cast<const SchemaType::Ptr>(simpleType) ? true : matchesType(myType, simpleType->wxsSuperType(), visitedTypes) );
                   } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
                       // for list type we test against the itemType property
      -                retval = (myType == simpleType->itemType() ? true : matchesType(myType, simpleType->itemType()->wxsSuperType(), visitedTypes));
      +                retval = (myType == static_cast<const SchemaType::Ptr>(simpleType->itemType()) ? true : matchesType(myType, simpleType->itemType()->wxsSuperType(), visitedTypes));
                   } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
                       // for union type we test against each member type
                       const XsdSimpleType::List members = simpleType->memberTypes();
                       for (int i = 0; i < members.count(); ++i) {
      -                    if (myType == members.at(i) ? true : matchesType(myType, members.at(i)->wxsSuperType(), visitedTypes)) {
      +                    if (myType == static_cast<const SchemaType::Ptr>(members.at(i)) ? true : matchesType(myType, members.at(i)->wxsSuperType(), visitedTypes)) {
                               retval = true;
                               break;
                           }
      @@ -159,7 +159,7 @@ static bool matchesType(const SchemaType::Ptr &myType, const SchemaType::Ptr &ot
        */
       static bool hasCircularUnionInheritance(const XsdSimpleType::Ptr &type, const SchemaType::Ptr &otherType, NamePool::Ptr &namePool)
       {
      -    if (type == otherType) {
      +    if (static_cast<const XsdSimpleType::Ptr>(type) == static_cast<const XsdSimpleType::Ptr>(otherType)) {
               return true;
           }
       
      @@ -172,7 +172,7 @@ static bool hasCircularUnionInheritance(const XsdSimpleType::Ptr &type, const Sc
           if (simpleOtherType->category() == XsdSimpleType::SimpleTypeUnion) {
               const XsdSimpleType::List memberTypes = simpleOtherType->memberTypes();
               for (int i = 0; i < memberTypes.count(); ++i) {
      -            if (otherType->wxsSuperType() == type) {
      +            if (static_cast<const XsdSimpleType::Ptr>(otherType->wxsSuperType()) == static_cast<const XsdSimpleType::Ptr>(type)) {
                       return true;
                   }
                   if (hasCircularUnionInheritance(type, memberTypes.at(i), namePool)) {
      @@ -732,7 +732,7 @@ void XsdSchemaChecker::checkComplexTypeConstraints()
                           return;
                       }
       
      -                if (complexType->contentType()->simpleType() != baseType) {
      +                if (static_cast<const SchemaType::Ptr>(complexType->contentType()->simpleType()) != static_cast<const SchemaType::Ptr>(baseType)) {
                           m_context->error(QtXmlPatterns::tr("Complex type %1 must have the same simple type as its base class %2.")
                                                             .arg(formatType(m_namePool, complexType))
                                                             .arg(formatType(m_namePool, baseType)),
      @@ -1590,7 +1590,7 @@ void XsdSchemaChecker::checkConstrainingFacets(const XsdFacet::Hash &facets, con
                   }
       
                   // @see http://www.w3.org/TR/xmlschema-2/#enumeration-valid-restriction
      -            if (facet->type() == XsdFacet::Enumeration && baseType != BuiltinTypes::xsNOTATION) {
      +            if (facet->type() == XsdFacet::Enumeration && static_cast<const SchemaType::Ptr>(baseType) != static_cast<const SchemaType::Ptr>(BuiltinTypes::xsNOTATION)) {
                       const AtomicValue::List multiValue = facet->multiValue();
                       for (int j = 0; j < multiValue.count(); ++j) {
                           const QString stringValue = DerivedString<TypeString>::Ptr(multiValue.at(j))->stringValue();
      @@ -1725,7 +1725,7 @@ void XsdSchemaChecker::checkElementConstraints()
                           return;
                       }
                   }
      -            if ((targetType == BuiltinTypes::xsID) || BuiltinTypes::xsID->wxsTypeMatches(type)) {
      +            if ((static_cast<const AtomicType::Ptr>(targetType) == static_cast<const AtomicType::Ptr>(BuiltinTypes::xsID)) || BuiltinTypes::xsID->wxsTypeMatches(type)) {
                       m_context->error(QtXmlPatterns::tr("Element %1 is not allowed to have a value constraint if its type is derived from %2.")
                                                         .arg(formatKeyword(element->displayName(m_namePool)))
                                                         .arg(formatType(m_namePool, BuiltinTypes::xsID)),
      diff --git a/schema/qxsdschemaresolver.cpp b/schema/qxsdschemaresolver.cpp
      index 7ca38080..d62c19e9 100644
      --- a/schema/qxsdschemaresolver.cpp
      +++ b/schema/qxsdschemaresolver.cpp
      @@ -314,12 +314,12 @@ void XsdSchemaResolver::copyDataTo(const XsdSchemaResolver::Ptr &other) const
       QXmlName XsdSchemaResolver::baseTypeNameOfType(const SchemaType::Ptr &type) const
       {
           for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
      -        if (m_simpleRestrictionBases.at(i).simpleType == type)
      +        if (static_cast<const SchemaType::Ptr>(m_simpleRestrictionBases.at(i).simpleType) == static_cast<const SchemaType::Ptr>(type))
                   return m_simpleRestrictionBases.at(i).baseName;
           }
       
           for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
      -        if (m_complexBaseTypes.at(i).complexType == type)
      +        if (static_cast<const SchemaType::Ptr>(m_complexBaseTypes.at(i).complexType) == static_cast<const SchemaType::Ptr>(type))
                   return m_complexBaseTypes.at(i).baseName;
           }
       
      diff --git a/type/qtypechecker.cpp b/type/qtypechecker.cpp
      index 04383bba..b1a9ee71 100644
      --- a/type/qtypechecker.cpp
      +++ b/type/qtypechecker.cpp
      @@ -141,7 +141,7 @@ Expression::Ptr TypeChecker::verifyType(const Expression::Ptr &operand,
                       const ItemType::Ptr expectedContextType(operand->expectedContextItemType());
       
                       /* Allow the empty sequence. We don't want to trigger XPTY0020 on ()/... . */
      -                if(!expectedContextType->xdtTypeMatches(contextType) && contextType != CommonSequenceTypes::Empty)
      +                if(!expectedContextType->xdtTypeMatches(contextType) && static_cast<const ItemType::Ptr>(contextType) != static_cast<const ItemType::Ptr>(CommonSequenceTypes::Empty))
                       {
                           context->error(wrongType(context->namePool(), operand->expectedContextItemType(), contextType),
                                                   ReportContext::XPTY0020, operand.data());
      

      Attachments

        1. QtXMLPatterns-5.15.2~Clang-12.patch
          7 kB
          Andrei Vukolov
        2. qtypechecker.cpp
          12 kB
          Andrei Vukolov
        3. qxsdschemachecker.cpp
          110 kB
          Andrei Vukolov
        4. qxsdschemaresolver.cpp
          78 kB
          Andrei Vukolov
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            Unassigned Unassigned
            twdragon Andrei Vukolov
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes