Skip to content

Commit 193ac44

Browse files
committed
Improved parsing of --bbox command line option
Without use of scanf.
1 parent 3ea6d93 commit 193ac44

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

src/command-line-parser.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
#include "util.hpp"
1919
#include "version.hpp"
2020

21+
#include <osmium/util/string.hpp>
2122
#include <osmium/version.hpp>
2223

2324
#include <CLI/CLI.hpp>
2425

2526
#include <lua.hpp>
2627

2728
#include <algorithm>
29+
#include <cmath>
2830
#include <cstdio>
2931
#include <cstring>
3032
#include <stdexcept>
@@ -33,21 +35,36 @@
3335

3436
namespace {
3537

36-
osmium::Box parse_bbox_param(std::string const &arg)
38+
void error_bbox()
39+
{
40+
throw std::runtime_error{"Bounding box must be specified like: "
41+
"minlon,minlat,maxlon,maxlat."};
42+
}
43+
44+
double parse_and_check_coordinate(std::string const &str)
3745
{
38-
double minx = NAN;
39-
double maxx = NAN;
40-
double miny = NAN;
41-
double maxy = NAN;
46+
char *end = nullptr;
47+
48+
double const value = std::strtod(str.c_str(), &end);
49+
if (end != &*str.end() || !std::isfinite(value)) {
50+
error_bbox();
51+
}
4252

43-
int const n =
44-
sscanf(arg.c_str(), "%lf,%lf,%lf,%lf", &minx, &miny, &maxx, &maxy);
53+
return value;
54+
}
4555

46-
if (n != 4) {
47-
throw std::runtime_error{"Bounding box must be specified like: "
48-
"minlon,minlat,maxlon,maxlat."};
56+
osmium::Box parse_bbox_param(std::string const &arg)
57+
{
58+
auto const values = osmium::split_string(arg, ',', true);
59+
if (values.size() != 4) {
60+
error_bbox();
4961
}
5062

63+
double const minx = parse_and_check_coordinate(values[0]);
64+
double const miny = parse_and_check_coordinate(values[1]);
65+
double const maxx = parse_and_check_coordinate(values[2]);
66+
double const maxy = parse_and_check_coordinate(values[3]);
67+
5168
if (maxx <= minx) {
5269
throw std::runtime_error{
5370
"Bounding box failed due to maxlon <= minlon."};
@@ -60,7 +77,12 @@ osmium::Box parse_bbox_param(std::string const &arg)
6077

6178
log_debug("Applying bounding box: {},{} to {},{}", minx, miny, maxx, maxy);
6279

63-
return osmium::Box{minx, miny, maxx, maxy};
80+
osmium::Box const box{minx, miny, maxx, maxy};
81+
if (!box.valid()) {
82+
error_bbox();
83+
}
84+
85+
return box;
6486
}
6587

6688
void parse_expire_tiles_param(char const *arg, uint32_t *expire_tiles_zoom_min,

tests/test-options-parse.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ TEST_CASE("Parsing bbox fails if wrong format", "[NoDB]")
8989
{
9090
bad_opt({"-b", "123"}, "Bounding box must be specified like:"
9191
" minlon,minlat,maxlon,maxlat.");
92+
93+
bad_opt({"-b", "1,2,3,4x"}, "Bounding box must be specified like:"
94+
" minlon,minlat,maxlon,maxlat.");
95+
96+
bad_opt({"-b", "1,,3,4"}, "Bounding box must be specified like:"
97+
" minlon,minlat,maxlon,maxlat.");
98+
99+
bad_opt({"-b", "1,2,3"}, "Bounding box must be specified like:"
100+
" minlon,minlat,maxlon,maxlat.");
101+
102+
bad_opt({"-b", "1,2,3,4,5"}, "Bounding box must be specified like:"
103+
" minlon,minlat,maxlon,maxlat.");
104+
105+
bad_opt({"-b", "1,2,INF,4"}, "Bounding box must be specified like:"
106+
" minlon,minlat,maxlon,maxlat.");
107+
108+
bad_opt({"-b", "1,NAN,3,4"}, "Bounding box must be specified like:"
109+
" minlon,minlat,maxlon,maxlat.");
92110
}
93111

94112
TEST_CASE("Parsing number-processes", "[NoDB]")

0 commit comments

Comments
 (0)