Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

Alejandro Colomar
2022-08-27T12:15:54Z

[-- Attachment #1.1: Type: text/plain, Size: 4593 bytes --]

Hi Ingo,

On 8/27/22 13:10, Ingo Schwarze wrote:
> Hi Alejandro,
>
>> -.BI "char *getcwd(char *" buf ", size_t " size );
>> +.BI "char *getcwd(char " buf [ size "], size_t " size );
>
> I dislike this.
>
> Manual pages should show function prototypes as they really are in
> the header file, or if the header file contains useless fluff like
> "restrict", a shortened form showing the essence that actually matters
> for using the API.

Regarding restrict, it is essential to differentiate memcpy(3) and
memmove(3), which are otherwise identical:

void *memmove(void *dest, const void *src, size_t n);

void *memcpy(void *restrict dest, const void *restrict src,
size_t n);

I guess you will argue that the description specified the difference, so
it's not necessary in the synopsis. That's true. But reality is that
programmers have historically not cared about those details; so much
that glibc had to provide a compat symbol for old programs, which
basically maps memcpy(3) to memmove(3) for code linked against old glibc
versions.

In some cases, like in memcpy(3), the use of restrict is important; in
others, such as in printf(3), it is irrelevant. But for consistency, I
decided to use restrict everywhere where one of POSIX, or glibc used it
(assuming that POSIX would never remove a restrict qualifier if ISO C
required it). In some cases, glibc and POSIX differed, and I used the
most restrictive prototype.

I didn't add that change about restrict without concerns about being too
noisy. I had them, and still have them. But I think the added value is
more than the one I removed. Now prototypes are more precise, and
overcoming the noise shouldn't be too much of a problem.

In the case of (abusing) VLA syntax, it's more or less the same thing,
with a bit of added WTF moments about the "Why is this code using an
identifier declared right after it? Is it a typo?". I guess the WTF
moments will be more relevant the first few months, and less so when
time passes and programmers get used to the syntax.

I used strlcpy(3) in the commit message on purpose, as it's a great
example, similar to how good is the one about memcpy(3). The competitor
(as they promoted it) to strlcpy(3) in the Linux kernel is strscpy(9)
(not available to user space). They seem to be the same thing, but they
are not. Let's show their prototypes:

size_t strlcpy(char dst[size], const char *src, size_t size);

ssize_t strscpy(char dst[size], const char src[size], size_t size);

From those prototypes, I can already see that the kernel accepts a
possibly-not-terminated string, while strlcpy(3) requires that the
string is terminated. I didn't use restrict here to more clearly show
the difference in VLA syntax (therefore admitting that a bit of noise is
true).

Then of course, there's no difference in the prototypes between
strscpy(9) and strncpy(3), apart from the return value, of course:

char *strncpy(char dest[n], const char src[n], size_t n);

And yet they are different functions (one guarantees the produced string
to be NUL-terminated and the other not (and also clears unnecessarily
the rest of the buffer, so strncpy(3) is just broken). But they are
more or less in the same league, as they are used for transforming
untrusted strings into proper strings (strncpy(3) only if you use it
with sizeof(buf) - 1), and that's shown by the prototypes.

Do you regard the (abused) VLA syntax as something much worse than the
use of restrict? Or are they more or less equivalent to you?

> They should certainly not show something imaginary
> that does not match reality, and even less so using invalid syntax.

Well, not that I haven't had those thoughts, but we already use ilegal
syntax in some cases for good reasons. See for example open(2):

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

Of course, you can't declare two conflicting prototypes like that. But
it shows that those are the two only ways you can use it. I'll admit
that a long time ago I told Michael that we should fix those prototypes
to match reality, with legal syntax, because otherwise they are
confusing. But with time, I got used to that weirdness, and it now
seems to me more informative than just '...' as FreeBSD and OpenBSD
document.

>
> Yours,
> Ingo

Cheers,

Alex

--
Alejandro Colomar