aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@theqtcompany.com>2016-05-20 14:27:04 +0200
committerChristian Kandeler <christian.kandeler@theqtcompany.com>2016-05-20 13:54:49 +0000
commitedc80ca148fe5832f4847e606d62e42f7b5d1aaf (patch)
treec0c6a0e51e444daa3a0e875ac9b1fb0544b2cf57
parent46bda21da1d0154dc5effdc334955bf25b96c366 (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.cpp11
-rw-r--r--src/lib/corelib/language/moduleloader.cpp22
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;