mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-29 16:37:13 +00:00
Bug fix for virtual_overrider_self_life_support ASAN heap-use-after-free failure. (#2942)
* Porting subset of absltest code from reproducer provided by @elkhrt. Baseline for debugging ASAN heap-use-after-free. * Moving Py_DECREF to resolve ASAN heap-use-after-free failure. * Fixing trivial formatting issue. * Workaround for clang 3.6 and 3.7.
This commit is contained in:
parent
7eb6d6f695
commit
2b4fbbd521
@ -26,10 +26,10 @@ struct virtual_overrider_self_life_support {
|
|||||||
void *value_void_ptr = loaded_v_h.value_ptr();
|
void *value_void_ptr = loaded_v_h.value_ptr();
|
||||||
if (value_void_ptr != nullptr) {
|
if (value_void_ptr != nullptr) {
|
||||||
PyGILState_STATE threadstate = PyGILState_Ensure();
|
PyGILState_STATE threadstate = PyGILState_Ensure();
|
||||||
Py_DECREF((PyObject *) loaded_v_h.inst);
|
|
||||||
loaded_v_h.value_ptr() = nullptr;
|
loaded_v_h.value_ptr() = nullptr;
|
||||||
loaded_v_h.holder<pybindit::memory::smart_holder>().release_disowned();
|
loaded_v_h.holder<pybindit::memory::smart_holder>().release_disowned();
|
||||||
detail::deregister_instance(loaded_v_h.inst, value_void_ptr, loaded_v_h.type);
|
detail::deregister_instance(loaded_v_h.inst, value_void_ptr, loaded_v_h.type);
|
||||||
|
Py_DECREF((PyObject *) loaded_v_h.inst); // Must be after deregister.
|
||||||
PyGILState_Release(threadstate);
|
PyGILState_Release(threadstate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ set(PYBIND11_TEST_FILES
|
|||||||
test_class_sh_factory_constructors.cpp
|
test_class_sh_factory_constructors.cpp
|
||||||
test_class_sh_inheritance.cpp
|
test_class_sh_inheritance.cpp
|
||||||
test_class_sh_trampoline_shared_ptr_cpp_arg.cpp
|
test_class_sh_trampoline_shared_ptr_cpp_arg.cpp
|
||||||
|
test_class_sh_trampoline_unique_ptr.cpp
|
||||||
test_class_sh_unique_ptr_member.cpp
|
test_class_sh_unique_ptr_member.cpp
|
||||||
test_class_sh_virtual_py_cpp_mix.cpp
|
test_class_sh_virtual_py_cpp_mix.cpp
|
||||||
test_class_sh_with_alias.cpp
|
test_class_sh_with_alias.cpp
|
||||||
|
48
tests/test_class_sh_trampoline_unique_ptr.cpp
Normal file
48
tests/test_class_sh_trampoline_unique_ptr.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright (c) 2021 The Pybind Development Team.
|
||||||
|
// All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "pybind11/smart_holder.h"
|
||||||
|
#include "pybind11/virtual_overrider_self_life_support.h"
|
||||||
|
#include "pybind11_tests.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class Class {
|
||||||
|
public:
|
||||||
|
virtual ~Class() = default;
|
||||||
|
virtual std::unique_ptr<Class> clone() const = 0;
|
||||||
|
virtual int foo() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Class() = default;
|
||||||
|
|
||||||
|
// Some compilers complain about implicitly defined versions of some of the following:
|
||||||
|
Class(const Class &) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Class)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class PyClass : public Class, public py::virtual_overrider_self_life_support {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<Class> clone() const override {
|
||||||
|
PYBIND11_OVERRIDE_PURE(std::unique_ptr<Class>, Class, clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
int foo() const override { PYBIND11_OVERRIDE_PURE(int, Class, foo); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_SUBMODULE(class_sh_trampoline_unique_ptr, m) {
|
||||||
|
py::classh<Class, PyClass>(m, "Class")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("clone", &Class::clone)
|
||||||
|
.def("foo", &Class::foo);
|
||||||
|
|
||||||
|
m.def("clone_and_foo", [](const Class &obj) { return obj.clone()->foo(); });
|
||||||
|
}
|
17
tests/test_class_sh_trampoline_unique_ptr.py
Normal file
17
tests/test_class_sh_trampoline_unique_ptr.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import pybind11_tests.class_sh_trampoline_unique_ptr as m
|
||||||
|
|
||||||
|
|
||||||
|
class MyClass(m.Class):
|
||||||
|
def foo(self):
|
||||||
|
return 10
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
return MyClass()
|
||||||
|
|
||||||
|
|
||||||
|
def test_py_clone_and_foo():
|
||||||
|
obj = MyClass()
|
||||||
|
assert obj.foo() == 10
|
||||||
|
assert m.clone_and_foo(obj) == 10
|
Loading…
Reference in New Issue
Block a user