milleniumbug
milleniumbug

Reputation: 15834

Are C++ strings and streams buffer overflow safe?

If I use std::cin, std::cout and std::string, is there any possibility that someone will exploit the buffer overflow?

I ask this because I still see a lot of people that still use null-terminated strings instead of standard containers in C++.

Upvotes: 10

Views: 6850

Answers (4)

sehe
sehe

Reputation: 393934

It depends. Of course, when you use C-style code/API's, there is no difference.

But using STL or C++ idioms doesn't guarantee that you're safe.

C++ gives you the choice, always. Contrast these two near-identical twins:

int n;
std::cin >> n;
std::string s(n, '*'); // create a data store of given size

std::vector<char> v(1000);
std::copy(s.begin(), s.end(), v.begin()); // NOT safe if n > 1000

safe variant:

int n;
std::cin >> n;
if (n > MAX_LIMIT) 
    throw std::runtime_error("input too large");
std::string s(std::min(0, n), '*'); // note input sanitation

std::vector<char> v;
v.reserve(1000);
std::copy(s.begin(), s.end(), std::back_inserter(v)); // safe

Upvotes: 4

cHao
cHao

Reputation: 86585

One of the big reasons you still see people using C-strings in C++ (besides not knowing about strings, or being stuck in a C mindset), is that std::istream::getline works with char pointers and not strings. As do a huge number of other parts of the library. Part of the reason for that was so that "you don't pay for what you don't use". IE: people that just want to get a line of text shouldn't have to instantiate a string (thereby also having to pull in another template class) to do so. You can use std::getline to get lines as strings if you want them, but that's not obvious. So some people think they still need to use char buffers to get a line of text.

(Seems a lot of that is changed in C++11, and you can use strings in a lot of places where you had to pass a char* before. Maybe that'll help a bit with the C-in-C++ problem.)

Standard strings and streams are designed to be overflow-resistant, and are all-around safer than a char pointer (at least when they're not used like a plain old array/pointer; blindly using str's iterator without regard for str.end() is usually a bad idea, but str.push_back(), str += "text", str.at(x), and stream insertion/extraction operators are perfectly safe). If you can use them, i highly recommend you do so.

Upvotes: 14

Yola
Yola

Reputation: 19093

C-strings may be faster, because std containers have to support some functionality that they support. So, nobody can point the best choice for all times.

Upvotes: 1

Alok Save
Alok Save

Reputation: 206646

Still lot of people use null-terminated strings because they do not realize the convenience of using std::string and they are really writing procedural c++ not c++.

Most programmers migrating/migrated from c to c++ are the ones who still use null-terminated strings.

It is perfectly safe and you should use std::string in c++ wherever you can.

std:string actually protects you against buffer overflow(unlike c strings) by dynamically growing in size as the data added to it is increased.

An code sample:

#include <iostream>
using namespace std;

int main()
{
    string str("std::String");
    for (int i=0; i<20; ++i)
    {
        cout << "capacity is " << str.capacity() << endl;
        str += " ,is Overrun safe string";
    }
    return 0;
}

Output:

capacity is 11
capacity is 35
capacity is 70
capacity is 140
capacity is 140
capacity is 140
capacity is 280
capacity is 280
capacity is 280
capacity is 280
capacity is 280
capacity is 280
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560
capacity is 560

Upvotes: 12

Related Questions