Skip to content

Commit a9467fb

Browse files
authored
Merge pull request OSGeo#3748 from rouault/fix_ossfuzz_57328
GeographicBoundingBox::intersection(): avoid infinite recursion and stack overflow on invalid bounding boxes
2 parents 641749e + 8409e8e commit a9467fb

File tree

6 files changed

+54
-14
lines changed

6 files changed

+54
-14
lines changed

src/iso19111/metadata.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,13 @@ GeographicBoundingBox::Private::intersection(const Private &otherExtent) const {
421421
return nullptr;
422422
}
423423

424+
// Bail out on longitudes not in [-180,180]. We could probably make
425+
// some sense of them, but this check at least avoid potential infinite
426+
// recursion.
427+
if (oW > 180 || oE < -180) {
428+
return nullptr;
429+
}
430+
424431
// Return larger of two parts of the multipolygon
425432
auto inter1 = intersection(Private(oW, oS, 180.0, oN));
426433
auto inter2 = intersection(Private(-180.0, oS, oE, oN));

test/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,8 @@ proj_add_gie_test("GIGS-5208" "gigs/5208.gie")
108108
add_subdirectory(cli)
109109
add_subdirectory(unit)
110110
add_subdirectory(benchmark)
111+
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/fuzzers")
112+
add_subdirectory(fuzzers)
113+
endif()
114+
115+

test/fuzzers/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
if(NOT WIN32)
2+
3+
add_compile_options(${PROJ_CXX_WARN_FLAGS})
4+
5+
add_executable(proj_crs_to_crs_fuzzer proj_crs_to_crs_fuzzer.cpp)
6+
target_compile_definitions(proj_crs_to_crs_fuzzer PRIVATE -DSTANDALONE)
7+
target_link_libraries(proj_crs_to_crs_fuzzer PRIVATE ${PROJ_LIBRARIES})
8+
endif()

test/fuzzers/README.TXT

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ and call scripts in this directory.
88
The list of issues is in:
99
https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj4
1010

11-
- Build standard_fuzzer in a standalone mode:
12-
13-
$ g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -fvisibility=hidden -DSTANDALONE ../../build/lib/libproj.a -lpthread -lsqlite3 -I../../src -I../../include
11+
- Build proj_crs_to_crs_fuzzer in a standalone mode with the
12+
-DBUILD_TESTING=ON CMake options
1413

1514
Run it:
16-
$ PROJ_DATA=../../data ./standard_fuzzer {file_generated_by_oss_fuzz}
15+
$ bin/proj_crs_to_crs_fuzzer {file_generated_by_oss_fuzz}
1716

1817
- Run locally OSS Fuzz:
1918
$ git clone https://github.com/google/oss-fuzz.git
@@ -24,8 +23,8 @@ https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj4
2423
Build fuzzers with the address sanitizer (could use undefined, etc...)
2524
$ python infra/helper.py build_fuzzers --sanitizer address $PROJECT_NAME
2625

27-
Test a particular fuzzer (replace standard_fuzzer by other fuzzers)
28-
$ python infra/helper.py run_fuzzer $PROJECT_NAME standard_fuzzer
26+
Test a particular fuzzer (replace proj_crs_to_crs_fuzzer by other fuzzers)
27+
$ python infra/helper.py run_fuzzer $PROJECT_NAME proj_crs_to_crs_fuzzer
2928

3029

3130
How to deal with issues reported in https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj4 ?

test/fuzzers/proj_crs_to_crs_fuzzer.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,12 @@ int main(int argc, char *argv[]) {
124124
fclose(f);
125125
exit(1);
126126
}
127-
fread(buf, nLen, 1, f);
127+
if (fread(buf, nLen, 1, f) != 1) {
128+
fprintf(stderr, "fread failed.\n");
129+
fclose(f);
130+
free(buf);
131+
exit(1);
132+
}
128133
fclose(f);
129134
nRet = LLVMFuzzerTestOneInput((const uint8_t *)(buf), nLen);
130135
free(buf);

test/unit/test_metadata.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,15 @@ TEST(metadata, extent_edge_cases) {
284284
optional<std::string>(), std::vector<GeographicExtentNNPtr>(),
285285
std::vector<VerticalExtentNNPtr>(), std::vector<TemporalExtentNNPtr>());
286286

287-
auto A = Extent::createFromBBOX(-180, -90, 180, 90);
288-
auto B = Extent::createFromBBOX(180, -90, 180, 90);
289-
EXPECT_FALSE(A->intersects(B));
290-
EXPECT_FALSE(B->intersects(A));
291-
EXPECT_FALSE(A->contains(B));
292-
EXPECT_TRUE(A->intersection(B) == nullptr);
293-
EXPECT_TRUE(B->intersection(A) == nullptr);
287+
{
288+
auto A = Extent::createFromBBOX(-180, -90, 180, 90);
289+
auto B = Extent::createFromBBOX(180, -90, 180, 90);
290+
EXPECT_FALSE(A->intersects(B));
291+
EXPECT_FALSE(B->intersects(A));
292+
EXPECT_FALSE(A->contains(B));
293+
EXPECT_TRUE(A->intersection(B) == nullptr);
294+
EXPECT_TRUE(B->intersection(A) == nullptr);
295+
}
294296

295297
EXPECT_THROW(Extent::createFromBBOX(
296298
std::numeric_limits<double>::quiet_NaN(), -90, 180, 90),
@@ -304,6 +306,20 @@ TEST(metadata, extent_edge_cases) {
304306
EXPECT_THROW(Extent::createFromBBOX(
305307
-180, -90, 180, std::numeric_limits<double>::quiet_NaN()),
306308
InvalidValueTypeException);
309+
310+
// Scenario of https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=57328
311+
{
312+
auto A = Extent::createFromBBOX(0, 1, 2, 3);
313+
auto B = Extent::createFromBBOX(200, -80, -100, 80);
314+
EXPECT_TRUE(A->intersection(B) == nullptr);
315+
EXPECT_TRUE(B->intersection(A) == nullptr);
316+
}
317+
{
318+
auto A = Extent::createFromBBOX(0, 1, 2, 3);
319+
auto B = Extent::createFromBBOX(100, -80, -200, 80);
320+
EXPECT_TRUE(A->intersection(B) == nullptr);
321+
EXPECT_TRUE(B->intersection(A) == nullptr);
322+
}
307323
}
308324

309325
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)