Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #93090 > unrolled thread
| Started by | will hunt <glovepm@gmail.com> |
|---|---|
| First post | 2016-09-01 18:50 -0700 |
| Last post | 2016-09-14 00:24 +0000 |
| Articles | 20 on this page of 76 — 21 participants |
Back to article view | Back to comp.lang.c
How to copy a string safely and efficiently in C? will hunt <glovepm@gmail.com> - 2016-09-01 18:50 -0700
Re: How to copy a string safely and efficiently in C? John Gordon <gordon@panix.com> - 2016-09-02 01:58 +0000
Re: How to copy a string safely and efficiently in C? will hunt <glovepm@gmail.com> - 2016-09-01 19:40 -0700
Re: How to copy a string safely and efficiently in C? Geoff <geoff@invalid.invalid> - 2016-09-01 20:29 -0700
Re: How to copy a string safely and efficiently in C? James Kuyper <jameskuyper@verizon.net> - 2016-09-02 12:29 -0400
Re: How to copy a string safely and efficiently in C? asetofsymbols@gmail.com - 2016-09-12 13:09 -0700
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-12 15:30 -0700
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-01 23:08 -0700
Re: How to copy a string safely and efficiently in C? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-04 23:59 -0700
Re: How to copy a string safely and efficiently in C? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-09-01 21:12 -0600
Re: How to copy a string safely and efficiently in C? <william@wilbur.25thandClement.com> - 2016-09-01 22:12 -0700
Re: How to copy a string safely and efficiently in C? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-01 23:58 -0700
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-02 10:42 +0100
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 22:23 -0700
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-04 23:20 -0700
Re: How to copy a string safely and efficiently in C? mark.bluemel@gmail.com - 2016-09-05 01:03 -0700
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-05 01:46 -0700
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-05 10:30 +0100
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-10 11:25 -0700
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-11 06:23 -0700
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-11 15:41 -0700
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-11 23:40 -0700
Re: How to copy a string safely and efficiently in C? Ian Collins <ian-news@hotmail.com> - 2016-09-12 21:04 +1200
Re: How to copy a string safely and efficiently in C? Melzzzzz <Melzzzzz@zzzzz.com> - 2016-09-12 09:21 +0000
Re: How to copy a string safely and efficiently in C? Ian Collins <ian-news@hotmail.com> - 2016-09-12 21:33 +1200
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-12 10:41 +0100
Re: How to copy a string safely and efficiently in C? Melzzzzz <Melzzzzz@zzzzz.com> - 2016-09-12 10:48 +0000
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-12 07:04 -0700
Re: How to copy a string safely and efficiently in C? Richard Heathfield <rjh@cpax.org.uk> - 2016-09-02 12:36 +0100
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-02 14:24 +0100
Re: How to copy a string safely and efficiently in C? Richard Heathfield <rjh@cpax.org.uk> - 2016-09-02 14:51 +0100
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 23:42 -0700
Re: How to copy a string safely and efficiently in C? Richard Heathfield <rjh@cpax.org.uk> - 2016-09-02 18:05 +0100
Re: How to copy a string safely and efficiently in C? Ike Naar <ike@iceland.freeshell.org> - 2016-09-02 19:48 +0000
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 01:45 +0000
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-13 11:06 +0100
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 14:09 +0000
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-13 15:30 +0100
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 14:52 +0000
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 14:54 +0000
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-13 17:18 +0100
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 18:15 +0000
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-13 20:30 -0700
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-15 14:03 +0000
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-15 12:32 -0700
Re: How to copy a string safely and efficiently in C? luser droog <luser.droog@gmail.com> - 2016-09-15 12:45 -0700
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-15 13:00 -0700
Re: How to copy a string safely and efficiently in C? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-09-15 14:52 -0600
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-15 16:04 -0700
Re: How to copy a string safely and efficiently in C? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-09-15 15:52 -0600
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-15 17:07 -0700
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-15 15:53 -0700
Re: How to copy a string safely and efficiently in C? Richard Heathfield <rjh@cpax.org.uk> - 2016-09-15 22:17 +0100
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-15 17:01 -0700
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-15 16:36 -0700
Re: How to copy a string safely and efficiently in C? Keith Thompson <kst-u@mib.org> - 2016-09-15 19:19 -0700
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-15 21:39 -0700
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-16 06:17 -0700
Re: How to copy a string safely and efficiently in C? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-09-16 07:04 -0700
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-16 09:11 -0700
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-22 22:24 -0700
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-19 15:15 +0000
Re: How to copy a string safely and efficiently in C? Richard Damon <Richard@Damon-Family.org> - 2016-09-13 08:19 -0400
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 14:07 +0000
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-13 07:57 -0700
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-13 17:33 +0100
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 18:13 +0000
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-13 11:30 -0700
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 20:03 +0000
Re: How to copy a string safely and efficiently in C? supercat@casperkitty.com - 2016-09-13 13:38 -0700
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-13 21:39 +0000
Re: How to copy a string safely and efficiently in C? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-13 23:26 +0100
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-13 16:14 -0700
Re: How to copy a string safely and efficiently in C? BartC <bc@freeuk.com> - 2016-09-13 15:59 +0100
Re: How to copy a string safely and efficiently in C? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-13 16:07 -0700
Re: How to copy a string safely and efficiently in C? cross@spitfire.i.gajendra.net (Dan Cross) - 2016-09-14 00:24 +0000
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-11 15:41 -0700 |
| Message-ID | <00a7e7b0-6557-4ca2-8e7c-a9eb51b61fc8@googlegroups.com> |
| In reply to | #93370 |
On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: > I would say that slightly differently. The return value of > strcpy() (and other str...() functions) is rarely used, because > people forget that these functions return a result. In many (or > most?) cases that happens because people are used to thinking > imperatively more than functionally. These return values are > actually useful noticeably more often than they are used. The functions return the pointer that was passed in, and thus represents something that the code already had. It may in some cases allow some things to be done in initialization expression which would otherwise require statements, but that's about the extent of their usefulness. Returning the address of the trailing 0 byte would have been more helpful, but that's not what the functions do.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-11 23:40 -0700 |
| Message-ID | <kfntwdlk4e1.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93381 |
supercat@casperkitty.com writes: > On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: >> I would say that slightly differently. The return value of >> strcpy() (and other str...() functions) is rarely used, because >> people forget that these functions return a result. In many (or >> most?) cases that happens because people are used to thinking >> imperatively more than functionally. These return values are >> actually useful noticeably more often than they are used. > > The functions return the pointer that was passed in, [...] I've heard this broken record before. It isn't any more interesting or convincing the eleventh time than it was the first ten times.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2016-09-12 21:04 +1200 |
| Message-ID | <e3n9crFbgeqU1@mid.individual.net> |
| In reply to | #93382 |
On 09/12/16 06:40 PM, Tim Rentsch wrote: > supercat@casperkitty.com writes: > >> On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: >>> I would say that slightly differently. The return value of >>> strcpy() (and other str...() functions) is rarely used, because >>> people forget that these functions return a result. In many (or >>> most?) cases that happens because people are used to thinking >>> imperatively more than functionally. These return values are >>> actually useful noticeably more often than they are used. >> >> The functions return the pointer that was passed in, [...] > > I've heard this broken record before. It isn't any more > interesting or convincing the eleventh time than it was > the first ten times. The Unix standard folks appear to think differently: "The stpcpy() function shall return a pointer to the terminating NUL character copied into the s1 buffer." http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html -- Ian
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <Melzzzzz@zzzzz.com> |
|---|---|
| Date | 2016-09-12 09:21 +0000 |
| Message-ID | <nr5s2u$1b9$8@news.albasani.net> |
| In reply to | #93387 |
On 2016-09-12, Ian Collins <ian-news@hotmail.com> wrote: > On 09/12/16 06:40 PM, Tim Rentsch wrote: >> supercat@casperkitty.com writes: >> >>> On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: >>>> I would say that slightly differently. The return value of >>>> strcpy() (and other str...() functions) is rarely used, because >>>> people forget that these functions return a result. In many (or >>>> most?) cases that happens because people are used to thinking >>>> imperatively more than functionally. These return values are >>>> actually useful noticeably more often than they are used. >>> >>> The functions return the pointer that was passed in, [...] >> >> I've heard this broken record before. It isn't any more >> interesting or convincing the eleventh time than it was >> the first ten times. > > The Unix standard folks appear to think differently: > > "The stpcpy() function shall return a pointer to the terminating NUL > character copied into the s1 buffer." > > http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html > Hm, gcc returns pointer to result. What does this means? We can't rely on what strcpy returns?
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2016-09-12 21:33 +1200 |
| Message-ID | <e3nb2lFbgeqU2@mid.individual.net> |
| In reply to | #93388 |
On 09/12/16 09:21 PM, Melzzzzz wrote: > On 2016-09-12, Ian Collins <ian-news@hotmail.com> wrote: >> On 09/12/16 06:40 PM, Tim Rentsch wrote: >>> supercat@casperkitty.com writes: >>> >>>> On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: >>>>> I would say that slightly differently. The return value of >>>>> strcpy() (and other str...() functions) is rarely used, because >>>>> people forget that these functions return a result. In many (or >>>>> most?) cases that happens because people are used to thinking >>>>> imperatively more than functionally. These return values are >>>>> actually useful noticeably more often than they are used. >>>> >>>> The functions return the pointer that was passed in, [...] >>> >>> I've heard this broken record before. It isn't any more >>> interesting or convincing the eleventh time than it was >>> the first ten times. >> >> The Unix standard folks appear to think differently: >> >> "The stpcpy() function shall return a pointer to the terminating NUL >> character copied into the s1 buffer." >> >> http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html >> > Hm, gcc returns pointer to result. What does this means? We can't rely on > what strcpy returns? Do what? The library function returns hat the standard says it returns, gcc return success or failure :) -- Ian
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-12 10:41 +0100 |
| Message-ID | <8737l5tpyo.fsf@bsb.me.uk> |
| In reply to | #93388 |
Melzzzzz <Melzzzzz@zzzzz.com> writes: > On 2016-09-12, Ian Collins <ian-news@hotmail.com> wrote: >> On 09/12/16 06:40 PM, Tim Rentsch wrote: >>> supercat@casperkitty.com writes: >>> >>>> On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: >>>>> I would say that slightly differently. The return value of >>>>> strcpy() (and other str...() functions) is rarely used, because >>>>> people forget that these functions return a result. In many (or >>>>> most?) cases that happens because people are used to thinking >>>>> imperatively more than functionally. These return values are >>>>> actually useful noticeably more often than they are used. >>>> >>>> The functions return the pointer that was passed in, [...] >>> >>> I've heard this broken record before. It isn't any more >>> interesting or convincing the eleventh time than it was >>> the first ten times. >> >> The Unix standard folks appear to think differently: >> >> "The stpcpy() function shall return a pointer to the terminating NUL >> character copied into the s1 buffer." >> >> http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html >> > Hm, gcc returns pointer to result. What does this means? We can't rely on > what strcpy returns? stpcpy != strcpy -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <Melzzzzz@zzzzz.com> |
|---|---|
| Date | 2016-09-12 10:48 +0000 |
| Message-ID | <nr6154$ma5$2@news.albasani.net> |
| In reply to | #93390 |
On 2016-09-12, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: > Melzzzzz <Melzzzzz@zzzzz.com> writes: > >> On 2016-09-12, Ian Collins <ian-news@hotmail.com> wrote: >>> >>> The Unix standard folks appear to think differently: >>> >>> "The stpcpy() function shall return a pointer to the terminating NUL >>> character copied into the s1 buffer." >>> >>> http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html >>> >> Hm, gcc returns pointer to result. What does this means? We can't rely on >> what strcpy returns? > > stpcpy != strcpy > Aaaaah, I missed that, sorry ;(
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-12 07:04 -0700 |
| Message-ID | <kfnlgyxjjsl.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93387 |
Ian Collins <ian-news@hotmail.com> writes: > On 09/12/16 06:40 PM, Tim Rentsch wrote: >> supercat@casperkitty.com writes: >> >>> On Sunday, September 11, 2016 at 8:23:15 AM UTC-5, Tim Rentsch wrote: >>>> I would say that slightly differently. The return value of >>>> strcpy() (and other str...() functions) is rarely used, because >>>> people forget that these functions return a result. In many (or >>>> most?) cases that happens because people are used to thinking >>>> imperatively more than functionally. These return values are >>>> actually useful noticeably more often than they are used. >>> >>> The functions return the pointer that was passed in, [...] >> >> I've heard this broken record before. It isn't any more >> interesting or convincing the eleventh time than it was >> the first ten times. > > The Unix standard folks appear to think differently: > > "The stpcpy() function shall return a pointer to the terminating NUL > character copied into the s1 buffer." > > http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcpy.html I think you are imagining I'm saying things other than what I actually said. There is no inconsistency between what I said and the Open Group's decision to define the stpcpy() function.
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-09-02 12:36 +0100 |
| Message-ID | <nqbo71$ou7$1@dont-email.me> |
| In reply to | #93090 |
On 02/09/16 02:50, will hunt wrote:
> should I use strncpy or snprintf, and why?
You have no doubt read the other answers by now. If and only if you
aren't happy with any of them, read on.
I generally prefer to write a function that does exactly what's
required, rather than pick one particular library function for general
use. And you need to establish exactly what's required. In this case,
the key point at issue is, I think, whether it's okay to discard data if
there's too much.
If losing data is acceptable, you can do this:
#include <string.h>
/* Copy As Much Of String As Possible (camosap) */
/* target: destination string */
/* maxlen: amount of storage allocated for string, inc null */
/* source: place from which to copy data */
/* return: 1 if truncated, else 0 */
int camosap(char *target, size_t maxlen, char *source)
{
int truncated = 0;
size_t len = strlen(source);
if(len >= maxlen)
{
/* if the strings are guaranteed not to overlap, you
can use memcpy instead of memmove */
memmove(target, source, len);
target[len] = '\0';
truncated = 1;
}
else
{
strcpy(target, source);
}
return truncated;
}
If losing data is unacceptable, then you can make sure there's enough by
allocating it yourself:
#include <stdlib.h>
#include <string.h>
char *dupstring(const char *source)
{
size_t len = strlen(source) + 1;
char *new = malloc(len);
if(new != NULL)
{
memcpy(new, source, len);
}
return new;
}
but then you take on responsibility for ensuring (as far too many sloppy
programmers do not ensure) that the allocation was successful, and of
course you have to free() it when you've finished with it.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-02 14:24 +0100 |
| Message-ID | <87k2eu4ep7.fsf@bsb.me.uk> |
| In reply to | #93101 |
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 02/09/16 02:50, will hunt wrote:
>> should I use strncpy or snprintf, and why?
<snip>
> If losing data is acceptable, you can do this:
>
> #include <string.h>
>
> /* Copy As Much Of String As Possible (camosap) */
> /* target: destination string */
> /* maxlen: amount of storage allocated for string, inc null */
> /* source: place from which to copy data */
> /* return: 1 if truncated, else 0 */
>
> int camosap(char *target, size_t maxlen, char *source)
> {
> int truncated = 0;
> size_t len = strlen(source);
> if(len >= maxlen)
> {
> /* if the strings are guaranteed not to overlap, you
> can use memcpy instead of memmove */
> memmove(target, source, len);
> target[len] = '\0';
> truncated = 1;
> }
> else
> {
> strcpy(target, source);
> }
> return truncated;
> }
Several things have gone wrong with that. You overrun the buffer by
using len rather than maxlen and you are careful to allow copying
between overlapping objects in once case and then use strcpy in the
other (strcpy is undefined when the source and destination overlap).
And the setting of the null was probably intended to be
target[maxlen - 1] = '\0';
I find using maxlen for a size (i.e. a string length plus the
terminating null) to be rather confusing, especially as you also have
len which is a string length (excluding the terminating null).
If I had to maintain house style, I think I'd rewrite it, with a const
added as well, like this:
int camosap(char *target, size_t target_size, const char *source)
{
int truncated = 0;
size_t len = strlen(source);
if (len >= target_size)
{
/* if the strings are guaranteed not to overlap, you
can use memcpy instead of memmove */
memmove(target, source, target_size - 1);
target[target_size - 1] = '\0';
truncated = 1;
}
else
{
memmove(target, source, len + 1);
}
return truncated;
}
But I'd probably actually write like this, swapping the sense of the
return value as well (I suspect you favour zero for success for Anna
Karenina reasons):
int camosap(char *target, size_t target_size, const char *source)
{
size_t source_size = strlen(source) + 1;
if (source_size > target_size) {
memmove(target, source, target_size - 1);
target[target_size - 1] = '\0';
return 0;
}
memmove(target, source, source_size);
return 1;
}
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-09-02 14:51 +0100 |
| Message-ID | <nqc04h$jld$1@dont-email.me> |
| In reply to | #93105 |
On 02/09/16 14:24, Ben Bacarisse wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>
>> On 02/09/16 02:50, will hunt wrote:
>>> should I use strncpy or snprintf, and why?
> <snip>
>> If losing data is acceptable, you can do this:
>>
>> #include <string.h>
>>
>> /* Copy As Much Of String As Possible (camosap) */
>> /* target: destination string */
>> /* maxlen: amount of storage allocated for string, inc null */
>> /* source: place from which to copy data */
>> /* return: 1 if truncated, else 0 */
>>
>> int camosap(char *target, size_t maxlen, char *source)
>> {
>> int truncated = 0;
>> size_t len = strlen(source);
>> if(len >= maxlen)
>> {
>> /* if the strings are guaranteed not to overlap, you
>> can use memcpy instead of memmove */
>> memmove(target, source, len);
>> target[len] = '\0';
>> truncated = 1;
>> }
>> else
>> {
>> strcpy(target, source);
>> }
>> return truncated;
>> }
>
> Several things have gone wrong with that.
I've got a bad feeling about this.
> You overrun the buffer by
> using len rather than maxlen
Ouch one.
> and you are careful to allow copying
> between overlapping objects in once case and then use strcpy in the
> other (strcpy is undefined when the source and destination overlap).
Ouch two.
> And the setting of the null was probably intended to be
>
> target[maxlen - 1] = '\0';
Ouch three.
> I find using maxlen for a size (i.e. a string length plus the
> terminating null) to be rather confusing, especially as you also have
> len which is a string length (excluding the terminating null).
Ouch four. In the grand scheme of ouches (as seen above), it's more of
an "ooh", but I do take your point. Believe it or not... and I know
you'll find it difficult to believe... I did actually think about that
issue. But, on balance, I think I'll spend the rest of the day doing
documentation. Today is clearly not meant to be a programming day.
>
> If I had to maintain house style, I think I'd rewrite it, with a const
> added as well, like this:
Ouch five. And, when I saw that you'd replied but hadn't yet got to your
reply, I reviewed my code, and the missing const was the /only/ thing I
could see that was wrong with the code! Today is so not being a good
day. But, of course, that's why we have code reviews.
There was an ouch six, too - the name. It's terrible. And I knew it was
terrible when I wrote it. I just wanted a name that wasn't mystrcpy.
>
> int camosap(char *target, size_t target_size, const char *source)
> {
> int truncated = 0;
> size_t len = strlen(source);
> if (len >= target_size)
> {
> /* if the strings are guaranteed not to overlap, you
> can use memcpy instead of memmove */
> memmove(target, source, target_size - 1);
> target[target_size - 1] = '\0';
> truncated = 1;
> }
> else
> {
> memmove(target, source, len + 1);
> }
> return truncated;
> }
>
> But I'd probably actually write like this, swapping the sense of the
> return value as well (I suspect you favour zero for success for Anna
> Karenina reasons):
Right. If it worked, it worked. If it didn't work, I want to know why.
For functions that return pointers, the indication of failure that makes
most sense to me is NULL, and I think the C standard library bears me
out on this (fopen, malloc, strchr, etc). (Alas, this technique can't
tell me why it failed.)
For integer returns, however, 0 makes an awful lot of sense. -1 would
/also/ make a lot of sense, with the return value otherwise being an
index into an array of reasons for screwup, but (a) that doesn't sit
well with the standard library (fclose, rename, etc), and (b) it sounds
terribly messy.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-04 23:42 -0700 |
| Message-ID | <kfneg4yn8zl.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #93105 |
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>
>> On 02/09/16 02:50, will hunt wrote:
>>> should I use strncpy or snprintf, and why?
>
> <snip>
>
>> If losing data is acceptable, you can do this:
>>
>> #include <string.h>
>>
>> /* Copy As Much Of String As Possible (camosap) */
>> /* target: destination string */
>> /* maxlen: amount of storage allocated for string, inc null */
>> /* source: place from which to copy data */
>> /* return: 1 if truncated, else 0 */
>>
>> int camosap(char *target, size_t maxlen, char *source)
>> {
>> int truncated = 0;
>> size_t len = strlen(source);
>> if(len >= maxlen)
>> {
>> /* if the strings are guaranteed not to overlap, you
>> can use memcpy instead of memmove */
>> memmove(target, source, len);
>> target[len] = '\0';
>> truncated = 1;
>> }
>> else
>> {
>> strcpy(target, source);
>> }
>> return truncated;
>> }
>
> Several things have gone wrong with that. You overrun the buffer by
> using len rather than maxlen and you are careful to allow copying
> between overlapping objects in once case and then use strcpy in the
> other (strcpy is undefined when the source and destination overlap).
> And the setting of the null was probably intended to be
>
> target[maxlen - 1] = '\0';
>
> I find using maxlen for a size (i.e. a string length plus the
> terminating null) to be rather confusing, especially as you also have
> len which is a string length (excluding the terminating null).
>
> If I had to maintain house style, I think I'd rewrite it, with a const
> added as well, like this:
>
> int camosap(char *target, size_t target_size, const char *source)
> {
> int truncated = 0;
> size_t len = strlen(source);
> if (len >= target_size)
> {
> /* if the strings are guaranteed not to overlap, you
> can use memcpy instead of memmove */
> memmove(target, source, target_size - 1);
> target[target_size - 1] = '\0';
> truncated = 1;
> }
> else
> {
> memmove(target, source, len + 1);
> }
> return truncated;
> }
>
> But I'd probably actually write like this, swapping the sense of the
> return value as well (I suspect you favour zero for success for Anna
> Karenina reasons):
>
> int camosap(char *target, size_t target_size, const char *source)
> {
> size_t source_size = strlen(source) + 1;
> if (source_size > target_size) {
> memmove(target, source, target_size - 1);
> target[target_size - 1] = '\0';
> return 0;
> }
> memmove(target, source, source_size);
> return 1;
> }
Two more alternatives: one that uses library functions, and one
that doesn't. The second one has different semantics in some
cases where the operands overlap, but still avoids undefined
behavior. The set of return values is expanded to deal with the
case that the "size" is zero. (Disclaimer: not tested.)
int
camosap( char *d, size_t n, const char *s ){
const char *t = memchr( s, 0, n );
size_t const k = t ? t-s+1 : n;
memmove( d, s, k );
return t ? 0 : n > 0 ? d[n-1] = 0, 1 : -1;
}
int
camosap( char *d, size_t n, const char *s ){
return n > 1 && (*d = *s) ? camosap( d+1, n-1, s+1 )
: n > 0 && *s == 0 ? *d = 0, 0
: n > 0 ? *d = 0, 1
: -1;
}
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-09-02 18:05 +0100 |
| Message-ID | <nqcbhb$thn$1@dont-email.me> |
| In reply to | #93090 |
On 02/09/16 17:22, Stefan Ram wrote: > will hunt <glovepm@gmail.com> writes: >> should I use strncpy or snprintf, and why? > > It is a good tradition in the Usenet to write > the full question into the body of the post. > > If safety is an issue, one can check out > > K.3.7.1.4 The strncpy_s function (a) Optional - compilers need not provide it. (b) This doesn't address the issue of incomplete copies. (c) It is easy (as I have already demonstrated in this thread) to specify the wrong length. > > and > > K.3.5.3.5 The snprintf_s function The same arguments apply. There is quite simply no substitute for taking care to ensure that the destination is sufficiently large to receive all the required data from the source. (Again, I have proved this, in the most embarrassing way possible, earlier in this thread.) -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Ike Naar <ike@iceland.freeshell.org> |
|---|---|
| Date | 2016-09-02 19:48 +0000 |
| Message-ID | <slrn3vfsnsjlrl.s0n.ike@iceland.freeshell.org> |
| In reply to | #93125 |
On 2016-09-02, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> The implementation of ?salsub? below /is/ using ?strncpy?,
> but I hope that this usage is correct.
Or use memcpy which has simpler semantics and does the job just as well.
> [...]
>
> s_type.c
>
> #include <stdarg.h> /* va_list, va_start, va_end */
> #include <stdio.h> /* vsnprintf, size_t, vsprintf */
> #include <string.h> /* strncpy */
> #include <stdlib.h> /* malloc, free */
> #include <stddef.h> /* ptrdiff_t */
> #include "s_type.h" /* s_type */
In my opinion it is best to move the #include of a header file
(in this case, s_type.h) to the very top of its implementation
(in this case, s_type.c).
Reason: this way one can easily check whether the header
s_type.h is self-contained and does not depend on other includes
used by its implementation s_type.c .
> [...]
> /* not tested! */
> s_type salfmt( s_type const f, ... )
> { va_list a;
> va_start(a,f);
> salfmtv( f, a );
That should be:
s_type const b = salfmtv(f, a);
> va_end(a);
> return b; }
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2016-09-13 01:45 +0000 |
| Message-ID | <nr7lnl$71m$1@reader2.panix.com> |
| In reply to | #93090 |
In article <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com>,
will hunt <glovepm@gmail.com> wrote:
>should I use strncpy or snprintf, and why?
This has been covered, but I'll throw my hat in the ring for the,
"neither" camp.
The biggest deficiencies of strncpy() have to do with its surprising
semantics: it was originally written for copying data into
fixed-width fields of data structures that were written to disk
(actually as part of a filesystem). Thus, it zeros out the part of
the destination after the end of the source if the source is shorter
than the buffer size (instead of just appending a single NUL
terminator), and possibly won't NUL terminate if the source is of
length equal-to or longer than the size argument. It always writes
exactly 'size' characters, which is inefficient for short source
strings and large destination buffers.
The possible lack of NUL termination requires care on the part of the
programmer and is sufficiently non-intuitive that it is often
overlooked: this has been a fruitful source of errors over the years.
Further, there's no way to detect truncation (short of comparison
against the source string after the copy or similar).
snprintf() doesn't have the NUL-termination or zeroing problem, but
requires a lot of machinery (all the rest of printf, which is
complicated in its full glory) and is inefficient. However,
snprintf() *does* return a useful value that can be used to probe
for truncation.
The,
*dst = 0;
strncat(dst, src, size - 1);
trick is clever and reasonably efficient, but leaves the programmer
no way to detect truncation (again, unless followed by a comparison
against the source or something).
It should be noted that this "compare against the source" business as
a workaround to detect truncation is redundant: the copying routine
could report if it truncates or not, so requiring a second probing
step should not be necessary. Perhaps that's fine for one's
particular application, but the general problem persists.
To summarize, no string-copying function in the C standard library
provides an acceptable combination of efficiency, safety and the
ability to detect truncation.
The OpenBSD people recognized this some years ago and came up with
functions that had the right properties: strlcpy() and strlcat().
These are pretty simple. They will *always* terminate a greater-than-
zero length destination buffer, they will never write more than one
terminating NUL character, and they return a value that can be used
to detect truncation. They are available from the OpenBSD
distribution under a permissive license and have made it into most
of the BSD distributions, the Mac, and (I think) Solaris. Most Linux
distributions provide copies in a BSD compatibility library, though
they were rejected from glibc because, well, Ulrich Drepper didn't
like them.
An ersatz implementation of strlcpy() taken from
http://pub.gajendra.net/src/strlcpy.c is:
#include <stddef.h>
#include <string.h>
size_t
strlcpy(char *dst, const char *src, size_t size)
{
size_t len, srclen;
/*
* Get the length of the source first, test for the
* pathological case, then copy as much as we can.
*/
srclen = strlen(src);
if (size-- == 0)
return(srclen);
len = (size < srclen) ? size : srclen;
memmove(dst, src, len);
dst[len] = '\0';
return(srclen);
}
Similarly, an implementation of strlcat() taken from
http://pub.gajendra.net/src/strlcat.c is:
#include <stddef.h>
#include <string.h>
size_t
strlcat(char *dst, const char *src, size_t size)
{
char *p;
size_t len;
/*
* This mimics the OpenBSD semantics most closely.
*
* We would like to use strlen() here, but the idea is to
* catch cases where dst isn't a C-style string, and this
* function is (presumably) called in error.
*/
p = memchr(dst, '\0', size);
if (p == NULL)
p = dst + size;
len = p - dst;
return(len + strlcpy(p, src, size - len));
}
Feel free to use these, if you'd like (I'm the original author of
these versions and have put them into the public domain).
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-13 11:06 +0100 |
| Message-ID | <87h99kqfjx.fsf@bsb.me.uk> |
| In reply to | #93408 |
cross@spitfire.i.gajendra.net (Dan Cross) writes: > In article <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com>, > will hunt <glovepm@gmail.com> wrote: >>should I use strncpy or snprintf, and why? <snip lots of stuff> > The, > > *dst = 0; > strncat(dst, src, size - 1); > > trick is clever and reasonably efficient, but leaves the programmer > no way to detect truncation (again, unless followed by a comparison > against the source or something). As written, yes, but a test similar to the one I use for detecting long lines with fgets can give you this information in O(1) time (i.e. with no re-scan for length or comparison). You just add one more null byte: dst[0] = dst[size - 2] = 0; strncat(dst, src, size - 1); after which the expression dst[size - 2] && src[size - 1] is true if, and only if, there was truncation. (Note: the context was with a constant STR_SIZE where you could be permitted to know that STR_SIZE - 2 was valid. Real life may not be so simple.) <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2016-09-13 14:09 +0000 |
| Message-ID | <nr91b6$mpd$2@reader2.panix.com> |
| In reply to | #93410 |
In article <87h99kqfjx.fsf@bsb.me.uk>, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes: > >> In article <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com>, >> will hunt <glovepm@gmail.com> wrote: >>>should I use strncpy or snprintf, and why? ><snip lots of stuff> > >> The, >> >> *dst = 0; >> strncat(dst, src, size - 1); >> >> trick is clever and reasonably efficient, but leaves the programmer >> no way to detect truncation (again, unless followed by a comparison >> against the source or something). > >As written, yes, but a test similar to the one I use for detecting long >lines with fgets can give you this information in O(1) time (i.e. with >no re-scan for length or comparison). You just add one more null byte: > > dst[0] = dst[size - 2] = 0; > strncat(dst, src, size - 1); > >after which the expression dst[size - 2] && src[size - 1] is true if, >and only if, there was truncation. > >(Note: the context was with a constant STR_SIZE where you could be >permitted to know that STR_SIZE - 2 was valid. Real life may not be so >simple.) That's clever, but sadly as you note it won't work in all cases specifically, when STR_SIZE - 2 is invalid. That case may seem superfluous, but one never knows. - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-13 15:30 +0100 |
| Message-ID | <87wpifq3db.fsf@bsb.me.uk> |
| In reply to | #93415 |
cross@spitfire.i.gajendra.net (Dan Cross) writes: > In article <87h99kqfjx.fsf@bsb.me.uk>, > Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >>cross@spitfire.i.gajendra.net (Dan Cross) writes: >> >>> In article <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com>, >>> will hunt <glovepm@gmail.com> wrote: >>>>should I use strncpy or snprintf, and why? >><snip lots of stuff> >> >>> The, >>> >>> *dst = 0; >>> strncat(dst, src, size - 1); >>> >>> trick is clever and reasonably efficient, but leaves the programmer >>> no way to detect truncation (again, unless followed by a comparison >>> against the source or something). >> >>As written, yes, but a test similar to the one I use for detecting long >>lines with fgets can give you this information in O(1) time (i.e. with >>no re-scan for length or comparison). You just add one more null byte: >> >> dst[0] = dst[size - 2] = 0; >> strncat(dst, src, size - 1); >> >>after which the expression dst[size - 2] && src[size - 1] is true if, >>and only if, there was truncation. >> >>(Note: the context was with a constant STR_SIZE where you could be >>permitted to know that STR_SIZE - 2 was valid. Real life may not be so >>simple.) > > That's clever, but sadly as you note it won't work in all cases > specifically, when STR_SIZE - 2 is invalid. That case may seem > superfluous, but one never knows. The original assumed that size was at least 1. If that's reasonable you can test src[size - 1] && size > 1 && dst[size - 2] and if size could be 0 the test gets more complicated still but not very much more complicated. The most obvious one being size && src[size - 1] && size > 1 && dst[size - 2] It may not be of any practical value, but I think it's interesting to know that O(1) overflow detection is always possible in these cases. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2016-09-13 14:52 +0000 |
| Message-ID | <nr93rt$lgt$1@reader2.panix.com> |
| In reply to | #93417 |
In article <87wpifq3db.fsf@bsb.me.uk>, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) writes: >> In article <87h99kqfjx.fsf@bsb.me.uk>, >> Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes: >>> >>>> In article <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com>, >>>> will hunt <glovepm@gmail.com> wrote: >>>>>should I use strncpy or snprintf, and why? >>><snip lots of stuff> >>> >>>> The, >>>> >>>> *dst = 0; >>>> strncat(dst, src, size - 1); >>>> >>>> trick is clever and reasonably efficient, but leaves the programmer >>>> no way to detect truncation (again, unless followed by a comparison >>>> against the source or something). >>> >>>As written, yes, but a test similar to the one I use for detecting long >>>lines with fgets can give you this information in O(1) time (i.e. with >>>no re-scan for length or comparison). You just add one more null byte: >>> >>> dst[0] = dst[size - 2] = 0; >>> strncat(dst, src, size - 1); >>> >>>after which the expression dst[size - 2] && src[size - 1] is true if, >>>and only if, there was truncation. >>> >>>(Note: the context was with a constant STR_SIZE where you could be >>>permitted to know that STR_SIZE - 2 was valid. Real life may not be so >>>simple.) >> >> That's clever, but sadly as you note it won't work in all cases >> specifically, when STR_SIZE - 2 is invalid. That case may seem >> superfluous, but one never knows. > >The original assumed that size was at least 1. If that's reasonable you >can test > > src[size - 1] && size > 1 && dst[size - 2] > >and if size could be 0 the test gets more complicated still but not very >much more complicated. The most obvious one being > > size && src[size - 1] && size > 1 && dst[size - 2] > >It may not be of any practical value, but I think it's interesting to >know that O(1) overflow detection is always possible in these cases. Yes yes, that's true, but surely we can see that one approaches a point of diminishing returns with these sorts of shenanigans. One could simply use strlcpy() and avoid all of this, no? - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2016-09-13 14:54 +0000 |
| Message-ID | <nr93vt$lgt$2@reader2.panix.com> |
| In reply to | #93419 |
In article <nr93rt$lgt$1@reader2.panix.com>, Dan Cross <cross@spitfire.i.gajendra.net> wrote: >In article <87wpifq3db.fsf@bsb.me.uk>, >Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >>> [snip] >> >>The original assumed that size was at least 1. If that's reasonable you >>can test >> >> src[size - 1] && size > 1 && dst[size - 2] >> >>and if size could be 0 the test gets more complicated still but not very >>much more complicated. The most obvious one being >> >> size && src[size - 1] && size > 1 && dst[size - 2] >> >>It may not be of any practical value, but I think it's interesting to >>know that O(1) overflow detection is always possible in these cases. > >Yes yes, that's true, but surely we can see that one approaches a point >of diminishing returns with these sorts of shenanigans. One could simply >use strlcpy() and avoid all of this, no? And to wit: Surely one would not expect a reasonable program to duplicate these checks at every strncat() call site. Instead, one would wrap this sequence of code up into some kind of function; at that point, one may as well simply call the 8 line strlcpy(). - Dan C.
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.lang.c
csiph-web