3

Possible Duplicate:
Why should you use strncpy instead of strcpy?

I'm reading a book about computers/cryptographic etc. And often the writer use thing such as strncpy(dest, src, strlen(src)); instead of strcpy(dest, src); it makes no much sense for me.. Well, I'm a professional programmer.

The question is: It make really a real difference? real applications use something like this?

Community
  • 1
  • 1
Jack
  • 16,276
  • 55
  • 159
  • 284
  • I can't see why `strncpy(dest, src, strlen(src));` would be faster than `strcpy(dest, src);`. – Mysticial Oct 08 '12 at 06:17
  • 1
    @Mysticial It's the same speed (though the strlen adds an overhead of using it). Speed is not why it's used. Defending against buffer overflows is why it's preferred. (`strncpy` is the same speed as `strcpy` I mean. The internals are the same speed, assuming the same amount of characters are copied are made.) By the way, the third parameter shouldn't be the string length, but rather the size of the dest buffer (or perhaps the size minus 1). – Corbin Oct 08 '12 at 06:17
  • @Mystical Just realized that you are not the question asker, and thus half of my previous comment is just rambling. Going to leave the previous comment though in case the asker does find it useful, and it's close to length limit so can't write this note there :). – Corbin Oct 08 '12 at 06:21

5 Answers5

13

The author is almost certainly abusing the strn* functions. Unfortunately, there is almost never a good reason to use strn* functions, since they don't actually do what you want.

Let's take a look at strcpy and strncpy:

char *strcpy(char *dest, const char *src);

char *strncpy(char *dest, const char *src, size_t n);

The strcpy function copies src into dest, including a trailing \0. It is only rarely useful:

  1. Unless you know the source string fits in the destination buffer, you have a buffer overflow. Buffer overflows are security hazards, they can crash your program, and cause it to behave incorrectly.

  2. If you do know the size of the source string and destination buffer, you might as well use memcpy.

By comparison, the strncpy copies at most n bytes of src into dest and then pads the rest with \0. It is only rarely useful:

  1. Unless you know the source string is smaller than the destination buffer, you cannot be certain that the resulting buffer will be nul-terminated. This can cause errors elsewhere in the program, if you assume the result is nul-terminated.

  2. If you do know the source string is smaller, again, you might as well use memcpy.

  3. You can simply terminate the string after you call strncpy, but are you sure that you want to silently truncate the result? I'd imagine most of the time, you'd rather have an error message.

Why do these functions exist?

The strcpy function is occasionally handy, but it is mostly a relic of an era where people did not care very much about validating input. Feeding a string that is too large to a program would crash it, and the advice was "don't do that".

The strncpy function is useful when you want to transmit data in fixed-size fields, and you don't want to put garbage in the remainder of the field. This is mostly a relic of an era where people used fixed-size fields.

So you will rarely see strcat or strncpy in modern C software.

A worse problem

However, your example combines the worst of both worlds. Let's examine this piece of source code:

strncpy(dest, src, strlen(src));

This copies src into dest, without a \0 terminator and without bounds checking. It combines the worst aspect of strcpy (no bounds checking) with the worst aspect of strncpy (no terminator). If you see code like this, run away.

How to work with strings

Good C code typically uses one of a few options for working with strings:

  1. Use fixed buffers and snprintf, as long as you don't mind fixed buffers.

  2. Use bounded string functions like strlcpy and strlcat. These are BSD extensions.

  3. Use a custom string point which tracks string lengths, and write your own functions using memcpy and malloc.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • "A worse problem" - specifically, `strncpy(dest, src, strlen(src));` is exactly equivalent to `memcpy(dest, src, strlen(src))`. So the only reason I can think of for writing it is that you don't know what you're doing, since you're writing the code to look like a string operation, when really it isn't one. – Steve Jessop Oct 08 '12 at 09:13
1

If that code is a verbatim copy from the book, the author either does not know C or is not a security specialist or both.

It could also be that he's using a misconfigured compiler, explicitly prohibiting the use of certain known to be potentially unsafe functions. And it's a questionable practice when the compiler cannot distinguish safe from unsafe from potentially unsafe and is just getting in the way all the time.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
0

The reason for the strn family is to prevent you from overflowing buffers. If you're passed data from a caller and blindly trust that it's properly null-terminated and won't overflow the buffer you're copying it to, your going to got owned by a buffer overrun attack.

The efficiency difference is negligible. The strn family might be slightly slower as it needs to keep checking that you're not overflowing.

Martin
  • 3,703
  • 2
  • 21
  • 43
0

strncpy(dest, src, strlen(src)); is the same as strcpy(dest, src); so there's no difference here, but..

Strcpy can lead to security holes, since you don't know how long the strings are. Somebody clever can overwrite something on your server using this.

kuniqs
  • 308
  • 1
  • 9
  • 1
    If `src` is not `\0`-terminated, `strncpy(dst, src, strlen(src))` clearly won't be of any help security-wise compared to plain `strcpy(dst, src)`. – Alexey Frunze Oct 08 '12 at 06:27
0

Use of strncpy against strcpy has little to do with its execution speed but strncpy strongly lowers the possibility of buffer overflow attacks. In C, the pointers are most powerful but they also make the system vulnerable.

Following excerpt from a good Hack-Proofing book might help you.

Many overflow bugs are a result of bad string manipulation. Calls such as strcpy() do not check the length of a string before copying it. The result is that a buffer overflow may occur. It is expected that a NULL terminator will be present. In one sense, the attacker relies on this bug in order to exploit a machine; however, it also means that the attacker’s injected buffer also must be free of NULL characters. If the attacker inserts a NULL character, the string copy will be terminated before the entire payload can be inserted.

mihirj
  • 1,199
  • 9
  • 15
  • 1
    "strncpy strongly lowers the possibility of buffer overflow attacks" the code in the question demonstrates that it doesn't, but that there exist programmers who think the `n` is a kind of magic pixie dust that improves their code. – Steve Jessop Oct 08 '12 at 09:10