Project

General

Profile

Actions

Bug #17023

closed

How to prevent String memory to be relocated in ruby-ffi

Added by larskanis (Lars Kanis) over 3 years ago. Updated over 3 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
[ruby-core:99115]

Description

ruby-ffi allows to pass String objects to C by using the :string argument type. This way the string memory returned by RSTRING_PTR is passed to the C function. The user has to ensure on Ruby level that the string isn't GC'ed - as long as it is used on C level. That's the contract and this worked with all past ruby versions, but ruby-2.7 introduced GC.compact, which can relocate strings to another memory location.

This example shows the situation and that the string is relocated although it is still referenced in ruby code:

File.write "string-relocate.c", <<-EOC
  static char *g_str;

  void set(char* str) {
    g_str = str;
  }

  char* get() {
    return g_str;
  }
EOC
system "gcc -shared -fPIC string-relocate.c -o string-relocate.so"

require 'ffi'

class Foo
  extend FFI::Library
  ffi_lib File.expand_path('string-relocate.so')

  attach_function :set, [:string], :void
  attach_function :get, [], :string

  def initialize(count)
    proc {} # necessary to trigger relocation
    a = "a" * count
    set(a)

    GC.verify_compaction_references(toward: :empty, double_heap: true)

    puts "get(#{count}): #{get} (should be: #{a})"
  end
end

Foo.new(23)
Foo.new(24)

The output looks like so on ruby-2.7.1:

get(23):  (should be: aaaaaaaaaaaaaaaaaaaaaaa)
get(24): aaaaaaaaaaaaaaaaaaaaaaaa (should be: aaaaaaaaaaaaaaaaaaaaaaaa)

So using GC.compact while a string parameter is in use, both on Ruby and on C level, can cause invalid memory access. How can this prevented?

A C extension is expected to use rb_gc_mark() in order to pin the VALUE to a memory location. But I couldn't find a way to pin a VALUE at the time the argument is passed to the C function, which is the only point in time ruby-ffi has access to it.


Files

string-relocate.rb (653 Bytes) string-relocate.rb larskanis (Lars Kanis), 07/10/2020 05:27 PM
0001-Only-marked-objects-should-be-considered-movable.patch (1.23 KB) 0001-Only-marked-objects-should-be-considered-movable.patch tenderlovemaking (Aaron Patterson), 07/13/2020 05:55 PM
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0