From 761b4835f961c302c0647a6068f6786d072e9355 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 2 Oct 2013 22:28:19 +0100 Subject: [PATCH] Make positioned queries more defensive. Validate the filter type range, to avoid crashing on bad ranges. Accept arbitrary type lists in the Nasal API for searching by distance --- src/Navaids/positioned.cxx | 30 +++++++++++++++++++++++ src/Scripting/NasalPositioned_cppbind.cxx | 9 +++---- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 51802c2ed..89d414755 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -54,6 +54,16 @@ static void validateSGGeod(const SGGeod& geod) } } +static bool validateFilter(FGPositioned::Filter* filter) +{ + if (filter->maxType() < filter->minType()) { + SG_LOG(SG_GENERAL, SG_WARN, "invalid positioned filter specified"); + return false; + } + + return true; +} + /////////////////////////////////////////////////////////////////////////////// @@ -231,6 +241,10 @@ FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilt { validateSGGeod(aPos); + if (!validateFilter(aFilter)) { + return FGPositionedList(); + } + FGPositionedList result; Octree::findAllWithinRange(SGVec3d::fromGeod(aPos), aRangeNm * SG_NM_TO_METER, aFilter, result, 0xffffff); @@ -242,6 +256,10 @@ FGPositioned::findWithinRangePartial(const SGGeod& aPos, double aRangeNm, Filter { validateSGGeod(aPos); + if (!validateFilter(aFilter)) { + return FGPositionedList(); + } + int limitMsec = 32; FGPositionedList result; aPartial = Octree::findAllWithinRange(SGVec3d::fromGeod(aPos), @@ -253,12 +271,20 @@ FGPositioned::findWithinRangePartial(const SGGeod& aPos, double aRangeNm, Filter FGPositionedList FGPositioned::findAllWithIdent(const std::string& aIdent, Filter* aFilter, bool aExact) { + if (!validateFilter(aFilter)) { + return FGPositionedList(); + } + return NavDataCache::instance()->findAllWithIdent(aIdent, aFilter, aExact); } FGPositionedList FGPositioned::findAllWithName(const std::string& aName, Filter* aFilter, bool aExact) { + if (!validateFilter(aFilter)) { + return FGPositionedList(); + } + return NavDataCache::instance()->findAllWithName(aName, aFilter, aExact); } @@ -267,6 +293,10 @@ FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter) { validateSGGeod(aPos); + if (!validateFilter(aFilter)) { + return NULL; + } + FGPositionedList l(findClosestN(aPos, 1, aCutoffNm, aFilter)); if (l.empty()) { return NULL; diff --git a/src/Scripting/NasalPositioned_cppbind.cxx b/src/Scripting/NasalPositioned_cppbind.cxx index eb9a14158..b2e104442 100644 --- a/src/Scripting/NasalPositioned_cppbind.cxx +++ b/src/Scripting/NasalPositioned_cppbind.cxx @@ -395,13 +395,10 @@ static naRef f_findWithinRange(nasal::CallContext ctx) { SGGeod pos = getPosition(ctx); double range_nm = ctx.requireArg(0); - - FGPositioned::Type ty = FGPositioned::typeFromName(ctx.getArg(1)); - if (ty == FGPositioned::INVALID) - naRuntimeError(ctx.c, "invalid filter type specification"); + + std::string typeSpec = ctx.getArg(1); + FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec)); - FGPositioned::TypeFilter filter(ty); - FGPositionedList items = FGPositioned::findWithinRange(pos, range_nm, &filter); FGPositioned::sortByRange(items, pos); return ctx.to_nasal(items);