Commit 60a5e4de authored by Victor Stinner's avatar Victor Stinner

Merged revisions 80421,80424 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r80421 | victor.stinner | 2010-04-23 23:41:56 +0200 (ven., 23 avril 2010) | 3 lines

  Issue #8391: os.execvpe() and os.getenv() supports unicode with surrogates and
  bytes strings for environment keys and values
........
  r80424 | victor.stinner | 2010-04-24 00:55:39 +0200 (sam., 24 avril 2010) | 13 lines

  Fix test_undecodable_env of test_subproces for non-ASCII directory

  This test was introduced by r80421 (issue #8391).

  The fix: copy the environment variables instead of starting Python in an empty
  environement. In an empty environment, the locale is C and Python uses ASCII
  for the default file system encoding. The non-ASCII directory will be encoded
  using surrogates, but Python3 is unable to load a module or package with a
  filename using surrogates.

  See issue #8242 for more information about running Python3 with a non-ascii
  directory in an empty environement.
........
parent 4aa50326
...@@ -443,6 +443,8 @@ environ = _Environ(environ, _keymap, _putenv, _unsetenv) ...@@ -443,6 +443,8 @@ environ = _Environ(environ, _keymap, _putenv, _unsetenv)
def getenv(key, default=None): def getenv(key, default=None):
"""Get an environment variable, return None if it doesn't exist. """Get an environment variable, return None if it doesn't exist.
The optional second argument can specify an alternate default.""" The optional second argument can specify an alternate default."""
if isinstance(key, bytes):
key = key.decode(sys.getfilesystemencoding(), "surrogateescape")
return environ.get(key, default) return environ.get(key, default)
__all__.append("getenv") __all__.append("getenv")
......
...@@ -539,6 +539,32 @@ class ProcessTestCase(unittest.TestCase): ...@@ -539,6 +539,32 @@ class ProcessTestCase(unittest.TestCase):
if err.errno != 2: # ignore "no such file" if err.errno != 2: # ignore "no such file"
raise raise
def test_undecodable_env(self):
for key, value in (('test', 'abc\uDCFF'), ('test\uDCFF', '42')):
value_repr = repr(value).encode("ascii")
# test str with surrogates
script = "import os; print(repr(os.getenv(%s)))" % repr(key)
env = os.environ.copy()
env[key] = value
stdout = subprocess.check_output(
[sys.executable, "-c", script],
env=env)
stdout = stdout.rstrip(b'\n\r')
self.assertEquals(stdout, value_repr)
# test bytes
key = key.encode("ascii", "surrogateescape")
value = value.encode("ascii", "surrogateescape")
script = "import os; print(repr(os.getenv(%s)))" % repr(key)
env = os.environ.copy()
env[key] = value
stdout = subprocess.check_output(
[sys.executable, "-c", script],
env=env)
stdout = stdout.rstrip(b'\n\r')
self.assertEquals(stdout, value_repr)
# #
# POSIX tests # POSIX tests
# #
......
...@@ -40,6 +40,10 @@ Core and Builtins ...@@ -40,6 +40,10 @@ Core and Builtins
Library Library
------- -------
- Issue #8391: os.execvpe() and os.getenv() supports unicode with surrogates
and bytes strings for environment keys and values, and use
sys.getfilesystemencoding() instead of sys.getdefautltencoding()
- Issue #2302: Fix a race condition in SocketServer.BaseServer.shutdown, - Issue #2302: Fix a race condition in SocketServer.BaseServer.shutdown,
where the method could block indefinitely if called just before the where the method could block indefinitely if called just before the
event loop started running. This also fixes the occasional freezes event loop started running. This also fixes the occasional freezes
......
...@@ -3212,6 +3212,86 @@ posix_execv(PyObject *self, PyObject *args) ...@@ -3212,6 +3212,86 @@ posix_execv(PyObject *self, PyObject *args)
return posix_error(); return posix_error();
} }
static char**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
{
char **envlist;
Py_ssize_t i, pos, envc;
PyObject *keys=NULL, *vals=NULL;
PyObject *key, *val, *key2, *val2;
char *p, *k, *v;
size_t len;
i = PyMapping_Size(env);
if (i < 0)
return NULL;
envlist = PyMem_NEW(char *, i + 1);
if (envlist == NULL) {
PyErr_NoMemory();
return NULL;
}
envc = 0;
keys = PyMapping_Keys(env);
vals = PyMapping_Values(env);
if (!keys || !vals)
goto error;
if (!PyList_Check(keys) || !PyList_Check(vals)) {
PyErr_Format(PyExc_TypeError,
"env.keys() or env.values() is not a list");
goto error;
}
for (pos = 0; pos < i; pos++) {
key = PyList_GetItem(keys, pos);
val = PyList_GetItem(vals, pos);
if (!key || !val)
goto error;
if (PyUnicode_FSConverter(key, &key2) == 0)
goto error;
if (PyUnicode_FSConverter(val, &val2) == 0) {
Py_DECREF(key2);
goto error;
}
#if defined(PYOS_OS2)
/* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
#endif
k = PyBytes_AsString(key2);
v = PyBytes_AsString(val2);
len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2;
p = PyMem_NEW(char, len);
if (p == NULL) {
PyErr_NoMemory();
Py_DECREF(key2);
Py_DECREF(val2);
goto error;
}
PyOS_snprintf(p, len, "%s=%s", k, v);
envlist[envc++] = p;
Py_DECREF(key2);
Py_DECREF(val2);
#if defined(PYOS_OS2)
}
#endif
}
Py_DECREF(vals);
Py_DECREF(keys);
envlist[envc] = 0;
*envc_ptr = envc;
return envlist;
error:
Py_XDECREF(keys);
Py_XDECREF(vals);
while (--envc >= 0)
PyMem_DEL(envlist[envc]);
PyMem_DEL(envlist);
return NULL;
}
PyDoc_STRVAR(posix_execve__doc__, PyDoc_STRVAR(posix_execve__doc__,
"execve(path, args, env)\n\n\ "execve(path, args, env)\n\n\
...@@ -3229,8 +3309,7 @@ posix_execve(PyObject *self, PyObject *args) ...@@ -3229,8 +3309,7 @@ posix_execve(PyObject *self, PyObject *args)
PyObject *argv, *env; PyObject *argv, *env;
char **argvlist; char **argvlist;
char **envlist; char **envlist;
PyObject *key, *val, *keys=NULL, *vals=NULL; Py_ssize_t i, argc, envc;
Py_ssize_t i, pos, argc, envc;
PyObject *(*getitem)(PyObject *, Py_ssize_t); PyObject *(*getitem)(PyObject *, Py_ssize_t);
Py_ssize_t lastarg = 0; Py_ssize_t lastarg = 0;
...@@ -3278,63 +3357,9 @@ posix_execve(PyObject *self, PyObject *args) ...@@ -3278,63 +3357,9 @@ posix_execve(PyObject *self, PyObject *args)
lastarg = argc; lastarg = argc;
argvlist[argc] = NULL; argvlist[argc] = NULL;
i = PyMapping_Size(env); envlist = parse_envlist(env, &envc);
if (i < 0) if (envlist == NULL)
goto fail_1;
envlist = PyMem_NEW(char *, i + 1);
if (envlist == NULL) {
PyErr_NoMemory();
goto fail_1; goto fail_1;
}
envc = 0;
keys = PyMapping_Keys(env);
vals = PyMapping_Values(env);
if (!keys || !vals)
goto fail_2;
if (!PyList_Check(keys) || !PyList_Check(vals)) {
PyErr_SetString(PyExc_TypeError,
"execve(): env.keys() or env.values() is not a list");
goto fail_2;
}
for (pos = 0; pos < i; pos++) {
char *p, *k, *v;
size_t len;
key = PyList_GetItem(keys, pos);
val = PyList_GetItem(vals, pos);
if (!key || !val)
goto fail_2;
if (!PyArg_Parse(
key,
"s;execve() arg 3 contains a non-string key",
&k) ||
!PyArg_Parse(
val,
"s;execve() arg 3 contains a non-string value",
&v))
{
goto fail_2;
}
#if defined(PYOS_OS2)
/* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
#endif
len = PyUnicode_GetSize(key) + PyUnicode_GetSize(val) + 2;
p = PyMem_NEW(char, len);
if (p == NULL) {
PyErr_NoMemory();
goto fail_2;
}
PyOS_snprintf(p, len, "%s=%s", k, v);
envlist[envc++] = p;
#if defined(PYOS_OS2)
}
#endif
}
envlist[envc] = 0;
execve(path, argvlist, envlist); execve(path, argvlist, envlist);
...@@ -3342,14 +3367,11 @@ posix_execve(PyObject *self, PyObject *args) ...@@ -3342,14 +3367,11 @@ posix_execve(PyObject *self, PyObject *args)
(void) posix_error(); (void) posix_error();
fail_2:
while (--envc >= 0) while (--envc >= 0)
PyMem_DEL(envlist[envc]); PyMem_DEL(envlist[envc]);
PyMem_DEL(envlist); PyMem_DEL(envlist);
fail_1: fail_1:
free_string_array(argvlist, lastarg); free_string_array(argvlist, lastarg);
Py_XDECREF(vals);
Py_XDECREF(keys);
fail_0: fail_0:
release_bytes(opath); release_bytes(opath);
return NULL; return NULL;
...@@ -3463,8 +3485,8 @@ posix_spawnve(PyObject *self, PyObject *args) ...@@ -3463,8 +3485,8 @@ posix_spawnve(PyObject *self, PyObject *args)
PyObject *argv, *env; PyObject *argv, *env;
char **argvlist; char **argvlist;
char **envlist; char **envlist;
PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; PyObject *res = NULL;
int mode, pos, envc; int mode, envc;
Py_ssize_t argc, i; Py_ssize_t argc, i;
Py_intptr_t spawnval; Py_intptr_t spawnval;
PyObject *(*getitem)(PyObject *, Py_ssize_t); PyObject *(*getitem)(PyObject *, Py_ssize_t);
...@@ -3514,55 +3536,9 @@ posix_spawnve(PyObject *self, PyObject *args) ...@@ -3514,55 +3536,9 @@ posix_spawnve(PyObject *self, PyObject *args)
lastarg = argc; lastarg = argc;
argvlist[argc] = NULL; argvlist[argc] = NULL;
i = PyMapping_Size(env); envlist = parse_envlist(env, &envc);
if (i < 0) if (envlist == NULL)
goto fail_1;
envlist = PyMem_NEW(char *, i + 1);
if (envlist == NULL) {
PyErr_NoMemory();
goto fail_1; goto fail_1;
}
envc = 0;
keys = PyMapping_Keys(env);
vals = PyMapping_Values(env);
if (!keys || !vals)
goto fail_2;
if (!PyList_Check(keys) || !PyList_Check(vals)) {
PyErr_SetString(PyExc_TypeError,
"spawnve(): env.keys() or env.values() is not a list");
goto fail_2;
}
for (pos = 0; pos < i; pos++) {
char *p, *k, *v;
size_t len;
key = PyList_GetItem(keys, pos);
val = PyList_GetItem(vals, pos);
if (!key || !val)
goto fail_2;
if (!PyArg_Parse(
key,
"s;spawnve() arg 3 contains a non-string key",
&k) ||
!PyArg_Parse(
val,
"s;spawnve() arg 3 contains a non-string value",
&v))
{
goto fail_2;
}
len = PyUnicode_GetSize(key) + PyUnicode_GetSize(val) + 2;
p = PyMem_NEW(char, len);
if (p == NULL) {
PyErr_NoMemory();
goto fail_2;
}
PyOS_snprintf(p, len, "%s=%s", k, v);
envlist[envc++] = p;
}
envlist[envc] = 0;
#if defined(PYOS_OS2) && defined(PYCC_GCC) #if defined(PYOS_OS2) && defined(PYCC_GCC)
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
...@@ -3586,14 +3562,11 @@ posix_spawnve(PyObject *self, PyObject *args) ...@@ -3586,14 +3562,11 @@ posix_spawnve(PyObject *self, PyObject *args)
res = Py_BuildValue("L", (PY_LONG_LONG) spawnval); res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
#endif #endif
fail_2:
while (--envc >= 0) while (--envc >= 0)
PyMem_DEL(envlist[envc]); PyMem_DEL(envlist[envc]);
PyMem_DEL(envlist); PyMem_DEL(envlist);
fail_1: fail_1:
free_string_array(argvlist, lastarg); free_string_array(argvlist, lastarg);
Py_XDECREF(vals);
Py_XDECREF(keys);
fail_0: fail_0:
release_bytes(opath); release_bytes(opath);
return res; return res;
...@@ -3698,8 +3671,8 @@ posix_spawnvpe(PyObject *self, PyObject *args) ...@@ -3698,8 +3671,8 @@ posix_spawnvpe(PyObject *self, PyObject *args)
PyObject *argv, *env; PyObject *argv, *env;
char **argvlist; char **argvlist;
char **envlist; char **envlist;
PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; PyObject *res=NULL;
int mode, i, pos, argc, envc; int mode, i, argc, envc;
Py_intptr_t spawnval; Py_intptr_t spawnval;
PyObject *(*getitem)(PyObject *, Py_ssize_t); PyObject *(*getitem)(PyObject *, Py_ssize_t);
int lastarg = 0; int lastarg = 0;
...@@ -3748,55 +3721,9 @@ posix_spawnvpe(PyObject *self, PyObject *args) ...@@ -3748,55 +3721,9 @@ posix_spawnvpe(PyObject *self, PyObject *args)
lastarg = argc; lastarg = argc;
argvlist[argc] = NULL; argvlist[argc] = NULL;
i = PyMapping_Size(env); envlist = parse_envlist(env, &envc);
if (i < 0) if (envlist == NULL)
goto fail_1; goto fail_1;
envlist = PyMem_NEW(char *, i + 1);
if (envlist == NULL) {
PyErr_NoMemory();
goto fail_1;
}
envc = 0;
keys = PyMapping_Keys(env);
vals = PyMapping_Values(env);
if (!keys || !vals)
goto fail_2;
if (!PyList_Check(keys) || !PyList_Check(vals)) {
PyErr_SetString(PyExc_TypeError,
"spawnvpe(): env.keys() or env.values() is not a list");
goto fail_2;
}
for (pos = 0; pos < i; pos++) {
char *p, *k, *v;
size_t len;
key = PyList_GetItem(keys, pos);
val = PyList_GetItem(vals, pos);
if (!key || !val)
goto fail_2;
if (!PyArg_Parse(
key,
"s;spawnvpe() arg 3 contains a non-string key",
&k) ||
!PyArg_Parse(
val,
"s;spawnvpe() arg 3 contains a non-string value",
&v))
{
goto fail_2;
}
len = PyUnicode_GetSize(key) + PyUnicode_GetSize(val) + 2;
p = PyMem_NEW(char, len);
if (p == NULL) {
PyErr_NoMemory();
goto fail_2;
}
PyOS_snprintf(p, len, "%s=%s", k, v);
envlist[envc++] = p;
}
envlist[envc] = 0;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
#if defined(PYCC_GCC) #if defined(PYCC_GCC)
...@@ -3811,14 +3738,11 @@ posix_spawnvpe(PyObject *self, PyObject *args) ...@@ -3811,14 +3738,11 @@ posix_spawnvpe(PyObject *self, PyObject *args)
else else
res = Py_BuildValue("l", (long) spawnval); res = Py_BuildValue("l", (long) spawnval);
fail_2:
while (--envc >= 0) while (--envc >= 0)
PyMem_DEL(envlist[envc]); PyMem_DEL(envlist[envc]);
PyMem_DEL(envlist); PyMem_DEL(envlist);
fail_1: fail_1:
free_string_array(argvlist, lastarg); free_string_array(argvlist, lastarg);
Py_XDECREF(vals);
Py_XDECREF(keys);
fail_0: fail_0:
release_bytes(opath); release_bytes(opath);
return res; return res;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment