471,086 Members | 1,451 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,086 software developers and data experts.

string concatenation

hi all,

i am writing a code in which i have a char buffer "cwdir[]"
which hold the current working directory by calling the function
getcwd(). later i change the directory to "/" as i have to make my
code Deamon. and later again i want to run some other executable
available at the path holded by the "cwdir[]" using the system()
system call. presently i concatenate program name (to be executed) to
the "cwdir[]" and use system(chdir)to run the program.

do we have any facility to automate this process as i need to run
many other programs also using the system() system call for ex as we
can use the ## symbol to cancatenate in macro ...

--shri
Nov 14 '05 #1
37 8251
sh*********@yahoo.com (Shri) wrote in
news:8a**************************@posting.google.c om:
i am writing a code in which i have a char buffer "cwdir[]"
which hold the current working directory by calling the function
getcwd(). later i change the directory to "/" as i have to make my
code Deamon. and later again i want to run some other executable
available at the path holded by the "cwdir[]" using the system()
system call. presently i concatenate program name (to be executed) to
the "cwdir[]" and use system(chdir)to run the program.

do we have any facility to automate this process as i need to run
many other programs also using the system() system call for ex as we
can use the ## symbol to cancatenate in macro ...


Does strcat() help? If you need fancier concatenation, sprintf() might be
an option.

--
- Mark ->
--
Nov 14 '05 #2
Shri wrote:
i am writing a code in which i have a char buffer "cwdir[]"
which hold the current working directory by calling the function
getcwd(). later i change the directory to "/" as i have to make my
code Deamon. and later again i want to run some other executable
available at the path holded by the "cwdir[]" using the system()
system call. presently i concatenate program name (to be executed) to
the "cwdir[]" and use system(chdir)to run the program.
do we have any facility to automate this process as i need to run
many other programs also using the system() system call for ex as we
can use the ## symbol to cancatenate in macro ...


I *think* that what you are asking for is strcpy(), strcat(), etc.
You might also want to use strdup(), which is not specified in the
C standard but is available in every modern Unix system's C library.
And of course in the Unix (POSIX) system C library is also a family
of exec() functions. Learn to use "man -k", and also study a good
Unix programming text such as Kernighan & Pike.

It should also be noted that you shouldn't be writing programs that
run with elevated privilege (set-UID, daemon) without knowing a lot
more about security loopholes than you seem to be aware of.
Nov 14 '05 #3

"Douglas A. Gwyn" <DA****@null.net> writes:
I *think* that what you are asking for is strcpy(), strcat(), etc.
You might also want to use strdup(), which is not specified in the
C standard but is available in every modern Unix system's C library.
And of course in the Unix (POSIX) system C library is also a family
of exec() functions. Learn to use "man -k", and also study a good
Unix programming text such as Kernighan & Pike.

It should also be noted that you shouldn't be writing programs that
run with elevated privilege (set-UID, daemon) without knowing a lot
more about security loopholes than you seem to be aware of.


Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.

-SEan
Nov 14 '05 #4
Sean Burke <fo****@mystery.org> wrote:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


Not in ISO C, they haven't. Maybe in POSIX.

Richard
Nov 14 '05 #5
Sean Burke wrote:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


If you think that helps very much with security
then you're much mistaken. Presumably the idea is
to prevent buffer overflows, but that can also be
done in many other ways, many of them involving
only the standard C library functions. And anyway
neither an unchecked failure to fill a buffer nor
an unchecked truncation of the contents of a buffer
is very good from the standpoint of security. It's
a big subject, and as usual the attempt to automate
correct programming just changes the symptoms of a
problem without curing the disease.

Nov 14 '05 #6
Sean Burke <fo****@mystery.org> writes:
"Douglas A. Gwyn" <DA****@null.net> writes:
I *think* that what you are asking for is strcpy(), strcat(), etc.
You might also want to use strdup(), which is not specified in the
C standard but is available in every modern Unix system's C library.
And of course in the Unix (POSIX) system C library is also a family
of exec() functions. Learn to use "man -k", and also study a good
Unix programming text such as Kernighan & Pike.

It should also be noted that you shouldn't be writing programs that
run with elevated privilege (set-UID, daemon) without knowing a lot
more about security loopholes than you seem to be aware of.


Since you mention security (e.g. buffer overflows), it's worth
adding that strcpy, strcat have long since been deprecated in favor
of strlcpy, strlcat.


I can't find those anywhere on my system, only strncpy and strncat.
The latter are defined by ISO C.

--
Måns Rullgård
mr*@kth.se
Nov 14 '05 #7
In message <40***************@news.individual.net> of Fri, 13 Feb 2004
08:06:19 in comp.std.c, Richard Bos <rl*@hoekstra-uitgeverij.nl> writes
Sean Burke <fo****@mystery.org> wrote:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


Not in ISO C, they haven't. Maybe in POSIX.


Neither there!
(http://www.opengroup.org/onlinepubs/.../string.h.html)

They ARE documented at http://www.courtesan.com/todd/papers/strlcpy.html

My summary of that is
size_t strlcpy(char *dst, const char *src, size_t size);
Copy a string of up to size-1 bytes from src to dst. Return strlen(src).

size_t strlcat(char *dst, const char *src, size_t size);
Concatenate bytes from src to dst to form a string with strlen(dst) <
size. Return strlen(dst) /* before concatenation */ + strlen(src).

The functions allow buffer overflow elimination.
For a pathological case given, strlcpy is slightly slower than strcpy
and much faster than strncpy because strncpy pads with nul bytes.

The authors added them to OpenBSD in 1996 and report their approval for
a future Solaris version in their undated paper. Source code is said to
be available at ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string

Have the functions been submitted for C standardisation?
--
Walter Briscoe
Nov 14 '05 #8
Walter Briscoe <wb******@ponle.demon.co.uk> wrote:
In message <40***************@news.individual.net> of Fri, 13 Feb 2004
08:06:19 in comp.std.c, Richard Bos <rl*@hoekstra-uitgeverij.nl> writes
Sean Burke <fo****@mystery.org> wrote:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.
Not in ISO C, they haven't. Maybe in POSIX.


Neither there!
(http://www.opengroup.org/onlinepubs/.../string.h.html)

They ARE documented at http://www.courtesan.com/todd/papers/strlcpy.html

My summary of that is
size_t strlcpy(char *dst, const char *src, size_t size);
Copy a string of up to size-1 bytes from src to dst. Return strlen(src).

size_t strlcat(char *dst, const char *src, size_t size);
Concatenate bytes from src to dst to form a string with strlen(dst) <
size. Return strlen(dst) /* before concatenation */ + strlen(src).

The functions allow buffer overflow elimination.


Nice, meaningless statement; so does strncat(), and so does using
strlen() and inserting a '\0' at the right place before using strcpy().
Have the functions been submitted for C standardisation?


No. Might be a nice addition, but I wouldn't describe them as vital.
Mind you, I won't complain if they _are_ added to C20XX.

Richard
Nov 14 '05 #9
Sean Burke <fo****@mystery.org> wrote in message news:<x7************@bolo.xenadyne.com>...
"Douglas A. Gwyn" <DA****@null.net> writes:
I *think* that what you are asking for is strcpy(), strcat(), etc.
You might also want to use strdup(), which is not specified in the
C standard but is available in every modern Unix system's C library.
And of course in the Unix (POSIX) system C library is also a family
of exec() functions. Learn to use "man -k", and also study a good
Unix programming text such as Kernighan & Pike.

It should also be noted that you shouldn't be writing programs that
run with elevated privilege (set-UID, daemon) without knowing a lot
more about security loopholes than you seem to be aware of.


Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


Have they?

They are not present in many frequently used operating systems.

They are not AFAIK part of the C standard, nor are they AFAIK part of
the POSIX standard.
Nov 14 '05 #10
In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.

Whoever wanted to improve upon strcpy and friends should have had enough
clues to avoid identifiers belonging to the implementation name space.

lstrcpy() and lstrcat() would have been ideal names for this purpose.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #11
Da*****@cern.ch (Dan Pop) writes:
In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.


Maybe Mr. Burke misspelled "strncpy" and "strncat", mentioned in
ISO/IEC 9899:1999 under 7.21.2.4 and 7.21.3.2 ? Their prototypes (in
<string.h>) are

char *strncpy(char * restrict, const char * restrict, size_t);
char *strncat(char * restrict, const char * restrict, size_t);

--
Maurizio Loreti http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy ROT13: yb****@cq.vasa.vg
Nov 14 '05 #12
Maurizio Loreti <ml*@foobar.it> writes:
Da*****@cern.ch (Dan Pop) writes:
In <x7************@bolo.xenadyne.com> Sean Burke
<fo****@mystery.org> writes:
>Since you mention security (e.g. buffer overflows),
>it's worth adding that strcpy, strcat have long since
>been deprecated in favor of strlcpy, strlcat.


On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.


Maybe Mr. Burke misspelled "strncpy" and "strncat", mentioned in
ISO/IEC 9899:1999 under 7.21.2.4 and 7.21.3.2 ? Their prototypes (in
<string.h>) are

char *strncpy(char * restrict, const char * restrict, size_t);
char *strncat(char * restrict, const char * restrict, size_t);


Maybe he meant those, but the non-standard strl* variants are more
useful. The return values from the standard str* functions are
utterly useless, since you already knew the value. Returning the
number bytes copied is much more useful. BTW, str*cat should be used
sparingly. In most cases you have, or can easily get (cheaper than
scanning), a pointer to the end of the destination string.

--
Måns Rullgård
mr*@kth.se
Nov 14 '05 #13

Maurizio Loreti <ml*@foobar.it> writes:
Da*****@cern.ch (Dan Pop) writes:
In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.


Maybe Mr. Burke misspelled "strncpy" and "strncat", mentioned in
ISO/IEC 9899:1999 under 7.21.2.4 and 7.21.3.2 ? Their prototypes (in
<string.h>) are

char *strncpy(char * restrict, const char * restrict, size_t);
char *strncat(char * restrict, const char * restrict, size_t);


No, I meant strlcpy/strlcat, and I find them to be better
than the strn* calls. I'm astonished to learn that they
aren't yet standardised.

-SEan

Nov 14 '05 #14

rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
Walter Briscoe <wb******@ponle.demon.co.uk> wrote:
In message <40***************@news.individual.net> of Fri, 13 Feb 2004
08:06:19 in comp.std.c, Richard Bos <rl*@hoekstra-uitgeverij.nl> writes
Sean Burke <fo****@mystery.org> wrote:

> Since you mention security (e.g. buffer overflows),
> it's worth adding that strcpy, strcat have long since
> been deprecated in favor of strlcpy, strlcat.

Not in ISO C, they haven't. Maybe in POSIX.


Neither there!
(http://www.opengroup.org/onlinepubs/.../string.h.html)

They ARE documented at http://www.courtesan.com/todd/papers/strlcpy.html

My summary of that is
size_t strlcpy(char *dst, const char *src, size_t size);
Copy a string of up to size-1 bytes from src to dst. Return strlen(src).

size_t strlcat(char *dst, const char *src, size_t size);
Concatenate bytes from src to dst to form a string with strlen(dst) <
size. Return strlen(dst) /* before concatenation */ + strlen(src).

The functions allow buffer overflow elimination.


Nice, meaningless statement; so does strncat(), and so does using
strlen() and inserting a '\0' at the right place before using strcpy().
Have the functions been submitted for C standardisation?


No. Might be a nice addition, but I wouldn't describe them as vital.
Mind you, I won't complain if they _are_ added to C20XX.


Don't tell me that snprintf, vsnprintf() are also nonstandard?

-SEan

Nov 14 '05 #15
Sean Burke wrote:
....
Don't tell me that snprintf, vsnprintf() are also nonstandard?


No: see sections 7.19.6.5 and 7.19.6.12.
Nov 14 '05 #16

In article <c0**********@sunnews.cern.ch>, Da*****@cern.ch (Dan Pop) writes:
In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.

Whoever wanted to improve upon strcpy and friends should have had enough
clues to avoid identifiers belonging to the implementation name space.


Presumably in at least some cases they could be provided by the
implementation, and in such a case programs using them would not
invoke UB, correct? This could potentially raise some tricky
questions about what is and what is not part of the implementation, I
suppose.

That said, I agree with the general point. An implementor has reason
to use a reserved identifier for a new function (it won't break
existing conforming code), but no one else does. I suppose someone
could argue that Miller and de Raadt were implementors when they
invented strlcpy and strlcat and added them to OpenBSD, since AFAICT
they added them directly to the standard library there, but their
choice of identifiers means non-implementors have to rename their
functions when porting them to other implementations.

--
Michael Wojcik mi************@microfocus.com

Pocket #9: A complete "artificial glen" with rocks, and artificial moon,
and forester's station. Excellent for achieving the effect of the
sublime without going out-of-doors. -- Joe Green
Nov 14 '05 #17
On Fri, 13 Feb 2004 10:19:47 +0000, Walter Briscoe wrote:

They ARE documented at http://www.courtesan.com/todd/papers/strlcpy.html

My summary of that is
size_t strlcpy(char *dst, const char *src, size_t size); Copy a string of
up to size-1 bytes from src to dst. Return strlen(src).

size_t strlcat(char *dst, const char *src, size_t size); Concatenate bytes
from src to dst to form a string with strlen(dst) < size. Return
strlen(dst) /* before concatenation */ + strlen(src).
All the documentation, including the above, is laughable compared to
normal std. C text. Which is probably why there are a couple of different
implementations and the two major non OpenBSD implementations are
_documented_ to act differently than the OpenBSD versions do.
The functions allow buffer overflow elimination. For a pathological case
given, strlcpy is slightly slower than strcpy and much faster than strncpy
because strncpy pads with nul bytes.
IMO they are even more worthless than asprintf(), they are documented
to act differently on different platforms and (unlike asprintf() you can
still cause security issues due to truncation of data).
The authors added them to OpenBSD in 1996 and report their approval for a
future Solaris version in their undated paper. Source code is said to be
available at ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string


The "undated" paper has references to papers published in 1998, and says:

"The strlcpy() and strlcat() functions first appeared in OpenBSD 2.4."

....which dates them between May 19, and December 1, 1998. People
_started_ to hear of them after the 1999 Usenix when the paper...

http://www.usenix.org/events/usenix9...rt/millert.pdf

....was presented, which even then as way too late for C99 ... and I don't
remember hearing about them until 2000 (which was after the last std. was
released).

--
James Antill -- ja***@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

Nov 14 '05 #18
On Fri, 13 Feb 2004 17:12:51 +0000, Sean Burke wrote:
No, I meant strlcpy/strlcat, and I find them to be better than the strn*
calls. I'm astonished to learn that they aren't yet standardised.


Not only are they not in std. C, they aren't available at all on any
of the major Linux variants. They also are/were implemented subtly
differently on Solaris.

You probably also want to read:

http://www.and.org/vstr/security.html#alloc

--
James Antill -- ja***@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

Nov 14 '05 #19
James Antill <ja***********@and.org> writes:
Not only are they not in std. C, they aren't available at all on any
of the major Linux variants. They also are/were implemented subtly
differently on Solaris.


They weren't implemented subtly different on Solaris; our implementation
is a straightforward clone from the original OpenBSD version and behaves
exactly the same.

You may be confused with "snprintf()" where Solaris originally
implemented it differently for "n = 0"; UNIX98 standardized
snprintf that it should return a value <= 0 for n = 0 and we're
a bit of a stickler for standards.

UNIX03 fixes that, fortunately, so the Solaris release will
have an snprintf which allows you to call it as follows:

size_t len = snprintf(0, NULL, .....);

to compute the length needed (note that snprintf can return
"-1" and set errno to EILSEQ.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Nov 14 '05 #20
James Antill <ja***********@and.org> writes:
All the documentation, including the above, is laughable compared to
normal std. C text. Which is probably why there are a couple of different
implementations and the two major non OpenBSD implementations are
_documented_ to act differently than the OpenBSD versions do.

Please cite the specific differences between the implementations;
I don't know of any.
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Nov 14 '05 #21
On Sat, 14 Feb 2004 09:37:56 +0000, Casper H. S. Dik wrote:
James Antill <ja***********@and.org> writes:
Not only are they not in std. C, they aren't available at all on any
of the major Linux variants. They also are/were implemented subtly
differently on Solaris.


They weren't implemented subtly different on Solaris; our implementation
is a straightforward clone from the original OpenBSD version and behaves
exactly the same.


That's what I would have expected, but I'd heard that they were
reimplemented to follow the "spec" and the return value was different in
the Solaris version[1].
I don't have access to a Solaris machine to check, and I apologize if
that wasn't the case.

[1]

http://www.dwheeler.com/secure-progr...c.html#STRLCPY

--
James Antill -- ja***@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

Nov 14 '05 #22
On Sat, 14 Feb 2004 09:41:31 +0000, Casper H. S. Dik wrote:
James Antill <ja***********@and.org> writes:
All the documentation, including the above, is laughable compared to
normal std. C text. Which is probably why there are a couple of different
implementations and the two major non OpenBSD implementations are
_documented_ to act differently than the OpenBSD versions do.


Please cite the specific differences between the implementations; I don't
know of any.


The "well known" one is the return value for strlcat(), see...

http://www.dwheeler.com/secure-progr...c.html#STRLCPY
http://docs.sun.com/db/doc/806-0627/...indexterm-1028
http://docs.sun.com/db/doc/816-0213/...indexterm-1099

....the later two links might mean that this has changed for 2.9 but
my reading of it doesn't suggest that. However even though glib commits
said they followed the Solaris spec. the code is basically the same as
that in OpenBSD, so i guess there's movement for Solaris to change.

Of course there's always...

http://www.oreillynet.com/pub/a/netw...eprogckbk.html

....where the strlcat() function is just broken.

--
James Antill -- ja***@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

Nov 14 '05 #23
James Antill <ja***********@and.org> writes:
On Sat, 14 Feb 2004 09:41:31 +0000, Casper H. S. Dik wrote:
James Antill <ja***********@and.org> writes:
All the documentation, including the above, is laughable compared to
normal std. C text. Which is probably why there are a couple of different
implementations and the two major non OpenBSD implementations are
_documented_ to act differently than the OpenBSD versions do.


Please cite the specific differences between the implementations; I don't
know of any.

The "well known" one is the return value for strlcat(), see... http://www.dwheeler.com/secure-progr...c.html#STRLCPY
http://docs.sun.com/db/doc/806-0627/...indexterm-1028
http://docs.sun.com/db/doc/816-0213/...indexterm-1099


For the bogus "size = 0" case; you can't have a string that takes 0 bytes
of storage. I don't consider that a serious impediment to portable
programming because the strlcat with a size == 0 argument is something that
I do not expect to happen.

Any call of "strlcat(dst, src, len)" where strlen(dst) >= len is suspect
and I would call any results in that domain "unspecified" and certainly not
any obstacle to using the functions in portable programs. Certainly not
sufficient to give this fact that much attention.

Come to think of it, abort() is possibly the better way to handle this.

Strange that the Solaris source does reference beyond the "len" in dest
because I distinctly remember telling Theo and Todd about the OpenBSD source
doing the same when we were about to implement it in Solaris.

you can find this fact in the CVS commit history at:

http://www.openbsd.org/cgi-bin/cvswe...ring/strlcat.c

rev 1.2

A case of "do as I say, not do as I do", I guess; I see about
getting us to follow suit.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Nov 14 '05 #24
nrk
Richard Bos wrote:
Sean Burke <fo****@mystery.org> wrote:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


Not in ISO C, they haven't. Maybe in POSIX.

Richard


I was introduced to them by someone who worked on *BSD platforms quite a
bit, and ended up writing equivalents of my own. This being a boring
afternoon, here's my implementation of strlcpy and strlcat. Comments most
likely lifted from *BSD sources as I am always too lazy to write them
myself. As everyone knows, my code *never* has any bugs :-)

strlcpy.c:
#include <stddef.h>

/*
* Copies src to string dst of size sz. sz is the full size of dst
* including the NUL character. At most sz-1 characters will be
* copied. Always NUL terminates dst, and doesn't fill dst with NULs
* like strncpy when sz > strlen(src). src *MUST* be a valid NUL
* terminated string.
*
* Returns strlen(src).
*
* If retval >= sz, truncation occurred.
*/
size_t strlcpy(char *dst, const char *src, size_t sz) {
register char *d = dst;
register const char *s = src;
register size_t n = sz;

if ( n ) {
--n;
while ( n && *s ) *d++ = *s++, --n;
*d = 0;
}

while ( *s++ );

return s - src - 1;
}

strlcat.c:

#include <stddef.h>

/*
* Appends src to string dst of size sz (unlike strncat, sz is the
* full size of dst, not space left). At most sz-1 characters will be
* copied. Always NUL terminates (unless sz <= strlen(dst)).
*
* Returns strlen(src) + MIN(sz, strlen(initial dst)).
*
* If retval >= sz, truncation occurred.
*/
size_t strlcat(char *dst, const char *src, size_t sz) {
register char *d = dst;
register const char *s = src;
register size_t n = sz;

if ( n ) {
--n;
while ( n && *d ) ++d, --n;
if ( n ) {
while ( n && *s ) *d++ = *s++, --n;
*d = 0;
}
n = d - dst + (*d != 0);
}

src = s;
while ( *s++ ) ;

return n + (s - src - 1);
}

-nrk.

--
Remove devnull for email
Nov 14 '05 #25

James Antill <ja***********@and.org> writes:
On Fri, 13 Feb 2004 17:12:51 +0000, Sean Burke wrote:
No, I meant strlcpy/strlcat, and I find them to be better than the strn*
calls. I'm astonished to learn that they aren't yet standardised.


Not only are they not in std. C, they aren't available at all on any
of the major Linux variants. They also are/were implemented subtly
differently on Solaris.

You probably also want to read:

http://www.and.org/vstr/security.html#alloc


An excellent summary of the reasons why strlcpy/cat are valuable.
I don't think availability is much of a problem either, since the
OpenBSD implementations are:

- Free as in beer
- Free as in speech
- A whopping 30 lines of code apiece.

-SEan




Nov 14 '05 #26
nrk wrote:
* ... Always NUL terminates dst, ...
Not when sz==0.
* .... src *MUST* be a valid NUL terminated string.


It doesn't need to be. It must point to at least sz-1
bytes and is terminated by the first 0-valued byte.

If this stuff is supposed to be used for safety-critical
programming, its interface specification should be
accurate. Also, once you fix it up you should see that
both example functions have behavior that is relatively
complicated to describe, which makes it relatively
difficult to use in provably correct algorithms.

It would be much better if a function either completes
a simply described task or else does nothing and reports
failure.

Nov 14 '05 #27
nrk
Douglas A. Gwyn wrote:
nrk wrote:
* ... Always NUL terminates dst, ...
Not when sz==0.


When sz == 0, there is no space to put the terminating NUL. I think that's
sort of self-evident :-)
* .... src *MUST* be a valid NUL terminated string.


It doesn't need to be. It must point to at least sz-1
bytes and is terminated by the first 0-valued byte.


From the relevant code:
register const char *s = src;
...
while ( *s++ );

Seems to me that nasal demons shall fly if src is not NUL terminated. Or
are you saying the specification needs to be changed? What am I missing?
The whole point is that you could send a src string that's larger than your
destination, in which case the copy is still safe, but the return value
tells you that truncation occurred.
If this stuff is supposed to be used for safety-critical
programming, its interface specification should be
accurate. Also, once you fix it up you should see that
both example functions have behavior that is relatively
complicated to describe, which makes it relatively
difficult to use in provably correct algorithms.

The only questionably difficult interface is strlcat. But the difficult
situation shouldn't arise in "well-behaved" programs (it happens when you
pass in a size for the destination that is <= strlen(destination)). As for
correctness, you can guarantee that the functions will:
a) Never write more than what you specify in the sz parameter
b) Result in NUL terminated dst (with the exception above)
c) Clearly report truncation whenever it occurs
It would be much better if a function either completes
a simply described task or else does nothing and reports
failure.


These are supposed to be analogous to strncpy and strncat. Under those
circumstances, I am not sure what failure means. My guess is that it's up
to the user to determine what constitutes failure and what actions to take.
Hence the design that says we'll do our best and tell the user that not
everything was ok. It's upto the user to decide then what to do with that
information. IMHO these functions (not particularly my implementations
though) are quite well thought out and well designed. They do report
"failure" (assuming that means truncation), simply and quite effectively.
I don't understand why you would bother with functional specifications of
what they do to dst when you are solely interested in distinguishing
"failure" and "success".

-nrk.

--
Remove devnull for email
Nov 14 '05 #28
In <c0*********@enews1.newsguy.com> mw*****@newsguy.com (Michael Wojcik) writes:

In article <c0**********@sunnews.cern.ch>, Da*****@cern.ch (Dan Pop) writes:
In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
>Since you mention security (e.g. buffer overflows),
>it's worth adding that strcpy, strcat have long since
>been deprecated in favor of strlcpy, strlcat.
On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.

Whoever wanted to improve upon strcpy and friends should have had enough
clues to avoid identifiers belonging to the implementation name space.


Presumably in at least some cases they could be provided by the
implementation, and in such a case programs using them would not
invoke UB, correct?


Wrong. Calling such a function *unconditionally* invokes undefined
behaviour.
This could potentially raise some tricky
questions about what is and what is not part of the implementation, I
suppose.


For the purpose of our discussion, it is enough that the function in
question is not part of the standard C library.

An implementation is free to provide such a function as an extension
without having its conformance affected, but *any* code using it invokes
undefined behaviour.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #29
mw*****@newsguy.com (Michael Wojcik) wrote in message news:<c0*********@enews1.newsguy.com>...
In article <c0**********@sunnews.cern.ch>, Da*****@cern.ch (Dan Pop) writes:
In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
Since you mention security (e.g. buffer overflows),
it's worth adding that strcpy, strcat have long since
been deprecated in favor of strlcpy, strlcat.


On the contrary, any C program using these identifiers with external
linkage invokes undefined behaviour.

Whoever wanted to improve upon strcpy and friends should have had enough
clues to avoid identifiers belonging to the implementation name space.


Presumably in at least some cases they could be provided by the
implementation, and in such a case programs using them would not
invoke UB, correct? This could potentially raise some tricky


You need to be careful when you read the standard, it contains many
pieces of technical jargon which are defined by the standard itself to
mean something not quite the same as the ordinary english definition.
This is one example. "undefined behavior" doesn't mean "behavior that
is undefined"; it's a piece of technical jargon used by the C
standard, which roughly means "behavior that is not defined by the C
standard".
The behavior of such code remains UB even if the implementation
chooses to provide it's own definition. UB includes, as one of it's
literal infinity of possibilities, behaving exactly as the
implementation has defined it to behave.
Nov 14 '05 #30

In article <8b**************************@posting.google.com >, ku****@wizard.net (James Kuyper) writes:
mw*****@newsguy.com (Michael Wojcik) wrote in message news:<c0*********@enews1.newsguy.com>...
Presumably in at least some cases they could be provided by the
implementation, and in such a case programs using them would not
invoke UB, correct?
You need to be careful when you read the standard, it contains many
pieces of technical jargon which are defined by the standard itself to
mean something not quite the same as the ordinary english definition.
This is one example. "undefined behavior" doesn't mean "behavior that
is undefined"; it's a piece of technical jargon used by the C
standard, which roughly means "behavior that is not defined by the C
standard".


Right. I understood that...
The behavior of such code remains UB even if the implementation
chooses to provide it's own definition. UB includes, as one of it's
literal infinity of possibilities, behaving exactly as the
implementation has defined it to behave.


....but missed this bit when I glanced over the Standard before posting
that message. I somehow got the impression that if the implementation
provided additional str* functions (with external linkage), a program
running under that implementation could invoke them without causing UB.
Which doesn't make much sense, now that I think about it.

(Thanks also to Dan for posting a similar correction.)

--
Michael Wojcik mi************@microfocus.com

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
-- David Bonde
Nov 14 '05 #31

Brian Inglis <Br**********@SystematicSw.Invalid> writes:
On Fri, 13 Feb 2004 17:12:51 GMT in comp.std.c, Sean Burke
<fo****@mystery.org> wrote:

Maurizio Loreti <ml*@foobar.it> writes:
Da*****@cern.ch (Dan Pop) writes:

> In <x7************@bolo.xenadyne.com> Sean Burke <fo****@mystery.org> writes:
>
> >Since you mention security (e.g. buffer overflows),
> >it's worth adding that strcpy, strcat have long since
> >been deprecated in favor of strlcpy, strlcat.
You mispelled n as noted below.
On the contrary, any C program using these identifiers with external
> linkage invokes undefined behaviour.

Maybe Mr. Burke misspelled "strncpy" and "strncat", mentioned in
ISO/IEC 9899:1999 under 7.21.2.4 and 7.21.3.2 ? Their prototypes (in
<string.h>) are

char *strncpy(char * restrict, const char * restrict, size_t);
char *strncat(char * restrict, const char * restrict, size_t);


No, I meant strlcpy/strlcat, and I find them to be better
than the strn* calls. I'm astonished to learn that they
aren't yet standardised.


You must be one of those Pascal types who like to access strings as
character arrays with indices, instead of pointers as K&R intended.
You wouldn't have liked BCPL, B, or NB either! ;^>

The BSD string functions strl{cat,cpy} are unlikely to be standardised
as they aren't supported by many libraries, and don't fit with any of
the current string handling functions, except strspn() and strcspn(),
which are also not heavily advertised or used, as their names are
confusing, nondescriptive, unobvious, and they too return counts
instead of pointers.

In any case, I prefer to check my string lengths before I do anything
with strcpy(); strncpy()'s handy for clearing previous junk from
buffers; never need strcat(), as I like to know where I am, and going
to be in a buffer. Avoids buffer overflows, heap and stack overwrites,
SIGSEGV, ACCVIO, and other unpleasantries, don't ya know.


I'm not sure why you've revived this long-dormant thread.
As far as factual matters go, I recall that the upshot of
the discussion was that:

1. strcpy/strcat have not been formally deprecated in the
C standard

2. strlcpy/strlcat have not been incorporated into the
C standard

As far as matters of preference go, if you find strncpy/ncat
adequate for your needs, that's great. I agree that strlen()
alone is sufficient to avoid overflows with strcpy/cat, as
long as you are careful.

I find that code using strlcpy/lcat is cleaner and less
susceptible to error, but YMMV.

Oh, and as for strspn, strcspn - I find these are very useful
functions, but it's another example of the power of idiom in
programming. It took me a long time to notice that I could
this, for example:

if (strspn(argv[i], "-0123456789") != strlen(argv[i]))
fprintf(stderr, "The argument \"%s\" must be a decimal integer.\n", argv[i]);

-SEan




Nov 14 '05 #32
Brian Inglis wrote:
.... snip ...
The BSD string functions strl{cat,cpy} are unlikely to be
standardised as they aren't supported by many libraries, and don't
fit with any of the current string handling functions, except
strspn() and strcspn(), which are also not heavily advertised or
used, as their names are confusing, nondescriptive, unobvious, and
they too return counts instead of pointers.


Which (return values) is precisely why they should be used in
preference to the already available standard routines. They
greatly reduce the prevalence of errors. They are also easily
implemented with purely standard C and no library dependencies, so
there is no reason to eschew them. For one implementation (put in
public domain) see:

<http://cbfalconer.home.att.net/download/strlcpy.zip>

For justifications for their use, etc, see:

<http://www.courtesan.com/todd/papers/strlcpy.html>

If your system has these routines, congratulations. If not, feel
free to mount mine. In either case using them will reduce your
error rate.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #33
Sean Burke <fo****@mystery.org> writes:
[...]
Oh, and as for strspn, strcspn - I find these are very useful
functions, but it's another example of the power of idiom in
programming. It took me a long time to notice that I could
this, for example:

if (strspn(argv[i], "-0123456789") != strlen(argv[i]))
fprintf(stderr,
"The argument \"%s\" must be a decimal integer.\n",
argv[i]);


[code reformatted to fit screen]

That's fine if you consider "3-2", "---", and "" to be decimal integers.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #34
# > if (strspn(argv[i], "-0123456789") != strlen(argv[i]))
# > fprintf(stderr,
# > "The argument \"%s\" must be a decimal integer.\n",
# > argv[i]);
#
# [code reformatted to fit screen]
#
# That's fine if you consider "3-2", "---", and "" to be decimal integers.

if (strtol(p,&q,0), p==q) not an integer
else if (*q) integer followed by something else
else an integer

--
Derk Gwen http://derkgwen.250free.com/html/index.html
We found a loophole; they can't keep us out anymore.
Nov 14 '05 #35

Derk Gwen <de******@HotPOP.com> writes:
# > if (strspn(argv[i], "-0123456789") != strlen(argv[i]))
# > fprintf(stderr,
# > "The argument \"%s\" must be a decimal integer.\n",
# > argv[i]);
#
# [code reformatted to fit screen]
#
# That's fine if you consider "3-2", "---", and "" to be decimal integers.

if (strtol(p,&q,0), p==q) not an integer
else if (*q) integer followed by something else
else an integer


Anyone who knows how to use strtol doesn't need advice from me. :-)
But how many people just pass the argument to atoi() and let any
problems manifest themselves further along?

I think the method I illustrated has the virtue of being a
"pretty good" filter, while also being much more widely
applicable than strtol().

Suppose I want to accept an IP address, but I want to ensure
that it's not a domain name:

if (strspn(argv[i], ".0123456789") != strlen(argv[i]))
fprintf(stderr, "Arg \"%s\" must be an numeric IP address.\n", argv[i]);

Sure, "...0" would pass this filter, but the chief goal is
to reject "foo.bar.com". Yes, I could use inet_addr() instead,
but what does inet_addr() do with "9.37.190.192.in-addr.arpa"?

Certainly, regcomp/regexec provide a filtering method that can
be both precise and very general. But strspn/cspn() provide a
useful balance of precision and convenience.

-SEan


Nov 14 '05 #36

Derk Gwen <de******@HotPOP.com> writes:
# > if (strspn(argv[i], "-0123456789") != strlen(argv[i]))
# > fprintf(stderr,
# > "The argument \"%s\" must be a decimal integer.\n",
# > argv[i]);
#
# [code reformatted to fit screen]
#
# That's fine if you consider "3-2", "---", and "" to be decimal integers.

if (strtol(p,&q,0), p==q) not an integer
else if (*q) integer followed by something else
else an integer


Anyone who knows how to use strtol doesn't need advice from me. :-)
But how many people just pass the argument to atoi() and let any
problems manifest themselves further along?

I think the method I illustrated has the virtue of being a
"pretty good" filter, while also being much more widely
applicable than strtol().

Suppose I want to accept an IP address, but I want to ensure
that it's not a domain name:

if (strspn(argv[i], ".0123456789") != strlen(argv[i]))
fprintf(stderr, "Arg \"%s\" must be an numeric IP address.\n", argv[i]);

Sure, "...0" would pass this filter, but the chief goal is
to reject "foo.bar.com". Yes, I could use inet_addr() instead,
but what does inet_addr() do with "9.37.190.192.in-addr.arpa"?

Certainly, regcomp/regexec provide a filtering method that can
be both precise and very general. But strspn/cspn() provide a
useful balance of precision and convenience.

-SEan


Nov 14 '05 #37
>>> Sean Burke wrote:

SB> Sure, "...0" would pass this filter, but the chief goal is
SB> to reject "foo.bar.com". Yes, I could use inet_addr() instead,
SB> but what does inet_addr() do with "9.37.190.192.in-addr.arpa"?

$ host 127.0.0.1
1.0.0.127.IN-ADDR.ARPA domain name pointer localhost
$ ping 1.0.0.127.in-addr.arpa
ping: cannot resolve 1.0.0.127.in-addr.arpa: No address associated with name

Feel the difference between asking A and PTR ;)
-netch-
Nov 14 '05 #38

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Jonas Galvez | last post: by
20 posts views Thread by hagai26 | last post: by
3 posts views Thread by John Ford | last post: by
9 posts views Thread by Justin M. Keyes | last post: by
16 posts views Thread by Mark A. Sam | last post: by
12 posts views Thread by Richard Lewis Haggard | last post: by
34 posts views Thread by Larry Hastings | last post: by
10 posts views Thread by =?Utf-8?B?RWxlbmE=?= | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.