Commit 9a5499b4 authored by Amaury Forgeot d'Arc's avatar Amaury Forgeot d'Arc

#3705: Command-line arguments were not correctly decoded when the

terminal does not use UTF8.

Now the code propagates the unicode string as far as possible, and avoids
the conversion to char* which implicitely uses utf-8.

Reviewed by Benjamin.
parent d3013ffa
...@@ -135,6 +135,12 @@ class CmdLineTest(unittest.TestCase): ...@@ -135,6 +135,12 @@ class CmdLineTest(unittest.TestCase):
self.exit_code('-c', 'pass'), self.exit_code('-c', 'pass'),
0) 0)
# Test handling of non-ascii data
command = "assert(ord('\xe9') == 0xe9)"
self.assertEqual(
self.exit_code('-c', command),
0)
def test_main(): def test_main():
test.support.run_unittest(CmdLineTest) test.support.run_unittest(CmdLineTest)
......
...@@ -13,6 +13,9 @@ What's New in Python 3.0 release candiate 3? ...@@ -13,6 +13,9 @@ What's New in Python 3.0 release candiate 3?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #3705: Command-line arguments were not correctly decoded when the
terminal does not use UTF8.
Library Library
------- -------
......
...@@ -287,7 +287,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -287,7 +287,7 @@ Py_Main(int argc, wchar_t **argv)
{ {
int c; int c;
int sts; int sts;
char *command = NULL; wchar_t *command = NULL;
wchar_t *filename = NULL; wchar_t *filename = NULL;
wchar_t *module = NULL; wchar_t *module = NULL;
FILE *fp = stdin; FILE *fp = stdin;
...@@ -299,7 +299,6 @@ Py_Main(int argc, wchar_t **argv) ...@@ -299,7 +299,6 @@ Py_Main(int argc, wchar_t **argv)
int version = 0; int version = 0;
int saw_unbuffered_flag = 0; int saw_unbuffered_flag = 0;
PyCompilerFlags cf; PyCompilerFlags cf;
char *oldloc;
cf.cf_flags = 0; cf.cf_flags = 0;
...@@ -310,30 +309,19 @@ Py_Main(int argc, wchar_t **argv) ...@@ -310,30 +309,19 @@ Py_Main(int argc, wchar_t **argv)
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) { while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
if (c == 'c') { if (c == 'c') {
size_t r1, r2; size_t len;
oldloc = setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "");
r1 = wcslen(_PyOS_optarg);
r2 = wcstombs(NULL, _PyOS_optarg, r1);
if (r2 == (size_t) -1)
Py_FatalError(
"cannot convert character encoding of -c argument");
if (r2 > r1)
r1 = r2;
r1 += 2;
/* -c is the last option; following arguments /* -c is the last option; following arguments
that look like options are left for the that look like options are left for the
command to interpret. */ command to interpret. */
command = (char *)malloc(r1);
len = wcslen(_PyOS_optarg) + 1 + 1;
command = (wchar_t *)malloc(sizeof(wchar_t) * len);
if (command == NULL) if (command == NULL)
Py_FatalError( Py_FatalError(
"not enough memory to copy -c argument"); "not enough memory to copy -c argument");
r2 = wcstombs(command, _PyOS_optarg, r1); wcscpy(command, _PyOS_optarg);
if (r2 > r1-1) command[len - 2] = '\n';
Py_FatalError( command[len - 1] = 0;
"not enough memory to copy -c argument");
strcat(command, "\n");
setlocale(LC_ALL, oldloc);
break; break;
} }
...@@ -543,8 +531,18 @@ Py_Main(int argc, wchar_t **argv) ...@@ -543,8 +531,18 @@ Py_Main(int argc, wchar_t **argv)
} }
if (command) { if (command) {
sts = PyRun_SimpleStringFlags(command, &cf) != 0; PyObject *commandObj = PyUnicode_FromWideChar(
command, wcslen(command));
free(command); free(command);
if (commandObj != NULL) {
sts = PyRun_SimpleStringFlags(
_PyUnicode_AsString(commandObj), &cf) != 0;
}
else {
PyErr_Print();
sts = 1;
}
Py_DECREF(commandObj);
} else if (module) { } else if (module) {
sts = RunModule(module, 1); sts = RunModule(module, 1);
} }
......
...@@ -2793,6 +2793,7 @@ call_find_module(char *name, PyObject *path) ...@@ -2793,6 +2793,7 @@ call_find_module(char *name, PyObject *path)
{ {
extern int fclose(FILE *); extern int fclose(FILE *);
PyObject *fob, *ret; PyObject *fob, *ret;
PyObject *pathobj;
struct filedescr *fdp; struct filedescr *fdp;
char pathname[MAXPATHLEN+1]; char pathname[MAXPATHLEN+1];
FILE *fp = NULL; FILE *fp = NULL;
...@@ -2836,9 +2837,9 @@ call_find_module(char *name, PyObject *path) ...@@ -2836,9 +2837,9 @@ call_find_module(char *name, PyObject *path)
fob = Py_None; fob = Py_None;
Py_INCREF(fob); Py_INCREF(fob);
} }
ret = Py_BuildValue("Os(ssi)", pathobj = PyUnicode_DecodeFSDefault(pathname);
fob, pathname, fdp->suffix, fdp->mode, fdp->type); ret = Py_BuildValue("NN(ssi)",
Py_DECREF(fob); fob, pathobj, fdp->suffix, fdp->mode, fdp->type);
PyMem_FREE(found_encoding); PyMem_FREE(found_encoding);
return ret; return ret;
...@@ -2849,7 +2850,9 @@ imp_find_module(PyObject *self, PyObject *args) ...@@ -2849,7 +2850,9 @@ imp_find_module(PyObject *self, PyObject *args)
{ {
char *name; char *name;
PyObject *path = NULL; PyObject *path = NULL;
if (!PyArg_ParseTuple(args, "s|O:find_module", &name, &path)) if (!PyArg_ParseTuple(args, "es|O:find_module",
Py_FileSystemDefaultEncoding, &name,
&path))
return NULL; return NULL;
return call_find_module(name, path); return call_find_module(name, path);
} }
......
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