From c02a6fbf2c2af8e82d917af6afc7ac4e4f73d9e2 Mon Sep 17 00:00:00 2001
From: Joshua Haberman <jhaberman@gmail.com>
Date: Fri, 16 Aug 2019 09:37:36 -0700
Subject: [PATCH] Bugfix for GC mark of oneof fields.

---
 ruby/ext/google/protobuf_c/encode_decode.c | 3 +++
 ruby/ext/google/protobuf_c/protobuf.h      | 1 +
 ruby/ext/google/protobuf_c/storage.c       | 2 +-
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
index f4d3de2543..ad3d554706 100644
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ b/ruby/ext/google/protobuf_c/encode_decode.c
@@ -155,6 +155,9 @@ static const void *newoneofhandlerdata(upb_handlers *h,
   // create a separate ID space. In addition, using the field tag number here
   // lets us easily look up the field in the oneof accessor.
   hd->oneof_case_num = upb_fielddef_number(f);
+  if (is_value_field(f)) {
+    hd->oneof_case_num |= ONEOF_CASE_MASK;
+  }
   hd->subklass = field_type_class(desc->layout, f);
   upb_handlers_addcleanup(h, hd, xfree);
   return hd;
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index 0925185e54..b8aed5a47f 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -370,6 +370,7 @@ VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
 void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value);
 uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
                               const upb_oneofdef* oneof);
+bool is_value_field(const upb_fielddef* f);
 
 extern rb_encoding* kRubyStringUtf8Encoding;
 extern rb_encoding* kRubyStringASCIIEncoding;
diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c
index 25628ed0fe..e72fa10df4 100644
--- a/ruby/ext/google/protobuf_c/storage.c
+++ b/ruby/ext/google/protobuf_c/storage.c
@@ -473,7 +473,7 @@ static size_t align_up_to(size_t offset, size_t granularity) {
   return (offset + granularity - 1) & ~(granularity - 1);
 }
 
-static bool is_value_field(const upb_fielddef* f) {
+bool is_value_field(const upb_fielddef* f) {
   return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
          upb_fielddef_isstring(f);
 }