aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-02-03 16:07:10 +0100
committerEven Rouault <even.rouault@spatialys.com>2019-02-03 16:07:10 +0100
commit4abfe10ab7a64552db242aa240bbcf2f92598604 (patch)
tree670f38370dae8af534aee200460a2ddf72c97839
parente121dc35abafd9a2eda01b05aa5fa13b13e6196e (diff)
downloadPROJ-4abfe10ab7a64552db242aa240bbcf2f92598604.tar.gz
PROJ-4abfe10ab7a64552db242aa240bbcf2f92598604.zip
init(): repair to_meter=num/denom that was broken in the general case in PROJ 5; repair vto_meter=num/denom that was broken, and avoid division by zero, which fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12869. Credit to OSS Fuzz
-rw-r--r--src/init.cpp35
-rw-r--r--test/gie/4D-API_cs2cs-style.gie8
-rw-r--r--test/gie/more_builtins.gie8
3 files changed, 36 insertions, 15 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 482e398d..2961bcca 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -764,20 +764,18 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
s = units[i].to_meter;
}
if (s || (s = pj_param(ctx, start, "sto_meter").s)) {
- double factor;
- int ratio = 0;
-
- /* ratio number? */
- if (strlen (s) > 1 && s[0] == '1' && s[1]=='/') {
- ratio = 1;
- s += 2;
+ char* end_ptr = const_cast<char*>(s);
+ PIN->to_meter = pj_strtod(s, &end_ptr);
+ s = end_ptr;
+ if (*s == '/') { /* ratio number */
+ ++s;
+ double denom = pj_strtod(s, nullptr);
+ if (denom == 0.0)
+ return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
+ PIN->to_meter /= denom;
}
-
- factor = pj_strtod(s, nullptr);
- if ((factor <= 0.0) || (1/factor==0))
+ if (PIN->to_meter <= 0.0)
return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
-
- PIN->to_meter = ratio? 1 / factor: factor;
PIN->fr_meter = 1 / PIN->to_meter;
} else
@@ -792,9 +790,16 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
s = units[i].to_meter;
}
if (s || (s = pj_param(ctx, start, "svto_meter").s)) {
- PIN->vto_meter = pj_strtod(s, nullptr);
- if (*s == '/') /* ratio number */
- PIN->vto_meter /= pj_strtod(++s, nullptr);
+ char* end_ptr = const_cast<char*>(s);
+ PIN->vto_meter = pj_strtod(s, &end_ptr);
+ s = end_ptr;
+ if (*s == '/') { /* ratio number */
+ ++s;
+ double denom = pj_strtod(s, nullptr);
+ if (denom == 0.0)
+ return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
+ PIN->vto_meter /= denom;
+ }
if (PIN->vto_meter <= 0.0)
return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
PIN->vfr_meter = 1. / PIN->vto_meter;
diff --git a/test/gie/4D-API_cs2cs-style.gie b/test/gie/4D-API_cs2cs-style.gie
index f66b26ec..215971a0 100644
--- a/test/gie/4D-API_cs2cs-style.gie
+++ b/test/gie/4D-API_cs2cs-style.gie
@@ -348,6 +348,14 @@ accept 0 0 1000
expect 0 0 1
roundtrip 1
+operation +proj=longlat +a=1 +b=1 +vto_meter=2000/2
+accept 0 0 1000
+expect 0 0 1
+roundtrip 1
+
+operation +proj=longlat +a=1 +b=1 +vto_meter=1/0
+expect failure errno unit_factor_less_than_0
+
operation +proj=longlat +a=1 +b=1 +vto_meter=1000 +geoc
accept 0 0 1000
expect 0 0 1
diff --git a/test/gie/more_builtins.gie b/test/gie/more_builtins.gie
index 44d01385..d1c978a3 100644
--- a/test/gie/more_builtins.gie
+++ b/test/gie/more_builtins.gie
@@ -496,6 +496,14 @@ expect failure errno unit_factor_less_than_0
operation proj=utm ellps=GRS80 zone=32 to_meter=10
accept 12 55
expect 69187.5632 609890.7825
+
+operation proj=utm ellps=GRS80 zone=32 to_meter=1/0
+expect failure errno unit_factor_less_than_0
+
+operation proj=utm ellps=GRS80 zone=32 to_meter=2.0/0.2
+accept 12 55
+expect 69187.5632 609890.7825
+
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------