Project

General

Profile

Actions

Bug #18428

closed

Calling Object#singleton_class mutates object's class from the C API's perspective

Added by antstorm (Anthony Dmitriyev) over 2 years ago. Updated over 2 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [arm64-darwin20]
[ruby-core:106783]

Description

Hi,

I'm not 100% sure if this is an actual bug, but it feels like it. When a Object#singleton_class method is called on an object it swaps the object's class with a singleton's class (as far as CLASS_OF C call is concerned).

Here's a simple example to reproduce the issue:

  1. The C extension that adds a #c_class method to the Object, returning back the value of CLASS_OF call
#include "ruby.h"
#include "extconf.h"

static VALUE c_class(VALUE self) {
  return CLASS_OF(self);
}

void Init_c_class(void) {
  rb_define_method(rb_cObject, "c_class", c_class, 0);
}
  1. With that extension required, we can expose the issue from the console:
>> a = 'test'
=> "test"
>> a.class
=> String
>> a.c_class
=> String
>> a.singleton_class
=> #<Class:#<String:0x00000001168372e8>>
>> a.class
=> String
>> a.c_class
=> #<Class:#<String:0x00000001168372e8>>

I would expect the last call to c_class to return the same value as previously — String, instead it returns a singleton class.

Originally noticed this behaviour when passing a string to Google protobuf generated files, which raises this error — https://github.com/protocolbuffers/protobuf/blob/master/ruby/ext/google/protobuf_c/convert.c#L161. If the string had singleton_class called on it this would raise.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0