You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[_winapi] correctly sort and remove duplicates in getenvironment() #87868
The getenvironment() function in "Modules/_winapi.c" needs to sort variables in the environment block and remove duplicates case insensitively1.
The sort order used to matter with SetEnvironmentVairableW(). As soon as it reached a name in the environment block that compared greater than the target name, it would insert a new variable. Nowadays, SetEnvironmentVairableW() searches the entire environment block before inserting a new value. Regardless, at the very least, getenvironment() is not well-behaved and is not setting the environment in the documented sort order that users, and possibly other programs, expect.
Case-insensitive sorting in Windows uses upper case. The variable names in the mapping can be added to a list and sorted with a key function that's based on LCMapStringEx(), with the flag LCMAP_UPPERCASE. Loop over the sorted list to create the environment block. Remove duplicates by skipping a name that compares equal to the previously stored name according to CompareStringOrdinal().
which name should be stored if they are duplicated with case insensitive?
Ideally os.environ would preserve the original case of the process environment, and os.environ.copy() would return a copy that's also case insensitive. That would prevent most problems with duplicates keys. See msg387676 in bpo-28824, and msg414319 in bpo-15373.
In msg390038 I suggested keeping the first key that's encountered. However, dicts preserve insertion order nowadays, so one could assume that the last one is the one that the caller wants to keep.
changed the title [-][Windows] correctly sort and remove duplicates in _winapi getenvironment()[/-][+][_winapi] correctly sort and remove duplicates in getenvironment()[/+]on Aug 8, 2022
Activity
eryksun commentedon Apr 2, 2021
The
getenvironment()function in "Modules/_winapi.c" needs to sort variables in the environment block and remove duplicates case insensitively1.The sort order used to matter with
SetEnvironmentVairableW(). As soon as it reached a name in the environment block that compared greater than the target name, it would insert a new variable. Nowadays,SetEnvironmentVairableW()searches the entire environment block before inserting a new value. Regardless, at the very least,getenvironment()is not well-behaved and is not setting the environment in the documented sort order that users, and possibly other programs, expect.Case-insensitive sorting in Windows uses upper case. The variable names in the mapping can be added to a list and sorted with a key function that's based on
LCMapStringEx(), with the flagLCMAP_UPPERCASE. Loop over the sorted list to create the environment block. Remove duplicates by skipping a name that compares equal to the previously stored name according toCompareStringOrdinal().Footnotes
Changing Environment Variables ↩
aisk commentedon Mar 19, 2022
I have a question, how to determine which name should be stored if they are duplicated with case insensitive?
eryksun commentedon Mar 19, 2022
Ideally
os.environwould preserve the original case of the process environment, andos.environ.copy()would return a copy that's also case insensitive. That would prevent most problems with duplicates keys. See msg387676 in bpo-28824, and msg414319 in bpo-15373.In msg390038 I suggested keeping the first key that's encountered. However, dicts preserve insertion order nowadays, so one could assume that the last one is the one that the caller wants to keep.
GalaxySnail commentedon May 14, 2022
This issue can be reproduced on msys2 (also cygwin, I think) easily:
Python behaves differently from both cmd.exe and powershell.
Case-sensitive environment variables are in
nt.environ, but they don't affect the real environment:This is because environment vairiables are not sorted correctly in
os._convertenviron:https://github.com/python/cpython/blob/v3.11.0b1/Lib/os.py#L750
Related to GH-91018, GH-73010.
[-][Windows] correctly sort and remove duplicates in _winapi getenvironment()[/-][+][_winapi] correctly sort and remove duplicates in getenvironment()[/+]pythongh-87868: correctly sort and remove duplicates in getenvironment()
5 remaining items
pythongh-87868: Sort and remove duplicates in getenvironment() (pytho…
gh-87868: Skip `test_one_environment_variable` in `test_subprocess` w…
gpshead commentedon Jan 10, 2024
i'll apply the test skip PR into the existing 3.12 and 3.11 backport branches.
pythongh-87868: Skip `test_one_environment_variable` in `test_subproc…
pythongh-87868: Skip `test_one_environment_variable` in `test_subproc…
gh-87868: Sort and remove duplicates in getenvironment() (GH-102731)
gh-87868: Sort and remove duplicates in getenvironment() (GH-102731)
pythongh-87868: Sort and remove duplicates in getenvironment() (pytho…
pythongh-87868: Skip `test_one_environment_variable` in `test_subproc…
pythongh-87868: Sort and remove duplicates in getenvironment() (pytho…
pythongh-87868: Skip `test_one_environment_variable` in `test_subproc…
pythongh-87868: Sort and remove duplicates in getenvironment() (pytho…
pythongh-87868: Skip `test_one_environment_variable` in `test_subproc…