Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > strncpy and 'n'

Reply
Thread Tools

strncpy and 'n'

 
 
Rich Webb
Guest
Posts: n/a
 
      02-21-2012
On Mon, 20 Feb 2012 16:46:01 -0800, Keith Thompson <(E-Mail Removed)>
wrote:

>Rich Webb <(E-Mail Removed)> writes:
>[...]
>> I'm surprised that the construct
>>
>> strncpy(dest, source, BUF_LEN)[BUF_LEN - 1] = '\0';
>>
>> hasn't been mentioned. It seems to be a reasonably compact way of
>> dealing with uncontrolled input.

>
>Yes, that should work. (I've never seen anyone actually use that
>idiom; have you?)


Ermmm, me, actually. Where I use it constantly is in parsing data inputs
that can have real-world issues, such as a noise burst that over-filled
a field or a separator character between two fields that got dropped. I
deal with the correctness of the buffer subsequently but first I need to
ensure that the buffer is safely filled and terminated so that I can
look at it.

There will typically be separate checks for overall format (e.g.,
framing words, number of fields) and a checksum/CRC/hash but some day
the planets will be in a bad alignment where everything else is okay
and, as the saying goes, in a field where "foo" was expected
"supercalifragilisticexpialidocious" was read.

>Note that if dest is, say, 1000 bytes, and strlen(source)==3,
>then it will write 997 null characters into dest, when 1 would do.
>If the source string is from user or file input, that's probably
>not going to be significant.


Which is fine, although the difference is usually on the order of an
input length of eight into a buffer with room for, say, twelve.

>This avoids that problem:
>
> dest[0] = '\0';
> strncat(dest, source, BUF_LEN - 1);


True. A more complete solution would probably be a strlen() test
followed by truncation with \0 and an application diagnostic if the
input is too long. But I'm often dealing with embedded systems where
it's just a black box that can not fail from a data line hiccup.

>Another problem is that it *silently* truncates overly long input.
>(That might be just what you want.)


Pretty much, yes.

--
Rich Webb Norfolk, VA
 
Reply With Quote
 
 
 
 
Joe keane
Guest
Posts: n/a
 
      02-21-2012
In article <(E-Mail Removed)>,
Keith Thompson <(E-Mail Removed)> wrote:
>If it had been defined something like this:
>
> char *better_strncpy(char *dest, const char *src, size_t n) {
> dest[0] = '\0';
> return strncat(dest, src, n);
> }
>
>then it would be reasonable to call it a "safer" version of strcpy.


Well there you go. You pretty much solved your complaint. It you are
catenating several strings, it's almost more natural to zero out at the
beginning, then use 'strcat' from there.

You can understand why you might want to zero out the whole array at the
start; from there 'strcat' is fine.
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      02-21-2012
On 02/21/2012 04:46 PM, Joe keane wrote:
> In article <(E-Mail Removed)>,
> Keith Thompson <(E-Mail Removed)> wrote:
>> If it had been defined something like this:
>>
>> char *better_strncpy(char *dest, const char *src, size_t n) {
>> dest[0] = '\0';
>> return strncat(dest, src, n);
>> }
>>
>> then it would be reasonable to call it a "safer" version of strcpy.

>
> Well there you go. You pretty much solved your complaint.


I don't see how the ability to define such a function changes any of the
issues he complained about - there's still a function named strncpy() in
standard library, and it's name still creates well-justified but false
expectations in newbies about what it might do. Careful reading of the
standard or good documentation will correct those mistaken expectations
- but that shouldn't have been necessary.

I'm not saying that newbies shouldn't need to read the documentation, or
that the standard should be written so that reading it is unnecessary.
I'm merely saying that good naming conventions can make it easier to
guess what the functions do, and easier to remember what they do once
you have learned what it is. Either the behavior should have matched
those expectations, or the name should have been changed to make them
not well-justified.

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      02-21-2012
http://www.velocityreviews.com/forums/(E-Mail Removed) (Joe keane) writes:
> In article <(E-Mail Removed)>,
> Keith Thompson <(E-Mail Removed)> wrote:
>>If it had been defined something like this:
>>
>> char *better_strncpy(char *dest, const char *src, size_t n) {
>> dest[0] = '\0';
>> return strncat(dest, src, n);
>> }
>>
>>then it would be reasonable to call it a "safer" version of strcpy.

>
> Well there you go. You pretty much solved your complaint. It you are
> catenating several strings, it's almost more natural to zero out at the
> beginning, then use 'strcat' from there.


Not really. My complaint is that strncpy() is in the standard library
with the name "strncpy", and that too many programmers use it
incorrectly.

> You can understand why you might want to zero out the whole array at the
> start; from there 'strcat' is fine.


Note that multiple strcat() calls can be quite inefficient, since
each one has to scan the destination to find the terminating '\0'
before it appends the new data.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      02-22-2012
On Feb 21, 10:29*pm, Keith Thompson <(E-Mail Removed)> wrote:
>
> Not really. *My complaint is that strncpy() is in the standard library
> with the name "strncpy", and that too many programmers use it
> incorrectly.
>

What's worse is that often the wrong use won't be detected.

strncpy() appears to eb a safe strcpy() if the buffer length is never
exceeded. Since normally the buffer will be larger than any string you
expect, this often won't be tested. Who's going to pass a string of
more than FILE_MAX to a program?

Then even if it is tested, there's a reasonable chance that the
character immediately folowing the buffer is a byte of value zero. So
it might well appear to a casual tester that the fucntin has worked as
expected - he might not notice the extra character.

--
Malcolm's website
http://www.malcolmmclean.site11.com/www
 
Reply With Quote
 
Joe keane
Guest
Posts: n/a
 
      02-23-2012
In article <(E-Mail Removed)>,
Keith Thompson <(E-Mail Removed)> wrote:
>My complaint is that strncpy() is in the standard library
>with the name "strncpy", and that too many programmers use it
>incorrectly.


I think i agree on naming. For example, 'strncpyz' zeros out the
buffer, 'strncpyu' can leave it without a terminator (the default is
less surprising), 'strncpyzu' does both. The zero seems harmless, at
worst it runs slower, at best it runs faster.

But 'strcpy' doesn't give us much guidance here.

It *can't* zero out the buffer, because it doesn't know the buffer size.
It *can't* decide to leave out the terminator, because it doesn't know
the buffer size. It can't avoid trashing your memory, for same reason.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      02-23-2012
(E-Mail Removed) (Joe keane) writes:
> In article <(E-Mail Removed)>,
> Keith Thompson <(E-Mail Removed)> wrote:
>>My complaint is that strncpy() is in the standard library
>>with the name "strncpy", and that too many programmers use it
>>incorrectly.

>
> I think i agree on naming. For example, 'strncpyz' zeros out the
> buffer, 'strncpyu' can leave it without a terminator (the default is
> less surprising), 'strncpyzu' does both. The zero seems harmless, at
> worst it runs slower, at best it runs faster.
>
> But 'strcpy' doesn't give us much guidance here.
>
> It *can't* zero out the buffer, because it doesn't know the buffer size.


It doesn't bother to zero out the buffer, because that's rarely a useful
thing to do. If you want to zero a buffer, use memset().

> It *can't* decide to leave out the terminator, because it doesn't know
> the buffer size.


It doesn't leave out the terminator because it *needs* to store the
terminator in order for the destination to be a valid string.

> It can't avoid trashing your memory, for same reason.


It's up to the caller to avoid trashing memory by ensuring that the
destination is big enough to hold the data to be copied into it.
(Admittedly strcpy() doesn't make this easy.)

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      02-23-2012
On Mon, 2012-02-20, Keith Thompson wrote:
> (E-Mail Removed) (Joe keane) writes:
>> In article <(E-Mail Removed)>,
>> Keith Thompson <(E-Mail Removed)> wrote:
>>>strncpy *looks* like it should be to strcpy as strncat is to strcat,
>>>but it isn't.

>>
>> Well there is a number of options.
>>
>> a) should it make sure there is a zero terminator
>> b) maybe you want to clear everything that isn't copied
>> c) does it handle overlapping copies
>>
>> Do i think it's slightly stupid that they don't match? A little bit.
>> But one can imagine that good choices were made, and that consistency is
>> sometimes negative.

>
> The point is that strncpy is a very different function from strcpy.
> It is not intended to work with a *string* in the target array;
> it works with a specialized data structure (used to store file
> names in very early Unix systems).


Malcolm McLean wrote something similar upthread. Do you have any
references for this?

It would explain the function's weird semantics, but I haven't seen
anything before which says this is its background. (There's also
wcsncpy() for wchar_t -- that one is certainly newer, and useless in
the data structures you mention.)

....
> I think you're understating the differences between strcpy and
> strncpy. The strncpy function is radically different from strcpy,
> and there are very few legitimate uses for it. On the other hand,
> the deceptive name has led many C programmers to use it incorrectly,
> and I strongly suspect that it's used incorrectly far more often
> than it's used correctly.


The static analysis tool we use at work screams bloody murder every
time I use strcpy() and tells me to use strncpy() instead. Argh ...

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      02-25-2012
On 2/20/2012 23:16, pete wrote:
> Shao Miller wrote:
>
>> My impression is that in:
>>
>> char foo[] = "foo";
>> char bar[3] = "bar";
>> char baz[10] = "baz";
>>
>> each of these could be roughly equivalent to:
>>
>> char foo[sizeof "foo"];
>> char bar[3];
>> char baz[10];
>>
>> strncat(foo, "foo", sizeof "foo");
>> strncat(bar, "bar", 3);
>> strncat(foo, "baz", 10);

>
> ITYM strncat(baz, "baz", 10);
>


Right. Except...

> foo, bar and baz
> would each have to be initialized with a null byte
> in order to properly use strncat on them like that.
>
> But, even if bar[3] had static duration
> and so was initialized with a null byte,
> strncat(bar, "bar", 3);
> writes 4 characters and overruns the array.
>
>
> n1570
> 7.24.3.2 The strncat function
> Synopsis
> 1 #include<string.h>
> char *strncat(char * restrict s1,
> const char * restrict s2, size_t n);
> Description
> 2 The strncat function appends not more than n characters
> (a null character and characters that follow it are not appended)
> from the array pointed to by s2 to the end of the string
> pointed to by s1.
> The initial character of s2 overwrites the null character
> at the end of s1.
> A terminating null character is always appended to the result.
>


Somehow, I completely was confusing 'strncpy' with 'strncat', here.
Please substitute 'strncpy' in place of 'strncat' in my post. Of
course, that makes it irrelevant to Keith's immediately-preceding post.

Thank you for the correction, pete!
 
Reply With Quote
 
Philip Lantz
Guest
Posts: n/a
 
      02-25-2012
Jorgen Grahn wrote:
> On Mon, 2012-02-20, Keith Thompson wrote:
> > The point is that strncpy is a very different function from strcpy.
> > It is not intended to work with a *string* in the target array;
> > it works with a specialized data structure (used to store file
> > names in very early Unix systems).

>
> Malcolm McLean wrote something similar upthread. Do you have any
> references for this?
>
> It would explain the function's weird semantics, but I haven't seen
> anything before which says this is its background. (There's also
> wcsncpy() for wchar_t -- that one is certainly newer, and useless in
> the data structures you mention.)


I've never seen a reference for that either, but I guessed that this was
its purpose when I first learned the sematics of the function, oh, about
30 years ago, and I've assumed that ever since. Fixed-length Unix file
names are the only place I know of where a string buffer had to be
padded out to its full length with nulls.

> > I think you're understating the differences between strcpy and
> > strncpy. The strncpy function is radically different from strcpy,
> > and there are very few legitimate uses for it. On the other hand,
> > the deceptive name has led many C programmers to use it incorrectly,
> > and I strongly suspect that it's used incorrectly far more often
> > than it's used correctly.

>
> The static analysis tool we use at work screams bloody murder every
> time I use strcpy() and tells me to use strncpy() instead. Argh ...


Aargh! Well, presumably a non-broken fix will shut it up just as well.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
strncpy copying beyond max length atapi103@gmail.com C++ 4 02-01-2005 01:32 PM
the minimum size when using strncpy(...) Simon C++ 3 09-06-2004 01:03 PM
strncpy() and null terminated strings Barry C Programming 4 04-08-2004 05:25 PM
Code Review: strncpy Vijay Kumar R Zanvar C Programming 30 01-19-2004 04:39 PM
Re: bizzare strncpy() sumit.sharma@wipro.com C Programming 4 07-09-2003 01:14 PM



Advertisments