Re: [PATCH] scanf.3: Do not mention the ERANGE error

G. Branden Robinson
2023-01-20T17:55:57Z

[-- Attachment #1: Type: text/plain, Size: 5155 bytes --]

[re-ordering the mail I'm quoting]

Hi Alex,

I have some observations on your deprecation initiative and people's
reactions to it.

At 2023-01-20T14:12:07+0100, Alejandro Colomar wrote:
> All implementations of sscanf(3) produce Undefined Behavior (UB),
> AFAIK. How much you consider UB to be a real-world issue differs for
> each programmer, but I tend to consider all UB to be as bad as nasal
> demons. I'm not saying UB shouldn't exist, just that you shouldn't
> invoke it. And a function that is used for scanning user input is one
> of those places where you really want to avoid invoking UB.

If there are common idioms that result in UB, it might be worth
documenting this in the man page, with a citation to the relevant
clause of the standard that declares it thus. I agree that UB is
something to be avoided and I think most other programmers do too. The
advantage to this approach is that if they disagree, they can take their
argument to the standards body instead of litigating it with you.

> This is similar but different to bzero(3). bzero(3) was broken or
> slow in some implementations. That's probably why it was never added
> to ISO C, and why POSIX later removed it. The API wasn't bad, and in
> fact it's great, I prefer it over memset(3). The difference between
> bzero(3) and sscanf(3) is that bzero(3) has now been fixed,

I still don't share your preference here. The exposure of a more
general interface (memset) by a general-purpose library when the
implementation otherwise has no additional implementation cost is the
correct choice. If a given programmer's use cases are restricted such
that one of the arguments to a general-purpose function is constant,
then that is exactly the time for them to write a macro or function
specific to their project to hide the complexity.

If you tilt your head right, this is similar to one of the ways closures
are used in other languages.

> I could change the "deprecated" statements by "see bugs",

I think you've hit upon one of the core drivers of resistance here. A
problem with calling something "deprecated" is that it's often unstated
_who_ is doing the deprecation. Traditionally, I think the Linux
man-pages have tended only to use this term in reference to one of the
standards bodies (WG14 or the Austin Group) formally employing it.

(Maybe I'm wrong, and Linux man-pages _has_ deprecated things in its own
authorial voice...but if other people also don't know that, it doesn't
matter, and confusion remains.)

So I suggest you adopt a new phrase, like "discouraged by Linux
man-pages", to characterize the authorial voice here. Some people will
ignore your advice either way, but at least they'll know who they're
ignoring.[1]

> However, if somebody really wants to use that function, and would like
> to fix it, I encourage that effort. If the function is fixed, which
> shouldn't be that hard, I'm fine removing the messages against its
> usage in the manual.
>
> While that doesn't happen, I prefer strongly recommending against
> their usage in the manual. And dict(1) seems to say that the verb for
> that is "to deprecate" :)

Your dictionary is correct but social knowledge, a.k.a. tradition and
folklore, impose a context on the discussion. Sometimes dumb things
become tradition (like calculating factorials or Fibonacci numbers with
recursive functions[2])--we don't have to acquiesce to that, but we will
have to document and sometimes defend our rejection of them.

> Right. memcpy(3) has a bug in the standard. However, implementations
> do the Right Thing (tm). If implementations did the right thing for
> sscanf(3), that would be enough to remove the recommendation against
> it. But my understanding is that the sscanf(3) implementation is not
> free of that problem.

This is a good opportunity to say so in these terms. "Linux man-pages
discourages use of sscanf [under the conditions XXX] until
implementations are corrected to avoid undefined behavior [cite URL
here]."[3]

Regards,
Branden

[1] In groff_man(7), I admit I have not taken my own advice, and use the
term "deprecated" in a subsection heading. I have two defenses for
this. (1) I reorganized the man page along those lines 5-6 years
ago, when I had less practice at writing technical documentation,
and (2) the man(7) macros are not formally standardized anywhere
anyway. There is no "official" body with which to conflict, or with
whom groff can be confused by the reader.

After groff 1.23 is released (good news, I heard from Bertrand last
weekend) I hope to add the SunOS extension "SB" to the deprecation
list now that Solaris's death seems irreversible.

[2] https://sleeplessafternoon.wordpress.com/2013/03/26/examples-of-recursion-the-good-the-bad-and-the-silly/

For the mathematically or algorithmically inclined, I also
recommend "The Genuine Sieve of Eratosthenes", by Melissa O'Neill.

https://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

[3] groff_man(7) gives you UR/UE, so use them! >:-)

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]