From owner-svn-src-all@freebsd.org Mon Sep 2 14:51:49 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 9A415DFDFB; Mon, 2 Sep 2019 14:51:49 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from smtp.freebsd.org (smtp.freebsd.org [IPv6:2610:1c1:1:606c::24b:4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "smtp.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46MY2F3J7hz3LvR; Mon, 2 Sep 2019 14:51:49 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from [192.168.0.6] (unknown [181.52.72.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) (Authenticated sender: pfg) by smtp.freebsd.org (Postfix) with ESMTPSA id 919662F32B; Mon, 2 Sep 2019 14:51:48 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Subject: Re: svn commit: r351659 - in head: contrib/libc++/include contrib/netbsd-tests/lib/libc/ssp gnu/lib/libssp include lib/libc/stdio To: Cy Schubert , cem@freebsd.org Cc: src-committers , svn-src-all , svn-src-head References: <201909011612.x81GC5DW097846@repo.freebsd.org> <201909011932.x81JWYts004074@slippy.cwsent.com> <201909012223.x81MN7jK005967@slippy.cwsent.com> <201909020336.x823ar42054344@slippy.cwsent.com> From: Pedro Giffuni Organization: FreeBSD Message-ID: Date: Mon, 2 Sep 2019 09:51:47 -0500 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: <201909020336.x823ar42054344@slippy.cwsent.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 02 Sep 2019 14:51:49 -0000 On 01/09/2019 22:36, Cy Schubert wrote: > In message om> > , Conrad Meyer writes: >> Hi Cy, >> >> On Sun, Sep 1, 2019 at 3:23 PM Cy Schubert wrote: >>> In message > 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.