Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Safe APIs the Simpler Way

5.00/5 (5 votes)
11 Jun 2013CPOL3 min read 17.8K   82  
This tip explains how to use Safe APIs which are a replacement for older APIs like strcpy, strcat, etc.

Introduction

This tip explains a simpler way of using Safe APIs which helps in easy code migration to newer versions of Visual Studio (i.e., newer versions of VC Compiler).

Background

While using the APIs strcat, strcpy, etc., many a times, there are chances of application crash due to buffer overflow. Due to this, Microsoft has come up with a newer set of safe APIs StringCb* APIs. When it comes to code migration to newer versions of Visual Studio, we do get lot of warnings regarding usage of safe APIs. Most of the times, due to scarcity of time, we tend to live with the old code since it takes time to change the old code and migrate it to the newer APIs and even we are worried about the testing part of the same. Like when we get warning from the compiler for using strcat_s, we do ignore it most of the times and try to live with existing strcat. With this tip, it would be easier to make such changes to the code in a simple and efficient manner.

StringCbCopy

Let's start with StringCbCopy API, it has the following signature:

C++
HRESULT StringCbCopy(
  _Out_  LPTSTR pszDest,
  _In_   size_t cbDest,
  _In_   LPCTSTR pszSrc
);

Cb in StringCbCopy stands for "Count of bytes":

  • pszDest: The destination buffer, which receives the copied string
  • pszSrc: The source string
  • cbDest: This is the maximum length of bytes allowed for copying the data

Parameters pszDest and pszSrc remain the same as strcpy so we need to just concentrate on "cbDest" parameter.

Let's introduce a macro which will do the job for us:

C++
#ifdef _UNICODE
#define STRING_SIZE_IN_BYTES(x)  (_countof(x) * sizeof(WCHAR))
#else
#define STRING_SIZE_IN_BYTES(x)  (_countof(x) * sizeof(CHAR))
#endif 

Macro STRING_SIZE_IN_BYTES calculates the number of characters in the string array and then multiplies it by type of character and hence gets the complete size of the Array in Bytes.

Example

C++
WCHAR wszTemp[1024] = {0}
STRING_SIZE_IN_BYTES(wszTemp) 

will give the size as 1024 * 2 = 2048 bytes, so maximum of 2048 bytes can be copied to this array.

C++
CHAR szTemp[1024] = {0}
STRING_SIZE_IN_BYTES(szTemp)

will give the size as 1024 * 1 = 1024 bytes, so maximum of 1024 bytes can be copied to this array.

Now let's add the macro which will replace the operation of StringCbCopy.

C++
#define SafeStrCbCopy(x, y) StringCbCopy(x, STRING_SIZE_IN_BYTES(x), y)

Example

C++
SafeStrCbCopy(wszDest, wszSource);

This will do the job of safe copy for us.

StringCbCat

On similar lines, we can create Macro for StringCbCat API.

C++
#define SafeStrCbCat(x, y) StringCbCat(x, STRING_SIZE_IN_BYTES(x), y)

Example

C++
SafeStrCbCat(wszDest, wszSource);

StringCchCopy

On similar lines as StringCbCopy, let's check with StringCchCopy:

C++
HRESULT StringCchCopy(
  _Out_  LPTSTR pszDest,
  _In_   size_t cchDest,
  _In_   LPCTSTR pszSrc
);

The only difference is size_t cchDest which is the size of string in "Count of Characters" rather than "Count of Bytes". Let's define a similar macro for the same.

C++
#define STRING_SIZE_IN_CHARACTERS(x)  (_countof(x))

This will give the number of characters in the string irrespective of type of string, i.e., WCHAR or CHAR
macro to replace StrinCchCopy.

C++
#define SafeStrCchCopy(x, y) StringCchCopy(x, STRING_SIZE_IN_CHARACTERS(x), y)

Example

C++
SafeStrCchCopy(wszDest, wszSource);

StringCchCat

C++
#define SafeStrCchCat(x, y) StringCchCat(x, STRING_SIZE_IN_CHARACTERS(x), y)

Example

C++
SafeStrCchCat(wszDest, wszSource);

Limitations

One drawback with the above approach is that it cannot be used for pointer to strings, e.g.: char* pszString since, we are using _countof API call which works only on static arrays. For pointer to strings, different set of macros needs to be defined which will define the size of the array.

C++
#define MAX_BUFF_SIZE 1024 //Max size which the buffer can hold
#define SafeStrCbCopy(x, y) StringCbCopy(x, MAX_BUFF_SIZE, y)

Summary

Overall, now it should be easier to migrate the code to Safe APIs.

History

  • 2013-06-10: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)