From d438adb7017a1ffb95ed10e6d5977664ea5b12ed Mon Sep 17 00:00:00 2001 From: Benson Joeris Date: Wed, 13 Feb 2019 11:16:04 -0500 Subject: [PATCH] Fix bug in `Intervals::update` When `Intervals::update` was called with `finish=UINT64_MAX`, the loop condition `i->start() < finish` would remain true for every interval, until `i` went past the last interval, at which point `i->start()` (and all the other accesses to `i` within the loop) have undefined behaviuor. --- renderdoc/core/intervals.h | 2 +- renderdoc/core/intervals_tests.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/renderdoc/core/intervals.h b/renderdoc/core/intervals.h index 77f7ebcd4..f1cc17283 100644 --- a/renderdoc/core/intervals.h +++ b/renderdoc/core/intervals.h @@ -222,7 +222,7 @@ public: i->split(start); // Loop over all the intervals in `a` that intersect the interval [start, finish) - for(; i->start() < finish; i++) + for(; i != end() && i->start() < finish; i++) { if(i->finish() > finish) { diff --git a/renderdoc/core/intervals_tests.cpp b/renderdoc/core/intervals_tests.cpp index 7ab42e617..a12bc8960 100644 --- a/renderdoc/core/intervals_tests.cpp +++ b/renderdoc/core/intervals_tests.cpp @@ -244,6 +244,27 @@ TEST_CASE("Test Intervals type", "[intervals]") test.update(7, 20, 1, [](uint64_t, uint64_t) -> uint64_t { return 1; }); check_intervals(test, {{0, 0, 5}, {5, 1, 30}, {30, 0, UINT64_MAX}}); }; + + SECTION("update a interval starting at 0") + { + Intervals test = make_intervals({{0, 0, 5}, {5, 1, 10}, {10, 0, UINT64_MAX}}); + test.update(0, 10, 1, [](uint64_t x, uint64_t y) -> uint64_t { return x + y; }); + check_intervals(test, {{0, 1, 5}, {5, 2, 10}, {10, 0, UINT64_MAX}}); + }; + + SECTION("update a interval finishing at UINT64_MAX") + { + Intervals test = make_intervals({{0, 0, 5}, {5, 1, 10}, {10, 0, UINT64_MAX}}); + test.update(5, UINT64_MAX, 1, [](uint64_t x, uint64_t y) -> uint64_t { return x + y; }); + check_intervals(test, {{0, 0, 5}, {5, 2, 10}, {10, 1, UINT64_MAX}}); + }; + + SECTION("update entire range") + { + Intervals test = make_intervals({{0, 0, 5}, {5, 1, 10}, {10, 0, UINT64_MAX}}); + test.update(0, UINT64_MAX, 1, [](uint64_t x, uint64_t y) -> uint64_t { return x + y; }); + check_intervals(test, {{0, 1, 5}, {5, 2, 10}, {10, 1, UINT64_MAX}}); + }; }; SECTION("mergeIntervals tests")