Microsoft Visual Studio: Secure CRT Functions


Application Security Testing: An Integral Part of DevOps


Two programmers went to buy cigarettes. One buys them and goes "Dude, did you read this? Warning! Smoking causes lung cancer witch is fatal". Then the other one says "Yeah, forget the warning, just tell me the errors!"

When using Microsoft Visual Studio 2005 or newer, the compiler may give a bunch of annoying warnings saying something like: "warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details". CRT functions like strcpy are standard functions, so why the compiler complains? Well, it simply recommends using of more secure versions of CRT functions which have '_s' postfix (strcpy_s instead of strcpy, sprintf_s instead of sprintf and so on). So, at a first look nothing fatal happened and we can go ahead. However, simply ignoring the warnings is not a good practice and moreover someone may work in a company or project in which "zero warnings" is a must.

This article is about how to deal with C4996 warning, what secure CRT functions are and how to correctly use them. Further, let's call them "_s functions".

Can we get rid of C4996 warnings?

Especially when porting code written under an older Visual C++ version, we may want to get rid of C4996 warnings. The answer is: yes, we can like in case of other compiler warnings, by adding pragma warning directive in the source code.

#pragma warning(disable: 4996)

You may add pragma warning in each source file or, if the project uses precompiled header, adding only it in StdAfx.h is pretty enough.

Another and better way is to add _CRT_SECURE_NO_WARNINGS to preprocessor definitions, as suggested in the description of the warning. To find out how to add _CRT_SECURE_NO_WARNINGS, take a look in MSDN at /D (Preprocessor Definitions).

No warnings, no more headaches, and the boss is happy. However, please read further! One good way to avoid C4996 warnings is… by using _s functions.

Why using _s functions?

Here, I would like to quote from one of Michael Howard's articles:

Think about it for a moment. When were functions like strcpy and strcat invented? They were designed in happier times when the C language was first developed by Kernighan and Ritchie long ago, when threats were by no means as serious as they are today, and when networking wasn't as pervasive as it is today. Now don't get me wrong, you can write secure code with functions like strcpy. It's the data that's the culprit, after all. But functions like strcpy don't help you write secure code, and an error in such a function can be catastrophic. Of course, gets is just plain evil! 'Nuff said.

I heard C/C++ programmers saying: "I've never ever made a bug". That's pretty possible if they never ever made a line of code. Otherwise, I can't believe them. Nobody is perfect and everyone can do mistakes.
In the first side, standard C functions were designed for speed. For that reason, they do not perform run-time checking which is usually performed in other programming languages. A programmer must be carefully when use those functions and validate parameters in the own code in order to avoid troubles like buffer overrun, access violation, malicious attacks, and so on.

Well, _s functions do additional checking for you. Details about Security Enhancements in the CRT can be found in MSDN library.
I will give just a trivial example concerning null termination string problem. One can say "this is stupid, something like that can never happen". Wrong! In the real programming world, other ones even more stupid, much more insidious and having uglier effects, can be found.

Two strings walk into a bar. One of them says: "A beer, please!%@8Hj(^&9))%@!$%*" The other one says: "You'll have to excuse my friend, he is not zero-terminated."

May be a good programmers' joke, but in a C/C++ application, a not-zero terminated string is not so funny. Let's try translating it into code:

#define MAX_BUFFER 1000
void append_joke(char* buff, const char* psz)
   strcat(buff, psz); // classic

int main()
   char* joke = new char[MAX_BUFFER];
   memcpy(joke, "A beer, please!", strlen("A beer, please!"));
   append_joke(joke, "You'll have to excuse my friend…");
   delete []joke;
#ifdef _DEBUG
   return 0;

If the program doesn't crash (here because of heap corruption) we can't say that we are lucky. The result may be a bunch of garbage like in the above joke. But if we use strcat_s instead of strcat, a run-time checking against not properly null terminated string will be performed. Further we'll see what's happen in this case.

Do _s functions prevent program crashing?

Most of programmers dealing first time with _s functions think that program will never crash even they are doing mistakes. In other words, simply replacing standard CRT functions with more secure ones, prevents application crashing. That is not true. Let's modify append_joke function and replace strcat with "more secure" strcat_s.

void append_joke(char* buff, const char* psz)
   strcat_s(buff, MAX_BUFFER, psz); // more secure

Now, let's run again the program in debug mode. Oups!.. A "Debug Assertion Failed" message box is shown. If press "Ignore" button, another "fatal error" message is shown then program terminates. What happened? First, strcat_s function checks parameters validity. If one is invalid (in our example we have not null terminated string) and if the program runs in debug mode, a "debug assertion failed" message is shown. That's very good, because we have a chance to fix the mistake, first looking at assertion message (here is "String is not null terminated"), then pressing "Retry" and search the source of error in "Call Stack" window. That is not possible in case of using the "classic" function strcat.
Finally, an invalid parameter handler function is called and the process terminates. That's also good because, if something is really going bad, it's preferable to close the application instead of let it doing unpredictable things.

How to customize the _s functions behavior?

As stated above, when _s functions detect an invalid parameter, a message is shown then the application process terminates. However, someone may want to do something else before application exits or simply wants application to continue. Someone else may wonder why the _s functions return an error code as long as by default, if an invalid parameter is passed, the process is terminated. Well, the default invalid parameter handler function may be replaced with an application-defined one. For doing that, we can call _set_invalid_parameter_handler function.

Here is an example. It prevents showing the debug assertion failure message and sets an application-defined invalid parameter handler function. In case that invalid parameter is passed, the process isn't terminated. Also, the error code returned by strcat_s is used by program, which prints out the string only if it's Ok.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h> 

void app_handler(const wchar_t * expression,
                 const wchar_t * function, 
                 const wchar_t * file, 
                 unsigned int line,
                 uintptr_t pReserved)
             expression, function, file, line);

#define MAX_BUFFER 1000
errno_t finish_joke(char* buff, const char* psz)
   return strcat_s(buff, MAX_BUFFER, psz); 

int main()
   // prevent showing "debug assertion failed" dialog box
   _CrtSetReportMode(_CRT_ASSERT, 0); 
    // set application-defined invalid parameter handler
   char* joke = new char[MAX_BUFFER];
   memcpy(joke, "A beer, please!", strlen("A beer, please!"));
   errno_t ret = finish_joke(joke, "You'll have to excuse my friend…");
   if(0 == ret) // prints only if finish_joke succeeded
   delete []joke;
#ifdef _DEBUG
   return 0;


  • It's no sweat to get rid of C4996 warnings but also it's good to know that secure CRT functions are great.
  • Secure CRT functions perform run-time parameters checking which helps to find mistakes and prevent troubles.
  • The default invalid parameter handler terminates the aplication process; if we want to change this, we have to use an application-defined handler.
  • Last but not the least: if you want to write more solid and secure code, prefer using secure version of CRT functions!

See also


About the Author

Ovidiu Cucu

Graduated at "Gh. Asachi" Technical University - Iasi, Romania. Programming in C++ using Microsoft technologies since 1995. Microsoft MVP awardee since 2006. Moderator and article reviewer at Codeguru.com, the number one developer site. Co-founder of Codexpert.ro, a website dedicated to Romanian C++ developers.

Related Articles


  • A bit misleading

    Posted by mlgoff on 02/24/2011 02:39pm

    "To disable deprecation" The CRT functions that trigger this warning are NOT deprecated. Microsoft promised to stop inferring that these standard functions are deprecated. A promise they have not kept. It needs to be noted that the _s version for the CRT functions are Microsoft specific. They are not cross-platform nor are they portable. Shame on you for not even mentioning that fact, let alone making it clear.

    • RE: A bit misleading

      Posted by ovidiucucu on 02/25/2011 05:43am

      I know, there are many discussions beside the word 'deprecated'. That is not in scope of this short article. However, it offers solutions to both situations: using _s functions or, not using and simply getting rid of C4996 warnings. I think that's pretty fair and no reason to be ashamed... ;)

  • Good article!

    Posted by VictorN on 02/24/2011 12:06pm

    Very good explained and P8Q P8Q very easy to read!

    • RE: Good article!

      Posted by ovidiucucu on 02/25/2011 05:50am

      Especially the old jokes, I think... :-) Thank you, Victor!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Discover the best practices from HPE’s IT Advisory Consulting Services for migrating and transforming applications in Hybrid IT by capitalizing on innovative platforms, modern application architectures, agile development tools and proven methodologies. There are a number of challenges our customers face when migrating and transforming applications for a Hybrid IT environment. This guide provide proven strategies and application approaches that can help them understand and reduce risks and complexity.

  • A CRM solution holds a wealth of information and document generation tools allow users to take that information and create documents with both visual appeal and function. Document generation is the process of automatically producing a file and document generation applications save companies time, mistakes, and money. You bought Salesforce to be more efficient — why are you still manually creating proposals, contracts, invoices, and account plans? Read this eBook to learn how you can automate virtually …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.