Source: Strsafe.h:safer String Handling in C Michael Howard compilation: Wangling
During the Microsoft Windows Security Push Campaign at Microsoft, a group of testers, program management managers, and common programmers decided to tailor a set of high-security string-handling functions to the C language, and wanted these functions to be made available to Windows Used by programmers and programmers within Microsoft Corporation.
Simply put, the existing C-language runtime functions are difficult to stand in today's context of malicious attack attempts. These functions either lack consistency on the return values and parameters, either imply a so-called "truncation Error" (Truncation errors) error, or do not provide powerful enough functionality. Frankly, the code that calls these functions is too prone to "memory overflow" problems.
We found that classes for C + + programmers were sufficient to handle the programming needs of various security processing strings, and they were able to choose MFC's CString class, ATL's CComBSTR class, or STL's string class, and so on. However, the classic C language program is still ubiquitous, not to mention that many people are using C + + as an "improved C-language", but have put a rich C + + class on the shelf.
In fact, just add one line of code and you'll be able to invoke the Safe Strsafe series function in your C code, for more information, see:
Using the Strsafe.h Functions These new functions are included in a header file and a library of functions (optional), which can be found in the new version of the Platform SDK. Yes, it's that simple:
#include "strsafe.h"
What are you waiting for?
Again, a reference to the Strsafe function library is optional.
In order to achieve the goal of the Strsafe series function, your code must meet the following criteria:
- Always ends a string with a NULL character.
- The length of the target buffer is always detected.
- Always produce a uniform return value with an HRESULT statement.
- Both 32-bit and 64-bit operating environments.
- With flexibility.
We feel that lack of uniformity is the root cause of many existing C-language string processing functions that are prone to security vulnerabilities, and the high degree of uniformity brought about by the Strsafe series of functions is just a medicine to solve this problem. However, Strsafe is not a panacea. Simply relying on the Strsafe series function does not guarantee the security and robustness of your code-you must also start your brain-but it will help to solve the problem!
Here is a code that uses the classic C language runtime function:
void Unsafefunc (LPTSTR szpath,dword cchpath) {TCHAR Szcwd[max_path]; GetCurrentDirectory (ARRAYSIZE (SZCWD), szcwd); strncpy (szpath, SZCWD, cchpath); Strncat (szpath, TEXT ("\"), cchpath); Strncat (szpath, TEXT ("Desktop.ini"), cchpath);}
The bugs in the above code are ubiquitous-it doesn't check for any of the return values, and Cchpath is not used correctly in calls to the Strncat function (because MAX_PATH holds the length of the remaining space in the target buffer, not the total length of the target buffer). As a result, the "memory overflow" problem will quickly come to the door. However, code snippets like this have already been overrun. If you use the Strsafe series function instead, the above code should become:
BOOL Saferfunc (LPTSTR Szpath,dword cchpath) {TCHAR szcwd[max_path];if (getcurrentdirectory (ARRAYSIZE), SZCWD) &&succeeded (StringCchCopy (szpath, Cchpath, SZCWD)) &&succeeded (StringCchCat (SzPath, CchPath, TEXT (" \ "))) &&succeeded (StringCchCat (szpath, Cchpath, TEXT (" Desktop.ini ")))) {return true;} return false;}
This code not only checks each return value, but also guarantees the total length of time to pass in the same target buffer. You can also use the Ex version of the Strsafe series functions to achieve more advanced functionality, such as:
- Gets the current pointer to the target buffer.
- Gets the remaining space length of the target buffer.
- Fills the free buffer with a specific character.
- Once the string handler fails, the string is populated with a specific value.
- Once the string processing function fails, the target buffer is set to NULL.
What about the performance of this improved code? Let me tell you the good news: it has almost no performance difference from the original code. I have tested the code of the various string connection functions in the classic C language on my 1.8 GHz computer, the code for mixing the various string connection functions in the Strsafe series, and the various string connection functions in the mixed Ex version Strsafe series. They run independently of each other 1 million times (yes, 10,000,000 times) and consume the time:
- Classic C Language--7.3 sec
- Strsafe Series--8.3 sec
- Strsafe Series (Ex version)--11.1 sec
In the test, the program that calls the Ex version of the Strsafe series function sets the buffer to NULL when the call fails and fills the byte with 0xFE as follows:
DWORD dwFlags = Strsafe_null_on_failure | Strsafe_fill_byte (0xFE);
The code that sets the padding bytes takes more time. In fact, if you just set the buffer to NULL, the code for the Ex version of the Strsafe series function will be the same as the code that takes the normal Strsafe series functions.
Thus, the performance difference of the above three kinds of schemes is very small. I'm sure you're not going to do it. Millions of times in a program repeatedly execute code that contains a lot of string processing functions!
It is also worth noting that when you refer to the Strsafe series functions, the original C-language string processing functions are automatically #undef processed. This is fine, because the error message during debugging will tell you which functions have been replaced by the corresponding Strsafe series functions. Well, please feel free to use strsafe.h! For more information, see Using the Strsafe.h Functions.
Strsafe.h: More secure C-language string handling functions