aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-02-03 14:48:17 +0100
committerEven Rouault <even.rouault@spatialys.com>2019-02-03 14:48:17 +0100
commit24c1272cf4397614fb7ea5502bba9258e6a8f972 (patch)
treed6d3579c439869fb0740dec37844e1cd34c84e56
parentb30ed5cba50688cea9ac2af90855177f84efea5a (diff)
downloadPROJ-24c1272cf4397614fb7ea5502bba9258e6a8f972.tar.gz
PROJ-24c1272cf4397614fb7ea5502bba9258e6a8f972.zip
WKT1 export: avoid division by zero. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12854. Credit to OSS Fuzz
-rw-r--r--src/iso19111/common.cpp15
-rw-r--r--src/iso19111/coordinateoperation.cpp16
-rw-r--r--test/unit/test_io.cpp58
3 files changed, 78 insertions, 11 deletions
diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp
index 57654d84..bdd836e1 100644
--- a/src/iso19111/common.cpp
+++ b/src/iso19111/common.cpp
@@ -172,21 +172,22 @@ void UnitOfMeasure::_exportToWKT(
{
const bool isWKT2 = formatter->version() == WKTFormatter::Version::WKT2;
- if (formatter->forceUNITKeyword() && type() != Type::PARAMETRIC) {
+ const auto l_type = type();
+ if (formatter->forceUNITKeyword() && l_type != Type::PARAMETRIC) {
formatter->startNode(WKTConstants::UNIT, !codeSpace().empty());
} else if (!unitType.empty()) {
formatter->startNode(unitType, !codeSpace().empty());
} else {
- if (isWKT2 && type() == Type::LINEAR) {
+ if (isWKT2 && l_type == Type::LINEAR) {
formatter->startNode(WKTConstants::LENGTHUNIT,
!codeSpace().empty());
- } else if (isWKT2 && type() == Type::ANGULAR) {
+ } else if (isWKT2 && l_type == Type::ANGULAR) {
formatter->startNode(WKTConstants::ANGLEUNIT, !codeSpace().empty());
- } else if (isWKT2 && type() == Type::SCALE) {
+ } else if (isWKT2 && l_type == Type::SCALE) {
formatter->startNode(WKTConstants::SCALEUNIT, !codeSpace().empty());
- } else if (isWKT2 && type() == Type::TIME) {
+ } else if (isWKT2 && l_type == Type::TIME) {
formatter->startNode(WKTConstants::TIMEUNIT, !codeSpace().empty());
- } else if (isWKT2 && type() == Type::PARAMETRIC) {
+ } else if (isWKT2 && l_type == Type::PARAMETRIC) {
formatter->startNode(WKTConstants::PARAMETRICUNIT,
!codeSpace().empty());
} else {
@@ -211,7 +212,7 @@ void UnitOfMeasure::_exportToWKT(
formatter->addQuotedString(l_name);
}
const auto &factor = conversionToSI();
- if (!isWKT2 || factor != 0.0) {
+ if (!isWKT2 || l_type != Type::TIME || factor != 0.0) {
// Some TIMEUNIT do not have a conversion factor
formatter->add(factor);
}
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 6f9b6283..8a10bc5a 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -2147,11 +2147,19 @@ void ParameterValue::_exportToWKT(io::WKTFormatter *formatter) const {
// registered linear / angular unit.
const auto &unitType = unit.type();
if (unitType == common::UnitOfMeasure::Type::LINEAR) {
- formatter->add(
- l_value.convertToUnit(*(formatter->axisLinearUnit())));
+ const auto &targetUnit = *(formatter->axisLinearUnit());
+ if (targetUnit.conversionToSI() == 0.0) {
+ throw io::FormattingException(
+ "cannot convert value to target linear unit");
+ }
+ formatter->add(l_value.convertToUnit(targetUnit));
} else if (unitType == common::UnitOfMeasure::Type::ANGULAR) {
- formatter->add(
- l_value.convertToUnit(*(formatter->axisAngularUnit())));
+ const auto &targetUnit = *(formatter->axisAngularUnit());
+ if (targetUnit.conversionToSI() == 0.0) {
+ throw io::FormattingException(
+ "cannot convert value to target angular unit");
+ }
+ formatter->add(l_value.convertToUnit(targetUnit));
} else {
formatter->add(l_value.getSIValue());
}
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 157614b4..69ef9073 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -8965,3 +8965,61 @@ TEST(wkt_export, precision) {
WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
wkt);
}
+
+// ---------------------------------------------------------------------------
+
+// Avoid division by zero
+
+TEST(wkt_export, invalid_linear_unit) {
+ auto wkt = "PROJCS[\"WGS 84 / UTM zone 31N\",\n"
+ " GEOGCS[\"WGS 84\",\n"
+ " DATUM[\"WGS_1984\",\n"
+ " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
+ " PRIMEM[\"Greenwich\",0],\n"
+ " UNIT[\"degree\",0.0174532925199433]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",0],\n"
+ " PARAMETER[\"central_meridian\",3],\n"
+ " PARAMETER[\"scale_factor\",0.9996],\n"
+ " PARAMETER[\"false_easting\",500000],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"foo\",0]]";
+
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ EXPECT_THROW(
+ crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
+ FormattingException);
+}
+
+// ---------------------------------------------------------------------------
+
+// Avoid division by zero
+
+TEST(wkt_export, invalid_angular_unit) {
+ auto wkt = "PROJCS[\"WGS 84 / UTM zone 31N\",\n"
+ " GEOGCS[\"WGS 84\",\n"
+ " DATUM[\"WGS_1984\",\n"
+ " SPHEROID[\"WGS 84\",6378137,298.257223563]],\n"
+ " PRIMEM[\"Greenwich\",0],\n"
+ " UNIT[\"foo\",0]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",0],\n"
+ " PARAMETER[\"central_meridian\",3],\n"
+ " PARAMETER[\"scale_factor\",0.9996],\n"
+ " PARAMETER[\"false_easting\",500000],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"meter\",1]]";
+
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ EXPECT_THROW(
+ crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()),
+ FormattingException);
+}