diff --git a/Include/fileobject.h b/Include/fileobject.h index ebbb521d17b..9fd0646be47 100644 --- a/Include/fileobject.h +++ b/Include/fileobject.h @@ -57,6 +57,11 @@ PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; char *Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); size_t Py_UniversalNewlineFread(char *, size_t, FILE *, PyObject *); +/* A routine to do sanity checking on the file mode string. returns + non-zero on if an exception occurred +*/ +int _PyFile_SanitizeMode(char *mode); + #ifdef __cplusplus } #endif diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 158b12e2eeb..b984c3004a1 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6170,16 +6170,23 @@ static PyObject * posix_fdopen(PyObject *self, PyObject *args) { int fd; - char *mode = "r"; + char *orgmode = "r"; int bufsize = -1; FILE *fp; PyObject *f; - if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize)) + char *mode; + if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize)) return NULL; - if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') { - PyErr_Format(PyExc_ValueError, - "invalid file mode '%s'", mode); + /* Sanitize mode. See fileobject.c */ + mode = PyMem_MALLOC(strlen(orgmode)+3); + if (!mode) { + PyErr_NoMemory(); + return NULL; + } + strcpy(mode, orgmode); + if (_PyFile_SanitizeMode(mode)) { + PyMem_FREE(mode); return NULL; } Py_BEGIN_ALLOW_THREADS @@ -6200,10 +6207,11 @@ posix_fdopen(PyObject *self, PyObject *args) #else fp = fdopen(fd, mode); #endif + PyMem_FREE(mode); Py_END_ALLOW_THREADS if (fp == NULL) return posix_error(); - f = PyFile_FromFile(fp, "", mode, fclose); + f = PyFile_FromFile(fp, "", orgmode, fclose); if (f != NULL) PyFile_SetBufSize(f, bufsize); return f; diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 869ded916cb..f954e36fa59 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -139,17 +139,16 @@ fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode, ignore stuff they don't understand... write or append mode with universal newline support is expressly forbidden by PEP 278. Additionally, remove the 'U' from the mode string as platforms - won't know what it is. */ -/* zero return is kewl - one is un-kewl */ -static int -sanitize_the_mode(char *mode) + won't know what it is. Non-zero return signals an exception */ +int +_PyFile_SanitizeMode(char *mode) { char *upos; size_t len = strlen(mode); if (!len) { PyErr_SetString(PyExc_ValueError, "empty mode string"); - return 1; + return -1; } upos = strchr(mode, 'U'); @@ -160,7 +159,7 @@ sanitize_the_mode(char *mode) PyErr_Format(PyExc_ValueError, "universal newline " "mode can only be used with modes " "starting with 'r'"); - return 1; + return -1; } if (mode[0] != 'r') { @@ -175,7 +174,7 @@ sanitize_the_mode(char *mode) } else if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') { PyErr_Format(PyExc_ValueError, "mode string must begin with " "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode); - return 1; + return -1; } return 0; @@ -204,7 +203,7 @@ open_the_file(PyFileObject *f, char *name, char *mode) } strcpy(newmode, mode); - if (sanitize_the_mode(newmode)) { + if (_PyFile_SanitizeMode(newmode)) { f = NULL; goto cleanup; }