diff options
author | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2016-05-20 14:27:04 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2016-05-20 13:54:49 +0000 |
commit | edc80ca148fe5832f4847e606d62e42f7b5d1aaf (patch) | |
tree | c0c6a0e51e444daa3a0e875ac9b1fb0544b2cf57 | |
parent | 46bda21da1d0154dc5effdc334955bf25b96c366 (diff) |
Fix null pointer accesses.
We used to call certain member functions on an object that could be
null. While that was never allowed, it did not cause problems so far
because these functions checked their "this" pointer and returned
immediately if it was null. With GCC 6, such constructs no longer work.
Measures taken:
- Fix the null pointer accesses by allocating the respective
objects earlier (in case they must not be null) or checking for a
null value at the calling site (in case they can legitimately be
null).
- Rewrite the aforementioned member functions so that they will
no longer silently tolerate undefined behavior with other
compilers than GCC 6.
Task-number: QBS-974
Change-Id: If07ddc5c0e536d36c19311357f871554aa692ad6
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Ilya Lyubimov <villytiger@gmail.com>
-rw-r--r-- | src/lib/corelib/language/item.cpp | 11 | ||||
-rw-r--r-- | src/lib/corelib/language/moduleloader.cpp | 22 |
2 files changed, 22 insertions, 11 deletions
diff --git a/src/lib/corelib/language/item.cpp b/src/lib/corelib/language/item.cpp index 304a80c58..c9bb6a79f 100644 --- a/src/lib/corelib/language/item.cpp +++ b/src/lib/corelib/language/item.cpp @@ -102,10 +102,12 @@ Item *Item::clone() const bool Item::hasProperty(const QString &name) const { - for (const Item *item = this; item; item = item->m_prototype) + const Item *item = this; + do { if (item->m_properties.contains(name)) return true; - + item = item->m_prototype; + } while (item); return false; } @@ -117,9 +119,12 @@ bool Item::hasOwnProperty(const QString &name) const ValuePtr Item::property(const QString &name) const { ValuePtr value; - for (const Item *item = this; item; item = item->m_prototype) + const Item *item = this; + do { if ((value = item->m_properties.value(name))) break; + item = item->m_prototype; + } while (item); return value; } diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp index 3d391fd0d..3bfa38211 100644 --- a/src/lib/corelib/language/moduleloader.cpp +++ b/src/lib/corelib/language/moduleloader.cpp @@ -251,7 +251,8 @@ private: if (value->item()->type() != ItemType::ModuleInstance && value->item()->type() != ItemType::ModulePrefix && m_parentItem->file() - && !m_parentItem->file()->idScope()->hasProperty(m_currentName) + && (!m_parentItem->file()->idScope() + || !m_parentItem->file()->idScope()->hasProperty(m_currentName)) && !value->createdByPropertiesBlock()) { const ErrorInfo error(Tr::tr("Item '%1' is not declared. " "Did you forget to add a Depends item?").arg(m_currentName), @@ -349,6 +350,10 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, auto &projectContext = *p; projectContext.topLevelProject = topLevelProjectContext; projectContext.result = loadResult; + ItemValuePtr itemValue = ItemValue::create(projectItem); + projectContext.scope = Item::create(m_pool); + projectContext.scope->setFile(projectItem->file()); + projectContext.scope->setProperty(QLatin1String("project"), itemValue); ProductContext dummyProductContext; dummyProductContext.project = &projectContext; dummyProductContext.moduleProperties = m_parameters.finalBuildConfigurationTree(); @@ -367,10 +372,6 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, << projectItem->file()->dirPath()); projectContext.searchPathsStack = m_reader->extraSearchPathsStack(); projectContext.item = projectItem; - ItemValuePtr itemValue = ItemValue::create(projectItem); - projectContext.scope = Item::create(m_pool); - projectContext.scope->setFile(projectItem->file()); - projectContext.scope->setProperty(QLatin1String("project"), itemValue); const QString minVersionStr = m_evaluator->stringValue(projectItem, QLatin1String("minimumQbsVersion"), @@ -566,13 +567,14 @@ void ModuleLoader::prepareProduct(ProjectContext *projectContext, Item *productI productContext.project = projectContext; initProductProperties(productContext); - mergeExportItems(productContext); - ItemValuePtr itemValue = ItemValue::create(productItem); productContext.scope = Item::create(m_pool); productContext.scope->setProperty(QLatin1String("product"), itemValue); productContext.scope->setFile(productItem->file()); productContext.scope->setScope(productContext.project->scope); + + mergeExportItems(productContext); + setScopeForDescendants(productItem, productContext.scope); projectContext->products << productContext; @@ -1473,8 +1475,12 @@ void ModuleLoader::instantiateModule(ProductContext *productContext, Item *expor QBS_CHECK(instanceScope->file()); moduleScope->setFile(instanceScope->file()); moduleScope->setScope(instanceScope); + QBS_CHECK(productContext->project->scope); productContext->project->scope->copyProperty(QLatin1String("project"), moduleScope); - productContext->scope->copyProperty(QLatin1String("product"), moduleScope); + if (productContext->scope) + productContext->scope->copyProperty(QLatin1String("product"), moduleScope); + else + QBS_CHECK(moduleName.toString() == QLatin1String("qbs")); // Dummy product. if (isProduct) { exportingProduct = 0; |