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

QT_NO_CAST_FROM_ASCII can break code without warning with QCharRef::operator=(*) and char > 127

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1: Critical
    • Resolution: Done
    • Affects Version/s: 5.15.1
    • Fix Version/s: None
    • Labels:
      None
    • Platform/s:
      Linux/X11
    • Commits:
      f8ad329f7ee01993c388f78851fc4ac88f5093b4 (qt/qtbase/5.15)

      Description

      QCharRef does not catch the char/uchar-overloads for QCharRef::operator=(...) in case QT_NO_CAST_FROM_ASCII is set. Instead the compiler will implicitly cast to int and use the QCharRef::operator=(int rc) overload.
      So in case of code assigning a (literal) char > 127 which works as expected before setting the QT_NO_CAST_FROM_ASCII flag, afterwards this will assign a negative and thus bogus unicode code point value instead, to create a QChar from. So breaking the behaviour without a notice by the compiler, and with the own previously working code still looking fine on first look (Nobody expects the Spanish Inquisition, but also not the direct cast of a literal char to an integer to become a code point).
      See the end for a proposal how to address this, based on other Qt string classes.
      ((Also is this code which will not build with Qt6 from what I was told, as there the bad assignment is caught, so this holds a surprise on porting despite having used the flag))

      // Set it to make  the code do bogus things without hint by the compiler
      // #define QT_NO_CAST_FROM_ASCII
      
      #include <QString>
      #include <QCoreApplication>
      #include <QDebug>
      
      int main(int argc, char**argv)
      {
          QCoreApplication app(argc, argv);
      
          QString s;
          s.resize(1);
          s[0] = '\xA0'; // setting no-break space, value 160, so > 127 -> negative signed char
          qDebug() << "First char is: " << s[0].unicode();
          qDebug() << "Is expected char: " << (s[0] == QLatin1Char('\xA0'));
      
          return 0;
      }
      

      Seems QCharRef is missing to catch those overloads in the case the flag is set, other than its sibling classes. This addition solved the issue locally and helped to detect some cases where char was casted to int unexpectedly:

      class QCharRef
      {
      // [...]
      private:
      #ifdef QT_NO_CAST_FROM_ASCII
          QCharRef &operator=(char c);
          QCharRef &operator=(uchar c);
      #endif
      };
      

      As a reference point for the effect of this addition: I tested this patch on 68 of the KF modules and only hit 3 cases (all non-critical <=127 char usages) where this would break the build. Currently fixing all those three. Issue found in an application which just got adapted to build with QT_NO_CAST_FROM_ASCII and show misbehaviour afterwards.

        Attachments

        For Gerrit Dashboard: QTBUG-88431
        # Subject Branch Project Status CR V

          Activity

            People

            Assignee:
            peppe Giuseppe D'Angelo
            Reporter:
            kossebau Friedrich W. H. Kossebau
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:

                Gerrit Reviews

                There are no open Gerrit changes