Re: [PATCH v1] man/man7/environ.7: Fix underspecification of "name=value" strings

Alejandro Colomar <[email protected]> Mon, 6 Jul 2026 17:27:55 +0200
Newsgroups org.kernel.vger.linux-man
Message-ID <akvEyqpWVMYkkJei@devuan>
Hi Jason,

On 2026-07-06T10:26:20-0400, Jason Yundt wrote:
> Before this change, environ(7) said this:
> 
> > By convention, the strings in environ have the form "name=value".  The
> > name is case-sensitive and may not contain the character "=".  The
> > value can be anything that can be represented as a string.  The name
> > and the value may not contain an embedded null byte ('\0'), since this
> > is assumed to terminate the string.
> 
> That description has a few problems:
> 
> 1. It talks about ‘the character "="’, but it doesn’t specify what
>    character encoding would be used to represent that character.  Two
>    different character encodings could represent that same “=” character
>    using two different bytes (or even sequences of bytes).

POSIX says that '=' is part of the portable character set.  Do we really
need to care about the value of '='?  Is this really possible?

> 2. It mentions that ‘The name is case-sensitive and may not contain the
>    character "=".’  It doesn’t clearly say what what is allowed to be in
>    a name.  It only says that those two things are explicitly
>    disallowed.

Anything else is allowed, obviously.

> This change fixes those two problems.  For the first problem, this
> change makes it so that the description is all about bytes, not
> characters.  Describing the format in terms of bytes allows us to
> sidestep the question of character encoding entirely.  Additionally, it
> is more accurate to describe strings in environ as being sequences of
> bytes instead of sequences of characters.  Both the name and value of an
> environment variable could be sequences of bytes that don’t contain any
> characters at all.
> 
> For the second problem, this change clarifies that the name of an
> environment variable can contain any byte except for 0x3D.  It also
> clarifies that while it’s OK for environment variable values to be
> empty, it’s not OK for environment variable names to be empty.
> 
> Additionally, this change replaces "=" with '='.  In the C programming
> language, "=" refers to two bytes: one for the equals character plus one
> for the terminating null byte.  In the C programming language, '='
> refers to a single byte.  In this particular instance, we’re talking
> about a single byte, so it’s better to use '='.  Using '=' also makes
> environ(7) more internally consistent.  Before this change, environ(7)
> used '\0' and "=".  This change makes it so that environ(7) uses '\0'
> and '='.
> 
> I was able to obtain obtain the information that I needed in order to
> create this change by writing a test program.  You can find the test
> program here [1].  Additionally, I got the information about the setenv(3)
> and unsetenv(3) functions from their man pages (specifically, the parts
> of their man pages that talk about EINVAL).
> 
> [1]: <https://codeberg.org/JasonYundt/environ-format-example-program>

Please include the C program in the commit message so that it can be
compiled and run easily, without having to understand Nix stuff.

> 
> Signed-off-by: Jason Yundt <[email protected]>
> ---
>  man/man7/environ.7 | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/man/man7/environ.7 b/man/man7/environ.7
> index 31a69017cf75..bf5726e32429 100644
> --- a/man/man7/environ.7
> +++ b/man/man7/environ.7
> @@ -28,12 +28,23 @@ .SH DESCRIPTION
>  .I environ
>  have the form
>  .RI \[dq] name\f[B]=\f[]value \[dq].
> -The name is case-sensitive and may not contain
> -the character
> -.RB \[dq] = \[dq].
> -The value can be anything that can be represented as a string.
> -The name and the value may not contain an embedded null byte (\[aq]\[rs]0\[aq]),
> -since this is assumed to terminate the string.

I liked the old wording about the terminating null byte more.

> +The name is case-sensitive
> +and may contain any byte
> +other than null (\[aq]\[rs]0\[aq]) and 0x3D (the
> +.BR ascii (7)
> +.RB \[aq] = \[aq]
> +character).
> +The name must be at least one byte long,
> +or else programs will not be able to manipulate it using the
> +.BR setenv (3)
> +or
> +.BR unsetenv (3)
> +functions.
> +Immediately after the name, there should be a 0x3D byte.

What should readers interpret of 'should'?  Is it a recommendation or an
obligation?  This is unclear wording.

> +Immediately after the 0x3D byte is the value.

This seems redundant with the sentence that shows the format
"name=value".

> +The value may contain any byte except for null.

What is the null value?  You mean an empty string?  Or you mean embedded
null bytes in the string?  Please clarify.

> +The value may be zero bytes long.

That's commonly known as an empty string.

I think saying that the value can be anything that can be represented as
a string is fine (the old wording).

> +Immediately after the value, there must be a terminating null byte.

The fact that it's a string already implied this.


Have a lovely day!
Alex

>  .P
>  Environment variables may be placed in the shell's environment by the
>  .I export
> 
> Range-diff against v0:
> -:  ------------ > 1:  d5b0d9b86029 man/man7/environ.7: Fix underspecification of "name=value" strings
> -- 
> 2.54.0
> 
> 

-- 
<https://www.alejandro-colomar.es>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmpLyXUACgkQ64mZXMKQ
wqkxIQ//Zl2XPssECX1utry8dTgzdoe3M3t4rs1YVI/i/cEuPTqtcAplgYrOyEhK
ithRpgeqipZERRBZtUQflzhydVAvH/HRaswdy6K2Y+yHYFh9vRwAyIPGgvISpXPM
pDHHCgZDASgYgtnijYze1ZmpnDe5SSEVsCgfTqCpkrbSRNIyEUYC448x2dxA39bK
v8R9xSqiU3EhuBcsFsC2lF7BmfwxXEODJKJAV0DOCMiqQ8VU2EqUixkUdbBVpJNG
Qpby7+8U6JiQzBFbU46lYteRMmz0MM3on1Mvq6flkytLV88ee9ukcz792DFKvmP6
SGB8fE94fmER6PjoLODV0r9SwOq6+SXKQOMuHy0GcrJpbhi1q47WrJo09UMAwnqE
K6J5/TuSmk89UWRCQkgOjGmu2mqhteTnvl/k/oc/D1Lgs4MdoeDMUuJNSovE7jek
5irscmJdAjsj48GGAQ/GZuSc5cR9xi5SY0N9MFZHVqPBAAqs2JelaUShFGoM4L42
3i83f7/WU2VReEdE0s1ADMX0mKpWpjOk+zuL8CYPKdZxc87jamVgv5k4VQgFsrPa
OmGxf1BRuaeFCsaM1PffGZcQ/noXkUC1B+o5z90mOvpBc7H0BZ4wjWDTnaEBNnXX
RdV9LbX6A/JAt0mBnuO/2VMYkA154C9wxD7o2M6rmBpMprVQNsM=
=gQXq
-----END PGP SIGNATURE-----