strncpy and using sizeof to copy maximum characters
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.
ant2009
Updated on June 25, 2022Comments
-
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 almost 15 yearsI 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 almost 15 yearsYes, 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 almost 15 yearsI am just wondering. Is there any real difference in using either strlen or sizeof?
-
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 almost 15 yearsThe 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 yearsThis is not a standard function. It may be not available.
-
Gerhardh almost 4 yearsWhat is
-1
supposed to do here? It will only shift the problem by one byte. If the string does not fit insizeof(call)-1
bytes, the remaining last element will still not be filled with0
. Also the use ofstrlcpy
was already suggested 6 years ago. -
Gerhardh almost 4 yearsThis only works if the destination buffer was cleared to 0 before the call. Not very helpful for general usage.