Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6c03245

Browse files
authored
fixed reference counting for exception objects in Py.With (#1062)
PyObject(s) constructed for __exit__ method referenced existing Python objects without increasing refcount appropriately, which could lead to double-free.
1 parent 22735f8 commit 6c03245

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

src/runtime/Util.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Python.Runtime
55
{
6-
internal class Util
6+
internal static class Util
77
{
88
internal static Int64 ReadCLong(IntPtr tp, int offset)
99
{
@@ -29,5 +29,12 @@ internal static void WriteCLong(IntPtr type, int offset, Int64 flags)
2929
Marshal.WriteInt64(type, offset, flags);
3030
}
3131
}
32+
33+
/// <summary>
34+
/// Null-coalesce: if <paramref name="primary"/> parameter is not
35+
/// <see cref="IntPtr.Zero"/>, return it. Otherwise return <paramref name="fallback"/>.
36+
/// </summary>
37+
internal static IntPtr Coalesce(this IntPtr primary, IntPtr fallback)
38+
=> primary == IntPtr.Zero ? fallback : primary;
3239
}
33-
}
40+
}

src/runtime/pythonengine.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -758,11 +758,14 @@ public static void With(PyObject obj, Action<dynamic> Body)
758758
catch (PythonException e)
759759
{
760760
ex = e;
761-
type = ex.PyType;
762-
val = ex.PyValue;
763-
traceBack = ex.PyTB;
761+
type = ex.PyType.Coalesce(type);
762+
val = ex.PyValue.Coalesce(val);
763+
traceBack = ex.PyTB.Coalesce(traceBack);
764764
}
765765

766+
Runtime.XIncref(type);
767+
Runtime.XIncref(val);
768+
Runtime.XIncref(traceBack);
766769
var exitResult = obj.InvokeMethod("__exit__", new PyObject(type), new PyObject(val), new PyObject(traceBack));
767770

768771
if (ex != null && !exitResult.IsTrue()) throw ex;

0 commit comments

Comments
 (0)