Index: Include/pyerrors.h =================================================================== --- Include/pyerrors.h (revision 68570) +++ Include/pyerrors.h (working copy) @@ -326,4 +326,58 @@ #ifdef __cplusplus } #endif + +#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) +/* macros for temporarily disabling strict CRT error handling on windows. + * this is needed where we we have to accept a "raw" parameter from the + * user and have the CRT respond leniently, e.g. by issuing a EINVAL. + * Examples are functions that take integral file descriptors, + * strftime which takes an arbitrary format string, and the + * mode string for open() + */ +static void +InvalidParameterHandler( + const wchar_t * expression, + const wchar_t * function, + const wchar_t * file, + unsigned int line, + uintptr_t pReserved) +{ + /* Do nothing, allow execution to continue. Usually this + * means that the CRT will set errno to EINVAL + */ +} +#ifdef _DEBUG +#include +#define Py_BEGIN_CRT_ERROR_HANDLING \ +{\ + _invalid_parameter_handler prevCrtHandler = \ + _set_invalid_parameter_handler(InvalidParameterHandler); \ + /* in _DEBUG mode, an _ASSERT is done as well! */ \ + int prevReportMode = _CrtSetReportMode(_CRT_ASSERT, 0); + +#define Py_END_CRT_ERROR_HANDLING \ + _CrtSetReportMode(_CRT_ASSERT, prevReportMode); \ + _set_invalid_parameter_handler(prevCrtHandler); \ +} + +#else + +#define Py_BEGIN_CRT_ERROR_HANDLING \ +{\ + _invalid_parameter_handler prevCrtHandler = \ + _set_invalid_parameter_handler(InvalidParameterHandler); + +#define Py_END_CRT_ERROR_HANDLING \ + _set_invalid_parameter_handler(prevCrtHandler); \ +} + +#endif /* _DEBUG */ + +#else +/* no-ops */ +#define Py_BEGIN_CRT_ERROR_HANDLING +#define Py_END_CRT_ERROR_HANDLING +#endif + #endif /* !Py_ERRORS_H */ Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 68570) +++ Modules/posixmodule.c (working copy) @@ -582,7 +582,12 @@ if (fd < 0) return NULL; Py_BEGIN_ALLOW_THREADS + /* Wherever we accept integral file descriptors, we must use + * weaker error checking in the windows C runtime + */ + Py_BEGIN_CRT_ERROR_HANDLING res = (*func)(fd); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS if (res < 0) return posix_error(); @@ -6189,7 +6194,9 @@ if (!PyArg_ParseTuple(args, "i:close", &fd)) return NULL; Py_BEGIN_ALLOW_THREADS + Py_BEGIN_CRT_ERROR_HANDLING res = close(fd); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS if (res < 0) return posix_error(); @@ -6209,8 +6216,10 @@ if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to)) return NULL; Py_BEGIN_ALLOW_THREADS + Py_BEGIN_CRT_ERROR_HANDLING for (i = fd_from; i < fd_to; i++) close(i); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS Py_RETURN_NONE; } @@ -6227,7 +6236,9 @@ if (!PyArg_ParseTuple(args, "i:dup", &fd)) return NULL; Py_BEGIN_ALLOW_THREADS + Py_BEGIN_CRT_ERROR_HANDLING fd = dup(fd); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS if (fd < 0) return posix_error(); @@ -6246,7 +6257,9 @@ if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2)) return NULL; Py_BEGIN_ALLOW_THREADS + Py_BEGIN_CRT_ERROR_HANDLING res = dup2(fd, fd2); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS if (res < 0) return posix_error(); @@ -6291,8 +6304,10 @@ Py_BEGIN_ALLOW_THREADS #if defined(MS_WIN64) || defined(MS_WINDOWS) + Py_BEGIN_CRT_ERROR_HANDLING res = _lseeki64(fd, pos, how); -#else + Py_END_CRT_ERROR_HANDLING + #else res = lseek(fd, pos, how); #endif Py_END_ALLOW_THREADS @@ -6326,7 +6341,9 @@ if (buffer == NULL) return NULL; Py_BEGIN_ALLOW_THREADS + Py_BEGIN_CRT_ERROR_HANDLING n = read(fd, PyString_AsString(buffer), size); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS if (n < 0) { Py_DECREF(buffer); @@ -6352,7 +6369,10 @@ if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf)) return NULL; Py_BEGIN_ALLOW_THREADS + /* turn off crt asserts on windows since we have no control over fd */ + Py_BEGIN_CRT_ERROR_HANDLING size = write(fd, pbuf.buf, (size_t)pbuf.len); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS PyBuffer_Release(&pbuf); if (size < 0) @@ -6378,7 +6398,9 @@ fsync(fd); #endif Py_BEGIN_ALLOW_THREADS + Py_BEGIN_CRT_ERROR_HANDLING res = FSTAT(fd, &st); + Py_END_CRT_ERROR_HANDLING Py_END_ALLOW_THREADS if (res != 0) { #ifdef MS_WINDOWS @@ -6435,7 +6457,9 @@ fp = fdopen(fd, mode); } #else + Py_BEGIN_CRT_ERROR_HANDLING fp = fdopen(fd, mode); + Py_END_CRT_ERROR_HANDLING #endif Py_END_ALLOW_THREADS PyMem_FREE(mode); @@ -6455,10 +6479,13 @@ static PyObject * posix_isatty(PyObject *self, PyObject *args) { - int fd; + int fd, atty; if (!PyArg_ParseTuple(args, "i:isatty", &fd)) return NULL; - return PyBool_FromLong(isatty(fd)); + Py_BEGIN_CRT_ERROR_HANDLING + atty = isatty(fd); + Py_END_CRT_ERROR_HANDLING + return PyBool_FromLong(atty); } #ifdef HAVE_PIPE Index: Modules/timemodule.c =================================================================== --- Modules/timemodule.c (revision 68570) +++ Modules/timemodule.c (working copy) @@ -470,6 +470,23 @@ return NULL; } +#ifdef MS_WINDOWS + /* check that the format string contains only valid directives */ + for(outbuf = strchr(fmt, '%'); + outbuf != NULL; + outbuf = strchr(outbuf+2, '%')) + { + if (outbuf[1]=='#') + ++outbuf; /* not documented by python, */ + if (outbuf[1]=='\0' || + !strchr("aAbBcdfHIjmMpSUwWxXyYzZ%", outbuf[1])) + { + PyErr_SetString(PyExc_ValueError, "Invalid format string"); + return 0; + } + } +#endif + fmtlen = strlen(fmt); /* I hate these functions that presume you know how big the output Index: Objects/exceptions.c =================================================================== --- Objects/exceptions.c (revision 68570) +++ Objects/exceptions.c (working copy) @@ -1972,29 +1972,7 @@ if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \ Py_FatalError("Module dictionary insertion problem."); -#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) -/* crt variable checking in VisualStudio .NET 2005 */ -#include -static int prevCrtReportMode; -static _invalid_parameter_handler prevCrtHandler; - -/* Invalid parameter handler. Sets a ValueError exception */ -static void -InvalidParameterHandler( - const wchar_t * expression, - const wchar_t * function, - const wchar_t * file, - unsigned int line, - uintptr_t pReserved) -{ - /* Do nothing, allow execution to continue. Usually this - * means that the CRT will set errno to EINVAL - */ -} -#endif - - PyMODINIT_FUNC _PyExc_Init(void) { @@ -2153,13 +2131,6 @@ } Py_DECREF(bltinmod); - -#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) - /* Set CRT argument error handler */ - prevCrtHandler = _set_invalid_parameter_handler(InvalidParameterHandler); - /* turn off assertions in debug mode */ - prevCrtReportMode = _CrtSetReportMode(_CRT_ASSERT, 0); -#endif } void @@ -2167,9 +2138,4 @@ { Py_XDECREF(PyExc_MemoryErrorInst); PyExc_MemoryErrorInst = NULL; -#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) - /* reset CRT error handling */ - _set_invalid_parameter_handler(prevCrtHandler); - _CrtSetReportMode(_CRT_ASSERT, prevCrtReportMode); -#endif } Index: Objects/fileobject.c =================================================================== --- Objects/fileobject.c (revision 68570) +++ Objects/fileobject.c (working copy) @@ -274,8 +274,13 @@ FILE_BEGIN_ALLOW_THREADS(f) /* PyUnicode_AS_UNICODE OK without thread lock as it is a simple dereference. */ + Py_BEGIN_CRT_ERROR_HANDLING + /* turn off error handling on windows since we have + * no control over the mode string + */ f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name), PyUnicode_AS_UNICODE(wmode)); + Py_END_CRT_ERROR_HANDLING FILE_END_ALLOW_THREADS(f) } Py_XDECREF(wmode); @@ -283,7 +288,9 @@ #endif if (NULL == f->f_fp && NULL != name) { FILE_BEGIN_ALLOW_THREADS(f) + Py_BEGIN_CRT_ERROR_HANDLING f->f_fp = fopen(name, newmode); + Py_END_CRT_ERROR_HANDLING FILE_END_ALLOW_THREADS(f) }