Skip to content

Commit

Permalink
createFromUserInput(): make approximate matching by name more restric…
Browse files Browse the repository at this point in the history
…tive to avoid false positives (fixes #3484)
  • Loading branch information
rouault committed Nov 24, 2022
1 parent 15c89f4 commit 15a7cbe
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/iso19111/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7433,7 +7433,14 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
// Second pass: exact match on other objects
// Third pass: approximate match on CRS objects
// Fourth pass: approximate match on other objects
for (int pass = 0; pass <= 3; ++pass) {
// But only allow approximate matching if the size of the text is
// large enough (>= 5), otherwise we get a lot of false positives:
// "foo" -> "Amersfoort", "bar" -> "Barbados 1938"
// Also only accept approximate matching if the ratio between the
// input and match size is not too small, so that "omerc" doesn't match
// with "WGS 84 / Pseudo-Mercator"
const int maxNumberPasses = text.size() <= 4 ? 2 : 4;
for (int pass = 0; pass < maxNumberPasses; ++pass) {
const bool approximateMatch = (pass >= 2);
auto ret = searchObject(
text, approximateMatch,
Expand All @@ -7447,10 +7454,14 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
AuthorityFactory::ObjectType::DATUM_ENSEMBLE,
AuthorityFactory::ObjectType::COORDINATE_OPERATION});
if (ret) {
return NN_NO_CHECK(ret);
if (!approximateMatch ||
ret->nameStr().size() < 2 * text.size())
return NN_NO_CHECK(ret);
}
if (compoundCRS) {
return NN_NO_CHECK(compoundCRS);
if (!approximateMatch ||
compoundCRS->nameStr().size() < 2 * text.size())
return NN_NO_CHECK(compoundCRS);
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions test/unit/test_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11956,6 +11956,15 @@ TEST(io, createFromUserInput) {
ASSERT_TRUE(ensemble != nullptr);
EXPECT_EQ(ensemble->identifiers().size(), 1U);
}

// Check that "foo" doesn't match with "Amersfoort"
EXPECT_THROW(createFromUserInput("foo", dbContext), ParsingException);

// Check that "omerc" doesn't match with "WGS 84 / Pseudo-Mercator"
EXPECT_THROW(createFromUserInput("omerc", dbContext), ParsingException);

// Missing space, dash: OK
EXPECT_NO_THROW(createFromUserInput("WGS84 PseudoMercator", dbContext));
}

// ---------------------------------------------------------------------------
Expand Down

0 comments on commit 15a7cbe

Please sign in to comment.