On 01/09/2019 22:36, Cy Schubert wrote:
In message <CAG6CVpW4Mj-w7SeB=nu7MHiH+gvkMeB9v8ojLgpnrvmN0Oo+gg@mail.gmail.c
om>
, Conrad Meyer writes:
Hi Cy,

On Sun, Sep 1, 2019 at 3:23 PM Cy Schubert <cy.schub...@cschubert.com> wrote:
In message <CAG6CVpVMN6BkATaz7qqhaVHhUpqQLrP3kSWHpMzPz2AR5GnaQw@mail.gmail.
c
om>
, Conrad Meyer writes:

Short version: no, we shouldn't [recommend the use of gets_s]. :-)

Longer version:  Annex K functions like gets_s have zero real adoption
(Microsoft's APIs that inspired Annex K are not actually compatible
with the version in the standards); broadly terrible APIs; and in this
particular case and others, unnecessarily duplicate the functionality
of existing long-standing standard C functions (e.g., fgets(3)).
That's not quite true. From the man page:

      The gets_s() function is equivalent to fgets() with a stream of stdin,
      except that the newline character (if any) is not stored in the string
.

I tried to make a distinction earlier that I don't think carried well
over email.  I wrote "unnecessarily duplicate(s) the _functionality_
of existing …" — not "is/are an exact duplicate(s) of …" — because
you're right, gets_s() has (trivial) behavioral differences from
fgets(stdin).

The thing that is important to me is that fgets(3) is portable, super
well understood, and provides a superset of the functionality of
gets_s().  One can easily construct the newline-free version of a line
from one containing a trailing newline.  I don't think this slight
behavioral difference justifies implementing, using, or especially
recommending gets_s().
If Microsoft chooses to ignore or anotherfunctions is their problem.
However in this case, according to the following they do support gets_s().
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/gets-s-getw
s-s?view=vs-2019

Having said all that, glibc is the odd man out here. In that case I'll pull
back my horns. It's sufficient not to not say anything or to highlight both.

BTW. we've had gets_s(3) in our tree for 17 months now. We don't need to
add anything. It's already there.

It is an application developer choice to use one function or another.

As someone who also works on the ports side, the newline is significant
distinction. As gets_s() is closer in function to gets() than fgets() is,
all one
needs to concern oneself with is buffer length. As there are no _other_
differences nothing else needs to be addressed. This is important to ports
maintainers and who must replace gets() with something else. Agreed this
shouldn't be an issue every time but gets_s() is still in our toolbox.

(IMO, it was probably a historical mistake that gets(3) even had
different behavior than fgets(3) to begin with.  gets(3) maybe
predated stdio FILE streams?)
I totally agree.

Some apps may be sensitive to this subtle difference. gets_s() preserves
this behaviour.
Correct conversion of gets()-using programs requires more analysis
than blind replacement with either function.
That's where gets_s() is handy. It requires less analysis. Remember, my
main concern here are our ports maintainers. Upstream developers should
always do analysis. It's not the job of the ports team to perform
significant rewrites of upstream software. IMO, if upsteam software needs
significant rewrite a port maintainer should notify the upstream
maintainer. If the upstream cannot or will not, requiring a maintainer of a
port to make significant changes, DEPRECATED= and EXPIRATION_DATE= are the
best answer. We are not here to rewrite other people's software for them.

Anyway, gets() use is largely behind us so the point is mostly moot —
there are few such programs to convert, and they should be viewed with
an extremely high level of skepticism given they are still using
gets(3) in 2019.
I'm not arguing for keeping gets(3). We already have gets_s(3). Let's use
it where it makes sense. Nor am I saying to use it in exclusion of
fgets(3). It (gets_s()) is in our libc. If it eases the job of maintaining
a port, use it instead.

[Annex K functions] are part of the
standard
They're an optional part of the standard.  Everyone takes the option
of "not."  Literally no one implements Annex K.  It's a bad set of
APIs.
Microsoft and we have chosen to implement some Annex K functions. We
haven't implemented all of them. I don't know if they implemented all _s
functions. Linux glibc has not.

I don't agree that it's a completely bad set of APIs. gets_s() will help
ports maintainers. AFAIK, no ports rely on gets() but that's not to say
some new port might not. Don't forget, my motivation for implementing
gets_s(3) in libc was to ease the pain of deprecating gets() for ports.

and though we support some _s functions it would behoove us to one
day (*) support them all.
If and when the C standard committee adopts Annex K as a required part
of the standard, then I agree we should make every attempt to support
the full standard library.  But in general, I am opposed to the
further adoption of Annex K, and hope the C2x standard committee
finally drops the annex.[1]  (It is weakly defended[2], just to
provide a counterargument.)
Again I disagree.

[1]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm  (pro-removal)
This explains glibc's not implementing the _s functions. His focus is
almost entirely on string copy and memory copy functions. Implementation of
string and memory copy functions would be more complex than the gets_s() I
added to FreeBSD. In terms of error detection (for calls to constraint
handlers), gets_s() is simple compared to strcpy_s(). I can understand his
issues. It would appear a similar lack of consideration of implementation
details went into defining the _s string functions as the lack of
consistency considerations went into the development of gets() and fgets().

https://en.cppreference.com/w/c/string/byte/strcpy, where clobbring the
rest of the destination is IMO "not optimal."  Throwing out the baby
(functions which were properly defined) with the bath water (functions
which make one wonder what they were smoking) isn't the right answer either.

[2]: https://www.nccgroup.trust/us/our-research/bounds-checking-interfaces-fi
eld-experience-and-future-directions/
  (pro-retention)
I don't have time to read completely through all of this tonight. The
assertion that there are unfounded criticisms as well as actual flaws. The
flaws are such that replacing some functions with _s will require some
care. Fortunately with gets_s() this is not a concern, except of course
having to specify a buffer length. A constraint handler is not required.
IMO constraint handlers add unnecessary complexity, good thing they are
optional.

I'm also sure some ports will probably break.
Check the exp-run PR: 222796 (comment #7).  13 ports.  Out of 37601,
according to FreshPorts.  Of those 13, eight don't have a maintainer.
Already did. Should someone choose to fix them we the tools are there.

I doubt you will convince me nor I convince you.

I'm not sure if you or anyone else has a copy of the standard. (I suspect
you already have these but maybe someone else might find them useful.)

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3631.pdf

FWIW, Intel has a safestringlib project which implements many of the _s functions:

https://github.com/intel/safestringlib

Microsoft has a related policy since 2012:

https://docs.microsoft.com/en-us/previous-versions/bb288454(v=msdn.10)

but perhaps nowadays we may want to be ready for rust modules.

Cheers,

Pedro.

_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to