Skip to content

Commit a36ebb1

Browse files
committed
vm_cc_new: don't assume cme is present.
[Bug #21694] `vm_search_super_method` explictly calls `vm_cc_new` with `cme=NULL` when there is no super class.
1 parent e920ee3 commit a36ebb1

3 files changed

Lines changed: 35 additions & 7 deletions

File tree

test/ruby/test_super.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,4 +759,19 @@ def initialize
759759
inherited = inherited_class.new
760760
assert_equal 2, inherited.test # it may read index=1 while it should be index=2
761761
end
762+
763+
def test_super_in_basic_object
764+
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
765+
begin;
766+
class ::BasicObject
767+
def no_super
768+
super()
769+
rescue ::NameError
770+
:ok
771+
end
772+
end
773+
774+
assert_equal :ok, "[Bug #21694]".no_super
775+
end;
776+
end
762777
end

vm_callinfo.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ struct rb_callcache {
302302
#define VM_CALLCACHE_REFINEMENT IMEMO_FL_USER3
303303
#define VM_CALLCACHE_UNMARKABLE IMEMO_FL_USER4
304304
#define VM_CALLCACHE_ON_STACK IMEMO_FL_USER5
305+
#define VM_CALLCACHE_INVALID_SUPER IMEMO_FL_USER6
305306

306307
enum vm_cc_type {
307308
cc_type_normal, // chained from ccs
@@ -344,8 +345,6 @@ vm_cc_new(VALUE klass,
344345
*((struct rb_callable_method_entry_struct **)&cc->cme_) = (struct rb_callable_method_entry_struct *)cme;
345346
*((vm_call_handler *)&cc->call_) = call;
346347

347-
VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS));
348-
349348
switch (type) {
350349
case cc_type_normal:
351350
break;
@@ -358,8 +357,13 @@ vm_cc_new(VALUE klass,
358357
break;
359358
}
360359

361-
if (cme->def->type == VM_METHOD_TYPE_ATTRSET || cme->def->type == VM_METHOD_TYPE_IVAR) {
362-
vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
360+
if (cme) {
361+
if (cme->def->type == VM_METHOD_TYPE_ATTRSET || cme->def->type == VM_METHOD_TYPE_IVAR) {
362+
vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
363+
}
364+
}
365+
else {
366+
*(VALUE *)&cc->flags |= VM_CALLCACHE_INVALID_SUPER;
363367
}
364368

365369
RB_DEBUG_COUNTER_INC(cc_new);
@@ -405,6 +409,14 @@ vm_cc_markable(const struct rb_callcache *cc)
405409
return FL_TEST_RAW((VALUE)cc, VM_CALLCACHE_UNMARKABLE) == 0;
406410
}
407411

412+
static inline bool
413+
vm_cc_invalid_super(const struct rb_callcache *cc)
414+
{
415+
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
416+
// Set when calling super and there is no superclass.
417+
return FL_TEST_RAW((VALUE)cc, VM_CALLCACHE_INVALID_SUPER);
418+
}
419+
408420
static inline bool
409421
vm_cc_valid(const struct rb_callcache *cc)
410422
{
@@ -418,10 +430,11 @@ static inline const struct rb_callable_method_entry_struct *
418430
vm_cc_cme(const struct rb_callcache *cc)
419431
{
420432
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
421-
VM_ASSERT(cc->klass != Qundef || !vm_cc_markable(cc));
433+
VM_ASSERT(cc->klass != Qundef || !vm_cc_markable(cc) || vm_cc_invalid_super(cc));
422434
VM_ASSERT(cc_check_class(cc->klass));
423435
VM_ASSERT(cc->call_ == NULL || // not initialized yet
424436
!vm_cc_markable(cc) ||
437+
vm_cc_invalid_super(cc) ||
425438
cc->cme_ != NULL);
426439

427440
return cc->cme_;
@@ -432,7 +445,7 @@ vm_cc_call(const struct rb_callcache *cc)
432445
{
433446
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
434447
VM_ASSERT(cc->call_ != NULL);
435-
VM_ASSERT(cc->klass != Qundef || !vm_cc_markable(cc));
448+
VM_ASSERT(cc->klass != Qundef || !vm_cc_markable(cc) || vm_cc_invalid_super(cc));
436449
VM_ASSERT(cc_check_class(cc->klass));
437450
return cc->call_;
438451
}

vm_insnhelper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5164,7 +5164,7 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
51645164

51655165
if (!klass) {
51665166
/* bound instance method of module */
5167-
cc = vm_cc_new(klass, NULL, vm_call_method_missing, cc_type_super);
5167+
cc = vm_cc_new(Qundef, NULL, vm_call_method_missing, cc_type_super);
51685168
RB_OBJ_WRITE(reg_cfp->iseq, &cd->cc, cc);
51695169
}
51705170
else {

0 commit comments

Comments
 (0)