Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #93090 > unrolled thread

How to copy a string safely and efficiently in C?

Started bywill hunt <glovepm@gmail.com>
First post2016-09-01 18:50 -0700
Last post2016-09-14 00:24 +0000
Articles 20 on this page of 76 — 21 participants

Back to article view | Back to comp.lang.c


Contents

  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 1 of 4  [1] 2 3 4  Next page →


#93090 — How to copy a string safely and efficiently in C?

Fromwill hunt <glovepm@gmail.com>
Date2016-09-01 18:50 -0700
SubjectHow to copy a string safely and efficiently in C?
Message-ID<0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com>
should I use strncpy or snprintf, and why?

[toc] | [next] | [standalone]


#93091

FromJohn Gordon <gordon@panix.com>
Date2016-09-02 01:58 +0000
Message-ID<nqamcf$fni$1@reader2.panix.com>
In reply to#93090
In <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com> will hunt <glovepm@gmail.com> writes:

> should I use strncpy or snprintf, and why?

It seems like strncpy() would be the obvious choice.  snprintf() is
meant for assembling an output string from one or more component
parts, which doesn't seem like what you want.

-- 
John Gordon                   A is for Amy, who fell down the stairs
gordon@panix.com              B is for Basil, assaulted by bears
                                -- Edward Gorey, "The Gashlycrumb Tinies"

[toc] | [prev] | [next] | [standalone]


#93094

Fromwill hunt <glovepm@gmail.com>
Date2016-09-01 19:40 -0700
Message-ID<196b9bd0-5b80-4194-9704-014dd19ff6c2@googlegroups.com>
In reply to#93091
On Friday, September 2, 2016 at 9:58:46 AM UTC+8, John Gordon wrote:
> In <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com> will hunt <glovepm@gmail.com> writes:
> 
> > should I use strncpy or snprintf, and why?
> 
> It seems like strncpy() would be the obvious choice.  snprintf() is
> meant for assembling an output string from one or more component
> parts, which doesn't seem like what you want.
> 
for copying a sting into a given size buffer,
char dst[size];
strncpy(dst, src, size);
snprintf(dst, size,"%s", src);
which is better?

[toc] | [prev] | [next] | [standalone]


#93096

FromGeoff <geoff@invalid.invalid>
Date2016-09-01 20:29 -0700
Message-ID<2crhsb5pobk1sgs1eghr10juhlhru14a1k@4ax.com>
In reply to#93094
On Thu, 1 Sep 2016 19:40:24 -0700 (PDT), will hunt <glovepm@gmail.com>
wrote:

>
>for copying a sting into a given size buffer,

char src[] = "ABC";

This is an error:
>char dst[size];
The size of the array must be a constant at compile time.
For example:
char dst[20];

assert(sizeof dst >= sizeof src);

>strncpy(dst, src, size);

Better to write
strncpy(dst, src, sizeof dst);

Why? 
Because if you change the size of dst, you don't have to rewrite the
call to strncpy. 

You could also write:

size_t size = sizeof dst;
strncpy(dst, src, size);

But this is redundant.

Be aware, the strncpy function copies the initial count characters of
src to dst and returns dst. If count is less than or equal to the
length of src, a nul character is not appended automatically to the
copied string. If count is greater than the length of src, the
destination string is padded with nul characters up to length count. 

>snprintf(dst, size,"%s", src);

Better to write:
snprintf(dst, sizeof dst, "%s", src);

Same reason as above.

Note: 
The snprintf function formats and stores count or fewer characters in
buffer, and appends a terminating null character if the formatted
string length is strictly less than count characters. 

You have to ensure that dst is large enough to receive the formatted
string that results from the function call.

>which is better?

That depends entirely on context.


#include <stdio.h>
#include <string.h>
#include <assert.h>

const char src[] = "ABC";

int main(void)
{
	char dst[10];

	assert(sizeof dst >= sizeof src);
	strncpy(dst, src, sizeof dst);
	snprintf(dst, sizeof dst, "%s", src);
}

[toc] | [prev] | [next] | [standalone]


#93122

FromJames Kuyper <jameskuyper@verizon.net>
Date2016-09-02 12:29 -0400
Message-ID<nqc9d2$li5$1@dont-email.me>
In reply to#93096
On 09/01/2016 11:29 PM, Geoff wrote:
> On Thu, 1 Sep 2016 19:40:24 -0700 (PDT), will hunt <glovepm@gmail.com>
> wrote:
[Snipped text restored:]
>> char dst[size];
>> strncpy(dst, src, size);
>> snprintf(dst, size,"%s", src);
...
> This is an error:
>> char dst[size];
> The size of the array must be a constant at compile time.

Such a declaration defines a variable length array (VLA).

VLAs were not standardized until C99, and since C2011, If
__STDC_NO_VLA__ is pre#defined by the implementation, VLAs will not be
supported (6.10.8.3p1). VLAs can only have block scope or function
prototype scope (6.7.6.2p1), no linkage,  and must not have static or
thread storage duration (6.7.6.2p2).  However, the context of this code
example was not given in sufficient detail to prohibit a VLA for any of
those reasons.

Taken literally, the example code had the declaration of dst immediately
followed by function calls, which implies block scope. Therefore, since
that declaration didn't use the static, extern or _Thread_local key
words, dst has no linkage and automatic storage duration. The fact that
it was written at all implies that the intended target supported VLAs.

[toc] | [prev] | [next] | [standalone]


#93398

Fromasetofsymbols@gmail.com
Date2016-09-12 13:09 -0700
Message-ID<39a5dfd7-a7d3-482f-ada2-c3ec7c3224b5@googlegroups.com>
In reply to#93094
______
for copying a sting into a given size buffer, 
char dst[size]; 
strncpy(dst, src, size); 
snprintf(dst, size,"%s", src); 
which is better?
-----+++
for(i=0; i<size&&(dst[i]=src[i]) ++i) ;
if(i>=size) return -1;

If the src and destination point
to the same array memmove
but i not remember args...

[toc] | [prev] | [next] | [standalone]


#93403

FromKeith Thompson <kst-u@mib.org>
Date2016-09-12 15:30 -0700
Message-ID<ln37l47nug.fsf@kst-u.example.com>
In reply to#93398
asetofsymbols@gmail.com writes:
> ______
> for copying a sting into a given size buffer, 
> char dst[size]; 
> strncpy(dst, src, size); 
> snprintf(dst, size,"%s", src); 
> which is better?
> -----+++
> for(i=0; i<size&&(dst[i]=src[i]) ++i) ;
> if(i>=size) return -1;
>
> If the src and destination point
> to the same array memmove
> but i not remember args...

Please learn to quote properly.  (Your newsreader should handle this for
you.)

This part of your followup:
    > for copying a sting into a given size buffer, 
    > char dst[size]; 
    > strncpy(dst, src, size); 
    > snprintf(dst, size,"%s", src); 
    > which is better?
was written by will hunt on September 1.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#93098

FromKeith Thompson <kst-u@mib.org>
Date2016-09-01 23:08 -0700
Message-ID<lninueal5q.fsf@kst-u.example.com>
In reply to#93091
John Gordon <gordon@panix.com> writes:
> In <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com> will hunt <glovepm@gmail.com> writes:
>
>> should I use strncpy or snprintf, and why?
>
> It seems like strncpy() would be the obvious choice.  snprintf() is
> meant for assembling an output string from one or more component
> parts, which doesn't seem like what you want.

Yes, strncpy() is the obvious choice.  It's also, most of the time, the
*wrong* choice.

I've written about strncpy() at some length here:

https://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html

To summarize: The name implies that strncpy() is to strcpy() as
strncat() is to strcat(), i.e., that it's a "safer" version that will
not write past the end of the target array (as long as you correct
tell it how big the target array is).  The name is misleading.
In a very real sense, strncpy() isn't really a string function.
If the target array isn't big enough, it will not be null-terminated,
meaning that it will not contain a string.  Any further attempt to
treat it as a string can fail in arbitrarily bad ways.  (It also
pads the target with nulls when it *is* big enough, but that's just
a very minor inefficiency.)

This:

    target[0] = '\0';
    strncat(target, src, sizeof target);

is very close to what strncpy() probably *would* do if it really
were a "safer" strcpy().

But even that provides what may be only a false sense of security.

The fact that you're considering using strncpy or snprintf rather than
strcpy means that you're at least thinking about avoiding overflowing
the target array.  That's a very good thing.  But simply avoiding a
buffer overflow may not be enough.  You should ask yourself, if the
target array isn't big enough to hold a copy of the source, *what should
I do*?  If you use strncat() or snprintf(), that question is already
answered for you: the copy quietly truncates your data.

Maybe that's what you want.  But imagine, for example, that you're
copying a Unix command string:

    "rm -rf /home/username/unimportant_directory"

And suppose the target only has enough room to hold:

    "rm -rf /home/username"

and you then pass it to system().  (If you're not familiar with
Unix-like systems, the latter will attempt to remove your entire
home directory.)

Only you can decide, in the context of your program, what should
happen if a target array isn't big enough.  Sometimes quiet
truncation is the right choice, sometimes you can try to use a bigger
array, and sometimes you'd be better off terminating the program
with a fatal error message rather than continuing to operate on
incomplete data.

snprintf() has the advantage that it returns the number of
characters it *would* have copied if there were enough room, so
you can detect truncation.  (You still have to remember to check,
and to decide how to handle it.)  snprintf() was added in C99,
and in the past Microsoft's implementation didn't support it
well; I don't think that's a problem these days, but check your
implementation's documentation.

To summarize: Programming is hard.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#93210

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2016-09-04 23:59 -0700
Message-ID<bc147262-68e8-467c-8b1a-4e220fc9fd99@googlegroups.com>
In reply to#93091
On Friday, September 2, 2016 at 2:58:46 AM UTC+1, John Gordon wrote:
> In <0b30b0cc-f7c5-4928-8acb-56bf2364797b@googlegroups.com> will hunt <glovepm@gmail.com> writes:
> 
> > should I use strncpy or snprintf, and why?
> 
> It seems like strncpy() would be the obvious choice.  snprintf() is
> meant for assembling an output string from one or more component
> parts, which doesn't seem like what you want.
> 
Please read other replies before responding.

The advice sounds sensible, and it's a mistake anyone could make.
But as others have pointed out, it's quite wrong.

[toc] | [prev] | [next] | [standalone]


#93095

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2016-09-01 21:12 -0600
Message-ID<1bvayf6lmj.fsf@pfeifferfamily.net>
In reply to#93090
will hunt <glovepm@gmail.com> writes:

> should I use strncpy or snprintf, and why?

In spite of its name, strncpy() isn't a good general purpose routine like
(for instance) strncat().  It copies exactly n bytes (even if the input
string is shorter) and doesn't necessarily null-terminate (if the input
string is longer).

I sort of like

dst[0] = '\0';
strncat(dst, src, n-1);

Does what you most likely intended strncpy() to do, and if you don't
know the length of the source string in advance it's hard to imagine a
significantly more efficient implementation.

If I were strictly limited to the choices in your question I'd probably
use snprintf(), since that would give me a result that didn't have extra
random bytes appended to my string by accident.

If I were limited to the two functions, but could put some extra code
in, I'd probably use

strncpy(dst, src, n);
dst[n-1] = '\0';

since that would be safe and would probably be faster than the extra
code needed to parse the format string in snprintf() unless the string
were *really* long.

(just last week I was bitten by passing the result of feeding an array
generated to xxd to a routine expecting a null-terminated string....).
-- 
"Erwin, have you seen the cat?" -- Mrs. Shrödinger

[toc] | [prev] | [next] | [standalone]


#93097

From<william@wilbur.25thandClement.com>
Date2016-09-01 22:12 -0700
Message-ID<gben9d-a4t.ln1@wilbur.25thandClement.com>
In reply to#93095
Joe Pfeiffer <pfeiffer@cs.nmsu.edu> wrote:
> will hunt <glovepm@gmail.com> writes:
> 
>> should I use strncpy or snprintf, and why?
> 
> In spite of its name, strncpy() isn't a good general purpose routine like
> (for instance) strncat().  It copies exactly n bytes (even if the input
> string is shorter) and doesn't necessarily null-terminate (if the input
> string is longer).
> 
> I sort of like
> 
> dst[0] = '\0';
> strncat(dst, src, n-1);
> 
> Does what you most likely intended strncpy() to do, and if you don't
> know the length of the source string in advance it's hard to imagine a
> significantly more efficient implementation.
> 
> If I were strictly limited to the choices in your question I'd probably
> use snprintf(), since that would give me a result that didn't have extra
> random bytes appended to my string by accident.
> 
> If I were limited to the two functions, but could put some extra code
> in, I'd probably use
> 
> strncpy(dst, src, n);
> dst[n-1] = '\0';
> 
> since that would be safe and would probably be faster than the extra
> code needed to parse the format string in snprintf() unless the string
> were *really* long.
> 
> (just last week I was bitten by passing the result of feeding an array
> generated to xxd to a routine expecting a null-terminated string....).

It may have changed since last time I checked, but the implementation of
snprintf in glibc could fail on allocation failure. It uses the same
internals as vfprintf, must allocate (at least once per thread) a special
FILE-like object, and deeper down the implementation wasn't shy about
dynamically allocating various temporaries so that even a simple format
specifier like "%s" could fail.

Things may have improved since then. And most people never cared to begin
with, or [wrongly] assumed allocation failure wasn't possible on Linux. But
because of that I avoided using snprintf, as failure-proof code is much
easier to work with.

Those details also made glibc's snprintf totally unsafe for use from signal
handlers. OpenBSD's snprintf is async-signal-safe, at least for anything not
formatting floats, and even that may have been fixed. OpenBSD has strlcpy,
anyhow, but it's nice when an implementation makes misuse difficult.

[toc] | [prev] | [next] | [standalone]


#93099

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2016-09-01 23:58 -0700
Message-ID<31bf7ead-3193-44cb-859f-34eb66916a0b@googlegroups.com>
In reply to#93090
On Friday, September 2, 2016 at 2:50:37 AM UTC+1, will hunt wrote:
>
> should I use strncpy or snprintf, and why?
>

As others have said, strncpy() is a trap (it is designed for databases
with fixed string fields instead of nul-terminated strings, and is
a sort of historical hangover).

if( snprintf(out, N, "%s", str) >= N)
  /* error */;

is safe.

Be use to use %s in case the string contains % characters.

Because C has undefined behaviour, a lot of people think that
they can make programs correct by removing the undefined behaviour.
Whilst that is an important first step, it doesn't do much good
if undefined behaviour is replaced by wrong behaviour. If a man's
name won't fit in your string field, what are you going to do
about it? Lots of possible answers, but just chopping it is
unlikely to be acceptable - you get complaints about that sort
of thing.

[toc] | [prev] | [next] | [standalone]


#93100

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-09-02 10:42 +0100
Message-ID<87fupitz86.fsf@bsb.me.uk>
In reply to#93090
will hunt <glovepm@gmail.com> writes:

> should I use strncpy or snprintf, and why?

...(from the subject line) to copy a string safely and efficiently in C?

I vote for neither.  Several people have explained why strncpy is out --
never use it unless you know its dangerous peculiarities happen to be
*exactly* what you need -- but snprintf, though safe, is rather
complicated for the job and requires a relatively recent C library.

One simple solution is to use strncat(dst, src, n).  This concatenates
two strings by adding at most n characters from src to those already
present in dst.  To use it for copying, dst must contain an empty
string, and you need to remember that a terminating null byte is added
in addition to the characters that get copied.  This means you would
write something like this

  char copy[STR_SIZE];
  *copy = 0;
  strncat(copy, src, STR_SIZE - 1);

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#93202

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-09-04 22:23 -0700
Message-ID<kfninuanclx.fsf@x-alumni2.alumni.caltech.edu>
In reply to#93100
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> will hunt <glovepm@gmail.com> writes:
>
>> should I use strncpy or snprintf, and why?
>
> ...(from the subject line) to copy a string safely and efficiently in C?
>
> I vote for neither.  Several people have explained why strncpy is out --
> never use it unless you know its dangerous peculiarities happen to be
> *exactly* what you need -- but snprintf, though safe, is rather
> complicated for the job and requires a relatively recent C library.
>
> One simple solution is to use strncat(dst, src, n).  This concatenates
> two strings by adding at most n characters from src to those already
> present in dst.  To use it for copying, dst must contain an empty
> string, and you need to remember that a terminating null byte is added
> in addition to the characters that get copied.  This means you would
> write something like this
>
>   char copy[STR_SIZE];
>   *copy = 0;
>   strncat(copy, src, STR_SIZE - 1);

Or maybe this (with the same declaration of 'copy')

    strncat( strcpy( copy, "" ), src, STR_SIZE-1 );

[toc] | [prev] | [next] | [standalone]


#93204

FromKeith Thompson <kst-u@mib.org>
Date2016-09-04 23:20 -0700
Message-ID<ln60qaamvx.fsf@kst-u.example.com>
In reply to#93202
Tim Rentsch <txr@alumni.caltech.edu> writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
[...]
>>   char copy[STR_SIZE];
>>   *copy = 0;
>>   strncat(copy, src, STR_SIZE - 1);
>
> Or maybe this (with the same declaration of 'copy')
>
>     strncat( strcpy( copy, "" ), src, STR_SIZE-1 );

Interesting.  It's easy to forget that strcpy() returns a result,
since that result is rarely useful and usually ignored.

(I'm resisting the temptation to repeat the warning that simple
truncation isn't always the correct response to an overflow.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#93215

Frommark.bluemel@gmail.com
Date2016-09-05 01:03 -0700
Message-ID<5592dce1-cdc3-4eef-8d69-4d4d3f4556fb@googlegroups.com>
In reply to#93204
On Monday, 5 September 2016 06:53:29 UTC+1, Keith Thompson  wrote:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
> > Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> [...]
> >>   char copy[STR_SIZE];
> >>   *copy = 0;
> >>   strncat(copy, src, STR_SIZE - 1);
> >
> > Or maybe this (with the same declaration of 'copy')
> >
> >     strncat( strcpy( copy, "" ), src, STR_SIZE-1 );
> 
> Interesting.  It's easy to forget that strcpy() returns a result,
> since that result is rarely useful and usually ignored.
> 
> (I'm resisting the temptation to repeat the warning that simple
s/resisting/unsuccessfully resisting/
> truncation isn't always the correct response to an overflow.)

FTFY

[toc] | [prev] | [next] | [standalone]


#93217

FromKeith Thompson <kst-u@mib.org>
Date2016-09-05 01:46 -0700
Message-ID<lnwpiq91js.fsf@kst-u.example.com>
In reply to#93215
mark.bluemel@gmail.com writes:
> On Monday, 5 September 2016 06:53:29 UTC+1, Keith Thompson  wrote:
[...]
>> (I'm resisting the temptation to repeat the warning that simple
> s/resisting/unsuccessfully resisting/
>> truncation isn't always the correct response to an overflow.)
>
> FTFY

Good point (but unsuccessful resistance is still resistance, futile
though it may be).

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#93219

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-09-05 10:30 +0100
Message-ID<87bn02zoau.fsf@bsb.me.uk>
In reply to#93204
Keith Thompson <kst-u@mib.org> writes:

> Tim Rentsch <txr@alumni.caltech.edu> writes:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> [...]
>>>   char copy[STR_SIZE];
>>>   *copy = 0;
>>>   strncat(copy, src, STR_SIZE - 1);
>>
>> Or maybe this (with the same declaration of 'copy')
>>
>>     strncat( strcpy( copy, "" ), src, STR_SIZE-1 );
>
> Interesting.  It's easy to forget that strcpy() returns a result,
> since that result is rarely useful and usually ignored.

For some reason, I find I use the return value of strcpy (and the
others) quite often.  Maybe too much LISP in my youth.  But when I want
an expression to do the job in question, I write (or, more accurately,
have written in the past)

  strncat((*copy = 0, copy), src, STR_SIZE-1)

so while I so use the value of strcpy, I've never thought to use it to
write the null as Tim did.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#93361

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-09-10 11:25 -0700
Message-ID<kfnwpijlihv.fsf@x-alumni2.alumni.caltech.edu>
In reply to#93219
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Keith Thompson <kst-u@mib.org> writes:
>
>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>> [...]
>>
>>>>   char copy[STR_SIZE];
>>>>   *copy = 0;
>>>>   strncat(copy, src, STR_SIZE - 1);
>>>
>>> Or maybe this (with the same declaration of 'copy')
>>>
>>>     strncat( strcpy( copy, "" ), src, STR_SIZE-1 );
>>
>> Interesting.  It's easy to forget that strcpy() returns a result,
>> since that result is rarely useful and usually ignored.
>
> For some reason, I find I use the return value of strcpy (and the
> others) quite often.  Maybe too much LISP in my youth.  But when I want
> an expression to do the job in question, I write (or, more accurately,
> have written in the past)
>
>   strncat((*copy = 0, copy), src, STR_SIZE-1)
>
> so while I so use the value of strcpy, I've never thought to use it to
> write the null as Tim did.

A different way of thinking of it is not writing a null but
initializing 'copy' to an empty string, so the strncat() can
then concatenate the 'src' string onto that empty string.  That
ideation may suggest using strcpy() more naturally.  Personally I
find this framing more attractive, because both operations are
occurring at the same level of abstraction.  (And I readily
confess to using the '*copy = 0' method myself at times.)

[toc] | [prev] | [next] | [standalone]


#93370

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-09-11 06:23 -0700
Message-ID<kfnsht6lgee.fsf@x-alumni2.alumni.caltech.edu>
In reply to#93204
Keith Thompson <kst-u@mib.org> writes:

> Tim Rentsch <txr@alumni.caltech.edu> writes:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
> [...]
>
>>>   char copy[STR_SIZE];
>>>   *copy = 0;
>>>   strncat(copy, src, STR_SIZE - 1);
>>
>> Or maybe this (with the same declaration of 'copy')
>>
>>     strncat( strcpy( copy, "" ), src, STR_SIZE-1 );
>
> Interesting.  It's easy to forget that strcpy() returns a result,
> since that result is rarely useful and usually ignored.

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.

[toc] | [prev] | [next] | [standalone]


Page 1 of 4  [1] 2 3 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web