2

According to this StackOverflow comment strncpy should never be used with a non-fixed length array.

strncpy should never be used unless you're working with fixed-width, not-necessarily-terminated string fields in structures/binary files. – R.. Jan 11 '12 at 16:22

I understand that it is redundant if you are dynamically allocating memory for the string but is there a reason why it would be bad to use strncpy over strcpy

Community
  • 1
  • 1
Puddler
  • 2,619
  • 2
  • 17
  • 26
  • 1
    You may find your answer here (http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy) – Md. Monirul Islam Jun 10 '16 at 03:51
  • The reason is that it doesn't do what you think it does. – user253751 Jun 10 '16 at 05:12
  • You should never use `strncpy` for any purpose, it is intrinsically unsafe, [see this](http://stackoverflow.com/questions/2114896/why-are-strlcpy-and-strlcat-considered-insecure). Instead, use `strcpy` together with a buffer size check. – Lundin Jun 10 '16 at 08:04
  • @Lundin: It's not uncommon for structures to have fixed-length fields which need to hold 4 or 8 characters. Any approach which insists upon applying zero termination would be limited to 3 or 7 characters or would require copying a string to an outside buffer and then using memcpy to store it. If a struct contains a char[8] and it's necessary to initialize it to "Hello", I think `strncpy(thing.name,"Hello",8);` would be cleaner and less brittle than `memcpy(thing.name, "Hello\0\0", 8);` – supercat Apr 15 '17 at 18:36
  • @supercat _Initialize_ a struct: `type_t type = { .str="Hello" };`. Run-time assign a struct: `type = (type) { .str="Hello" };`. Which doesn't have much to with `strncpy`, that remains a dangerous, obsolete function only to be used for ancient string types in Unix. – Lundin Apr 18 '17 at 06:18
  • @Lundin: Those approaches wouldn't work if the structure contained anything else (as would often be the case, though it wasn't in this specific example). – supercat Apr 18 '17 at 14:48

4 Answers4

4

strncpy will copy data up to the limit you specify--but if it reaches that limit before the end of the string, it'll leave the destination unterminated.

In other words, there are two possibilities with strncpy. One is that you get behavior precisely like strcpy would have produced anyway (except slower, since it fills the remainder of the destination buffer with NULs, which you virtually never actually want or care about). The other is that it produces a result you generally can't put to any real use.

If you want to copy a string up to a maximum length into a fixed-length buffer, you can (for example) use sprintf to do the job:

char buffer[256];

sprintf(buffer, "%255s", source);

Unlike strncpy, this always zero-terminates the result, so the result is always usable as a string.

If you don't want to use sprintf (or similar), I'd advise just writing a function that actually does what you want, something on this general order:

void copy_string(char const *dest, char const *source, size_t max_len) { 
    size_t i;
    for (i=0; i<max_len-1 && source[i]; i++)
        dest[i] = source[i];
    dest[i] = '\0';
}

Since you've tagged this as C++ (in addition to C): my advice would be to generally avoid this whole mess in C++ by just using std::string.

If you really have to work with NUL-terminated sequences in C++, you might consider another possibility:

template <size_t N>
void copy_string(char const (&dest)[N], char const *source) {
    size_t i;
    for (i=0; i<N-1 && source[i]; i++)
        dest[i] = source[i];
    dest[i] = '\0';
}

This only works when the destination is an actual array (not a pointer), but for that case, it gets the compiler to deduce the size of the array, instead of requiring the user to pass it explicitly. This will generally make the code a tiny bit faster (less overhead in the function call) and much harder to screw up and pass the wrong size.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    you can as well null-terminate it manually: `strncpy(dest,source,size-1); dest[size] = '\0';`. Not so elegant maybe, but I'd prefer it over `sprintf` – Andrei R. Jun 10 '16 at 04:01
  • 1
    @AndreiR.: good general point (it's often done), but `dest[size]`? ;-) – Tony Delroy Jun 10 '16 at 04:08
  • @AndreiR.: Alternatives added to answer. – Jerry Coffin Jun 10 '16 at 04:16
  • It seems I've been doing it as `char dest[256]; if (snprintf(dest,256,"Value: %s",source) >= 256) {\\do error mitigation}` in the parts of the code I'm working on. I just got a little confused because I've been chasing down this bug caused by a bad `strcpy` for so long and my sleep deprived brain just changed it to `strncpy` thinking it would fix it but it didn't and I went on a wild goose chasing trying to figure out if all my previous logic was wrong. – Puddler Jun 10 '16 at 04:44
2

The argument against using strncpy is that it does not guarentee that your string will be null terminated.

The less error prone way to copy a string in C when using non-fixed length arrays is to use snprintf which does guarentee null termination of your string.

A good Blog Post Commenting on *n* functions.

These functions let you specify the size of the buffer but – and this is really important – they do not guarantee null-termination. If you ask these functions to write more characters than will fill the buffer then they will stop – thus avoiding the buffer overrun – but they will not null-terminate the buffer.

Which means that the use of strncpy and other such functions when not dealing with fixed arrays introduces unnessisary risk of non-null terminated strings which can be time-bombs in your code.

Serdalis
  • 10,296
  • 2
  • 38
  • 58
  • *"less error prone"* - true, but properly checking your output was complete is still ugly: `int n = snprintf(buffer, sizeof buffer, "%s", source); assert(n >= 0 && n < sizeof buffer);` vs. `strncpy(buffer, source, sizeof buffer); assert(buffer[sizeof buffer-1] == '\0');` (possible as [`strncpy`](http://en.cppreference.com/w/cpp/string/byte/strncpy) pads out the full buffer with NULs). – Tony Delroy Jun 10 '16 at 03:56
  • @TonyD A matter of style I suppose? I personally prefer the first `assert` because you aren't doing an array access, and you also have access to how many characters were written. – Serdalis Jun 10 '16 at 04:04
  • 1
    yeah - pretty much style, and specifics of the situation - e.g. countering the `n` being potentially useful, if unwanted it's potentially cluttering up your local symbols and you're quickly juggling `n2`, `n3` or `o`, `p` or using more verbose `this_len`, `that_len`. – Tony Delroy Jun 10 '16 at 04:22
0

char * strncpy ( char * destination, const char * source, size_t num );

Limitations of strncpy():

  1. It doesn't put a null-terminator on the destination string if it is completely filled. And, no null-character is implicitly appended at the end of destination if source is longer than num.
  2. If num is greater than the length of source string, the destination string is padded with null characters up to num length.

Like strcpy, it is not a memory-safe operation. Because it does not check for sufficient space in destination before it copies source, it is a potential cause of buffer overruns.

Refer: Why should you use strncpy instead of strcpy?

Community
  • 1
  • 1
  • Especially with your original wording *"Oddities of strncpy()"*, that and the start of the first point appear lifted from [this answer](http://stackoverflow.com/a/1258577/410767). If you do use something from elsewhere, please quote, attribute and link to it. Cheers. – Tony Delroy Jun 10 '16 at 05:17
  • I mentioned this link on my comment. Btw, Now I added this in my answer also. Thanks !!! – Md. Monirul Islam Jun 10 '16 at 05:53
-1

We have 2 versions for copy string from one to another 1> strcpy 2> strncpy These two versions is used for fixed and non-fixed length array. The strcpy don't check the upper bound for destination string when copy string, strncpy will check it. When the destination string is reached to this upper bound, the function strncpy will return error code, in the meantime the function strcpy will cause some effect in memory of the current process and terminate the process immediately. So that the strncpy is more secure than strcpy

Loc Tran
  • 1,170
  • 7
  • 15