[#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:99126] [Ruby master Bug#17023] How to prevent String memory to be relocated in ruby-ffi
From:
nobu@...
Date:
2020-07-11 10:11:45 UTC
List:
ruby-core #99126
Issue #17023 has been updated by nobu (Nobuyoshi Nakada).
Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED
Status changed from Assigned to Closed
As it doesn't seem to occur in the master but only in 2.7, I'll close this and set "Backport to 2.7" required, although I'm not sure if it is a bug.
Aaron, could you tell which commit fixed this?
----------------------------------------
Bug #17023: How to prevent String memory to be relocated in ruby-ffi
https://bugs.ruby-lang.org/issues/17023#change-86503
* Author: larskanis (Lars Kanis)
* Status: Closed
* Priority: Normal
* Assignee: tenderlovemaking (Aaron Patterson)
* ruby -v: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
* Backport: 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED
----------------------------------------
[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:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>