mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	#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.
This commit is contained in:
		
							parent
							
								
									d3013ffa49
								
							
						
					
					
						commit
						9a5499b4e5
					
				
					 4 changed files with 35 additions and 25 deletions
				
			
		|  | @ -135,6 +135,12 @@ def test_run_code(self): | ||||||
|             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? | ||||||
| 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) | ||||||
| { | { | ||||||
| 	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) | ||||||
| 	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) | ||||||
| 
 | 
 | ||||||
| 	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) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	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) | ||||||
| { | { | ||||||
| 	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) | ||||||
| 		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) | ||||||
| { | { | ||||||
| 	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); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Amaury Forgeot d'Arc
						Amaury Forgeot d'Arc