[devel] [qt6-base] nullptr передаётся в constexpr функцию?

Ilya Kurdyukov ilyakurdyukov на basealt.ru
Сб Окт 22 13:19:41 MSK 2022


На Эльбрусе такое возникло.

Срабатывает при выполнении qdbusxml2cpp, что используется в некоторых 
пакетах (qt6-sensors, qt6-positioning).

Считаю что баг в апстриме. Но как это вообще может работать на других 
архитектурах (компиляторах) ?

Для Эльбурса используется EDG, что "constexpr int normalizeType()" 
выполянет в рантайме.


Стектрейс:

#0  0x0000455555cfec30 in QtPrivate::QTypeNormalizer::normalizeType(char 
const*, char const*, bool) () from /usr/lib64/libQt6Core.so.6
#1  0x0000455555d010b8 in QtPrivate::qNormalizeType(char const*, char 
const*, char*) () from /usr/lib64/libQt6Core.so.6
#2  0x0000455555ce3b00 in 
_INTERNAL_15_qmetaobject_cpp_4823c95c::normalizeTypeInternal(char 
const*, char const*) () from /usr/lib64/libQt6Core.so.6
#3  0x0000455555ce8a68 in QMetaObject::normalizedType(char const*) ()
    from /usr/lib64/libQt6Core.so.6
#4  0x0000455555d984b0 in (anonymous 
namespace)::QMetaTypeCustomRegistry::registerCustomType(QtPrivate::QMetaTypeInterface 
const*) ()
    from /usr/lib64/libQt6Core.so.6
#5  0x0000455555d2c8b8 in QMetaType::idHelper() const ()
    from /usr/lib64/libQt6Core.so.6
#6  0x000000000003aea0 in QMetaType::id(int) const ()
#7  0x0000000000022d88 in 
_INTERNAL_16_qdbusxml2cpp_cpp_4823c95c::qtTypeName(QString const&, 
QMap<QString, QString> const&, int, char const*, bool) ()
#8  0x0000000000027838 in 
_INTERNAL_16_qdbusxml2cpp_cpp_4823c95c::writeProxy(QString const&, 
QMap<QString, QSharedDataPointer<QDBusIntrospection::Interface> > const&) ()
#9  0x0000000000032db0 in main ()

Последние три функции, в *t приходит нулевой указатель:

static QByteArray normalizeTypeInternal(const char *t, const char *e)
{
     int len = QtPrivate::qNormalizeType(t, e, nullptr);
     if (len == 0)
         return QByteArray();
     QByteArray result(len, Qt::Uninitialized);
     len = QtPrivate::qNormalizeType(t, e, result.data());
     Q_ASSERT(len == result.size());
     return result;
}

constexpr int qNormalizeType(const char *begin, const char *end, char 
*output)
{
     return QTypeNormalizer { output }.normalizeType(begin, end);
}

struct QTypeNormalizer
{
     constexpr int normalizeType(const char *begin, const char *end, 
bool adjustConst = true)
     {
         // Trim spaces
         while (begin != end && is_space(*begin))
             begin++;
         while (begin != end && is_space(*(end - 1)))
             end--;

         // Convert 'char const *' into 'const char *'. Start at index 1,
         // not 0, because 'const char *' is already OK.
         const char *cst = begin + 1;
         if (*begin == '\'' || *begin == '"')
             cst = skipString(begin, end);
         bool seenStar = false;
         bool hasMiddleConst = false;
         while (cst < end) {

...

Падает на *begin == '\''.


Отсюда (qdbusxml2cpp.cpp):

static QByteArray qtTypeName(const QString &signature, const 
QDBusIntrospection::Annotations &annotations, int paramId = -1, const 
char *direction = "Out", bool isSignal = false)
{
     int type = 
QDBusMetaType::signatureToMetaType(signature.toLatin1()).id();
     if (type == QMetaType::UnknownType) {
...

вызывается id() -> idHelper() -> registerCustomType() ... -> normalizeType()

QMetaType QDBusMetaType::signatureToMetaType(const char *signature)
{
     if (!signature)
         return QMetaType(QMetaType::UnknownType);

     QDBusMetaTypeId::init();
     switch (signature[0])
     {
...
     default:
         return QMetaType(QMetaType::UnknownType);
     }
}

QMetaType::UnknownType имеет name = nullptr, с нулевой длиной.

qmetatype.cpp:

static const struct { const char * typeName; int typeNameLength; int 
type; } types[] = {
     QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
     QT_ADD_STATIC_METATYPE(_, QMetaTypeId2<qreal>::MetaType, qreal)
     {nullptr, 0, QMetaType::UnknownType}
};


Подробная информация о списке рассылки Devel