Skip to content

Stream corruption when reading from forward-iterator range exceeding stream buffer size #191

Description

@michaeldonovan

It would appear that when an istream reads from a forward iterator range (e.g. boost::adaptors::transformed) larger than the stream's internal buffer, a garbage byte gets inserted at the stream's buffer boundary.

Reproducer

#include <iostream>
#include <iomanip>
#include <string>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/iterator_range.hpp>

int main() {
    std::vector<int> input(5000, 0x41);
    auto transformed = input | boost::adaptors::transformed([](int c) { return static_cast<char>(c); });

    boost::iostreams::filtering_istream in(boost::make_iterator_range(transformed));
    std::string output(std::istreambuf_iterator<char>(in), {});

    std::cout << "Input size: " << input.size() << ", output size: " << output.size() << "\n";
    for (size_t i = 0; i < std::max(input.size(), output.size()); ++i) {
        if (input[i] != output[i]) {
            std::cout << "First mismatch at [" << i << "]";
            std::cout << " expected 0x"
                        << std::hex << std::setw(2) << std::setfill('0') << input[i]
                        << ", got 0x"
                        << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(output[i]);
            break;
        }
    }
}

Output:

Input size: 5000, output size: 5001
First mismatch at [4096] expected 0x41, got 0x00

Cause

range_adapter_impl<std::forward_iterator_tag>::read post-decrements rem in the loop condition:

std::streamsize rem = n;
while (cur != last && rem-- > 0) *s++ = *cur++;
return n - rem != 0 ? n - rem : -1;

When exactly n chars have been read but cur != last , the loop evaluates cur != last → true, then rem-- > 00 > 0 is false so the loop exits, but rem is now -1. The function returns n + 1, overrunning the buffer.

range_adapter_impl<std::forward_iterator_tag>::write appears to have the same issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions