tcbrindle / flux

A C++20 library for sequence-orientated programming
https://tristanbrindle.com/flux/
Boost Software License 1.0
484 stars 29 forks source link

Attempted out-of-bounds read in flatten() #150

Closed tcbrindle closed 8 months ago

tcbrindle commented 8 months ago
int main() {
    const std::vector<std::string> vec{"a", "b", "c"};

    auto str = flux::ref(vec).flatten().to<std::string>(); // Error, out-of-bounds access
}

Gives:

/opt/compiler-explorer/libs/flux/trunk/include/flux/core/default_impls.hpp:193: Fatal error: out-of-bounds sequence access
terminate called without an active exception
Program terminated with signal: SIGSEGV

https://flux.godbolt.org/z/Eo3e9vrPM

tcbrindle commented 8 months ago

In the multipass version of flatten_adaptor, we stop iterating when the outer cursor reaches the end of the outer sequence. However, when we get there, we don't reset the inner cursor, which is left pointing to wherever it previously pointed to. This means that a cursor which has iterated through to the end winds up not equal to the cursor returned from last() (which contains a default-constructed inner cursor).

This showed up when using to() because it uses (adapted) iterators which, of course, want to stop iterating when iter == last. Since that equality never happened, we end up trying to read past the end. The good news is we got a bounds violation runtime error rather than UB -- the system works!

Anyway, the solution is to make sure we reset the inner cursor when we reach the end in multipass flatten_adaptor. PR incoming...