tags:

views:

271

answers:

5

Hello,

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,

+3  A: 

Your idea:

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

would not work, as you would be calling strlen() on a non-terminated string

anon
+1  A: 

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;
sharptooth
+7  A: 

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

Tim Sylvester
One simple way to ensure the destination is nul terminated here is to do call[sizeof call -1] = 0;
nos
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.
robUK
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.
Tim Sylvester
If you're using VC++ I'd recommend to use strncpy_s, which makes sure that strings are always terminated
jn_
+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...
Andrew Y
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).
Jonathan Leffler
+1  A: 

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
Artyom
I am just wondering. Is there any real difference in using either strlen or sizeof?
robUK
sizeof is constant it returns sizeof objet, when strlen actually calculates in runtime the length of the string. For example for char tar[2]={0,0}; sizeof(tar)==2 but, strlen(tar)==0;
Artyom
+1  A: 

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.

Martin B