Fix oneof message in array constructor (#5727)
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index d4c29b5..ba3b11b 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -366,17 +366,29 @@
const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(submsgdef);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
- zend_property_info* property_info;
- PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
+
+ CACHED_VALUE* cached = NULL;
+ if (upb_fielddef_containingoneof(field)) {
+ void* memory = slot_memory(intern->descriptor->layout,
+ message_data(intern), field);
+ int property_cache_index =
+ intern->descriptor->layout->fields[upb_fielddef_index(field)]
+ .cache_index;
+ cached = OBJ_PROP(Z_OBJ_P(msg), property_cache_index);
+ *(CACHED_VALUE**)(memory) = cached;
+ } else {
+ zend_property_info* property_info;
+ PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
#if PHP_MAJOR_VERSION < 7
- property_info =
- zend_get_property_info(Z_OBJCE_P(msg), &key, true TSRMLS_CC);
+ property_info =
+ zend_get_property_info(Z_OBJCE_P(msg), &key, true TSRMLS_CC);
#else
- property_info =
- zend_get_property_info(Z_OBJCE_P(msg), Z_STR_P(&key), true);
+ property_info =
+ zend_get_property_info(Z_OBJCE_P(msg), Z_STR_P(&key), true);
#endif
- PHP_PROTO_FAKE_SCOPE_END;
- CACHED_VALUE* cached = OBJ_PROP(Z_OBJ_P(msg), property_info->offset);
+ PHP_PROTO_FAKE_SCOPE_END;
+ cached = OBJ_PROP(Z_OBJ_P(msg), property_info->offset);
+ }
#if PHP_MAJOR_VERSION < 7
SEPARATE_ZVAL_IF_NOT_REF(cached);
#endif
diff --git a/php/tests/generated_class_test.php b/php/tests/generated_class_test.php
index 93b7b29..a9ad793 100644
--- a/php/tests/generated_class_test.php
+++ b/php/tests/generated_class_test.php
@@ -1447,6 +1447,20 @@
}
}
+ public function testOneofMessageInArrayConstructor()
+ {
+ $m = new TestMessage([
+ 'oneof_message' => new Sub(),
+ ]);
+ }
+
+ public function testOneofStringInArrayConstructor()
+ {
+ $m = new TestMessage([
+ 'oneof_string' => 'abc',
+ ]);
+ }
+
#########################################################
# Test message equals.
#########################################################