🔒 Locked
Are STL strings bad for code security?
Advertisement
Original Post
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
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
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.
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.
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]
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++.
Quote:
Original post by dyerseve
Normal ASCII for the win.
Easy for you to say, being an american.
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.
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
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..).
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
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
Quote:
Original post by Vexorian
well char arrays are faster than basic_stringthat's for sure...
Not it isn't. In fact, there's a reasonably good chance they are actually slower.
CM
Quote:
Original post by Vexorian
well char arrays are faster than basic_stringthat'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.
Advertisement