Преглед на файлове

Fix c extension doesn' allow message reference in array (#5599)

* Fix c extension doesn' allow message reference in array

* Fix array constructor handling reference of array.

* Change test name
Paul Yang преди 6 години
родител
ревизия
1069565a68
променени са 4 файла, в които са добавени 43 реда и са изтрити 0 реда
  1. 5 0
      php/ext/google/protobuf/message.c
  2. 6 0
      php/ext/google/protobuf/storage.c
  3. 31 0
      php/tests/array_test.php
  4. 1 0
      php/tests/proto/test.proto

+ 5 - 0
php/ext/google/protobuf/message.c

@@ -319,6 +319,11 @@ void Message_construct(zval* msg, zval* array_wrapper) {
        zend_hash_move_forward_ex(array, &pointer)) {
        zend_hash_move_forward_ex(array, &pointer)) {
     zend_hash_get_current_key_zval_ex(array, &key, &pointer);
     zend_hash_get_current_key_zval_ex(array, &key, &pointer);
     field = upb_msgdef_ntofz(intern->descriptor->msgdef, Z_STRVAL_P(&key));
     field = upb_msgdef_ntofz(intern->descriptor->msgdef, Z_STRVAL_P(&key));
+#if PHP_MAJOR_VERSION >= 7
+    if (Z_ISREF_P((CACHED_VALUE*)value)) {
+      value = Z_REFVAL_P((CACHED_VALUE*)value);
+    }
+#endif
     if (field == NULL) {
     if (field == NULL) {
       zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(&key));
       zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(&key));
     }
     }

+ 6 - 0
php/ext/google/protobuf/storage.c

@@ -186,6 +186,12 @@ bool native_slot_set_by_array(upb_fieldtype_t type,
       break;
       break;
     }
     }
     case UPB_TYPE_MESSAGE: {
     case UPB_TYPE_MESSAGE: {
+#if PHP_MAJOR_VERSION >= 7
+      if (Z_ISREF_P(value)) {
+        ZVAL_DEREF(value);
+      }
+#endif
+
       if (Z_TYPE_P(value) != IS_OBJECT) {
       if (Z_TYPE_P(value) != IS_OBJECT) {
         zend_error(E_USER_ERROR, "Given value is not message.");
         zend_error(E_USER_ERROR, "Given value is not message.");
         return false;
         return false;

+ 31 - 0
php/tests/array_test.php

@@ -529,6 +529,37 @@ class RepeatedFieldTest extends \PHPUnit\Framework\TestCase
         $this->assertSame(3, $arr[2]);
         $this->assertSame(3, $arr[2]);
     }
     }
 
 
+    #########################################################
+    # Test reference in array
+    #########################################################
+
+    public function testArrayElementIsReference()
+    {
+        $m = new TestMessage();
+        $subs = [1, 2];
+
+        foreach ($subs as &$sub) {
+            $sub = new Sub(['a' => $sub]);
+        }
+
+        $m->setRepeatedMessage($subs);
+    }
+
+    public function testArrayIsReference()
+    {
+        $keys = [['repeated_message' => [['a' => 1]]]];
+
+        foreach ($keys as &$key) {
+            foreach ($key['repeated_message'] as &$element) {
+              $element = new Sub($element);
+            }
+            $key = new TestMessage($key);
+        }
+
+        $m = new TestMessage();
+        $m->setRepeatedDeep($keys);
+    }
+
     #########################################################
     #########################################################
     # Test memory leak
     # Test memory leak
     #########################################################
     #########################################################

+ 1 - 0
php/tests/proto/test.proto

@@ -31,6 +31,7 @@ message TestMessage {
   Sub optional_message = 17;
   Sub optional_message = 17;
   bar.TestInclude optional_included_message = 18;
   bar.TestInclude optional_included_message = 18;
   TestMessage recursive = 19;
   TestMessage recursive = 19;
+  repeated TestMessage repeated_deep = 20;
 
 
   // Repeated
   // Repeated
   repeated    int32 repeated_int32    = 31;
   repeated    int32 repeated_int32    = 31;