Skip to content

Commit 34a4fbe

Browse files
committed
Fix an infinite recursion issue with native extensions that redefine frozen?.
MRI defines `frozen?` with `rb_obj_frozen_p`, which in turn, uses `RB_OBJ_FROZEN`. Since TruffleRuby doesn't have flag bits in an object header like MRI does, we implement `RB_OBJ_FROZEN` with `rb_obj_frozen_p`, which would lead to an infinite loop if a native extension redefined `frozen?` in terms of `RB_OBJ_FROZEN`. We break the loop by introducing a new primitive, which a native extension would not be able to redefine.
1 parent 07b77f7 commit 34a4fbe

File tree

3 files changed

+11
-1
lines changed

3 files changed

+11
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Bug fixes:
77

88
* Fix `Range#cover?` on begin-less ranges and non-integer values (@nirvdrum, @rwstauner).
99
* Fix `Time.new` with String argument and handle nanoseconds correctly (#3836, @andrykonchin).
10+
* Fix a possible case of infinite recursion when implementing `frozen?` in a native extension (@nirvdrum).
1011

1112
Compatibility:
1213

lib/truffle/truffle/cext.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ def rb_obj_freeze(obj)
477477
end
478478

479479
def rb_obj_frozen_p(object)
480-
object.frozen?
480+
Primitive.frozen?(object)
481481
end
482482

483483
def rb_obj_id(object)

src/main/java/org/truffleruby/core/support/TypeNodes.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@ Object freeze(Object self,
161161
}
162162
}
163163

164+
@Primitive(name = "frozen?")
165+
public abstract static class IsFrozenPrimitive extends PrimitiveArrayArgumentsNode {
166+
@Specialization
167+
boolean isFrozen(Object self,
168+
@Cached IsFrozenNode isFrozenNode) {
169+
return isFrozenNode.execute(self);
170+
}
171+
}
172+
164173
@Primitive(name = "immediate_value?")
165174
public abstract static class IsImmediateValueNode extends PrimitiveArrayArgumentsNode {
166175

0 commit comments

Comments
 (0)