There are no Safe Functions – only Safe Programming
The Platform SDK includes a set of string manipulation functions defined in strsafe.h. These functions were added during the Windows Security push. The functions offer an alternative to the C run-time string functions which is more consistent, and less error-prone than the C standard functions.
But in order for the functions to actually be safe, they still must be used correctly. Wrongly used these functions are as unsafe as the old C runtime functions.
In order to use the functions safely the following must be true:
- The first parameter is a pointer to a memory buffer,
- The second parameter is the size of the buffer in bytes if when the function name begins with StringCb. The second parameter is the size of the buffer in chars if when function name begins with StringCch
- The return code of the function is checked for errors
So when I see something like:
StringCbCopy(Foo, 2, “\\“);
It immediately raises a red flag for me. Unless 2 happens to be the number of bytes in Foo, this is not a safe use of the function! The second parameter here is not the number of bytes remaining in the buffer but rather the number of bytes needed from the second string. Usually, code like this is the results of someone who just converted the code from strncpy to StringCbCopy without making the necessary changes to actually benefit from the new API.
Now consider the following code:
char FileName[MAX_PATH];
…
StringCbCopy(FileName, MAX_PATH, DirectoryName);
Is this usage a safe use of the function?
Only if you will never try to convert the file name and directory name to wide char. Although for a char, count of chars and count of bytes have the same numeric value, in this case MAX_PATH is a count of chars so either of the following would be better:
// Use Count of Chars
StringCChCopy(FileName, MAX_PATH, DirectoryName);
// Use a count of bytes
StringCbCopy(FileName, sizeof(FileName), DirectoryName);
Each of the String APIs supports an Ex version that has output parameters returning a pointer to the terminating null at the end of the target string, and the remaining chars/bytes in the buffer. The Ex versions provide an alternative to doing the pointer arithmetic yourself which is error prone and dangerous.
Program safely.
[edited 8-13-04]
Comments
- Anonymous
July 20, 2004
The comment has been removed - Anonymous
July 20, 2004
Niclas,
The strsafe.h functions exist for exactly the reason you mentioned, they treat strings consistently. As you noted, the standard libc implementations all have their own quirks (not always null terminating strings is one of the worst, IMHO) and not all of them fail in useful ways. Personally, I think one of the best ways to approach "Safe Programming" is to have consistent APIs.
Before the strsafe.h header existed, I had wrapped the string functions I needed in much the same way. I immediately switched to strsafe.h because I knew someone else had done all the testing for me. That alone was a huge win. - Anonymous
August 01, 2004
As I'm sure MS has figured out, the core C language's string manipulation capabilities are woefully inadequate which is why strsafe.h was created. While I applaud Microsoft's effort wrt its security push, I believe strsafe.h is an imperfect solution to the problem.
The real problem with string manipulation in C is the buffer management itself. I think its too much to ask to hope that by changing the buffer management problem from one way to another way while still keeping it in the hands of the programmer is going to appreciably aid in mitigation of the buffer management problem. The only correct answer has to be to solve the problem for the programmer.
Microsoft's CString class, for example is far superior because it handles all buffer management automatically and because its thread safe. Though, of course, it requires the programmer move to C++ and does nothing to deprecate the older unsafe C library functions.
I have created yet another string library alternative for C (and C++), that I believe better solves the string manipulation safety problem for C than strsafe.h. I call it the Better String Library (or just bstrlib) and it can be found here: http://bstring.sf.net/
The main points of this library is that it totally abstracts away the buffer manipulation (much like CString) while remaining interoperable with C and CLib semantics. Like strsafe.h, all strings are '�' terminated automatically, however the length is also stored seperately which improves safety and speed at the same time. Deprecation of the old C string functions is facilitated by the optional bsafe module which simply overrides the worst offenders of the older C library with run time bailouts.
bstrlib also has lots of nice bonuses like automatic alias detection (and acceleration!), intial declaration macros and parameter integrity checking which also contribute to the overall safety.
So I am not sure I can agree with the premise that there are no "safe functions", since I would contend that bstrlib provides something at least close to this ideal -- or at least somewhat closer than strsafe.h . I would certainly like to encourage our friends at Microsoft (or anyone else) to do a more detailed analysis of bstrlib and its safety features. - Anonymous
August 12, 2004
>2) The second parameter is the number of remaining bytes if when the function name begins with StringCb. The second parameter is the number of remaining chars if when function name begins with StringCch
Remaining chars? Have I been using the functions wrong? The MSDN docs for StringCChCat say:
cchDest
[in] Size of the destination buffer, in characters. This value must equal the length of pszSrc plus the length of pszDest plus 1 to account for both strings and the terminating null character. The maximum number of characters allowed is STRSAFE_MAX_CCH.
This seems to say the TOTAL length of the buffer, not the REMAINING length.
I guess my question is, is the following safe?
char path[MAX_PATH];
StringCchCopy(path,MAX_PATH,root);
StringCchCat(path,MAX_PATH,dir1);
StringCchCat(path,MAX_PATH,folder);
(Obviously I should really be checking for success...)
or do I need to keep updating the second parameter to be the bytes characters remaining in the buffer?
If this is illegal, I'll agree that the functions are not as 'safe' as they appear. If it is OK, I think they come pretty close. - Anonymous
August 13, 2004
Yes, the number is the size of the buffer.