homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: [Windows] correctly sort and remove duplicates in _winapi getenvironment()
Type: behavior Stage: needs patch
Components: Extension Modules, Windows Versions: Python 3.11, Python 3.10, Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: asaka, eryksun, paul.moore, steve.dower, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2021年04月02日 04:16 by eryksun, last changed 2022年04月11日 14:59 by admin.

Messages (3)
msg390038 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2021年04月02日 04:16
getenvironment() in Modules/_winapi.c needs to sort variables in the environment block and remove duplicates case insensitively [1]. 
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 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() [2], 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() [3].
_winapi.LCMapStringEx(src, flags=LCMAP_UPPERCASE, locale=LOCALE_NAME_INVARIANT) could also be used in ntpath.normcase(), which would resolve bpo-42658.
---
[1] https://docs.microsoft.com/en-us/windows/win32/procthread/changing-environment-variables
[2] https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-lcmapstringex
[3] https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-comparestringordinal 
msg415560 - (view) Author: AN Long (asaka) * Date: 2022年03月19日 16:48
I have a question, how to determine which name should be stored if they are duplicated with case insensitive?
msg415563 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2022年03月19日 18:03
> 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.
History
Date User Action Args
2022年04月11日 14:59:43adminsetgithub: 87868
2022年03月19日 18:03:11eryksunsetmessages: + msg415563
2022年03月19日 16:48:09asakasetnosy: + asaka
messages: + msg415560
2022年02月26日 06:06:11eryksunsetversions: + Python 3.11, - Python 3.8
2021年04月02日 04:16:14eryksuncreate

AltStyle によって変換されたページ (->オリジナル) /