Me myself and I
Me myself and I

Reputation: 4060

Why does my buffer take more bytes than allowed?

I set the buffer of my stringstream to a 5 byte buffer. Only when I call sputn it can read in more characters than I want. Why is this?

#include <iostream>
#include <sstream>

int main()
{
    std::stringstream ss;
    char buf[5];

    ss.rdbuf()->pubsetbuf(buf, sizeof buf);
    ss.rdbuf()->sputn("hello world", 12);

    std::cout << ss.rdbuf(); // prints "Hello world"
}

Upvotes: 0

Views: 417

Answers (3)

Jesse Good
Jesse Good

Reputation: 52365

First, note that pubsetbuf is implementation defined. On gcc it sets a new buffer, but for example on MSVC nothing happens (it calls the base class setbuf which does nothing).

Now, as mentioned here, sputn calls overflow (or achieves the effect of calling it by some other means):

If the put area becomes full (pptr() == epptr()), this function may call overflow(), or achieve the effect of calling overflow() by some other, unspecified, means.

Now according to the docs for overflow:

Ensures that there is space at the put area for at least one character by saving some initial subsequence of characters starting at pbase() to the output sequence and updating the pointers to the output area (if needed). If ch is not traits::eof() (i.e. traits::eq_int_type(c, traits::eof()) != true), it is either put to the output area or directly saved to the output sequence.

The function may update pptr, epptr and pback pointers to define the location to write more data. On failure, the function ensures that either pptr() == nullptr or pptr() == epptr.

Basically, what this means is that is may resize the buffer appropriately to fit more data, and with gcc this is exactly what is happening. Here is the actually code take from here:

const __size_type __opt_len = std::max(__size_type(2 * __capacity), __size_type(512));
const __size_type __len = std::min(__opt_len, __max_size);

As you can see it either doubles the capacity or sets it to a size of 512 until it hits the maximum size the string buffer can reach.

Upvotes: 5

Kristian Evensen
Kristian Evensen

Reputation: 1345

C/C++ does not do any explicit bounds checking, so overflowing memory is possible (and easy to do). If you run your code through a debugger like Valgrind, it will tell you that you are reading uninitialized memory.

Upvotes: 0

alexbuisson
alexbuisson

Reputation: 8469

Your buffer is still 5 bytes long and doesn't take more byte than allowed, but putting 12 bytes in will "just" perform a write out of boundary that can cause a lot of issue in software programming (crash, UB, data corruption...)

strlen may be use to check what you write against the buffer size before copying.

Upvotes: -1

Related Questions