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

QUrlQuery: operator== does not handle a case where exactly one object has null pimpl

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P2: Important
    • 6.4.3, 6.5.0, 6.6.0
    • 5.15.2
    • Core: I/O
    • None
    • 3d584b109 (dev), b1684da6e (6.5), 81ed4430e (6.4)

    Description

      QUrlQuery implements operator== the following way:

       

      bool QUrlQuery::operator ==(const QUrlQuery &other) const
      {
          if (d == other.d)
              return true;
          if (d && other.d)
              // keep in sync with qHash(QUrlQuery):
              return d->valueDelimiter == other.d->valueDelimiter &&
                      d->pairDelimiter == other.d->pairDelimiter &&
                      d->itemList == other.d->itemList;
          return false;
      } 

      (conventionally it should be non-member to avoid inconsistent argument implicit convertions but that's not the point of this issue)

       

      The implementation doesn't handle a case where one object has a non-null d (pimpl) and one has default-constructed/initialized pimpl. Analogy: 2 QString objects where one has no buffer allocated (isNull() returns true) and one has a buffer containing "" (isEmpty() returns true but isNull() returns false). For QString, operator== still considers such objects equal. QUrlQuery does not handle this case - if exactly one pimpl is null then the function flows to return false; statement.

       

      Reproduction test:

          QUrlQuery q1(QUrl(QStringLiteral("https://example.com")).query());
          QUrlQuery q2;
          q2.setQuery(q1.query());
      
          QCOMPARE(q1.toString(), q2.toString());
          QCOMPARE(q1.queryPairDelimiter(), q2.queryPairDelimiter());
          QCOMPARE(q1.queryValueDelimiter(), q2.queryValueDelimiter());
          QCOMPARE(q1.queryItems(), q2.queryItems());
          QCOMPARE(q1.query(), q2.query());
      
          // compare class bodies (one will be 0s and one will not)
          QByteArray a1(reinterpret_cast<const char*>(&q1), sizeof(q1));
          QByteArray a2(reinterpret_cast<const char*>(&q2), sizeof(q2));
          QCOMPARE(a1, a2); // fails
      
          QCOMPARE(q1, q2); // fails 

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            michal_urbanski Michał Urbański
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There is 1 open Gerrit change