]> granicus.if.org Git - python/commitdiff
Issue #28114: Fix a crash in parse_envlist() when env contains byte strings
authorBerker Peksag <berker.peksag@gmail.com>
Thu, 15 Sep 2016 17:19:47 +0000 (20:19 +0300)
committerBerker Peksag <berker.peksag@gmail.com>
Thu, 15 Sep 2016 17:19:47 +0000 (20:19 +0300)
Patch by Eryk Sun.

Lib/test/test_os.py
Misc/NEWS
Modules/posixmodule.c

index d82a4a7f78d84e7abfcfa7b4d05f5c9d04044b81..9096665b6ce65f5a5234cb34d71c0d8c043eb5ef 100644 (file)
@@ -2165,7 +2165,7 @@ class PidTests(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
 
         filename = support.TESTFN
@@ -2185,7 +2185,13 @@ class SpawnTests(unittest.TestCase):
         with open(filename, "w") as fp:
             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')
     def test_spawnl(self):
@@ -2248,6 +2254,13 @@ class SpawnTests(unittest.TestCase):
         else:
             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
 # *nix buildbots. Temporarily skip this to let the buildbots move along.
index 4655b5ea7dab0e710bf1490d672b393db34438a4..a7ba7d836cf92e42dd568308ba8b0c80c9939072 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
 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().
 
 Build
index 43e3c77cbb29727a0a96461d6d2a0bc1a1395e79..32d097872bfe53072fe8b774679f692fbdd0f921 100644 (file)
@@ -4729,28 +4729,31 @@ free_string_array(EXECV_CHAR **array, Py_ssize_t count)
     PyMem_DEL(array);
 }
 
-static
-int fsconvert_strdup(PyObject *o, EXECV_CHAR**out)
+static int
+fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
 {
     Py_ssize_t size;
+    PyObject *ub;
+    int result = 0;
 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
-    *out = PyUnicode_AsWideCharString(o, &size);
-    if (!*out)
+    if (!PyUnicode_FSDecoder(o, &ub))
         return 0;
+    *out = PyUnicode_AsWideCharString(ub, &size);
+    if (*out)
+        result = 1;
 #else
-    PyObject *bytes;
-    if (!PyUnicode_FSConverter(o, &bytes))
+    if (!PyUnicode_FSConverter(o, &ub))
         return 0;
-    size = PyBytes_GET_SIZE(bytes);
-    *out = PyMem_Malloc(size+1);
-    if (!*out) {
+    size = PyBytes_GET_SIZE(ub);
+    *out = PyMem_Malloc(size + 1);
+    if (*out) {
+        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
+        result = 1;
+    } else
         PyErr_NoMemory();
-        return 0;
-    }
-    memcpy(*out, PyBytes_AsString(bytes), size+1);
-    Py_DECREF(bytes);
 #endif
-    return 1;
+    Py_DECREF(ub);
+    return result;
 }
 #endif
 
@@ -4760,7 +4763,7 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
 {
     Py_ssize_t i, pos, envc;
     PyObject *keys=NULL, *vals=NULL;
-    PyObject *key, *val, *keyval;
+    PyObject *key, *val, *key2, *val2, *keyval;
     EXECV_CHAR **envlist;
 
     i = PyMapping_Size(env);
@@ -4790,7 +4793,26 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
         if (!key || !val)
             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)
             goto error;
 
@@ -4798,7 +4820,7 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
             Py_DECREF(keyval);
             goto error;
         }
-        
+
         Py_DECREF(keyval);
     }
     Py_DECREF(vals);