[#99115] [Ruby master Bug#17023] How to prevent String memory to be relocated in ruby-ffi — larskanis@...
Issue #17023 has been reported by larskanis (Lars Kanis).
22 messages
2020/07/10
[#99375] [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings — merch-redmine@...
Issue #17055 has been reported by jeremyevans0 (Jeremy Evans).
29 messages
2020/07/28
[#101207] [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings
— merch-redmine@...
2020/12/02
Issue #17055 has been updated by jeremyevans0 (Jeremy Evans).
[#101231] Re: [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings
— Austin Ziegler <halostatue@...>
2020/12/03
What does this mean?
[ruby-core:99116] [Ruby master Bug#17023] How to prevent String memory to be relocated in ruby-ffi
From:
chris@...
Date:
2020-07-10 19:51:29 UTC
List:
ruby-core #99116
Issue #17023 has been updated by chrisseaton (Chris Seaton).
> The user has to ensure on Ruby level that the string isn't GC'ed
The contract has always been more than that - the user must also not modify the string, as this may cause the character pointer to be reallocated.
----------------------------------------
Bug #17023: How to prevent String memory to be relocated in ruby-ffi
https://bugs.ruby-lang.org/issues/17023#change-86491
* Author: larskanis (Lars Kanis)
* Status: Open
* Priority: Normal
* ruby -v: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
[ruby-ffi](https://github.com/ffi/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:
```ruby
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)
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>