[Libguestfs] [PATCH v2 2/4] python: do not try to malloc 0 elements in get_all_event_callbacks

Pino Toscano ptoscano at redhat.com
Fri Mar 3 17:13:17 UTC 2017


In case there are no event handlers registered with the handle,
get_all_event_callbacks will count 0 elements, trying to malloc a buffer
of that size.  POSIX says that this can result in either a null pointer,
or an unusable pointer.

Short-circuit get_all_event_callbacks to allocate nothing when there are
no events, making sure to use its results only when there were events.
---
 python/handle.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/python/handle.c b/python/handle.c
index f4cc8ca..806408f 100644
--- a/python/handle.c
+++ b/python/handle.c
@@ -71,7 +71,7 @@ guestfs_int_py_close (PyObject *self, PyObject *args)
   PyThreadState *py_save = NULL;
   PyObject *py_g;
   guestfs_h *g;
-  size_t i, len;
+  size_t len;
   PyObject **callbacks;
 
   if (!PyArg_ParseTuple (args, (char *) "O:guestfs_close", &py_g))
@@ -81,9 +81,14 @@ guestfs_int_py_close (PyObject *self, PyObject *args)
   /* As in the OCaml bindings, there is a hard to solve case where the
    * caller can delete a callback from within the callback, resulting
    * in a double-free here.  XXX
+   *
+   * Take care of the result of get_all_event_callbacks: NULL can be
+   * both an error (and some PyErr_* was called), and no events.
+   * 'len' is specifically 0 only in the latter case, so filter that
+   * out.
    */
   callbacks = get_all_event_callbacks (g, &len);
-  if (callbacks == NULL)
+  if (len != 0 && callbacks == NULL)
     return NULL;
 
   if (PyEval_ThreadsInitialized ())
@@ -92,9 +97,12 @@ guestfs_int_py_close (PyObject *self, PyObject *args)
   if (PyEval_ThreadsInitialized ())
     PyEval_RestoreThread (py_save);
 
-  for (i = 0; i < len; ++i)
-    Py_XDECREF (callbacks[i]);
-  free (callbacks);
+  if (len > 0) {
+    size_t i;
+    for (i = 0; i < len; ++i)
+      Py_XDECREF (callbacks[i]);
+    free (callbacks);
+  }
 
   Py_INCREF (Py_None);
   return Py_None;
@@ -260,6 +268,10 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn)
     cb = guestfs_next_private (g, &key);
   }
 
+  /* No events, so no need to allocate anything. */
+  if (*len_rtn == 0)
+    return NULL;
+
   /* Copy them into the return array. */
   r = malloc (sizeof (PyObject *) * (*len_rtn));
   if (r == NULL) {
-- 
2.9.3




More information about the Libguestfs mailing list