Almost every developer knows the cost of using insecure string function such as strcpy which can lead to buffer overflow exploits.  But no one knows the cost of using the secure string functions. Here is just illustration of how much pain it can cause sometimes…

Have a look at the sample code below,

void main()
{
char test[]=”hello”;

//converting text to lowercase
_strlwr_s( test,  strlen(test)  );
}

This is very simple program which converts the text to lowercase using secure version of string function _strlwr_s( ).  Now take a closer look at this program and see if you can sense anything wrong.

Even with eagle eye, everything looks obviously correct in the above program. However it crashes into debugger when executed. Surprised ???

I was surprised indeed, how can such simple straight code lead to crash. I was wondering if something wrong with its implementation itself.

Beaten down by the crash and curious at the same time, I decided to find it out. I had used this code in the big project and it took me a while to narrow down the crash location to _strlwr_s( ) function.  I tried couple of tweaks here and there to see if I can quickly figure out, nothing worked as usual 🙂 .  It was crashing into Windbg which I had registered as default debugger.

Finally I started with traditional debugging with debug version and it asserted as shown below…

See the fun here, it is complaining ‘String is not null terminated’.  Naturally I looked at the code to make sure that string is null terminated and it is perfect as you can see. Then I checked the MSDN documentation for strlwr function which was like below

errno_t _strlwr_s( char *str, size_t sizeInBytes );

Then it suddenly striked me that the problem was with the second parameter ‘sizeInBytes’ which refers to total size of string buffer rather than just string length as in normal string functions…!

Finally I corrected it by passing the size of the string as parameter instead of string length.

_strlwr_s( test, strlen(test)+1 );

_strlwr_s( test,  sizeof(test) );  //This is right method

This may appear to be classical case of overlooking, but this is what happens when things change even slightly from the standard behavior.

.