Skip to content

Commit 4bc706c

Browse files
committed
Fix PyUnicode_FromString memory leak in nif_event_loop_run_async
PyUnicode_FromString called inside PyTuple_Pack would leak if the tuple allocation failed. Create strings first, check for NULL, and properly decref on all failure paths.
1 parent 7d5432c commit 4bc706c

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

c_src/py_event_loop.c

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,18 +1775,48 @@ ERL_NIF_TERM nif_event_loop_run_async(ErlNifEnv *env, int argc,
17751775
}
17761776

17771777
/* Build result tuple: ('async_result', ref, ('ok', result)) */
1778-
PyObject *ok_tuple = PyTuple_Pack(2, PyUnicode_FromString("ok"), coro);
1779-
PyObject *msg = PyTuple_Pack(3,
1780-
PyUnicode_FromString("async_result"),
1781-
py_ref,
1782-
ok_tuple);
1778+
PyObject *ok_str = PyUnicode_FromString("ok");
1779+
PyObject *async_result_str = PyUnicode_FromString("async_result");
1780+
if (ok_str == NULL || async_result_str == NULL) {
1781+
Py_XDECREF(ok_str);
1782+
Py_XDECREF(async_result_str);
1783+
Py_DECREF(py_ref);
1784+
Py_DECREF((PyObject *)pid_obj);
1785+
Py_DECREF(erlang_mod);
1786+
Py_DECREF(coro);
1787+
result = make_error(env, "string_alloc_failed");
1788+
goto cleanup;
1789+
}
1790+
1791+
PyObject *ok_tuple = PyTuple_Pack(2, ok_str, coro);
1792+
Py_DECREF(ok_str); /* PyTuple_Pack increments refcount */
1793+
if (ok_tuple == NULL) {
1794+
Py_DECREF(async_result_str);
1795+
Py_DECREF(py_ref);
1796+
Py_DECREF((PyObject *)pid_obj);
1797+
Py_DECREF(erlang_mod);
1798+
Py_DECREF(coro);
1799+
result = make_error(env, "tuple_alloc_failed");
1800+
goto cleanup;
1801+
}
1802+
1803+
PyObject *msg = PyTuple_Pack(3, async_result_str, py_ref, ok_tuple);
1804+
Py_DECREF(async_result_str); /* PyTuple_Pack increments refcount */
1805+
Py_DECREF(ok_tuple); /* PyTuple_Pack increments refcount */
1806+
if (msg == NULL) {
1807+
Py_DECREF(py_ref);
1808+
Py_DECREF((PyObject *)pid_obj);
1809+
Py_DECREF(erlang_mod);
1810+
Py_DECREF(coro);
1811+
result = make_error(env, "tuple_alloc_failed");
1812+
goto cleanup;
1813+
}
17831814

17841815
/* Send via erlang.send() */
17851816
PyObject *send_result = PyObject_CallMethod(erlang_mod, "send", "OO",
17861817
(PyObject *)pid_obj, msg);
17871818
Py_XDECREF(send_result);
17881819
Py_DECREF(msg);
1789-
Py_DECREF(ok_tuple);
17901820
Py_DECREF(py_ref);
17911821
Py_DECREF((PyObject *)pid_obj);
17921822
Py_DECREF(erlang_mod);

0 commit comments

Comments
 (0)