Blob Blame History Raw
From e84c63a2ca4bf2366af96eb1a1222cf494e228c9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 27 Jul 2021 08:55:27 +0100
Subject: [PATCH] python: Don't leak fields when creating Python structs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When creating and returning a Python struct we were adding fields from
the C struct, but did not reduce the ref count on the temporary value
after it had been moved to the struct, resulting in a memory leak.

Reported-by: 朱丹 <zhudan24@huawei.com>
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1985912
---
 generator/python.ml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/generator/python.ml b/generator/python.ml
index b3d3a5579..1afd05dd6 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -173,44 +173,52 @@ and generate_python_structs () =
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, FBuffer ->
             pr "  value = PyBytes_FromStringAndSize (%s->%s, %s->%s_len);\n"
               typ name typ name;
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, FUUID ->
             pr "  value = guestfs_int_py_fromstringsize (%s->%s, 32);\n"
               typ name;
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, (FBytes|FUInt64) ->
             pr "  value = PyLong_FromUnsignedLongLong (%s->%s);\n" typ name;
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, FInt64 ->
             pr "  value = PyLong_FromLongLong (%s->%s);\n" typ name;
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, FUInt32 ->
             pr "  value = PyLong_FromUnsignedLong (%s->%s);\n" typ name;
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, FInt32 ->
             pr "  value = PyLong_FromLong (%s->%s);\n" typ name;
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
         | name, FOptPercent ->
             pr "  if (%s->%s >= 0) {\n" typ name;
             pr "    value = PyFloat_FromDouble ((double) %s->%s);\n" typ name;
             pr "    if (value == NULL)\n";
             pr "      goto err;\n";
             pr "    PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "    Py_DECREF (value);\n";
             pr "  }\n";
             pr "  else {\n";
             pr "    Py_INCREF (Py_None);\n";
@@ -222,6 +230,7 @@ and generate_python_structs () =
             pr "  if (value == NULL)\n";
             pr "    goto err;\n";
             pr "  PyDict_SetItemString (dict, \"%s\", value);\n" name;
+            pr "  Py_DECREF (value);\n"
       ) cols;
       pr "  return dict;\n";
       pr " err:\n";
-- 
2.31.1