QMetaObjectBuilder: add assert to setParameterNames()

Amends 58b4be482cb481addebc966d713bc0521cca3218; we have:
QList<QByteArray> paramNames = method.parameterNames;

The above commit changed the code from:
while (paramNames.size() < paramCount)
    paramNames.append(QByteArray());
for (int i = 0; i < paramCount; ++i)

To:
if (paramNames.size() < paramCount) // (paraphrased for brevity)
    paramNames.resize(paramCount);
for (auto &foo : paramNames)

Calling something like this:
methodBuilder = builder.addSlot("foo(int)");
methodBuilder.setParameterNames({"", "i"});

Worked with the code before that commit, where it just used the first
element in `paramNames` and didn't look at the second one at all.

The new for-loop, `for (auto &foo : paramNames)`, iterated
paraNames.size() times, which led to the `dataIndex` being off by one.
Which would eventually hit an assert in buildMetaObject():
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);

Friedemann Kleint debugged the issue in the bug report, so this patch
applies his suggestion of adding an assert in setParameterNames(), right
where the bug actually happens, because the assert in buildMetaObject()
makes it hard to connect the dots and fix the actual bug in user code.

Fixes: QTBUG-139845
Pick-to: 6.10
Done-with: Friedemann Kleint <Friedemann.Kleint@qt.io>
Change-Id: Icd355241834396c1c8659df621d0f785ef0cceee
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2025-09-04 16:33:16 +03:00
parent 285adfd59c
commit db2bbbb251
2 changed files with 33 additions and 0 deletions

View File

@ -1649,6 +1649,7 @@ QList<QByteArray> QMetaMethodBuilder::parameterNames() const
void QMetaMethodBuilder::setParameterNames(const QList<QByteArray> &value)
{
QMetaMethodBuilderPrivate *d = d_func();
Q_ASSERT(d->parameterCount() >= value.size());
if (d)
d->parameterNames = value;
}

View File

@ -45,6 +45,8 @@ private slots:
void ownMetaTypeNoProperties();
// void tooLongParameterNamesList(); // QTBUG-139845
private:
static bool checkForSideEffects
(const QMetaObjectBuilder& builder,
@ -1770,6 +1772,36 @@ void tst_QMetaObjectBuilder::enumCloning()
}
}
// Can't use this unittest on the CI because it hits an assert
// void tst_QMetaObjectBuilder::tooLongParameterNamesList()
// {
// // QTBUG-139845
// QMetaObjectBuilder builder;
//
// builder.setSuperClass(&QObject::staticMetaObject);
//
// QMetaMethodBuilder methodBuilder = builder.addSignal("iChanged(int)");
// methodBuilder.setParameterNames({"i"});
// int icIdx = methodBuilder.index();
//
// methodBuilder = builder.addSignal("fChanged(float)");
// methodBuilder.setParameterNames({"f"});
// int fcIdx = methodBuilder.index();
//
// methodBuilder = builder.addSlot("pushI(int)");
// methodBuilder.setParameterNames({"i"});
// builder.addSlot("reset()");
// methodBuilder = builder.addSlot("add(int)");
// methodBuilder.setParameterNames({"", "i"});
//
// methodBuilder.setReturnType("int");
//
// builder.addProperty("i", "int", icIdx);
// builder.addProperty("f", "float", fcIdx);
//
// builder.toMetaObject();
// }
void tst_QMetaObjectBuilder::ownMetaTypeNoProperties()
{
QMetaObjectBuilder builder;