vm_cc_new: don't assume cme is present. (#15322)

[Bug #21694]

`vm_search_super_method` explictly calls `vm_cc_new` with `cme=NULL`
when there is no super class.
This commit is contained in:
Jean Boussier 2025-12-01 18:44:46 +01:00 committed by GitHub
parent 7482835d0b
commit 3b09e559da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 4 deletions

View File

@ -759,4 +759,19 @@ class TestSuper < Test::Unit::TestCase
inherited = inherited_class.new
assert_equal 2, inherited.test # it may read index=1 while it should be index=2
end
def test_super_in_basic_object
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
begin;
class ::BasicObject
def no_super
super()
rescue ::NameError
:ok
end
end
assert_equal :ok, "[Bug #21694]".no_super
end;
end
end

View File

@ -305,6 +305,7 @@ struct rb_callcache {
#define VM_CALLCACHE_BF IMEMO_FL_USER1
#define VM_CALLCACHE_SUPER IMEMO_FL_USER2
#define VM_CALLCACHE_REFINEMENT IMEMO_FL_USER3
#define VM_CALLCACHE_INVALID_SUPER IMEMO_FL_USER6
enum vm_cc_type {
cc_type_normal, // chained from ccs
@ -335,7 +336,7 @@ vm_cc_new(VALUE klass,
*((struct rb_callable_method_entry_struct **)&cc->cme_) = (struct rb_callable_method_entry_struct *)cme;
*((vm_call_handler *)&cc->call_) = call;
VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS));
VM_ASSERT(UNDEF_P(klass) || RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS));
switch (type) {
case cc_type_normal:
@ -348,8 +349,10 @@ vm_cc_new(VALUE klass,
break;
}
if (cme->def->type == VM_METHOD_TYPE_ATTRSET || cme->def->type == VM_METHOD_TYPE_IVAR) {
vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
if (cme) {
if (cme->def->type == VM_METHOD_TYPE_ATTRSET || cme->def->type == VM_METHOD_TYPE_IVAR) {
vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
}
}
RB_DEBUG_COUNTER_INC(cc_new);
@ -401,6 +404,7 @@ vm_cc_cme(const struct rb_callcache *cc)
{
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
VM_ASSERT(cc->call_ == NULL || // not initialized yet
UNDEF_P(cc->klass) ||
!vm_cc_markable(cc) ||
cc->cme_ != NULL);

View File

@ -5048,7 +5048,7 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
if (!klass) {
/* bound instance method of module */
cc = vm_cc_new(klass, NULL, vm_call_method_missing, cc_type_super);
cc = vm_cc_new(Qundef, NULL, vm_call_method_missing, cc_type_super);
RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
}
else {