From 1c60f4cc408e85aff78482659a80fe974ee5d57b Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 2 Feb 2019 09:44:44 +0100 Subject: PROJStringSyntaxParser: avoid assertion on illegal input. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12837. Credit to OSS Fuzz --- src/iso19111/io.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/iso19111/io.cpp') diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 3517c225..f854e21a 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -5285,6 +5285,8 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, const char *c_str = projString.c_str(); std::vector tokens; + bool hasProj = false; + bool hasInit = false; { size_t i = 0; while (true) { @@ -5313,6 +5315,13 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, if (token.empty()) { break; } + if (!hasProj && + (starts_with(token, "proj=") || starts_with(token, "+proj="))) { + hasProj = true; + } else if (!hasInit && (starts_with(token, "init=") || + starts_with(token, "+init="))) { + hasInit = true; + } tokens.emplace_back(token); } } @@ -5320,14 +5329,6 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, bool prevWasTitle = false; if (projString.find("proj=pipeline") == std::string::npos) { - const bool hasProj = projString.find("proj=") == 0 || - projString.find("+proj=") == 0 || - projString.find(" proj=") != std::string::npos || - projString.find(" +proj=") != std::string::npos; - const bool hasInit = projString.find("init=") == 0 || - projString.find("+init=") == 0 || - projString.find(" init=") != std::string::npos || - projString.find(" +init=") != std::string::npos; if (hasProj || hasInit) { steps.push_back(Step()); } -- cgit v1.2.3 From 3ed6153400299db04163ffe8fd9fd785eb9ca12e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 2 Feb 2019 11:13:12 +0100 Subject: createFromUserInput(): fix infinite recursion. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12842. Credit to OSS Fuzz --- src/iso19111/io.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/iso19111/io.cpp') diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index f854e21a..1f4a7c8b 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -5287,6 +5287,7 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, bool hasProj = false; bool hasInit = false; + bool hasPipeline = false; { size_t i = 0; while (true) { @@ -5315,8 +5316,11 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, if (token.empty()) { break; } - if (!hasProj && - (starts_with(token, "proj=") || starts_with(token, "+proj="))) { + if (!hasPipeline && + (token == "proj=pipeline" || token == "+proj=pipeline")) { + hasPipeline = true; + } else if (!hasProj && (starts_with(token, "proj=") || + starts_with(token, "+proj="))) { hasProj = true; } else if (!hasInit && (starts_with(token, "init=") || starts_with(token, "+init="))) { @@ -5328,7 +5332,7 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, bool prevWasTitle = false; - if (projString.find("proj=pipeline") == std::string::npos) { + if (!hasPipeline) { if (hasProj || hasInit) { steps.push_back(Step()); } -- cgit v1.2.3 From 149bd81691e309d4ab22bed944ea69fbeaec450f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 5 Feb 2019 23:48:32 +0100 Subject: PROJStringParser::createFromPROJString(): avoid potential infinite loop. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12913. Credit to OSS Fuzz --- src/iso19111/io.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/iso19111/io.cpp') diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 1f4a7c8b..431c75af 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -5313,6 +5313,9 @@ PROJStringSyntaxParser(const std::string &projString, std::vector &steps, } token += c_str[i]; } + if (in_string) { + throw ParsingException("Unbalanced double quote"); + } if (token.empty()) { break; } @@ -7452,6 +7455,13 @@ static const metadata::ExtentPtr &getExtent(const crs::CRS *crs) { */ BaseObjectNNPtr PROJStringParser::createFromPROJString(const std::string &projString) { + + // In some abnormal situations involving init=epsg:XXXX syntax, we could + // have infinite loop + if (d->ctx_ && d->ctx_->curStringInCreateFromPROJString == projString) { + throw ParsingException("invalid PROJ string"); + } + d->steps_.clear(); d->title_.clear(); d->globalParamValues_.clear(); @@ -7760,11 +7770,17 @@ PROJStringParser::createFromPROJString(const std::string &projString) { proj_log_func(pj_context, &logger, Logger::log); proj_context_use_proj4_init_rules(pj_context, d->usePROJ4InitRules_); } + if (d->ctx_) { + d->ctx_->curStringInCreateFromPROJString = projString; + } auto pj = pj_create_internal( pj_context, (projString.find("type=crs") != std::string::npos ? projString + " +disable_grid_presence_check" : projString) .c_str()); + if (d->ctx_) { + d->ctx_->curStringInCreateFromPROJString.clear(); + } valid = pj != nullptr; // Remove parameters not understood by PROJ. -- cgit v1.2.3 From 5141b3908e59a26c9fe66de94bb7388bff741b58 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 11 Feb 2019 23:58:16 +0100 Subject: Make tmerc an alias for etmerc. (#1234) * Make tmerc an alias for etmerc This switches the algorithm used in tmerc to the Poder/Engsager tmerc algorithm. The original tmerc algorithm of Evenden/Snyder origin can still be accessed by adding the +approx flag when initializing a tmerc projection. The +approx flag can also be used when initializing UTM projections, in which case the Evenden/Snyder algorithm is used as well. If a tmerc projection is instantiated on a spherical earth the Evenden/Snyder algorithm is used as well since the Poder/Engsager algorithm is only defined on the ellipsoid. +proj=etmerc can still be instantiated for backwards compatibility reasons. Co-authored-by: Kristian Evers Co-authored-by: Even Rouault --- src/iso19111/io.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'src/iso19111/io.cpp') diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 431c75af..60c28201 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -4746,8 +4746,7 @@ struct PROJStringFormatter::Private { bool omitProjLongLatIfPossible_ = false; bool omitZUnitConversion_ = false; DatabaseContextPtr dbContext_{}; - bool useETMercForTMerc_ = false; - bool useETMercForTMercSet_ = false; + bool useApproxTMerc_ = false; bool addNoDefs_ = true; bool coordOperationOptimizations_ = false; bool crsExport_ = false; @@ -4803,11 +4802,9 @@ PROJStringFormatter::create(Convention conventionIn, // --------------------------------------------------------------------------- -/** \brief Set whether Extended Transverse Mercator (etmerc) should be used - * instead of tmerc */ -void PROJStringFormatter::setUseETMercForTMerc(bool flag) { - d->useETMercForTMerc_ = flag; - d->useETMercForTMercSet_ = true; +/** \brief Set whether approximate Transverse Mercator or UTM should be used */ +void PROJStringFormatter::setUseApproxTMerc(bool flag) { + d->useApproxTMerc_ = flag; } // --------------------------------------------------------------------------- @@ -5256,9 +5253,8 @@ PROJStringFormatter::Convention PROJStringFormatter::convention() const { // --------------------------------------------------------------------------- -bool PROJStringFormatter::getUseETMercForTMerc(bool &settingSetOut) const { - settingSetOut = d->useETMercForTMercSet_; - return d->useETMercForTMerc_; +bool PROJStringFormatter::getUseApproxTMerc() const { + return d->useApproxTMerc_; } // --------------------------------------------------------------------------- @@ -7081,8 +7077,10 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS( : UnitOfMeasure::NONE))); } - if (step.name == "etmerc") { - methodMap.set("proj_method", "etmerc"); + if (step.name == "tmerc" && hasParamValue(step, "approx")) { + methodMap.set("proj_method", "tmerc approx"); + } else if (step.name == "utm" && hasParamValue(step, "approx")) { + methodMap.set("proj_method", "utm approx"); } conv = Conversion::create(mapWithUnknownName, methodMap, parameters, -- cgit v1.2.3