mridoni / gixsql

GixSQL is an ESQL preprocessor and a series of runtime libraries to enable GnuCOBOL to access PostgreSQL, ODBC, MySQL, Oracle and SQLite databases.
GNU General Public License v3.0
13 stars 6 forks source link

Connection.cpp:31 invalid read of size 8 (in destructor) #159

Open GitMensch opened 1 year ago

GitMensch commented 1 year ago

In this case there was a connection along with working access to the DB and on unloading (cob_stop_run() calling exit(0)) valgrind reports the following on the destructor

Invalid read of size 8
   at 0xB83F198: std::_Sp_counted_ptr<IDbInterface*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:377)
   by 0xB7B7523: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:155)
   by 0xB7B20E2: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:728)
   by 0xB7B1615: std::__shared_ptr<IDbInterface, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1167)
   by 0xB7B1631: std::shared_ptr<IDbInterface>::~shared_ptr() (shared_ptr.h:103)
   by 0xB7AE08E: Connection::~Connection() (Connection.cpp:31)
   by 0xB8069F3: void __gnu_cxx::new_allocator<Connection>::destroy<Connection>(Connection*) (new_allocator.h:140)
   by 0xB8068A6: void std::allocator_traits<std::allocator<Connection> >::destroy<Connection>(std::allocator<Connection>&, Connection*) (alloc_traits.h:487)
   by 0xB8061AC: std::_Sp_counted_ptr_inplace<Connection, std::allocator<Connection>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:554)
   by 0xB7B7523: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:155)
   by 0xB7B20E2: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:728)
   by 0xB7FA315: std::__shared_ptr<Connection, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1167)
 Address 0x13b3e718 is not stack'd, malloc'd or (recently) free'd

Note: libgixsql is not static linked in this case but loaded with COB_PRE_LOAD (so dlopen'd by libcob). This may or may not make a difference.

As a follow up (because some stack data is trashed) libcob then aborts during teardown attempt to reference invalid memory address (signal).

GitMensch commented 1 year ago

Any insights where that pointer comes from and what it should point to (where it gets trashed/freed)?

GitMensch commented 1 year ago

@mridoni Can you reproduce this?

Checked with GDB and found the issue to be the ( delete _m_ptr; ) called by Connection::~Connection() (Connection.cpp:31).

As my testing environment moved to a new virtual machine which has all perf counters enabled I now could use rr to successfully record that session, which allowed me to make this 100% reproducible - and to check with a watchpoint where that memory came from:

(rr) bt
#0  DbInterfaceFactory::load_dblib (...) at ../../../runtime/libgixsql/DbInterfaceFactory.cpp:204
#1  0x00007f90b2ca73c4 in DbInterfaceFactory::getInterface (...) at ../../../runtime/libgixsql/DbInterfaceFactory.cpp:85
#2  0x00007f90b2ca9c39 in GIXSQLConnect (...) at ../../../runtime/libgixsql/gixsql.cpp:157

(... ok, that's nearly just what valgrind said, but this time I can check any details...) will retest after version update.

GitMensch commented 1 year ago

After version update:

==3632523== Invalid read of size 8
==3632523==    at 0x93BBE08: std::_Sp_counted_ptr<IDbInterface*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:348)
==3632523==    by 0x93387B7: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:168)
==3632523==    by 0x9332B98: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:705)
==3632523==    by 0x9332133: std::__shared_ptr<IDbInterface, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1154)
==3632523==    by 0x933214F: std::shared_ptr<IDbInterface>::~shared_ptr() (shared_ptr.h:122)
==3632523==    by 0x932E162: Connection::~Connection() (Connection.cpp:35)
==3632523==    by 0x9383A5F: void __gnu_cxx::new_allocator<Connection>::destroy<Connection>(Connection*) (new_allocator.h:168)
==3632523==    by 0x938393A: void std::allocator_traits<std::allocator<Connection> >::destroy<Connection>(std::allocator<Connection>&, Connection*) (alloc_traits.h:535)
==3632523==    by 0x938315E: std::_Sp_counted_ptr_inplace<Connection, std::allocator<Connection>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:528)
==3632523==    by 0x93387B7: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:168)
==3632523==    by 0x9332B98: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:705)
==3632523==    by 0x9378209: std::__shared_ptr<Connection, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1154)
==3632523==  Address 0xcb964c8 is not stack'd, malloc'd or (recently) free'd
GitMensch commented 10 months ago

I likely should recheck if this also happens, when I just do:

cobcrun -> PROG -> connect
              -> STOP RUN

In this case the connection part may directly reference memory from the calling PROG, which is dlclose'd before the gixsql shared objects are unloaded; that wouldn't work.