Skip to main content
gamedev.net
🔒 Locked

Are STL strings bad for code security?

Started by jollyjeffers Oct 27, 2005 at 1:59 PM 13 replies 2k views
Original Post
jollyjeffers
jollyjeffers
By code security I mean things like buffer-overrun/underrun and other tricks to exploit "holes" in software [smile] Anyway, I use a lot of std::wstring and std::wostringstream in my code, but I recently handed it over to MS and they replaced every single instance of these with various WCHAR related functions. Basically got rid of all STL strings. Now, I can understand what they're doing there... but I'm not sure of the fundamental problem/reason: 1. Is STL, by design, unsecure in the specification of strings (and related operations)? 2. Is it nothing to do with design, but a risk based on the "unknown black-box" nature of the various STL implementations? I just read the thread further down the forum on c-strings vs stl-strings which makes me think it's #2 rather than #1... Any thoughts from the more knowledgeable STL guru's? [smile] Cheers, Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
jollyjeffers
jollyjeffers
Quote:
Original post by Anonymous Poster
I think it's possibly because the wide character things are somewhat ambiguous. They rely alot on locales, which are often poorly implemented.

Interesting.. I hadn't thought about that aspect.

Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
jdhardy
jdhardy
Wide character strings in general are poorly understood (at least by me). Character encodings, code pages...ugh.

As for security, std::basic_string should be immune to buffer overruns and underruns if implemented properly. That is the *point* of the template, after all.

C++ doesn't have the best internationalization story, so I wouldn't be surprised if MS developers used Windows' i18n facilities instead. I don't know if they're better or worse, but familiarity counts for a lot.
load_bitmap_file
load_bitmap_file
I most certainly am not a knowledgeable STL guru, but maybe Microsoft simply wanted your code to conform with the rest of their established coding style? Like how they still use TRUE/FALSE instead of true/false? Or (I don't know what you were writing) they wanted it to be able to be used with C as well? I'm no expert but I doubt the STL is particularly bad for security. [wink]
Arild Fines
Arild Fines
Quote:
Original post by jdhardy
Wide character strings in general are poorly understood (at least by me). Character encodings, code pages...ugh.

I blame C++.

--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
dyerseve
dyerseve
I think you can do unicode strings with stl and localizations.

Then again I wouldn't know. Normal ASCII for the win.
Arild Fines
Arild Fines
Quote:
Original post by dyerseve
Normal ASCII for the win.

Easy for you to say, being an american.

--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
MaulingMonkey
MaulingMonkey
Quote:
Original post by jollyjeffers
By code security I mean things like buffer-overrun/underrun and other tricks to exploit "holes" in software [smile]


You can create buffer overflows using std::string, but you can prevent them just as well. What are they replacing them with? They're definately better than C-style strings...

...for example, I can be confident these won't read past the end:

//where string is a std::string or reference tofor ( std::string::iterator i = string.begin() ; i != string.end() ; ++i ) {    //use i...}for ( size_t i = 0 ; i < string.size() ; ++i ){    //use string...}


This is because std::string mantains a few invariants which ensure the end iterator is properly mantained and that the string is allways really size() elements. I cannot say the same for these examples:

//where string is a (const char *) and string_size is a (std::size_t)for ( size_t i = 0 ; i < string_size ; ++i ) {    //use string...}


This is because no piece of code is mantaining the invariant that string_size really is string's size. I can easly crash this past piece of code by providing "foo" for string and 1284784937534 for string_size. In the former two pieces, however, I'm much more challanged - I must somehow overwrite the std::string structure with invalid data. To do this I need to do nasty casts (reinterpert_cast) or have a buffer overflow somewhere else in my program get "lucky".

Plus, std::string has a mechanism for being flexible yet careful at the expense of some speed:

for ( size_t i = 0 ; i < _____ ; ++i ) {    //use string.at( ___ )...}


When using at(), I can be assured that worst case scenario a std::out_of_range exception will be thrown.
markr
markr
Quote:
Original post by jollyjeffers
By code security I mean things like buffer-overrun/underrun and other tricks to exploit "holes" in software [smile]


If used correctly, they cannot overrun. The buffers are automatically maintained.

The main security problems come from the fact that to pass them to a lot of library functions, they must be converted to C-strings using .c_str()

STL strings can contain null characters (both wide and normal), whereas null-terminated strings cannot, by definition.

Historically this has meant that an app using "proper" strings, passing strings into a library function, can have them truncated at the place of an attacker's choosing, sometimes introducing a vulnerability.

At one point, it was possible to download the source code of certain executable pages from web servers with

http://vulnerableserver.example.com/secretcode.aspnul byte.txt

Or similar.

Mark
jollyjeffers
jollyjeffers
Thanks for the replies everyone (Have some ratings++) - my apologies for the slow reply, I've been a little busy lately [smile]

Definitely some interesting information - I've been vaguely aware of the security issues surrounding strings from the outside world, but never paid much attention to the actual details.

Basically they replaced everything with WCHAR arrays and StringCchPrintf() calls (etc..).

Quote:
maybe Microsoft simply wanted your code to conform with the rest of their established coding style?

From what I gather that is the primary reason. Fully understand it as well - I've done professional software development and had to make sure my code conformed to the coding standards laid down by the powers-that-be...

The security side of things was just based on a few bits and pieces I picked up - they didn't officially state that as the reason (they just 'tidied up' my code to remove some warnings from the VC8 compiler).

Thanks,
Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
Vexorian
Vexorian
well char arrays are faster than basic_string that's for sure (although just a little bit), perhaps they actually made the change for speed reasons?

[Edited by - Vexorian on October 28, 2005 8:05:16 PM]
------ XYE - A new edition of the classic Kye
Conner McCloud
Conner McCloud
Quote:
Original post by Vexorian
well char arrays are faster than basic_string that's for sure...

Not it isn't. In fact, there's a reasonably good chance they are actually slower.

CM
MaulingMonkey
MaulingMonkey
Quote:
Original post by Vexorian
well char arrays are faster than basic_string that's for sure

blatent lies

I believe this article covers some of the reasons why std::basic_string can actually be faster than char arrays in any situation that you're actually modifying strings:

http://www.joelonsoftware.com/articles/fog0000000319.html

If you're not modifying them (e.g. when you'd just be copying pointers in C), you should be using const references... in which case they'll still be faster! No O(N) complexity size() function. The ability to know the amount of buffer required to store a copy for modification is instantly available, instead of requiring a count. It's faster. End of story.

[Edited by - MaulingMonkey on October 28, 2005 9:07:25 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.