[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