diff options
Diffstat (limited to 'Source')
| -rw-r--r-- | Source/WebCore/ChangeLog | 46 | ||||
| -rw-r--r-- | Source/WebCore/bridge/qt/qt_runtime.cpp | 14 |
2 files changed, 56 insertions, 4 deletions
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index db002064a..7b3d70b5a 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,49 @@ +2012-12-19 Simon Hausmann <simon.hausmann@digia.com>, Jedrzej Nowacki <jedrzej.nowacki@digia.com> + + [Qt] JS bridge does not transmit QVariants anymore in Qt5 + https://bugs.webkit.org/show_bug.cgi?id=104540 + + Reviewed by Kenneth Rohde Christiansen. + + A data corruption exists in the QObject bridge when calling slots that + take a QVariant. + + The calling convention for slots is that the void* parameter array must + contain pointers to the actually required destination argument type. If + a function takes an int for example, the corresponding entry in the + void* parameter array must be a pointer to an int that the moc + generated code then can "safely" cast to an int* and dereference. + Similarly if the function takes a QVariant it must be a pointer to a + QVariant. + + We implement this calling convention by constructing QVariants of the + requested parameter types and passing the value of data() into the + void* parameter array. This works fine for all types except if the + requested type is a QVariant. In that case data() will _not_ return a + pointer that can later be safely casted to a QVariant pointer and + dereferenced. Instead we must use the address of our variant to ensure + a working cast. + + Our auto tests cover this case, but they worked by accident because the + provided pointer when casted to a QVariant happens to have the correct + type id that doesn't produce the warning seen in the test case of the + provided example and the unit test just copies the QVariant and thus + pointer. + + * bridge/qt/qt_runtime.cpp: + (JSC::Bindings::QtMethodMatchType::typeId): Replace string based meta + type id determination of QVariant with a quicker table lookup. + (JSC::Bindings::findMethodIndex): Remember the chosen (requested) types + and pass the pointer to the QVariant instead of its data() pointer if + requested. + (JSC::Bindings::QtRuntimeMethod::call): Fixed determination of whether + we need to convert a return value or not solely based on the return + type _specified_ in the meta method instead of the variant value + returned. The latter is not sufficient because a slot can return an + invalid variant, which is not the same as returning void. This was + triggered by an unit test that accidentally passed due to this memory + corruption in the first place. + 2012-12-12 Csaba Osztrogonác <ossy@webkit.org> [Qt] Unreviewed typo fix after r137446. diff --git a/Source/WebCore/bridge/qt/qt_runtime.cpp b/Source/WebCore/bridge/qt/qt_runtime.cpp index 951fa1cde..131239533 100644 --- a/Source/WebCore/bridge/qt/qt_runtime.cpp +++ b/Source/WebCore/bridge/qt/qt_runtime.cpp @@ -893,7 +893,7 @@ private: QMetaType::Type QtMethodMatchType::typeId() const { if (isVariant()) - return (QMetaType::Type) QMetaType::type("QVariant"); + return (QMetaType::Type) qMetaTypeId<QVariant>(); return (QMetaType::Type) (isMetaEnum() ? QMetaType::Int : m_typeId); } @@ -1086,6 +1086,7 @@ static int findMethodIndex(JSContextRef context, && (matchDistance == 0)) { // perfect match, use this one chosenIndex = index; + chosenTypes = types; break; } QtMethodMatchData currentMatch(matchDistance, index, types, args); @@ -1163,6 +1164,7 @@ static int findMethodIndex(JSContextRef context, setException(context, exception, message); } else { chosenIndex = bestMatch.index; + chosenTypes = bestMatch.types; args = bestMatch.args; } } @@ -1173,7 +1175,10 @@ static int findMethodIndex(JSContextRef context, vars.resize(args.count()); for (i=0; i < args.count(); i++) { vars[i] = args[i]; - vvars[i] = vars[i].data(); + if (chosenTypes[i].isVariant()) + vvars[i] = &vars[i]; + else + vvars[i] = vars[i].data(); } } @@ -1238,14 +1243,15 @@ JSValueRef QtRuntimeMethod::call(JSContextRef context, JSObjectRef function, JSO QVarLengthArray<QVariant, 10> vargs; void* qargs[11]; + const QMetaObject* metaObject = obj->metaObject(); - int methodIndex = findMethodIndex(context, obj->metaObject(), d->m_identifier, argumentCount, arguments, + int methodIndex = findMethodIndex(context, metaObject, d->m_identifier, argumentCount, arguments, (d->m_flags & AllowPrivate), vargs, (void **)qargs, exception); if (QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0) return JSValueMakeUndefined(context); - if (vargs.size() > 0 && vargs[0].isValid()) + if (vargs.size() > 0 && metaObject->method(methodIndex).returnType() != QMetaType::Void) return convertQVariantToValue(context, d->m_instance->rootObject(), vargs[0], exception); return JSValueMakeUndefined(context); |
