8000 gh-87868: correctly sort and remove duplicates in getenvironment() · aisk/cpython@eb5e3f2 · GitHub
[go: up one dir, main page]

Skip to content

Commit eb5e3f2

Browse files
committed
pythongh-87868: correctly sort and remove duplicates in getenvironment()
1 parent 2999e02 commit eb5e3f2

File tree

1 file changed

+71
-5
lines changed

1 file changed

+71
-5
lines changed

Modules/_winapi.c

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -772,23 +772,88 @@ gethandle(PyObject* obj, const char* name)
772772
return ret;
773773
}
774774

775+
static PyObject* sortenvironmentkey(PyObject *module, PyObject *item) {
776+
Py_ssize_t n;
777+
wchar_t* s = PyUnicode_AsWideCharString(item, &n);
778+
if (s == NULL) {
779+
return NULL;
780+
}
781+
return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE, s);
782+
}
783+
784+
static PyMethodDef sortenvironmentkey_def = {
785+
"sortenvironmentkey",
786+
_PyCFunction_CAST(sortenvironmentkey),
787+
METH_O,
788+
""
789+
};
790+
791+
static PyObject *
792+
normalize_environment(PyObject* environment) {
793+
PyObject *result, *keys, *keyfunc, *sort, *args, *kwargs;
794+
795+
keys = PyMapping_Keys(environment);
796+
if (keys == NULL) {
797+
return NULL;
798+
}
799+
800+
keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL);
801+
sort = PyObject_GetAttrString(keys, "sort");
802+
args = PyTuple_New(0);
803+
kwargs = PyDict_New();
804+
PyDict_SetItemString(kwargs, "key", keyfunc);
805+
if (PyObject_Call(sort, args, kwargs) == NULL) {
806+
goto error;
807+
}
808+
809+
result = PyDict_New();
810+
811+
for (int i = 0; i<PyList_GET_SIZE(keys); i++) {
812+
if (i < 1) {
813+
continue;
814+
}
815+
PyObject *key = PyList_GET_ITEM(keys, i);
816+
wchar_t *key_string = PyUnicode_AsWideCharString(key, NULL);
817+
wchar_t *prev_key_string = PyUnicode_AsWideCharString(PyList_GET_ITEM(keys, i-1), NULL);
818+
if (CompareStringOrdinal(prev_key_string, -1, key_string, -1, TRUE) == CSTR_EQUAL) {
819+
continue;
820+
}
821+
PyObject* value = PyDict_GetItem(environment, key);
822+
PyDict_SetItem(result, key, value);
823+
}
824+
825+
error:
826+
Py_DECREF(keys);
827+
Py_DECREF(keyfunc);
828+
Py_DECREF(sort);
829+
Py_DECREF(args);
830+
Py_DECREF(kwargs);
831+
832+
return result;
833+
}
834+
775835
static wchar_t *
776-
getenvironment(PyObject* environment)
836+
getenvironment(PyObject* env)
777837
{
778838
Py_ssize_t i, envsize, totalsize;
779839
wchar_t *buffer = NULL, *p, *end;
780-
PyObject *keys, *values;
840+
PyObject *environment = NULL, *keys = NULL, *values = NULL;
781841

782842
/* convert environment dictionary to windows environment string */
783-
if (! PyMapping_Check(environment)) {
843+
if (! PyMapping_Check(env)) {
784844
PyErr_SetString(
785845
PyExc_TypeError, "environment must be dictionary or None");
786846
return NULL;
787847
}
788848

849+
environment = normalize_environment(env);
850+
if (environment == NULL) {
851+
goto error;
852+
}
853+
789854
keys = PyMapping_Keys(environment);
790855
if (!keys) {
791-
return NULL;
856+
goto error;
792857
}
793858
values = PyMapping_Values(environment);
794859
if (!values) {
@@ -869,7 +934,8 @@ getenvironment(PyObject* environment)
869934
*p++ = L'\0';
870935
assert(p == end);
871936

872-
error:
937+
error:
938+
Py_XDECREF(environment);
873939
Py_XDECREF(keys);
874940
Py_XDECREF(values);
875941
return buffer;

0 commit comments

Comments
 (0)
0