Issue #28114: Fix a crash in parse_envlist() when env contains byte strings
Patch by Eryk Sun.
This commit is contained in:
parent
8987c9d219
commit
8181646931
|
@ -2165,7 +2165,7 @@ class PidTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class SpawnTests(unittest.TestCase):
|
class SpawnTests(unittest.TestCase):
|
||||||
def create_args(self, with_env=False):
|
def create_args(self, with_env=False, use_bytes=False):
|
||||||
self.exitcode = 17
|
self.exitcode = 17
|
||||||
|
|
||||||
filename = support.TESTFN
|
filename = support.TESTFN
|
||||||
|
@ -2185,7 +2185,13 @@ class SpawnTests(unittest.TestCase):
|
||||||
with open(filename, "w") as fp:
|
with open(filename, "w") as fp:
|
||||||
fp.write(code)
|
fp.write(code)
|
||||||
|
|
||||||
return [sys.executable, filename]
|
args = [sys.executable, filename]
|
||||||
|
if use_bytes:
|
||||||
|
args = [os.fsencode(a) for a in args]
|
||||||
|
self.env = {os.fsencode(k): os.fsencode(v)
|
||||||
|
for k, v in self.env.items()}
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, 'spawnl'), 'need os.spawnl')
|
@unittest.skipUnless(hasattr(os, 'spawnl'), 'need os.spawnl')
|
||||||
def test_spawnl(self):
|
def test_spawnl(self):
|
||||||
|
@ -2248,6 +2254,13 @@ class SpawnTests(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.assertEqual(status, self.exitcode << 8)
|
self.assertEqual(status, self.exitcode << 8)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'spawnve'), 'need os.spawnve')
|
||||||
|
def test_spawnve_bytes(self):
|
||||||
|
# Test bytes handling in parse_arglist and parse_envlist (#28114)
|
||||||
|
args = self.create_args(with_env=True, use_bytes=True)
|
||||||
|
exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
|
||||||
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
|
||||||
# The introduction of this TestCase caused at least two different errors on
|
# The introduction of this TestCase caused at least two different errors on
|
||||||
# *nix buildbots. Temporarily skip this to let the buildbots move along.
|
# *nix buildbots. Temporarily skip this to let the buildbots move along.
|
||||||
|
|
|
@ -27,6 +27,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #28114: Fix a crash in parse_envlist() when env contains byte strings.
|
||||||
|
Patch by Eryk Sun.
|
||||||
|
|
||||||
- Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
|
- Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
|
||||||
|
|
||||||
Build
|
Build
|
||||||
|
|
|
@ -4729,28 +4729,31 @@ free_string_array(EXECV_CHAR **array, Py_ssize_t count)
|
||||||
PyMem_DEL(array);
|
PyMem_DEL(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int
|
||||||
int fsconvert_strdup(PyObject *o, EXECV_CHAR**out)
|
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
|
||||||
{
|
{
|
||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
|
PyObject *ub;
|
||||||
|
int result = 0;
|
||||||
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
|
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
|
||||||
*out = PyUnicode_AsWideCharString(o, &size);
|
if (!PyUnicode_FSDecoder(o, &ub))
|
||||||
if (!*out)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
*out = PyUnicode_AsWideCharString(ub, &size);
|
||||||
|
if (*out)
|
||||||
|
result = 1;
|
||||||
#else
|
#else
|
||||||
PyObject *bytes;
|
if (!PyUnicode_FSConverter(o, &ub))
|
||||||
if (!PyUnicode_FSConverter(o, &bytes))
|
|
||||||
return 0;
|
return 0;
|
||||||
size = PyBytes_GET_SIZE(bytes);
|
size = PyBytes_GET_SIZE(ub);
|
||||||
*out = PyMem_Malloc(size+1);
|
*out = PyMem_Malloc(size + 1);
|
||||||
if (!*out) {
|
if (*out) {
|
||||||
|
memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
|
||||||
|
result = 1;
|
||||||
|
} else
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(*out, PyBytes_AsString(bytes), size+1);
|
|
||||||
Py_DECREF(bytes);
|
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
Py_DECREF(ub);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4760,7 +4763,7 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
|
||||||
{
|
{
|
||||||
Py_ssize_t i, pos, envc;
|
Py_ssize_t i, pos, envc;
|
||||||
PyObject *keys=NULL, *vals=NULL;
|
PyObject *keys=NULL, *vals=NULL;
|
||||||
PyObject *key, *val, *keyval;
|
PyObject *key, *val, *key2, *val2, *keyval;
|
||||||
EXECV_CHAR **envlist;
|
EXECV_CHAR **envlist;
|
||||||
|
|
||||||
i = PyMapping_Size(env);
|
i = PyMapping_Size(env);
|
||||||
|
@ -4790,7 +4793,26 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
|
||||||
if (!key || !val)
|
if (!key || !val)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
keyval = PyUnicode_FromFormat("%U=%U", key, val);
|
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
|
||||||
|
if (!PyUnicode_FSDecoder(key, &key2))
|
||||||
|
goto error;
|
||||||
|
if (!PyUnicode_FSDecoder(val, &val2)) {
|
||||||
|
Py_DECREF(key2);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
|
||||||
|
#else
|
||||||
|
if (!PyUnicode_FSConverter(key, &key2))
|
||||||
|
goto error;
|
||||||
|
if (!PyUnicode_FSConverter(val, &val2)) {
|
||||||
|
Py_DECREF(key2);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
|
||||||
|
PyBytes_AS_STRING(val2));
|
||||||
|
#endif
|
||||||
|
Py_DECREF(key2);
|
||||||
|
Py_DECREF(val2);
|
||||||
if (!keyval)
|
if (!keyval)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue