From ec2319c46d11e8f486e7def785339af5415a3559 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 20 Sep 2016 23:00:59 +0200 Subject: [PATCH] Fix memleak in os.getrandom() Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is interrupted by a signal and a signal handler raises a Python exception. Modify also os_getrandom_impl() to avoid the temporary buffer, use directly a Python bytes object. --- Misc/NEWS | 3 +++ Modules/posixmodule.c | 28 ++++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 97f669d6652..bda0576fe1a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Core and Builtins Library ------- +- Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is + interrupted by a signal and a signal handler raises a Python exception. + - Issue #28200: Fix memory leak on Windows in the os module (fix path_converter() function). diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 470ee92fa19..28d30b0f9ab 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12047,42 +12047,50 @@ static PyObject * os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ { - char *buffer; - Py_ssize_t n; PyObject *bytes; + Py_ssize_t n; if (size < 0) { errno = EINVAL; return posix_error(); } - buffer = PyMem_Malloc(size); - if (buffer == NULL) { + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) { PyErr_NoMemory(); return NULL; } while (1) { - n = syscall(SYS_getrandom, buffer, size, flags); + n = syscall(SYS_getrandom, + PyBytes_AS_STRING(bytes), + PyBytes_GET_SIZE(bytes), + flags); if (n < 0 && errno == EINTR) { if (PyErr_CheckSignals() < 0) { - return NULL; + goto error; } + + /* getrandom() was interrupted by a signal: retry */ continue; } break; } if (n < 0) { - PyMem_Free(buffer); PyErr_SetFromErrno(PyExc_OSError); - return NULL; + goto error; } - bytes = PyBytes_FromStringAndSize(buffer, n); - PyMem_Free(buffer); + if (n != size) { + _PyBytes_Resize(&bytes, n); + } return bytes; + +error: + Py_DECREF(bytes); + return NULL; } #endif /* HAVE_GETRANDOM_SYSCALL */