Skip to content

Commit a024c79

Browse files
committed
VS2015 Support: Backport of "Issue python#23524: Replace _PyVerify_fd function with calling _set_thread_local_invalid_parameter_handler on every thread."
This commit is a partial backport of python/cpython@d81431f. It was originally designed to work with python-cmake-buildsystem. Implementation of "_PyVerify_fd" in "Python/fileutils.c" found only in Python 3.x has been copied into "Modules/posixmodule.c" The following modules have NOT been backported: * PCbuild
1 parent 713c06e commit a024c79

File tree

3 files changed

+63
-25
lines changed

3 files changed

+63
-25
lines changed

Modules/posixmodule.c

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ extern int lstat(const char *, struct stat *);
277277
#include "osdefs.h"
278278
#include <malloc.h>
279279
#include <windows.h>
280+
#include <malloc.h>
280281
#include <shellapi.h> /* for ShellExecute() */
281282
#define popen _popen
282283
#define pclose _pclose
@@ -533,8 +534,28 @@ _PyInt_FromDev(PY_LONG_LONG v)
533534
# define _PyInt_FromDev PyInt_FromLong
534535
#endif
535536

537+
#ifdef _MSC_VER
538+
#if _MSC_VER >= 1900
539+
540+
/* This function lets the Windows CRT validate the file handle without
541+
terminating the process if it's invalid. */
542+
int
543+
_PyVerify_fd(int fd)
544+
{
545+
intptr_t osh;
546+
/* Fast check for the only condition we know */
547+
if (fd < 0) {
548+
_set_errno(EBADF);
549+
return 0;
550+
}
551+
osh = _get_osfhandle(fd);
552+
return osh != (intptr_t)-1;
553+
}
554+
555+
#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0)
556+
557+
#elif _MSC_VER >= 1400
536558

537-
#if defined _MSC_VER && _MSC_VER >= 1400
538559
/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
539560
* valid and raise an assertion if it isn't.
540561
* Normally, an invalid fd is likely to be a C program error and therefore
@@ -559,35 +580,18 @@ _PyInt_FromDev(PY_LONG_LONG v)
559580
* Only the first items must be present.
560581
*/
561582

562-
#if _MSC_VER >= 1900
563-
564-
typedef struct {
565-
CRITICAL_SECTION lock;
566-
intptr_t osfhnd;
567-
__int64 startpos;
568-
char osfile;
569-
} my_ioinfo;
570-
571-
#define IOINFO_L2E 6
572-
#define IOINFO_ARRAYS 128
573-
574-
#else
575-
576583
typedef struct {
577584
intptr_t osfhnd;
578585
char osfile;
579586
} my_ioinfo;
580587

581-
#define IOINFO_L2E 5
582-
#define IOINFO_ARRAYS 64
583-
584-
#endif
585-
586588
extern __declspec(dllimport) char * __pioinfo[];
587589
#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
588590
#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
589591
#define FOPEN 0x01
590592
#define _NO_CONSOLE_FILENO (intptr_t)-2
593+
#define IOINFO_L2E 5
594+
#define IOINFO_ARRAYS 64
591595

592596
/* This function emulates what the windows CRT does to validate file handles */
593597
int
@@ -645,6 +649,8 @@ _PyVerify_fd_dup2(int fd1, int fd2)
645649
#define _PyVerify_fd_dup2(A, B) (1)
646650
#endif
647651

652+
#endif /* defined _MSC_VER */
653+
648654
/* Return a dictionary corresponding to the POSIX environment table */
649655
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
650656
/* On Darwin/MacOSX a shared library or framework has no access to
@@ -1248,14 +1254,10 @@ win32_fstat(int file_number, struct win32_stat *result)
12481254

12491255
h = (HANDLE)_get_osfhandle(file_number);
12501256

1251-
/* Protocol violation: we explicitly clear errno, instead of
1252-
setting it to a POSIX error. Callers should use GetLastError. */
12531257
errno = 0;
12541258

12551259
if (h == INVALID_HANDLE_VALUE) {
1256-
/* This is really a C library error (invalid file handle).
1257-
We set the Win32 error to the closes one matching. */
1258-
SetLastError(ERROR_INVALID_HANDLE);
1260+
errno = EBADF;
12591261
return -1;
12601262
}
12611263
memset(result, 0, sizeof(*result));
@@ -1264,6 +1266,7 @@ win32_fstat(int file_number, struct win32_stat *result)
12641266
if (type == FILE_TYPE_UNKNOWN) {
12651267
DWORD error = GetLastError();
12661268
if (error != 0) {
1269+
errno = EINVAL;
12671270
return -1;
12681271
}
12691272
/* else: valid but unknown file */
@@ -1278,6 +1281,7 @@ win32_fstat(int file_number, struct win32_stat *result)
12781281
}
12791282

12801283
if (!GetFileInformationByHandle(h, &info)) {
1284+
errno = EINVAL;
12811285
return -1;
12821286
}
12831287

PC/invalid_parameter_handler.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifdef _MSC_VER
2+
3+
#include <stdlib.h>
4+
5+
#if _MSC_VER >= 1900
6+
/* pyconfig.h uses this function in the _Py_BEGIN/END_SUPPRESS_IPH
7+
* macros. It does not need to be defined when building using MSVC
8+
* earlier than 14.0 (_MSC_VER == 1900).
9+
*/
10+
11+
static void __cdecl _silent_invalid_parameter_handler(
12+
wchar_t const* expression,
13+
wchar_t const* function,
14+
wchar_t const* file,
15+
unsigned int line,
16+
uintptr_t pReserved) { }
17+
18+
void *_Py_silent_invalid_parameter_handler =
19+
(void*)_silent_invalid_parameter_handler;
20+
#endif
21+
22+
#endif

Python/pystate.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ the expense of doing their own locking).
2222
#endif
2323
#endif
2424

25+
#if defined _MSC_VER && _MSC_VER >= 1900
26+
/* Issue #23524: Temporary fix to disable termination due to invalid parameters */
27+
PyAPI_DATA(void*) _Py_silent_invalid_parameter_handler;
28+
#include <stdlib.h>
29+
#endif
30+
2531
#ifdef __cplusplus
2632
extern "C" {
2733
#endif
@@ -202,6 +208,12 @@ new_threadstate(PyInterpreterState *interp, int init)
202208
tstate->next = interp->tstate_head;
203209
interp->tstate_head = tstate;
204210
HEAD_UNLOCK();
211+
212+
#if defined _MSC_VER && _MSC_VER >= 1900
213+
/* Issue #23524: Temporary fix to disable termination due to invalid parameters */
214+
_set_thread_local_invalid_parameter_handler((_invalid_parameter_handler)_Py_silent_invalid_parameter_handler);
215+
#endif
216+
205217
}
206218

207219
return tstate;

0 commit comments

Comments
 (0)