views:

1895

answers:

11

Edit: I've added the source for the example.

I came across this example:

char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;

/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);

/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );

Which produced this output:

destination is originally = 'abcdefg'
After strcpy, destination becomes '123456789'

destination1 is originally = 'abcdefg'
After strncpy, destination1 becomes '12345fg'

Which makes me wonder why anyone would want this effect. It looks like it would be confusing. This program makes me think you could basically copy over someone's name (eg. Tom Brokaw) with Tom Bro763.

What are the advantages of using strncpy() over strcpy()?

+25  A: 

strncpy combats buffer overflow by requiring you to put a length in it. strcpy depends on a trailing \0, which may not always occur.

Secondly, why you chose to only copy 5 characters on 7 character string is beyond me, but it's producing expected behavior. It's only copying over the first n characters, where n is the third argument.

The n functions are all used as defensive coding against buffer overflows. Please use them in lieu of older functions, such as strcpy.

Eric
See http://www.lysator.liu.se/c/rat/d11.html :`strncpy` was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter names to null assures efficient field-wise comparisons. **`strncpy` is not by origin a "bounded strcpy," and the Committee has preferred to recognize existing practice rather than alter the function to better suit it to such use.**
Sinan Ünür
I am not sure why this is getting lots of up votes - strncpy was never intended as a safer alternative to strcpy and in fact isn't any safer as it doesn't zero termninate the string. It also has different functionality in that it pads up the supplied length with NUL chars.As caf says in his reply - it is for overwriting strings in a fixed size array.
Dipstick
Eric
The fact remains that `strncpy` is **not** a safer version of `strcpy`.
Sinan Ünür
@Sinan: I never said it was safer. It's defensive. It forces you to put in a length, ergo making you think about what you're doing. There are better solutions, but the fact remains that people would (and do) use `strncpy` instead of `strcpy` because it's a much more defensive function...which is what I said.
Eric
+3  A: 

the strncpy is a safer version of strcpy as a matter of fact you should never use strcpy because its potential buffer overflow vulnerability which makes you system vulnerable to all sort of attacks

bashmohandes
See http://www.lysator.liu.se/c/rat/d11.html : The strncpy functionstrncpy was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter names to null assures efficient field-wise comparisons. strncpy is not by origin a ``bounded strcpy,'' and the Committee has preferred to recognize existing practice rather than alter the function to better suit it to such use.
Sinan Ünür
+5  A: 

The strncpy() function is the safer one: you have to pass the maximum length the destination buffer can accept. Otherwise it could happen that the source string is not correctly 0 terminated, in which case the strcpy() function could write more characters to destination, corrupting anything which is in the memory after the destination buffer. This is the buffer-overrun problem used in many exploits

Also for POSIX API functions like read() which does not put the terminating 0 in the buffer, but returns the number of bytes read, you will either manually put the 0, or copy it using strncpy().

In your example code, index is actually not an index, but a count - it tells how many characters at most to copy from source to destination. If there is no null byte among the first n bytes of source, the string placed in destination will not be null terminated

CsTamas
A: 

You question is probably reversed (as pointed by 280Z28). The answer? The older method is deprecated but not removed for legacy support, what else is new? :)

DroidIn.net
A: 

strncpy() did exactly what you told it to do, it copied the source to the destination up to index characters. Its used to prevent buffer overflows.

Yes, a good program should know the length of the source and destination buffer, however sometimes ill intended people find great ways to do bad things to good programs. Hurling 10 meg chunks through a pipe to another program's stdin, or the same via a socket is a good example of input that was not anticipated.

Its good practice to just always use strncpy(), however its most important when your program is gathering input from the user, or from a source (i.e. file / socket) that the user can control. Using it is cheap, and relieves most of the headache of wondering how someone might abuse your program.

Sure, your program will not produce the expected resulsts if a user abuses it, however if you take care to eliminate buffer overflows, your program will not become a trampoline for nasty things like privilege escallation.

Tim Post
A: 

This may be used in many other scenarios, where you need to copy only a portion of your original string to the destination. Using strncpy() you can copy a limited portion of the original string as opposed by strcpy(). I see the code you have put up comes from publib.boulder.ibm.com.

ARV
+10  A: 

While I know the intent behind strncpy, it is not really a good function. Avoid both. Raymond Chen explains.

See also Why is strncpy insecure?

Sinan Ünür
+31  A: 

The strncpy() function was designed with a very particular problem in mind: manipulating strings stored in the manner of original UNIX directory entries. These used a fixed sized array, and a nul-terminator was only used if the filename was shorter than the array.

That's what's behind the two oddities of strncpy():

  • It doesn't put a nul-terminator on the destination if it is completely filled; and
  • It always completely fills the destination, with nuls if necessary.

For a "safer strcpy()", you are better off using strncat() like so:

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

That will always nul-terminate the result, and won't copy more than necessary.

caf
But, of course, strncpy isn't always what you want either: strncpy accepts the maximum number of characters to *add* and *not* the destination buffer size... But that's only a minor thing, so probably won't be an issue unless you're trying to concatenate one string onto another.
David Wolever
I did not know the reason for it, and it's very relevant to what I'm working on atm.
Matt Joiner
A: 

As everybody said strcpy() is very insecure. Secure Programming Lint (Splint) would actually warn you if you use strcpy() instead of strncpy() because of its vulnerabilities.

Gerhard
The tragedy being that it doesn't warn you about using strncpy, despite its vulnerabilities.
Steve Jessop
+5  A: 

strncpy is NOT safer than strcpy, it just trades one type of bugs with another. In C, when handling C strings, you need to know the size of your buffers, there is no way around it. strncpy was justified for the directory thing mentioned by others, but otherwise, you should never use it:

  • if you know the length of your string and buffer, why using strncpy ? It is a waste of computing power at best (adding useless 0)
  • if you don't know the lengths, then you risk silently truncating your strings, which is not much better than a buffer overflow
David Cournapeau
I think this is a good description for strncpy, so I have voted it up. strncpy has it's own set of troubles. I guess that's the reason that e.g glib has it's own extensions. And yes it's unfortunate that you as programmmer has to be aware of the Size of all the arrays. The decison having 0 terminated char array as string, has cost us all dearly....
Friedrich
+3  A: 

What you're looking for is the function strlcpy which does terminate always the string with 0 and does initialise the buffer. It also is able to detect overflows. Only problem, it's not (really) portable and is present only on some systems (BSD, Solaris). The problem with this function is that it opens another can of worms as can be seen by the discussions on http://en.wikipedia.org/wiki/Strlcpy

My personal opinion is that it is vastly more useful than strncpy and strcpy, has better performance and is a good companion to snprintf. For platforms which do not have it, it is relatively easy to implement. (for the developement phase of a application I substitute these two function (snprinf and strlcpy) with a trapping version which aborts brutally the program on buffer overflows or truncations, this allows to catch quickly the worst offenders, especially if you work on a codebase from someone else.

tristopia
You could write that strlcpy is available on pretty much everything other than Linux and Windows! It is, however, BSD licensed, so you can just drop it into one of your libraries and use it from there.
Michael van der Westhuizen