[new compiler] Fix invalid memory reads when JS closures outlive QML types

If QQmlCompiledData gets destroyed while somebody still has refcount on the
QV4::CompiledData::CompilationUnit, then unit's _data_ would be freed already
by ~QQmlCompiledData. Given that compilationUnit->data is pointing to the same
malloc'ed address as QQmlCompiledData::qmlUnit, we can just let the
CompilationUnit always own the data.

Fixes tst_qquickloader and makes it possible to run the qquickcomponent tests.

Change-Id: Ie3f3e5335139236d7c2524a327665bda0a9cc847
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Simon Hausmann 2014-03-04 16:15:26 +01:00 committed by The Qt Project
parent 0d84dab380
commit e4e4a7912b
5 changed files with 6 additions and 9 deletions

View File

@ -215,7 +215,8 @@ bool QQmlTypeCompiler::compile()
if (jsUnit) {
Q_ASSERT(!jsUnit->data);
jsUnit->ownsData = false;
Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header);
// The js unit owns the data and will free the qml unit.
jsUnit->data = &qmlUnit->header;
}

View File

@ -150,8 +150,7 @@ void CompilationUnit::unlink()
if (engine)
engine->compilationUnits.erase(engine->compilationUnits.find(this));
engine = 0;
if (ownsData)
free(data);
free(data);
data = 0;
free(runtimeStrings);
runtimeStrings = 0;

View File

@ -549,7 +549,6 @@ struct Q_QML_EXPORT CompilationUnit
: refCount(0)
, engine(0)
, data(0)
, ownsData(false)
, runtimeStrings(0)
, runtimeLookups(0)
, runtimeRegularExpressions(0)
@ -563,7 +562,6 @@ struct Q_QML_EXPORT CompilationUnit
int refCount;
ExecutionEngine *engine;
Unit *data;
bool ownsData;
QString fileName() const { return data->stringAt(data->sourceFileIndex); }

View File

@ -86,10 +86,8 @@ QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool gener
run(i);
QV4::CompiledData::CompilationUnit *unit = backendCompileStep();
if (generateUnitData) {
if (generateUnitData)
unit->data = jsGenerator->generateUnit();
unit->ownsData = true;
}
return unit;
}

View File

@ -140,9 +140,10 @@ QQmlCompiledData::~QQmlCompiledData()
if (rootPropertyCache)
rootPropertyCache->release();
qmlUnit = 0;
if (compilationUnit)
compilationUnit->deref();
free(qmlUnit);
}
void QQmlCompiledData::clear()