Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve strncpy() functionality with strncpy_s() function?

There're certain cases when I really need strncpy() funcitonalty - for example I have a function in a predefined interface that is passed an address of the buffer and the size of the buffer:

HRESULT someFunction( char* buffer, size_t length );

and it is documented that I can copy a null-terminated string there with length no more than length - if it is exactly of length length I don't null-terminate the string and the caller knows that the string ends at either a null character or at length length whichever happens first and it all works.

Of course I will use strncpy() for that

HRESULT someFunction( char* buffer, size_t length )
{
    const char* toCopy = ...
    size_t actualLength = strlen( toCopy );
    if( actualLength > length ) {
        return E_UNEXPECTED; // doesn't fit, can't do anything reasonable 
    }
    strncpy( buffer, toCopy, length );
    return S_OK;
}

Now I have this code and need to migrate it from Visual C++ 7 to Visual C++ 9. I compile it and see a warning that strncpy() is unsafe and I should instead use strncpy_s().

strncpy_s() is designed to always null-terminate the buffer, so I can't use it as a direct replacement in the above scenario. I'll have to return E_UNEXPECTED on strings longer than length - 1 (not length as previously) or it will just fire an invalid parameters error handler once a string is of length or longer or the program will run into undefined behavior.

The solution I applied so far is to just define a _CRT_SECURE_NO_WARNINGS and make the compiler shut up.

is there any way to use strncpy_s() as an actual replacement to strncpy()?

like image 673
sharptooth Avatar asked Feb 18 '11 07:02

sharptooth


People also ask

What is the difference between strncpy and strncpy_s?

strcpy_s() is a security enhanced version of strcpy() . With strcpy_s you can specify the size of the destination buffer to avoid buffer overflows during copies. char tuna[5]; // a buffer which holds 5 chars incluing the null character.

How is strncpy implemented?

Implement strncpy() function in C Write an efficient function to implement strncpy() like function in C, which copies the given n characters from source C-string to another string. The prototype of the strncpy() is: char* strncpy(char* destination, const char* source, size_t num);

What can I use instead of strncpy?

C11 Annex K specifies the strncpy_s() and strncat_s() functions as close replacements for strncpy() and strncat(). The strncpy_s() function copies not more than a specified number of successive characters (characters that follow a null character are not copied) from a source string to a destination character array.

What is the difference between strncpy and strcpy?

strcpy( ) function copies whole content of one string into another string. Whereas, strncpy( ) function copies portion of contents of one string into another string. If destination string length is less than source string, entire/specified source string value won't be copied into destination string in both cases.


1 Answers

The problem you're facing here is that your function is unsafe in itself, just like strncpy() is. It is unsafe because callers of your function might forget that the returned strings are not null terminated. If this really is the desired behavior of your function I recommend not to define _CRT_SECURE_NO_WARNINGS and disable the warnings globally but use #pragmas instead:

// document here exactly why you can not use strncpy_s
#pragma warning( push )
#pragma warning( disable : 4996 )
// your code that uses strncpy instead of strncpy_s
#pragma warning( pop ) 

That way you disable those warnings only for those situations where you absolutely have to use unsafe functions.

like image 141
Stefan Avatar answered Sep 23 '22 10:09

Stefan