rails-sqlserver / tiny_tds

TinyTDS - Simple and fast FreeTDS bindings for Ruby using DB-Library.
Other
607 stars 189 forks source link

Segmentation fault after closing connection and asking for `dead?` #519

Closed jecastro1 closed 10 months ago

jecastro1 commented 2 years ago

Hi! First I'd like to thank you for developing this gem

Environment

Operating System

ProductName: macOS ProductVersion: 12.5 BuildVersion: 21G72

TinyTDS Version and Information

2.1.5 (also happens with 2.1.3)

Please paste the full output of `ttds-tsql -C` (or `tsql -C` for older versions
of TinyTDS) here. If TinyTDS does not install, please provide the gem version.

FreeTDS Version

Compile-time settings (established with the "configure" script)
                            Version: freetds v1.3.13
             freetds.conf directory: /opt/homebrew/etc
     MS db-lib source compatibility: no
        Sybase binary compatibility: yes
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 7.3
                              iODBC: no
                           unixodbc: yes
              SSPI "trusted" logins: no
                           Kerberos: yes
                            OpenSSL: yes
                             GnuTLS: no
                               MARS: yes

Description

There's a segmentation fault when one calls dead? after closing the client.

Expected behaviour I'd expect the method to just return true. Even an exception would be acceptable if you think this case is a misuse of the client.

Repro

client = TinyTds::Client.new(<params>)
client.close
client.dead? # <-- Segmentation fault
aharpervc commented 2 years ago

Interesting. I can also repro on macOS, but it's fine on Windows. Here was my program:

require 'tiny_tds'

puts "TinyTds::VERSION #{TinyTds::VERSION}"
puts "RUBY_VERSION #{RUBY_VERSION}"

c = TinyTds::Client.new username: 'sa', password: 'Testing123@@', host: 'localhost', database: 'master', login_timeout: 2
c.close
puts c.closed?.inspect
puts c.dead?.inspect

Here's the code that implements dead?:

https://github.com/rails-sqlserver/tiny_tds/blob/e3e79a030271891b11b6e7676382fe31f389b099/ext/tiny_tds/client.c#L272-L275

Things to investigate:

  1. Does cwrap and cwrap->client exist at this point or is there a null pointer (etc) sneaking in here somehow?
  2. dbdead is from FreeTDS, what is it doing? (link)
  3. I see it's at least logging, so if we re-run these repros with more verbose logging, can we confirm we make it all the way into FreeTDS or is the problem sooner than that?
matias-martini commented 1 year ago

I think we could close this Issue after having merged #527 😬

andyundso commented 10 months ago

The fix submitted by @matias-martini has been released with 2.1.6.