Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strcpy... want to replace with strcpy_mine which will strncpy and null terminate

Tags:

c++

c

strcpy

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)

like image 847
timB33 Avatar asked Jun 04 '09 14:06

timB33


People also ask

Will strcpy null terminate?

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.

Does strncpy null terminate?

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.

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.

How do I replace strcpy?

strcpy and friends are, at best, incredibly niche, and the correct replacement is memcpy .


2 Answers

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.

like image 100
Douglas Leeder Avatar answered Sep 18 '22 18:09

Douglas Leeder


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.

like image 31
Suma Avatar answered Sep 19 '22 18:09

Suma