strncpy and using sizeof to copy maximum characters

17,330

Solution 1

If the source's length is less than the max number passed as third parameter strncpy will null-terminate the destination, otherwise - not.

If the source is equal or greater in length than the destination - it's your problem to deal with it. Doing like you suggest - calling strlen() - will not work since the buffer will be not null-terminated and you'll run into undefined behaviour.

You could allocate a bigger buffer:

char buffer[bufferSize + 1];
strncpy( buffer, source, bufferSize );
*(buffer + bufferSize ) = 0;

Solution 2

strncpy will not null-terminate the destination if it truncates the string. If you must use strncpy, you need to ensure that the result is terminated, something like:

strncpy(call, info.called, sizeof(call) - 1);
call[sizeof(call) - 1] = '\0';

BSD's strlcpy(), among others, is generally considered superior:

http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy

Solution 3

But I am now wondering if it will null terminate the destination.

No, strncpy does not promise that target string would be null terminated.

char tar[2]={0,0};
char bar="AB";
strncpy(tar,bar,2);
// result tar[0]=='A'; tar[1]=='B'

It order to make it correct you should use:

strncpy(traget,string,sizeof(target)-1);
target[sizeof(target)-1]=0

Solution 4

1) From cplusplus.com: "No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num." So you if you need your string to be null-terminated, you need to do this:

call[sizeof(call) - 1] = '\0';

A good way to do this would be to write a wrapper function for strncpy that always makes sure the string is terminated.

2) If the source is shorter than the destination, the destination will be null-terminated.

Solution 5

Just use strlcpy() instead of strncpy(). You'll have to check if it's available on all platforms. Early versions of linux probably don't have it.

Share:
17,330
ant2009
Author by

ant2009

Updated on June 25, 2022

Comments

  • ant2009
    ant2009 about 2 years

    I am using the code below

    char call[64] = {'\0'} /* clean buffer */
    strncpy(call, info.called, sizeof(call));
    

    I always use the sizeof for the destination for protecting a overflow, incase source is greater than the destination. This way I can prevent a buffer overflow as it will only copy as much as the destination can handle.

    But I am now wondering if it will null terminate the destination.

    A couple of cases.

    1) If the source is greater. I could do this:

    call[strlen(call) - 1] = '\0'; /* insert a null at the last element.*/
    

    2) If the source is less than the destination. call is 64 bytes, and I copy 50 bytes as that is the size of the source. Will it automatically put the null in the 51 element?

    Many thanks for any information,

  • ant2009
    ant2009 almost 15 years
    I didn't think strncpy would terminate the string. By not terminating the string. Could this lead to a real problem? Also by doing this call[strlen(info.called - 1] = '\0'; What that be the correct way to terminate if the source is greater or less than the destination? Thanks.
  • Tim Sylvester
    Tim Sylvester almost 15 years
    Yes, an unterminated string will cause strlen(), strcat(), etc., to be wrong, corrupt memory, and/or crash. Setting the last byte of the buffer to zero doesn't harm anything when the string is shorter than the destination, so there's really no reason to make it conditional.
  • ant2009
    ant2009 almost 15 years
    I am just wondering. Is there any real difference in using either strlen or sizeof?
  • Andrew Y
    Andrew Y almost 15 years
    +1 for accounting for the termination, but I think blindly terminating the string is a bad idea. Consider (an artificial) example of that final string being used later to recursively delete a directory tree...
  • Jonathan Leffler
    Jonathan Leffler almost 15 years
    The other trick of strncpy() is that it always fully null-pads the target string to the length specified when the source is shorter than the target. This matters if you copy 32 bytes of data into a 4 KB buffer; as well as the 32 bytes of data, it will copy 4064 '\0' characters - which can become a problem. In my view, strncpy() was designed to copy file name components of up to 14 characters into the file name portion of an old Unix directory entry. The file name portion was up to 14 characters, null padded but not null terminated (and the two preceding bytes were a 2-byte inode number).
  • Деян Добромиров
    Деян Добромиров over 8 years
    This is not a standard function. It may be not available.
  • Gerhardh
    Gerhardh almost 4 years
    What is -1 supposed to do here? It will only shift the problem by one byte. If the string does not fit in sizeof(call)-1 bytes, the remaining last element will still not be filled with 0. Also the use of strlcpywas already suggested 6 years ago.
  • Gerhardh
    Gerhardh almost 4 years
    This only works if the destination buffer was cleared to 0 before the call. Not very helpful for general usage.