diff --git a/CHANGELOG.md b/CHANGELOG.md index cc3f92b..ded0166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.32.9 + +* Limit tile detail to 30 and buffer size to 127 to prevent coordinate + delta overflow in vector tiles. + ## 1.32.8 * Better error message if the output tileset already exists diff --git a/main.cpp b/main.cpp index 6848854..56eb64c 100644 --- a/main.cpp +++ b/main.cpp @@ -2632,6 +2632,7 @@ int main(int argc, char **argv) { {"check-polygons", no_argument, &additional[A_DEBUG_POLYGON], 1}, {"no-polygon-splitting", no_argument, &prevent[P_POLYGON_SPLIT], 1}, {"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 1}, + {"help", no_argument, 0, '?'}, {0, 0, 0, 0}, }; @@ -2799,10 +2800,21 @@ int main(int argc, char **argv) { case 'd': full_detail = atoi_require(optarg, "Full detail"); + if (full_detail > 30) { + // So the maximum geometry delta of just under 2 tile extents + // is less than 2^31 + + fprintf(stderr, "%s: --full-detail can be at most 30\n", argv[0]); + exit(EXIT_FAILURE); + } break; case 'D': low_detail = atoi_require(optarg, "Low detail"); + if (low_detail > 30) { + fprintf(stderr, "%s: --low-detail can be at most 30\n", argv[0]); + exit(EXIT_FAILURE); + } break; case 'm': @@ -2886,6 +2898,14 @@ int main(int argc, char **argv) { case 'b': buffer = atoi_require(optarg, "Buffer"); + if (buffer > 127) { + // So the maximum geometry delta is under 2 tile extents, + // from less than half a tile beyond one side to less than + // half a tile beyond the other. + + fprintf(stderr, "%s: --buffer can be at most 127\n", argv[0]); + exit(EXIT_FAILURE); + } break; case 'f': @@ -2990,8 +3010,10 @@ int main(int argc, char **argv) { break; default: { + if (i != '?') { + fprintf(stderr, "Unknown option -%c\n", i); + } int width = 7 + strlen(argv[0]); - fprintf(stderr, "Unknown option -%c\n", i); fprintf(stderr, "Usage: %s [options] [file.json ...]", argv[0]); for (size_t lo = 0; long_options_orig[lo].name != NULL && strlen(long_options_orig[lo].name) > 0; lo++) { if (long_options_orig[lo].val == 0) { diff --git a/mvt.cpp b/mvt.cpp index b069302..27486f8 100644 --- a/mvt.cpp +++ b/mvt.cpp @@ -356,7 +356,7 @@ std::string mvt_tile::encode() { std::vector geometry; - int px = 0, py = 0; + long long px = 0, py = 0; int cmd_idx = -1; int cmd = -1; int length = 0; @@ -381,8 +381,13 @@ std::string mvt_tile::encode() { long long wwx = geom[g].x; long long wwy = geom[g].y; - int dx = wwx - px; - int dy = wwy - py; + long long dx = wwx - px; + long long dy = wwy - py; + + if (dx < INT_MIN || dx > INT_MAX || dy < INT_MIN || dy > INT_MAX) { + fprintf(stderr, "Internal error: Geometry delta is too big: %lld,%lld\n", dx, dy); + exit(EXIT_FAILURE); + } geometry.push_back(protozero::encode_zigzag32(dx)); geometry.push_back(protozero::encode_zigzag32(dy)); diff --git a/version.hpp b/version.hpp index 5ea5ce8..2154349 100644 --- a/version.hpp +++ b/version.hpp @@ -1,6 +1,6 @@ #ifndef VERSION_HPP #define VERSION_HPP -#define VERSION "v1.32.8" +#define VERSION "v1.32.9" #endif