mirror of
https://github.com/python/cpython.git
synced 2025-10-17 12:18:23 +00:00
PyUnicode_EncodeFS() raises an exception if _Py_wchar2char() fails
* Add error_pos optional argument to _Py_wchar2char() * PyUnicode_EncodeFS() raises a UnicodeEncodeError or MemoryError if _Py_wchar2char() fails
This commit is contained in:
parent
0cfba09b09
commit
2f02a51135
4 changed files with 37 additions and 11 deletions
|
@ -10,7 +10,8 @@ PyAPI_FUNC(wchar_t *) _Py_char2wchar(
|
||||||
size_t *size);
|
size_t *size);
|
||||||
|
|
||||||
PyAPI_FUNC(char*) _Py_wchar2char(
|
PyAPI_FUNC(char*) _Py_wchar2char(
|
||||||
const wchar_t *text);
|
const wchar_t *text,
|
||||||
|
size_t *error_pos);
|
||||||
|
|
||||||
#if defined(HAVE_STAT) && !defined(MS_WINDOWS)
|
#if defined(HAVE_STAT) && !defined(MS_WINDOWS)
|
||||||
PyAPI_FUNC(int) _Py_wstat(
|
PyAPI_FUNC(int) _Py_wstat(
|
||||||
|
|
|
@ -646,7 +646,7 @@ Py_Main(int argc, wchar_t **argv)
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
char *cfilename_buffer;
|
char *cfilename_buffer;
|
||||||
const char *cfilename;
|
const char *cfilename;
|
||||||
cfilename_buffer = _Py_wchar2char(filename);
|
cfilename_buffer = _Py_wchar2char(filename, NULL);
|
||||||
if (cfilename_buffer != NULL)
|
if (cfilename_buffer != NULL)
|
||||||
cfilename = cfilename_buffer;
|
cfilename = cfilename_buffer;
|
||||||
else
|
else
|
||||||
|
|
|
@ -1606,14 +1606,31 @@ PyUnicode_EncodeFSDefault(PyObject *unicode)
|
||||||
wchar_t *wchar;
|
wchar_t *wchar;
|
||||||
char *bytes;
|
char *bytes;
|
||||||
PyObject *bytes_obj;
|
PyObject *bytes_obj;
|
||||||
|
size_t error_pos;
|
||||||
|
|
||||||
wchar = PyUnicode_AsWideCharString(unicode, NULL);
|
wchar = PyUnicode_AsWideCharString(unicode, NULL);
|
||||||
if (wchar == NULL)
|
if (wchar == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
bytes = _Py_wchar2char(wchar);
|
bytes = _Py_wchar2char(wchar, &error_pos);
|
||||||
PyMem_Free(wchar);
|
if (bytes == NULL) {
|
||||||
if (bytes == NULL)
|
if (error_pos != (size_t)-1) {
|
||||||
|
char *errmsg = strerror(errno);
|
||||||
|
PyObject *exc = NULL;
|
||||||
|
if (errmsg == NULL)
|
||||||
|
errmsg = "Py_wchar2char() failed";
|
||||||
|
raise_encode_exception(&exc,
|
||||||
|
"filesystemencoding",
|
||||||
|
PyUnicode_AS_UNICODE(unicode), PyUnicode_GET_SIZE(unicode),
|
||||||
|
error_pos, error_pos+1,
|
||||||
|
errmsg);
|
||||||
|
Py_XDECREF(exc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PyErr_NoMemory();
|
||||||
|
PyMem_Free(wchar);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
PyMem_Free(wchar);
|
||||||
|
|
||||||
bytes_obj = PyBytes_FromString(bytes);
|
bytes_obj = PyBytes_FromString(bytes);
|
||||||
PyMem_Free(bytes);
|
PyMem_Free(bytes);
|
||||||
|
|
|
@ -132,15 +132,21 @@ oom:
|
||||||
This function is the reverse of _Py_char2wchar().
|
This function is the reverse of _Py_char2wchar().
|
||||||
|
|
||||||
Return a pointer to a newly allocated byte string (use PyMem_Free() to free
|
Return a pointer to a newly allocated byte string (use PyMem_Free() to free
|
||||||
the memory), or NULL on error (conversion error or memory error). */
|
the memory), or NULL on conversion or memory allocation error.
|
||||||
|
|
||||||
|
If error_pos is not NULL: *error_pos is the index of the invalid character
|
||||||
|
on conversion error, or (size_t)-1 otherwise. */
|
||||||
char*
|
char*
|
||||||
_Py_wchar2char(const wchar_t *text)
|
_Py_wchar2char(const wchar_t *text, size_t *error_pos)
|
||||||
{
|
{
|
||||||
const size_t len = wcslen(text);
|
const size_t len = wcslen(text);
|
||||||
char *result = NULL, *bytes = NULL;
|
char *result = NULL, *bytes = NULL;
|
||||||
size_t i, size, converted;
|
size_t i, size, converted;
|
||||||
wchar_t c, buf[2];
|
wchar_t c, buf[2];
|
||||||
|
|
||||||
|
if (error_pos != NULL)
|
||||||
|
*error_pos = (size_t)-1;
|
||||||
|
|
||||||
/* The function works in two steps:
|
/* The function works in two steps:
|
||||||
1. compute the length of the output buffer in bytes (size)
|
1. compute the length of the output buffer in bytes (size)
|
||||||
2. outputs the bytes */
|
2. outputs the bytes */
|
||||||
|
@ -168,6 +174,8 @@ _Py_wchar2char(const wchar_t *text)
|
||||||
if (converted == (size_t)-1) {
|
if (converted == (size_t)-1) {
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
PyMem_Free(result);
|
PyMem_Free(result);
|
||||||
|
if (error_pos != NULL)
|
||||||
|
*error_pos = i;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (bytes != NULL) {
|
if (bytes != NULL) {
|
||||||
|
@ -208,7 +216,7 @@ _Py_wstat(const wchar_t* path, struct stat *buf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char *fname;
|
char *fname;
|
||||||
fname = _Py_wchar2char(path);
|
fname = _Py_wchar2char(path, NULL);
|
||||||
if (fname == NULL) {
|
if (fname == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -263,7 +271,7 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cpath = _Py_wchar2char(path);
|
cpath = _Py_wchar2char(path, NULL);
|
||||||
if (cpath == NULL)
|
if (cpath == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
f = fopen(cpath, cmode);
|
f = fopen(cpath, cmode);
|
||||||
|
@ -317,7 +325,7 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
|
||||||
int res;
|
int res;
|
||||||
size_t r1;
|
size_t r1;
|
||||||
|
|
||||||
cpath = _Py_wchar2char(path);
|
cpath = _Py_wchar2char(path, NULL);
|
||||||
if (cpath == NULL) {
|
if (cpath == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -361,7 +369,7 @@ _Py_wrealpath(const wchar_t *path,
|
||||||
wchar_t *wresolved_path;
|
wchar_t *wresolved_path;
|
||||||
char *res;
|
char *res;
|
||||||
size_t r;
|
size_t r;
|
||||||
cpath = _Py_wchar2char(path);
|
cpath = _Py_wchar2char(path, NULL);
|
||||||
if (cpath == NULL) {
|
if (cpath == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue