2727#include "pycore_bytesobject.h" // _PyBytes_Find()
2828#include "pycore_fileutils.h" // _Py_stat_struct
2929
30+ #include <stdbool.h>
3031#include <stddef.h> // offsetof()
3132#ifndef MS_WINDOWS
3233# include <unistd.h> // close()
@@ -255,6 +256,44 @@ do { \
255256} while (0)
256257#endif /* UNIX */
257258
259+ #if defined(MS_WIN32 ) && !defined(DONT_USE_SEH )
260+ static DWORD
261+ HandlePageException (EXCEPTION_POINTERS * ptrs , EXCEPTION_RECORD * record )
262+ {
263+ * record = * ptrs -> ExceptionRecord ;
264+ if (ptrs -> ExceptionRecord -> ExceptionCode == EXCEPTION_IN_PAGE_ERROR ) {
265+ return EXCEPTION_EXECUTE_HANDLER ;
266+ }
267+ return EXCEPTION_CONTINUE_SEARCH ;
268+ }
269+ #endif
270+
271+ bool
272+ safe_memcpy (void * restrict dest , const void * restrict src , size_t count ) {
273+ #if defined(MS_WIN32 ) && !defined(DONT_USE_SEH )
274+
275+ // never fail for count 0
276+ if (count == 0 ) {
277+ return true;
278+ }
279+
280+ EXCEPTION_RECORD record ;
281+ __try {
282+ memcpy (dest , src , count );
283+ return true;
284+ }
285+ __except (HandlePageException (GetExceptionInformation (), & record )) {
286+ NTSTATUS status = record .ExceptionInformation [2 ];
287+ ULONG code = LsaNtStatusToWinError (status );
288+ PyErr_SetFromWindowsErr (code );
289+ return false;
290+ }
291+ #else
292+ memcpy (dest , src , count );
293+ return true;
294+ #endif
295+ }
296+
258297static PyObject *
259298mmap_read_byte_method (mmap_object * self ,
260299 PyObject * Py_UNUSED (ignored ))
@@ -264,7 +303,14 @@ mmap_read_byte_method(mmap_object *self,
264303 PyErr_SetString (PyExc_ValueError , "read byte out of range" );
265304 return NULL ;
266305 }
267- return PyLong_FromLong ((unsigned char )self -> data [self -> pos ++ ]);
306+ unsigned char dest ;
307+ if (safe_memcpy (dest , self -> data + self -> pos , 1 )) {
308+ self -> pos ++ ;
309+ return PyLong_FromLong (dest );
310+ }
311+ else {
312+ return NULL ;
313+ }
268314}
269315
270316static PyObject *
@@ -291,17 +337,6 @@ mmap_read_line_method(mmap_object *self,
291337 return result ;
292338}
293339
294- #if defined(MS_WIN32 ) && !defined(DONT_USE_SEH )
295- static DWORD HandlePageException (EXCEPTION_POINTERS * ptrs , EXCEPTION_RECORD * record )
296- {
297- * record = * ptrs -> ExceptionRecord ;
298- if (ptrs -> ExceptionRecord -> ExceptionCode == EXCEPTION_IN_PAGE_ERROR ) {
299- return EXCEPTION_EXECUTE_HANDLER ;
300- }
301- return EXCEPTION_CONTINUE_SEARCH ;
302- }
303- #endif
304-
305340static PyObject *
306341mmap_read_method (mmap_object * self ,
307342 PyObject * args )
@@ -319,22 +354,16 @@ mmap_read_method(mmap_object *self,
319354 if (num_bytes < 0 || num_bytes > remaining )
320355 num_bytes = remaining ;
321356
322- #if defined(MS_WIN32 ) && !defined(DONT_USE_SEH )
323- EXCEPTION_RECORD record ;
324- __try {
325- result = PyBytes_FromStringAndSize (& self -> data [self -> pos ], num_bytes );
357+ result = PyBytes_FromStringAndSize (NULL , num_bytes );
358+ if (result == NULL ) {
359+ return NULL ;
360+ }
361+ if (safe_memcpy (((PyBytesObject * ) result )-> ob_sval , self -> data + self -> pos , num_bytes )) {
326362 self -> pos += num_bytes ;
327363 }
328- __except (HandlePageException (GetExceptionInformation (), & record )) {
329- NTSTATUS code = record .ExceptionInformation [2 ];
330- PyErr_SetFromWindowsErr (code );
331- result = NULL ;
364+ else {
365+ Py_CLEAR (result );
332366 }
333- #else
334- result = PyBytes_FromStringAndSize (& self -> data [self -> pos ], num_bytes );
335- self -> pos += num_bytes ;
336- #endif
337-
338367 return result ;
339368}
340369
0 commit comments