changeset: 103975:d31b4de433b7 branch: 3.6 parent: 103973:27d05bb6f832 user: Victor Stinner date: Tue Sep 20 23:00:59 2016 +0200 files: Misc/NEWS Modules/posixmodule.c description: 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. diff -r 27d05bb6f832 -r d31b4de433b7 Misc/NEWS --- a/Misc/NEWS Tue Sep 20 22:49:52 2016 +0200 +++ b/Misc/NEWS Tue Sep 20 23:00:59 2016 +0200 @@ -32,6 +32,9 @@ 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 -r 27d05bb6f832 -r d31b4de433b7 Modules/posixmodule.c --- a/Modules/posixmodule.c Tue Sep 20 22:49:52 2016 +0200 +++ b/Modules/posixmodule.c Tue Sep 20 23:00:59 2016 +0200 @@ -12047,42 +12047,50 @@ os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ { - char *buffer; + PyObject *bytes; Py_ssize_t n; - PyObject *bytes; 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; - } - - bytes = PyBytes_FromStringAndSize(buffer, n); - PyMem_Free(buffer); + goto error; + } + + if (n != size) { + _PyBytes_Resize(&bytes, n); + } return bytes; + +error: + Py_DECREF(bytes); + return NULL; } #endif /* HAVE_GETRANDOM_SYSCALL */