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. qxsdschemaresolver.cpp
          78 kB
        2. qxsdschemachecker.cpp
          110 kB
        3. qtypechecker.cpp
          12 kB
        4. QtXMLPatterns-5.15.2~Clang-12.patch
          7 kB

        Activity

          People

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

            Dates

              Created:
              Updated: