Issue #28114: Fix a crash in parse_envlist() when env contains byte strings

Patch by Eryk Sun.
This commit is contained in:
Berker Peksag 2016-09-15 20:19:47 +03:00
parent 8987c9d219
commit 8181646931
3 changed files with 57 additions and 19 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;