Commit 08df9827 authored by Georges Racinet's avatar Georges Racinet
Browse files

Demonstrate how naive lifetime extension leads to segfaults

In order to restore safety, we'll have to add safeguards forbidding
mutation of `RustSet` from Python if an iterator still references it.
It's easy to trigger the segfault by freeing the underlying buffers, but
in principle, even adding more data to the set could end up the same, by
reallocating elsewhere and freeing the original buffer.

At this point, this is also first evidence that we met the goal of
avoiding the copy of the data.
parent 3160d97c8d3f
......@@ -50,6 +50,15 @@ py_class!(class RustSet |py| {
RefCell::new(as_static.iter()))
}
def clear(&self) -> PyResult<PyObject> {
let mut hs = self.hs(py).borrow_mut();
hs.clear();
// Force freeing of underlying memory to underline the risk of
// segfault
hs.shrink_to_fit();
Ok(py.None())
}
});
......
......@@ -38,6 +38,18 @@ def test_iter():
del it2
def test_race_safety():
rs = RustSet()
# have Rust allocate some real amount of memory
rs.extend(range(10000))
it = iter(rs)
# Trigger freeing the underlying memory
rs.clear()
next(it) # segfault
def run():
test_basic()
test_iter()
test_race_safety()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment