mirror of https://github.com/Icinga/icinga2.git
Fix crash on API queries with Fedora 28 hardening and GCC 8
The actual fix is to handle nullptr references differently for an empty filter expression. The other changes include oob checks not necesarily involved. fixes #6533
This commit is contained in:
parent
1c2a59bf63
commit
1f4f6282c7
|
@ -127,7 +127,7 @@ static void FilteredAddTarget(ScriptFrame& permissionFrame, Expression *permissi
|
||||||
ScriptFrame& frame, Expression *ufilter, std::vector<Value>& result, const String& variableName, const Object::Ptr& target)
|
ScriptFrame& frame, Expression *ufilter, std::vector<Value>& result, const String& variableName, const Object::Ptr& target)
|
||||||
{
|
{
|
||||||
if (FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target, variableName) && FilterUtility::EvaluateFilter(frame, ufilter, target, variableName))
|
if (FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target, variableName) && FilterUtility::EvaluateFilter(frame, ufilter, target, variableName))
|
||||||
result.emplace_back(target);
|
result.emplace_back(std::move(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **permissionFilter)
|
void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **permissionFilter)
|
||||||
|
@ -206,7 +206,7 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
|
||||||
if (attr == "type")
|
if (attr == "type")
|
||||||
attr = "name";
|
attr = "name";
|
||||||
|
|
||||||
if (query->Contains(attr)) {
|
if (query && query->Contains(attr)) {
|
||||||
String name = HttpUtility::GetLastParameter(query, attr);
|
String name = HttpUtility::GetLastParameter(query, attr);
|
||||||
Object::Ptr target = provider->GetTargetByName(type, name);
|
Object::Ptr target = provider->GetTargetByName(type, name);
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
|
||||||
attr = provider->GetPluralName(type);
|
attr = provider->GetPluralName(type);
|
||||||
boost::algorithm::to_lower(attr);
|
boost::algorithm::to_lower(attr);
|
||||||
|
|
||||||
if (query->Contains(attr)) {
|
if (query && query->Contains(attr)) {
|
||||||
Array::Ptr names = query->Get(attr);
|
Array::Ptr names = query->Get(attr);
|
||||||
if (names) {
|
if (names) {
|
||||||
ObjectLock olock(names);
|
ObjectLock olock(names);
|
||||||
|
@ -235,7 +235,7 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query->Contains("filter") || result.empty()) {
|
if ((query && query->Contains("filter")) || result.empty()) {
|
||||||
if (!query->Contains("type"))
|
if (!query->Contains("type"))
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Type must be specified when using a filter."));
|
BOOST_THROW_EXCEPTION(std::invalid_argument("Type must be specified when using a filter."));
|
||||||
|
|
||||||
|
@ -251,26 +251,31 @@ std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, c
|
||||||
frame.Sandboxed = true;
|
frame.Sandboxed = true;
|
||||||
Dictionary::Ptr uvars = new Dictionary();
|
Dictionary::Ptr uvars = new Dictionary();
|
||||||
|
|
||||||
std::unique_ptr<Expression> ufilter;
|
|
||||||
|
|
||||||
if (query->Contains("filter")) {
|
if (query->Contains("filter")) {
|
||||||
String filter = HttpUtility::GetLastParameter(query, "filter");
|
String filter = HttpUtility::GetLastParameter(query, "filter");
|
||||||
ufilter = ConfigCompiler::CompileText("<API query>", filter);
|
std::unique_ptr<Expression> ufilter = ConfigCompiler::CompileText("<API query>", filter);
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary::Ptr filter_vars = query->Get("filter_vars");
|
Dictionary::Ptr filter_vars = query->Get("filter_vars");
|
||||||
if (filter_vars) {
|
if (filter_vars) {
|
||||||
ObjectLock olock(filter_vars);
|
ObjectLock olock(filter_vars);
|
||||||
for (const Dictionary::Pair& kv : filter_vars) {
|
for (const Dictionary::Pair& kv : filter_vars) {
|
||||||
uvars->Set(kv.first, kv.second);
|
uvars->Set(kv.first, kv.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frame.Self = uvars;
|
||||||
|
|
||||||
|
provider->FindTargets(type, std::bind(&FilteredAddTarget,
|
||||||
|
std::ref(permissionFrame), permissionFilter,
|
||||||
|
std::ref(frame), &*ufilter, std::ref(result), variableName, _1));
|
||||||
|
} else {
|
||||||
|
/* Ensure to pass a nullptr as filter expression.
|
||||||
|
* GCC 8.1.1 on F28 causes problems, see GH #6533.
|
||||||
|
*/
|
||||||
|
provider->FindTargets(type, std::bind(&FilteredAddTarget,
|
||||||
|
std::ref(permissionFrame), permissionFilter,
|
||||||
|
std::ref(frame), nullptr, std::ref(result), variableName, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.Self = uvars;
|
|
||||||
|
|
||||||
provider->FindTargets(type, std::bind(&FilteredAddTarget,
|
|
||||||
std::ref(permissionFrame), permissionFilter,
|
|
||||||
std::ref(frame), &*ufilter, std::ref(result), variableName, _1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue