Buffer overflow protection

Buffer overflow protection

Post by Howar » Wed, 14 Apr 2004 20:24:08


I'm puzzled. Is it even *possible* for s.size() to have a value greater
than s.max_size()? That would seem to violate the concept of "max",
wouldn't it? So, shouldn't the streaming operator prevent s.size() from
ever exceeding s.max_size() in the first place, making any such check on
your part redundant?

I know that checking for buffer overruns is important when filling arrays,
but I would think one of the advantages of using a string class and
streaming operators is to protect against such things.

But for filling arrays, I'd agree on your design, where you add one
character at a time. It's silly to try to see if you've *already* overrun
memory.

-Howard
 
 
 

Buffer overflow protection

Post by Ioannis Vr » Wed, 14 Apr 2004 20:59:35

If we want our programs to be protected against buffer overflows, must we
check the size of the various containers explicitly?

E.g.

#include <iostream>
#include <string>


int main()
{
using namespace std;

string s;

while(cin>>s)
;

// ...
}


should become:


#include <iostream>
#include <string>
#include <cctype>


int main()
{
using namespace std;

string s;

while(cin && s.size()<s.max_size())
{
char c;

cin>>c;

if(isspace(c))
continue;

s.push_back(c);
}



// ...
}






Ioannis Vranos

 
 
 

Buffer overflow protection

Post by Ioannis Vr » Wed, 14 Apr 2004 21:09:13


string s, temp;


while(cin>>temp)
s+=temp;
 
 
 

Buffer overflow protection

Post by David Harm » Thu, 15 Apr 2004 04:20:04

On Tue, 13 Apr 2004 14:59:35 +0300 in comp.lang.c++, "Ioannis Vranos"
< XXXX@XXXXX.COM > wrote,

You need to ensure that the sizes are checked.
How explicit it is, is another matter.


Here std::string and its operator>> do the checking.
So, it does not need to be explicit.
 
 
 

Buffer overflow protection

Post by Kevin Good » Thu, 15 Apr 2004 04:24:53


I believe so. I was unable to find exact details, but I'm fairly sure
that attempting to exceed a container's max_size will fail for one
reason or another. I suspect it will fail due to memory exhaustion
before you get to that point, and if that doesn't occur it will probably
throw an exception. The standard definitely says that an exception will
be thrown in a few cases (like calling reserve() for a vector where the
new capacity is too large, if I recall correctly).


I think the container (or string) itself will prevent it.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
 
 

Buffer overflow protection

Post by Kevin Good » Thu, 15 Apr 2004 04:53:18


The library is responsible for managing the buffers and preventing their
overflowing. I generally assume memory exhaustion will occur before
anything else. If max_size() is reached first, I'm not 100% sure what
should happen. My guess is that an exception will be thrown, either
length_error or bad_alloc. In effect, exceeding max_size() means
exhausting the memory of the allocator I think, so bad_alloc might be
appropriate, though I suppose I should check the standard and see how
allocators are supposed to handle running out of memory.

From a security standpoint, if we assume that an overflow of this sort
could exist, it seems likely that an attack exploiting such an overflow
would have much less chance of succeeding than a traditional
fixed-buffer-length overflow attack. max_size() is probably up around 2
or 4 billion. That's a hell of a lot of data to dump into the program.
If it were a remote attack, it would take quite a while to transfer all
that (over 3 minutes on a 10 Mbps connection?), and I imagine a IDS
(which I know nothing about) would have a very good chance of detecting
that.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
 
 

Buffer overflow protection

Post by Ioannis Vr » Thu, 15 Apr 2004 05:20:09


This can't happen on all modern systems using virtual memory (swap) file. If
one has 10 GB swap file my guess is that max_size() can be reached. I am too
bored to check the standard but if noone provides an answer i shall be
forced to do so, since i can't live for long with such a question.




Buffer overflow attacks happen all the time. However i am not checking about
protection against attacks here. This is a general reliability question. If
there is no such a check implicitly in standard library containers, the
whole scenario will defeat the abstraction mechanism of the standard library
and i do not think this can happen anyway. In 15 minutes or so i 'll check
the standard and drop a message here.






Ioannis Vranos
 
 
 

Buffer overflow protection

Post by Kevin Good » Thu, 15 Apr 2004 05:34:34


I found this in the unofficial list of C++2003 changes:

Insert subclause 21.3, paragraph 4a:

4a For any string operation, if as a result of the operation,
size() would exceed max_size() then the operation throws
length_error.


Strangely, I couldn't find anything similar for other containers.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
 
 

Buffer overflow protection

Post by Kevin Good » Thu, 15 Apr 2004 05:36:51


This document, by the way, came from Stroustrup's web page if I recall
correctly. If it's not there, then maybe it was Koenig's page.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
 
 

Buffer overflow protection

Post by Ioannis Vr » Thu, 15 Apr 2004 05:38:03


file. If
too


Can you provide the URL please? And what is C++2003? I assume C++0x as it
had so far?






Regards,

Ioannis Vranos
 
 
 

Buffer overflow protection

Post by Kevin Good » Thu, 15 Apr 2004 05:58:13


I think this is it:

http://www.yqcomputer.com/ ++std/revisions.pdf

C++2003 is an official update to the language that includes corrections
and clarifications, but no new features.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
 
 
 

Buffer overflow protection

Post by Ioannis Vr » Thu, 15 Apr 2004 06:04:59


From the C++98 standard:

<stdexcept>

19.1.4 Class length_error

namespace std {
class length_error : public logic_error {
public:
explicit length_error(const string& what_arg);
};
}

1 The class length_error defines the type of objects thrown as exceptions to
report an attempt to produce
an object whose length exceeds its maximum allowable size.
length_error(const string& what_arg);

2 Effects: Constructs an object of class length_error.

3 Postcondition: strcmp(what(), what_arg.c_str()) == 0.


...


21.3 Template class basic_string

3 In all cases, size() <= capacity().

4 The functions described in this clause can report two kinds of errors,
each associated with a distinct exception:
- a length error is associated with exceptions of type length_error
(19.1.4);
- an outofrange
error is associated with exceptions of type out_of_range (19.1.5).


[Elsewhere it mentions length error check in the constructors: "Throws:
length_error if n == npos". And in many other places. ]

...

vector throws it too: "Throws: length_error if n > max_size()."



basic_string (including string of course), and vector are the only standard
library containers that throw std::length_error exception.


Naturally i should not expect any such checks from classes of the kind
valarray. For classes like std::bitset i shall check some other time...






Regards,

Ioannis Vranos
 
 
 

Buffer overflow protection

Post by Ioannis Vr » Thu, 15 Apr 2004 06:14:23


Provided the length_error exception the reliability of the code can be
ensured:


#include <iostream>
#include <string>
#include <stdexcept>


int main()
{
using namespace std;

string s, temp;

try
{
while(cin>>temp)
s+=temp;
}

catch(length_error)
{
// ...
}

// ...
}


or

#include <iostream>
#include <string>
#include <stdexcept>


int main() try
{
using namespace std;

string s, temp;

while(cin>>temp)
s+=temp;

// ...
}

catch(std::length_error)
{
// ...
}






Ioannis Vranos
 
 
 

Buffer overflow protection

Post by tom_usene » Thu, 15 Apr 2004 19:11:42

On Tue, 13 Apr 2004 23:20:09 +0300, "Ioannis Vranos"





On a 32 bit system, you generally only have about 2GB of virtual
memory to play with - hitting this limit with modern software is a
real possibility. The size of the swap file and physical memory have
no bearing on this - it's an addressing problem that is solved only by
moving to 64-bit architecture, or coming up with another arcane
segmented pointer architecture like DOS's near and far pointers.

Tom
--
C++ FAQ: http://www.yqcomputer.com/ ++-faq-lite/
C FAQ: http://www.yqcomputer.com/ ~scs/C-faq/top.html