Skip to content

Commit cd4b1fc

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

File tree

1 file changed

+54
-26
lines changed

1 file changed

+54
-26
lines changed

Modules/mmapmodule.c

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,44 @@ do { \
255255
} while (0)
256256
#endif /* UNIX */
257257

258+
#if defined(MS_WIN32) && !defined(DONT_USE_SEH)
259+
static DWORD
260+
HandlePageException(EXCEPTION_POINTERS *ptrs, EXCEPTION_RECORD *record)
261+
{
262+
*record = *ptrs->ExceptionRecord;
263+
if (ptrs->ExceptionRecord->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) {
264+
return EXCEPTION_EXECUTE_HANDLER;
265+
}
266+
return EXCEPTION_CONTINUE_SEARCH;
267+
}
268+
#endif
269+
270+
int
271+
safe_memcpy(void *restrict dest, const void *restrict src, size_t count) {
272+
#if defined(MS_WIN32) && !defined(DONT_USE_SEH)
273+
274+
// never fail for count 0
275+
if (count == 0) {
276+
return 0;
277+
}
278+
279+
EXCEPTION_RECORD record;
280+
__try {
281+
memcpy(dest, src, count);
282+
return 0;
283+
}
284+
__except (HandlePageException(GetExceptionInformation(), &record)) {
285+
NTSTATUS status = record.ExceptionInformation[2];
286+
ULONG code = LsaNtStatusToWinError(status);
287+
PyErr_SetFromWindowsErr(code);
288+
return -1;
289+
}
290+
#else
291+
memcpy(dest, src, count);
292+
return 0;
293+
#endif
294+
}
295+
258296
static PyObject *
259297
mmap_read_byte_method(mmap_object *self,
260298
PyObject *Py_UNUSED(ignored))
@@ -264,7 +302,14 @@ mmap_read_byte_method(mmap_object *self,
264302
PyErr_SetString(PyExc_ValueError, "read byte out of range");
265303
return NULL;
266304
}
267-
return PyLong_FromLong((unsigned char)self->data[self->pos++]);
305+
unsigned char dest;
306+
if (safe_memcpy(dest, self->data + self->pos, 1) < 0) {
307+
return NULL;
308+
}
309+
else {
310+
self->pos++;
311+
return PyLong_FromLong(dest);
312+
}
268313
}
269314

270315
static PyObject *
@@ -291,17 +336,6 @@ mmap_read_line_method(mmap_object *self,
291336
return result;
292337
}
293338

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-
305339
static PyObject *
306340
mmap_read_method(mmap_object *self,
307341
PyObject *args)
@@ -319,22 +353,16 @@ mmap_read_method(mmap_object *self,
319353
if (num_bytes < 0 || num_bytes > remaining)
320354
num_bytes = remaining;
321355

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);
326-
self->pos += num_bytes;
356+
result = PyBytes_FromStringAndSize(NULL, num_bytes);
357+
if (result == NULL) {
358+
return NULL;
327359
}
328-
__except (HandlePageException(GetExceptionInformation(), &record)) {
329-
NTSTATUS code = record.ExceptionInformation[2];
330-
PyErr_SetFromWindowsErr(code);
331-
result = NULL;
360+
if (safe_memcpy(((PyBytesObject *) result)->ob_sval, self->data + self->pos, num_bytes) < 0) {
361+
Py_CLEAR(result);
362+
}
363+
else {
364+
self->pos += num_bytes;
332365
}
333-
#else
334-
result = PyBytes_FromStringAndSize(&self->data[self->pos], num_bytes);
335-
self->pos += num_bytes;
336-
#endif
337-
338366
return result;
339367
}
340368

0 commit comments

Comments
 (0)