From 90db664635013f6e857ec696403f2164032410a8 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 12 Apr 2022 12:49:19 +1000 Subject: [PATCH] Fix crash when deleting a buffer from a user mapping Deleting a buffer resets normal mode on all clients that were displaing that buffer, but ScopedForceNormalMode that are used from user mode do not take this possiblity into account on destruction, which leads to deleting the last normal mode from the context, ending up with an empty mode stack. Fixes #3909 --- src/input_handler.cc | 9 ++------- src/ref_ptr.hh | 4 ++-- .../3909-crash-on-closing-buffer-with-user-mapping/cmd | 1 + .../3909-crash-on-closing-buffer-with-user-mapping/in | 1 + .../3909-crash-on-closing-buffer-with-user-mapping/out | 1 + .../3909-crash-on-closing-buffer-with-user-mapping/rc | 2 ++ 6 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 test/regression/3909-crash-on-closing-buffer-with-user-mapping/cmd create mode 100644 test/regression/3909-crash-on-closing-buffer-with-user-mapping/in create mode 100644 test/regression/3909-crash-on-closing-buffer-with-user-mapping/out create mode 100644 test/regression/3909-crash-on-closing-buffer-with-user-mapping/rc diff --git a/src/input_handler.cc b/src/input_handler.cc index 8adbbcee..26d255c0 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -1698,14 +1698,9 @@ InputHandler::ScopedForceNormal::~ScopedForceNormal() if (m_mode == m_handler.m_mode_stack.back().get()) m_handler.pop_mode(m_mode); - else - { - auto it = find_if(m_handler.m_mode_stack, - [this](const RefPtr& m) - { return m.get() == m_mode; }); - kak_assert(it != m_handler.m_mode_stack.end()); + else if (auto it = find(m_handler.m_mode_stack, m_mode); + it != m_handler.m_mode_stack.end()) m_handler.m_mode_stack.erase(it); - } } static bool is_valid(Key key) diff --git a/src/ref_ptr.hh b/src/ref_ptr.hh index 235ee2a3..4b576039 100644 --- a/src/ref_ptr.hh +++ b/src/ref_ptr.hh @@ -88,8 +88,8 @@ struct RefPtr acquire(); } - friend bool operator==(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr == rhs.m_ptr; } - friend bool operator!=(const RefPtr& lhs, const RefPtr& rhs) { return lhs.m_ptr != rhs.m_ptr; } + friend bool operator==(const RefPtr& lhs, const RefPtr& rhs) = default; + friend bool operator==(const RefPtr& lhs, const T* rhs) { return lhs.m_ptr == rhs; } private: T* m_ptr = nullptr; diff --git a/test/regression/3909-crash-on-closing-buffer-with-user-mapping/cmd b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/cmd new file mode 100644 index 00000000..b870f425 --- /dev/null +++ b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/cmd @@ -0,0 +1 @@ +i,d diff --git a/test/regression/3909-crash-on-closing-buffer-with-user-mapping/in b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/in new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/in @@ -0,0 +1 @@ + diff --git a/test/regression/3909-crash-on-closing-buffer-with-user-mapping/out b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/out new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/out @@ -0,0 +1 @@ + diff --git a/test/regression/3909-crash-on-closing-buffer-with-user-mapping/rc b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/rc new file mode 100644 index 00000000..13e1f91e --- /dev/null +++ b/test/regression/3909-crash-on-closing-buffer-with-user-mapping/rc @@ -0,0 +1,2 @@ +edit -scratch +map global user d :delete-buffer