This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Implement C11 annex K?


On Sat, 16 Aug 2014 01:01:01 -0400, Rich Felker <dalias@libc.org> wrote:
> Actually snprintf has both if you want:
> 
> snprintf(dest, destsize, "%.*s", srcsize, src);

As far as I can tell this doesn't guarantee that *reading* stops immediately once
you exceed the length.

ISO/IEC 9899:2011 (E) section 7.21.6.1 ("The fprintf function") says under "s":
"If no l length modifier is present, the argument shall be a pointer to the initial
element of an array of character type.280) Characters from the array are
written up to (but not including) the terminating null character. If the
precision is specified, no more than that many bytes are written."

Sure, src isn't required to point to a null-terminated string, so the spec requires that
the implementation stop reading eventually.  But there's no guarantee in the spec
that it'll stop at any particular point.  It could read 2G, then notice :-).
If people are *really* objecting to strlcpy because it keeps reading, then this
is an overly complex *AND* weak alternative.


> Only caveat: srcsize needs to have type int. If you pass a size_t
> here, you invoke UB, since the * expects an int. In practice it
> probably always works anyway due to calling conventions, but formally
> it's UB.

String manipulations happen often, so a common pattern like this shouldn't be UB.
You could argue if the maxlength should be srcsize or destsize.
I could imagine that snprintf really stops reading once the precision is met, and
perhaps a future spec could be modified to guarantee that.


So the "simple" way to copy a string with fixed buffers is:

  len = snprintf(dest, destsize, "%.*s", (int) srcsize, src);
  if (len < 0 || len >= destsize) ... // error or truncation

I think that's absurdly complex for a common case, and it appears to depend on
assumptions not actually specified.

--- David A. Wheeler


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]