Skip to content

Commit 8a3c0d4

Browse files
committed
restructure to use safe_memcpy to avoid memory leak
1 parent 71218d2 commit 8a3c0d4

File tree

1 file changed

+54
-25
lines changed

1 file changed

+54
-25
lines changed

Modules/mmapmodule.c

+54-25
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
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+
258297
static PyObject *
259298
mmap_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

270316
static 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-
305340
static PyObject *
306341
mmap_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

Comments
 (0)