blackwinter / rb-gsl

Ruby interface to the GNU Scientific Library [Ruby 2.x and GSL 1.16 compatible fork of the gsl gem]
https://blackwinter.github.io/rb-gsl
Other
27 stars 7 forks source link

GSL::Vector::View usage is not safe, crashes Ruby #21

Open rbalint opened 9 years ago

rbalint commented 9 years ago

Hi, From https://www.gnu.org/software/gsl/manual/html_node/Vector-views.html :

A vector view is a temporary object, stored on the stack, which can be used to operate on a subset of vector elements. Vector views can be defined for both constant and non-constant vectors, using separate types that preserve constness. A vector view has the type gsl_vector_view and a constant vector view has the type gsl_vector_const_view. In both cases the elements of the view can be accessed as a gsl_vector using the vector component of the view object. A pointer to a vector of type gsl_vector * or const gsl_vector * can be obtained by taking the address of this component with the & operator.

When using this pointer it is important to ensure that the view itself remains in scope—the simplest way to do so is by always writing the pointer as &view.vector, and never storing this value in another variable.

The following simple test demonstrates the problem:

require 'gsl'
GC.stress = true
x = (1..100000).to_gsl_vector[(0..-1)]
p x

Result:

/home/rbalint/interp-gsl-vector-gone.rb:5: [BUG] Segmentation fault at 0x007f6509358010
ruby 2.1.5p273 (2014-11-13) [x86_64-linux-gnu]

-- Control frame information -----------------------------------------------
c:0004 p:---- s:0011 e:000010 CFUNC  :inspect
c:0003 p:---- s:0009 e:000008 CFUNC  :p
c:0002 p:0045 s:0005 E:000f90 EVAL   /home/rbalint/interp-gsl-vector-gone.rb:5 [FINISH]
c:0001 p:0000 s:0002 E:000f78 TOP    [FINISH]

-- Ruby level backtrace information ----------------------------------------
/home/rbalint/interp-gsl-vector-gone.rb:5:in `<main>'
/home/rbalint/interp-gsl-vector-gone.rb:5:in `p'
/home/rbalint/interp-gsl-vector-gone.rb:5:in `inspect'

-- C level backtrace information -------------------------------------------
/usr/lib/x86_64-linux-gnu/libruby-2.1.so.2.1(+0x18a837) [0x7f650903e837]

I think rb-gsl should not expose GSL views because it seems to be impossible to implement it properly.

blackwinter commented 9 years ago

Thanks, I'll look into it.

rbalint commented 9 years ago

To correct myself if it is not impossible to implement views, but hard due to some parts are stored on the stack. They can be moved to heap, but this is not trivial.

blackwinter commented 9 years ago

Hi Balint,

I'm sorry, but I have to retract my earlier statement. At the moment, I don't have time to work on this library. I only created this fork to add support for newer Ruby and GSL versions and I'm not familiar with the inner workings of this code or GSL. I can give you commit access if you want and assist you in any way I can.

Cheers, Jens

rbalint commented 9 years ago

Hi Jens, Sorry, but I'm not familiar with the codebase either and I'm not sure if I can find time for fixing this problem in the near future. :-( If I come up with something useful I'll submit a pull request. Cheers, Balint

blackwinter commented 9 years ago

Sure, I totally understand. I'm no longer working on this library, so I leave it to the new maintainer(s) to decide what to do about this issue.

rbalint commented 9 years ago

To help people using ruby-gsl in the meantime if you keep the vector in scope in does not get GC-ed and the program works properly.

$ cat interp-gsl-vector-gone.rb
require 'gsl'
GC.stress = true
in_scope_vector = (1..100000).to_gsl_vector
x = in_scope_vector[(0..-1)]
p x
$ ruby /home/rbalint/interp-gsl-vector-gone.rbGSL::Vector::View
[ 1.000e+00 2.000e+00 3.000e+00 4.000e+00 5.000e+00 6.000e+00 7.000e+00 ... ]
$