Use rb_obj_class instead of CLASS_OF in Ruby C to ignore singleton classes (#9342)

Co-authored-by: Adam Cozzette <acozzette@google.com>
This commit is contained in:
Anthony Dmitriyev 2022-02-11 19:04:10 +00:00 committed by GitHub
parent 2495d220fa
commit 2ce9604227
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 3 deletions

View File

@ -162,9 +162,9 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
}
case kUpb_CType_String: {
VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
if (CLASS_OF(value) == rb_cSymbol) {
if (rb_obj_class(value) == rb_cSymbol) {
value = rb_funcall(value, rb_intern("to_s"), 0);
} else if (CLASS_OF(value) != rb_cString) {
} else if (rb_obj_class(value) != rb_cString) {
rb_raise(cTypeError,
"Invalid argument for string field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));
@ -185,7 +185,7 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
}
case kUpb_CType_Bytes: {
VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
if (CLASS_OF(value) != rb_cString) {
if (rb_obj_class(value) != rb_cString) {
rb_raise(cTypeError,
"Invalid argument for bytes field '%s' (given %s).", name,
rb_class2name(CLASS_OF(value)));

View File

@ -644,5 +644,19 @@ module BasicTest
assert_equal 2, m.map_string_int32.size
assert_equal 1, m.map_string_msg.size
end
def test_string_with_singleton_class_enabled
str = 'foobar'
# NOTE: Accessing a singleton class of an object changes its low level class representation
# as far as the C API's CLASS_OF() method concerned, exposing the issue
str.singleton_class
m = proto_module::TestMessage.new(
optional_string: str,
optional_bytes: str
)
assert_equal str, m.optional_string
assert_equal str, m.optional_bytes
end
end
end