The clue is in the title but basically I've inherited some code which has 800+ instances of strcpy. I want to write a new function and then to replace strcpy with strcpy_mine.
So I'm trying to work out what parameter list strcpy_mine will have.
I tried:
void strcpy_mine( char* pTarget, const char* const pCopyMe )
{
const unsigned int lenAlwaysFour = sizeof(pCopyMe ); //:(
strncpy( pTarget, pCopyMe, lenAlwaysFour );
//add extra terminator in case of overrun
pTarget[lenAlwaysFour] = 0;
}
but the sizeof is always 4 pCopyMe is a pointer
what I don't want to do is replace
strcpy (buf, pCopyMe);
with
strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0;
Any ideas? (strcpy_l isn't available)
Description. The strcpy() function copies string2, including the ending null character, to the location that is specified by string1. The strcpy() function operates on null-ended strings. The string arguments to the function should contain a null character (\0) that marks the end of the string.
The standard functions strncpy() and strncat() copy a specified number of characters n from a source string to a destination array. In the case of strncpy() , if there is no null character in the first n characters of the source array, the result will not be null-terminated and any remaining characters are truncated.
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.
strcpy and friends are, at best, incredibly niche, and the correct replacement is memcpy .
sizeof() returns the size of the type - in this case const char* const
which will be 4 on 32-bit machines.
I think you think you want strlen()
. But that isn't the right way to use strncpy functions.
You need the size of the output buffer for strncpy.
To fix this you need to examine the code at each call site, and work out the size of the output buffer, and pass that as an argument to strcpy_mine
. If the call-site for strcpy (or strcpy_mine) doesn't know the size of the output buffer, you need to search backwards in the code for the location that allocates the buffer, and pass the size all the way down to the strcpy site.
Basically you can't write a drop in replacement for strcpy that takes the same arguments and hope to avoid the problems that produced strncpy in the first place (and better replacements beyond that). You can create a function that takes the same arguments as strncpy, but ensures the result is null-terminated - look at the implementation of OpenBSD's strlcpy() function. But the first step has to be to change the calling sites to pass on knowledge of the output buffer size.
Depending on how the call-sites look like, often majority of cases can be handled by a simple template:
#include <string.h>
template <int bufferSize>
void strcpy_mine( char (&pTarget)[bufferSize], const char* const pCopyMe )
{
strncpy( pTarget, pCopyMe, bufferSize-1 );
//add extra terminator in case of overrun
pTarget[bufferSize-1] = 0;
}
int main()
{
char buf[128];
strcpy_mine(buf,"Testing");
return 0;
}
If you are using Microsoft Visual Studio 2005 or newer, see Secure Template Overloads for a Microsoft implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With