Skip to content

Commit b9d0ca0

Browse files
committed
[GR-15444] Fix #get_pointer_value to ensure it keeps the argument alive during the native call
* Otherwise, an autorelease pointer could be freed after getting the address but before or during the native call.
1 parent 3cc35b4 commit b9d0ca0

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

lib/truffle/truffle/ffi_backend/function.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,16 @@ def free
178178
end
179179
end
180180

181+
# Returns a Truffle::FFI::Pointer, to correctly keep the argument alive during the native call
181182
private def get_pointer_value(value)
182183
if Truffle::FFI::Pointer === value
183-
value.address
184+
value
184185
elsif nil.equal?(value)
185-
0
186+
Truffle::FFI::Pointer::NULL
186187
elsif String === value
187-
Truffle::CExt.string_pointer_to_native(value)
188+
Truffle::CExt.string_to_pointer(value)
188189
elsif value.respond_to?(:to_ptr)
189-
value.to_ptr.address
190+
Truffle::Type.coerce_to value, Truffle::FFI::Pointer, :to_ptr
190191
else
191192
raise ArgumentError, "#{value.inspect} (#{value.class}) is not a pointer"
192193
end

src/main/java/org/truffleruby/cext/CExtNodes.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
import org.truffleruby.language.dispatch.DoesRespondDispatchHeadNode;
9191
import org.truffleruby.language.methods.DeclarationContext;
9292
import org.truffleruby.language.methods.InternalMethod;
93+
import org.truffleruby.language.objects.AllocateObjectNode;
9394
import org.truffleruby.language.objects.InitializeClassNode;
9495
import org.truffleruby.language.objects.InitializeClassNodeGen;
9596
import org.truffleruby.language.objects.IsFrozenNode;
@@ -1002,6 +1003,20 @@ public long toNative(DynamicObject string,
10021003

10031004
}
10041005

1006+
@CoreMethod(names = "string_to_pointer", onSingleton = true, required = 1)
1007+
public abstract static class StringToPointerNode extends CoreMethodArrayArgumentsNode {
1008+
1009+
@Specialization(guards = "isRubyString(string)")
1010+
public DynamicObject toNative(DynamicObject string,
1011+
@Cached("create()") StringToNativeNode stringToNativeNode,
1012+
@Cached("create()") AllocateObjectNode allocateObjectNode) {
1013+
final NativeRope nativeRope = stringToNativeNode.executeToNative(string);
1014+
1015+
return allocateObjectNode.allocate(coreLibrary().getTruffleFFIPointerClass(), nativeRope.getNativePointer());
1016+
}
1017+
1018+
}
1019+
10051020
@CoreMethod(names = "string_pointer_is_native?", onSingleton = true, required = 1)
10061021
public abstract static class StringPointerIsNativeNode extends CoreMethodArrayArgumentsNode {
10071022

0 commit comments

Comments
 (0)