]> granicus.if.org Git - python/commitdiff
Fix memleak in os.getrandom()
authorVictor Stinner <victor.stinner@gmail.com>
Tue, 20 Sep 2016 21:00:59 +0000 (23:00 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 20 Sep 2016 21:00:59 +0000 (23:00 +0200)
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
Modules/posixmodule.c

index 97f669d66522520ab48758bb4c9df5e86090f2b9..bda0576fe1aa4aa2fbf0d9e43865eb254d5a7fc9 100644 (file)
--- 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).
 
index 470ee92fa194b0247102aec3bf9913ee0678d912..28d30b0f9ab6967a6ce5dbb4caf51ac55f8a0a26 100644 (file)
@@ -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 */