Project

General

Profile

Bug #8610

Wt 4.5.0: segfault in WebController::generateNewSessionId

Added by Chris Sykes 18 days ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
06/01/2021
Due date:
% Done:

0%

Estimated time:

Description

Summary

We recently hit a segfault in WebController::generateNewSessionId().

The crash appears to have occured while a user was logging in.

  • GCC 9.3.0 armv7l from Yocto Dunfell
  • Wt 4.5.0 (Release build)

So far it's a one-off for us, we do not have a way to reproduce the crash.

Here's a partial stack trace of the crashing thread taken from the core dump:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  __GI___libc_free (mem=0x1) at malloc.c:3102
3102    malloc.c: No such file or directory.
[Current thread is 1 (LWP 691)]


(gdb) bt
#0  __GI___libc_free (mem=0x1) at malloc.c:3102
#1  0x76009004 in operator delete (ptr=<optimized out>)
    at ../../../../../../../../../work-shared/gcc-9.3.0-r0/gcc-9.3.0/libstdc++-v3/libsupc++/del_op.cc:49
#2  0x76dee10e in __gnu_cxx::new_allocator<char>::deallocate (this=0x1795344, __p=<optimized out>)
    at /usr/include/c++/9.3.0/ext/new_allocator.h:119
#3  std::allocator_traits<std::allocator<char> >::deallocate (__a=..., __n=<optimized out>, __p=<optimized out>)
    at /usr/include/c++/9.3.0/bits/alloc_traits.h:470
#4  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_destroy (__size=<optimized out>, 
#5  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose (this=0x1795344)
    at /usr/include/c++/9.3.0/bits/basic_string.h:232
#6  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string (this=0x1795344, 
    __in_chrg=<optimized out>) at /usr/include/c++/9.3.0/bits/basic_string.h:658
#7  std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >::~pair (this=0x1795344, __in_chrg=<optimized out>) at /usr/include/c++/9.3.0/bits/stl_pair.h:208
#8  __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > >::destroy<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > (this=0x1795330, __p=0x1795344)
    at /usr/include/c++/9.3.0/ext/new_allocator.h:153
#9  std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > > >::destroy<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > (__a=..., __p=0x1795344)
    at /usr/include/c++/9.3.0/bits/alloc_traits.h:497
#10 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > >::_M_destroy_node (this=0x1795330, __p=0x1795334) at /usr/include/c++/9.3.0/bits/stl_tree.h:642
#11 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > >::_M_drop_node (this=0x1795330, __p=0x1795334) at /usr/include/c++/9.3.0/bits/stl_tree.h:650
#12 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > >::_M_erase_aux (this=this@entry=0x1795330, __position=..., Python Exception <class 'gdb.error'> No type named std::_Rb_tree_node<struct std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >>.: 
__position@entry=...) at /usr/include/c++/9.3.0/bits/stl_tree.h:2511
#13 0x76ded996 in std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > >::erase[abi:cxx11](std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > >) (Python Exception <class 'gdb.error'> No type named std::_Rb_tree_node<struct std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >>.: 
__position=..., this=0x1795330)
    at /usr/include/c++/9.3.0/bits/stl_tree.h:1215
#14 std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<Wt::WebSession>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > > >::erase[abi:cxx11](std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> > >) (Python Exception <class 'gdb.error'> No type named std::_Rb_tree_node<struct std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::shared_ptr<Wt::WebSession> >>.: 
__position=..., this=0x1795330) at /usr/include/c++/9.3.0/bits/stl_map.h:1037
#15 Wt::WebController::generateNewSessionId[abi:cxx11](std::shared_ptr<Wt::WebSession> const&) (this=0x17952b8, 
    session=std::shared_ptr<class Wt::WebSession> (use count 7, weak count 4) = {...})
    at /usr/src/debug/wt/4.5.0-r1/git/src/web/WebController.C:833
#16 0x76df588e in Wt::WebSession::generateNewSessionId (this=0x724ebf88) at /usr/include/c++/9.3.0/bits/shared_ptr_base.h:251
#17 0x76b7d892 in Wt::WApplication::changeSessionId (this=<optimized out>)
    at /usr/src/debug/wt/4.5.0-r1/git/src/Wt/WApplication.C:596
#18 0x76cede3e in Wt::Auth::AuthWidget::onLoginChange (this=0x18bbd68)
    at /usr/src/debug/wt/4.5.0-r1/git/src/Wt/Auth/AuthWidget.C:291
#19 0x76b64548 in std::function<void ()>::operator()() const (this=0x18a6864)
    at /usr/include/c++/9.3.0/bits/std_function.h:683

Frame 15 is the interesting part WebController.C:833:

  816 std::string
  817 WebController::generateNewSessionId(const std::shared_ptr<WebSession>& session)
  818 {
  819 #ifdef WT_THREADED
  820   std::unique_lock<std::recursive_mutex> lock(mutex_);
  821 #endif // WT_THREADEDâ‹„â‹„
  822 
  823   std::string newSessionId;
  824   do {
  825     newSessionId = conf_.generateSessionId();
  826     if (!conf_.registerSessionId(session->sessionId(), newSessionId))
  827       newSessionId.clear();
  828   } while (newSessionId.empty());
  829 
  830   sessions_[newSessionId] = session;
  831 
  832   SessionMap::iterator i = sessions_.find(session->sessionId());
* 833   sessions_.erase(i);
  834 
  835   if (!singleSessionId_.empty())
  836     singleSessionId_ = newSessionId;
  837 
  838   return newSessionId;
  839 }
(gdb) p newSessionId
$1 = "bMETm7O6IUX392TY"

(gdb) p i
$2 = 
    {first = <error: Cannot access memory at address 0x1>, second = std::shared_ptr<Wt::WebSession> (use count -1, weak count -1) = {get() = 0x0}}

(gdb) p sessions_
$3 = std::map with 1 element = {["bMETm7O6IUX392TY"] = std::shared_ptr<Wt::WebSession> (use count 7, weak count 4) = {
    get() = 0x724ebf88}}

I notice there is no check for i == sessions_.end().

Perhaps this is intentional, and sessions_.find is never expected to fail?

If failure is (sometimes) expected, suggest making the call to erase conditional on i != sessions_.end(), or, as i is otherwise unused, use the size_type std::map::erase( const key_type& key ) overload which handles this for you.

Happy to provide more information if needed.

No data to display

Also available in: Atom PDF