Skip to content

Commit

Permalink
[3.12] gh-111841: Fix os.putenv() and os.unsetenv() with embedded NUL…
Browse files Browse the repository at this point in the history
… on Windows (GH-111842) (GH-111966)

(cherry picked from commit 0b06d24)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
  • Loading branch information
miss-islington and serhiy-storchaka authored Nov 11, 2023
1 parent 2c6000c commit 3bd8b74
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 9 deletions.
5 changes: 4 additions & 1 deletion Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -1142,9 +1142,12 @@ def test_putenv_unsetenv(self):
def test_putenv_unsetenv_error(self):
# Empty variable name is invalid.
# "=" and null character are not allowed in a variable name.
for name in ('', '=name', 'na=me', 'name=', 'name\0', 'na\0me'):
for name in ('', '=name', 'na=me', 'name='):
self.assertRaises((OSError, ValueError), os.putenv, name, "value")
self.assertRaises((OSError, ValueError), os.unsetenv, name)
for name in ('name\0', 'na\0me'):
self.assertRaises(ValueError, os.putenv, name, "value")
self.assertRaises(ValueError, os.unsetenv, name)

if sys.platform == "win32":
# On Windows, an environment variable string ("name=value" string)
Expand Down
14 changes: 7 additions & 7 deletions Lib/test/test_posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,20 +1011,20 @@ def test_environ(self):
self.assertEqual(type(k), item_type)
self.assertEqual(type(v), item_type)

@unittest.skipUnless(os.name == 'posix', "see bug gh-111841")
def test_putenv(self):
with self.assertRaises(ValueError):
os.putenv('FRUIT\0VEGETABLE', 'cabbage')
with self.assertRaises(ValueError):
os.putenv(b'FRUIT\0VEGETABLE', b'cabbage')
with self.assertRaises(ValueError):
os.putenv('FRUIT', 'orange\0VEGETABLE=cabbage')
with self.assertRaises(ValueError):
os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage')
with self.assertRaises(ValueError):
os.putenv('FRUIT=ORANGE', 'lemon')
with self.assertRaises(ValueError):
os.putenv(b'FRUIT=ORANGE', b'lemon')
if os.name == 'posix':
with self.assertRaises(ValueError):
os.putenv(b'FRUIT\0VEGETABLE', b'cabbage')
with self.assertRaises(ValueError):
os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage')
with self.assertRaises(ValueError):
os.putenv(b'FRUIT=ORANGE', b'lemon')

@unittest.skipUnless(hasattr(posix, 'getcwd'), 'test needs posix.getcwd()')
def test_getcwd_long_pathnames(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix truncating arguments on an embedded null character in :meth:`os.putenv`
and :meth:`os.unsetenv` on Windows.
7 changes: 6 additions & 1 deletion Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -12006,7 +12006,6 @@ win32_putenv(PyObject *name, PyObject *value)
}

Py_ssize_t size;
/* PyUnicode_AsWideCharString() rejects embedded null characters */
wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
Py_DECREF(unicode);

Expand All @@ -12020,6 +12019,12 @@ win32_putenv(PyObject *name, PyObject *value)
PyMem_Free(env);
return NULL;
}
if (wcslen(env) != (size_t)size) {
PyErr_SetString(PyExc_ValueError,
"embedded null character");
PyMem_Free(env);
return NULL;
}

/* _wputenv() and SetEnvironmentVariableW() update the environment in the
Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
Expand Down

0 comments on commit 3bd8b74

Please sign in to comment.