strncpy and 'n'

N

nroberts

Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that? I'm working on a
project that has such uses all throughout it and before I tell the
team leader that he's using a basic C function incorrectly I thought
I'd make sure I'm right.
 
A

Anders Wegge Keller

nroberts said:
Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that?

If you want to avoid havig the '\0' copied from the incoming text,
and risk overrunning buf, there could be a point. But apart from that, no.

I would rather use strncpy like this:

strncpy (buf, incoming, MAX);
buf[MAX] = 0;
I'm working on a project that has such uses all throughout it and
before I tell the team leader that he's using a basic C function
incorrectly I thought I'd make sure I'm right.

Submit some code to www.thedailywtf.com :)
 
K

Keith Thompson

nroberts said:
Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that? I'm working on a
project that has such uses all throughout it and before I tell the
team leader that he's using a basic C function incorrectly I thought
I'd make sure I'm right.

There's rarely *any* reason to use strncpy(). It's not a "safer"
version of strcpy(); it's a quite different function. It can leave
the target buffer without a terminating '\0' (i.e., not a string),
or it can pad it with multiple needless '\0' bytes.

For that particular call, if strlen(incoming) is 10, for example,
it will only copy 10 bytes; it will not copy the terminating '\0'.
If that's what you want (either buf doesn't need to be a string, or
some other code supplies the '\0'), then memcpy() makes more sense.
 
L

lawrence.jones

nroberts said:
Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that?

Maybe, but almost certainly not. If the incoming string is longer than
MAX bytes, you get a buffer overflow, which is very bad. If it happens
to be exactly MAX characters long, you get an unterminated string in
buf, which is bad if the following code (you don't show any, but I
presume there is some or the function is completely pointless) expects
to treat it as a string. And if the incoming string is less than MAX
bytes, since the code doesn't copy the null byte, you get whatever is
leftover in buf tacked on to the end. (buf is initialized to all null
bytes, but since it's static, that only happens once, not on each call.)
 
A

A. K.

nroberts said:
Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that?

If you want to avoid havig the '\0' copied from the incoming text,
and risk overrunning buf, there could be a point. But apart from that, no.

I would rather use strncpy like this:

strncpy (buf, incoming, MAX);
buf[MAX] = 0;

buffer overflow !!! :eek:)
 
M

Markus Schaub

nroberts said:
Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that? I'm working on a
project that has such uses all throughout it and before I tell the
team leader that he's using a basic C function incorrectly I thought
I'd make sure I'm right.

He has probably heard that strcpy() is bad and that he should use
strncpy().

Markus
 
M

Malcolm McLean

There's rarely *any* reason to use strncpy().  It's not a "safer"
version of strcpy(); it's a quite different function.  It can leave
the target buffer without a terminating '\0' (i.e., not a string),
or it can pad it with multiple needless '\0' bytes.
It's designed for databases with fixed fields and non-nul terminated
strings. The padding zeros aren't unnecessary, because often these
databases do a quick match or lookup by applying some algorithm to the
whole field.
 
B

Ben Pfaff

nroberts said:
char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that?

It looks very odd. I think it would be equivalent code if you
replaced "strncpy" by "memcpy" here.

The behavior here make sense for the first call to the function,
if strlen(incoming) < MAX, but it will be strange on subsequent
calls.
 
S

Stephen Sprunk

Consider:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}

Is there ANY reason to use strncpy like that? I'm working on a
project that has such uses all throughout it and before I tell the
team leader that he's using a basic C function incorrectly I thought
I'd make sure I'm right.

Assuming this is representative of the actual code, it's clearly wrong
because strncpy() will overflow buf if strlen(incoming)+1 is greater
than MAX. This means it is no better than strcpy(buf, incoming).

The correct way to write this would be:

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, MAX);
}

Unlike the above code, this guarantees the copy will not overflow buf.

S
 
I

ImpalerCore

Consider:

char const* f(char const* incoming)
{
  static char buf[MAX];

  strncpy(buf, incoming, strlen(incoming));

}

Is there ANY reason to use strncpy like that?  I'm working on a
project that has such uses all throughout it and before I tell the
team leader that he's using a basic C function incorrectly I thought
I'd make sure I'm right.

When you're working with fixed width character buffers, use a fixed
width strlen.

size_t c_strnlen( const char* str, size_t n )
{
const char* p;
p = memchr( str, '\0', n );
return p ? (size_t)( p - str ) : n;
}

Then use the following

strncpy(buf, incoming, c_strnlen(incoming, sizeof (buf)));

Of course, this replaces the potential of a buffer overrun with
truncation, which can lead to other subtle problems.

An alternative is to use something like 'strlcpy', if you want to
guarantee a '\0' character at the end of the string.

Best regards,
John D.
 
K

Keith Thompson

Malcolm McLean said:
It's designed for databases with fixed fields and non-nul terminated
strings. The padding zeros aren't unnecessary, because often these
databases do a quick match or lookup by applying some algorithm to the
whole field.

Yes, the padding zeros are necessary *if* you're dealing with that
kind of data structure.

I suspect that strncpy() is used incorrectly, under the assumption
that it's a "safer" strcpy(), more often than it's used correctly.
IMHO it shouldn't be in the standard library, at least not with
that name.
 
I

Ike Naar

char const* f(char const* incoming)
{
static char buf[MAX];

strncpy(buf, incoming, strlen(incoming));
}
Assuming this is representative of the actual code, it's clearly wrong
because strncpy() will overflow buf if strlen(incoming)+1 is greater
than MAX. This means it is no better than strcpy(buf, incoming).

Nit: it wil overflow if strlen(incoming) is greater than MAX.
It wil not overflow if strlen(incoming) equals MAX.
In that case, it will leave an unterminated string in buf,
but most people wouldn't call that an overflow.
 
N

Nick Keighley

Consider:

char const* f(char const* incoming)
{
  static char buf[MAX];

  strncpy(buf, incoming, strlen(incoming));

}

Is there ANY reason to use strncpy like that?

no. Besides all the other problems the function doesn't return
anything and buf[] is inaccessible. I suspect you meant to return
&buf[0].
 
M

Malcolm McLean

I suspect that strncpy() is used incorrectly, under the assumption
that it's a "safer" strcpy(), more often than it's used correctly.
IMHO it shouldn't be in the standard library, at least not with
that name.
You're right.
There's no point providing strncpy() but not functions like hash() and
faststrncmpwithtrailingzeros() to actually use fixed width strings.
 
J

James Kuyper

You're right.
There's no point providing strncpy() but not functions like hash() and
faststrncmpwithtrailingzeros() to actually use fixed width strings.

What would be the benefits of using faststrncmpwithtrailingzeros()
rather than memcmp() be?
 
M

Malcolm McLean

What would be the benefits of using faststrncmpwithtrailingzeros()
rather than memcmp() be?
That's a point. It documents that you're doing a string compare, but
actually it's the same as memcmp(). On most platforms, it will need
guaranteed integer-aligned fields to be fast, however. That's not
something it's easy to specify in the C standard.
 
M

Malcolm McLean

What would be the benefits of using faststrncmpwithtrailingzeros()
rather than memcmp() be?
If you have long fields with mainly short contents, it could also be
faster, since it can terminate at the first pair of nul bytes.
 
J

James Kuyper

If you have long fields with mainly short contents, it could also be
faster, since it can terminate at the first pair of nul bytes.

If you know that the the end of the string will be determined either by
the end of a fixed-length field, or by a terminating null character,
strncmp(). If you want to check the entire length of the fixed length
field, regardless of null terminators, memcmp() would do. I don't think
that there's sufficient need for a function whose behavior falls
between those two extremes, to make it a standard library function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,184
Latest member
ZNOChrista

Latest Threads

Top