Closed oremanj closed 4 months ago
I see how this could be dangerous. I would be open to a fix by expanding the instance state to a two-bit value. But in that case, it should probably be named state
as opposed to ready
.
@oremanj do you plan to make further changes here or shall I close the issue?
Whoops, I missed your reply a few weeks ago. I will try and get a PR up for this this week.
Problem description
The
nb_inst::ready
flag being false is used both to mark an instance that hasn't been constructed yet, and to mark an instance that has had its innards handed over to a C++ unique_ptr. This double use means that a hollowed-out instance (where a C++ unique_ptr assumes ownership of the innards) can be reinitialized by calling__init__
on it from Python. This will call the C++ constructor on an already-constructed object, potentially causing resource leaks or other confusion for the C++ code that thought it had exclusive access. It can also produce an assertion failure when trying to pass the C++ unique_ptr back to Python, as shown below.Potential solution: expand
nb_inst::ready
to a 2-bit field (and maybe rename it). 0 = not constructed, 1 = relinquished, 2 = normal. Change the test innb_type_get
from the currentto
relying on the fact that
cast_flags::construct
has numeric value 2.Of course it is also possible to do this less cryptically by adding another flag
relinquished
, but I couldn't figure out how to make that equivalent-cost to the current test.Reproducible example code