Pass the element default instance to Add in RepeatedPtrFieldAccessor.

Constructing the element using the user-provided to-be-added value is error prone, as it allows users to add a message of an unrelated type to repeated fields.

With this change, if the `value` to be added is an unrelated type, `CopyFrom` will crash in `Message::CopyFrom`'s `CHECK_EQ(from.GetDescriptor(), descriptor)`.

PiperOrigin-RevId: 950631755
diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel
index 24aadcb..261fb06 100644
--- a/src/google/protobuf/BUILD.bazel
+++ b/src/google/protobuf/BUILD.bazel
@@ -2564,11 +2564,11 @@
     }),
     deps = [
         ":cc_test_protos",
-        ":port",
         ":protobuf",
         ":test_util",
         "//src/google/protobuf/stubs",
-        "@abseil-cpp//absl/base",
+        "@abseil-cpp//absl/log:absl_check",
+        "@abseil-cpp//absl/strings",
         "@abseil-cpp//absl/strings:cord",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index fe6e6f9..da3fe68 100644
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -138,7 +138,8 @@
     if constexpr (internal::CanMakeConstSpan<T, Container>::value) {
       absl::Span<const T> span = absl::MakeConstSpan(container);
       if (!span.empty()) {
-        accessor_->AddRange(data_, span.data(), sizeof(T), span.size());
+        accessor_->AddRange(data_, span.data(), sizeof(T), span.size(),
+                            /*prototype=*/nullptr);
       }
     } else {
       for (const auto& value : container) {
@@ -255,7 +256,9 @@
   void Set(int index, const T& value) const {
     accessor_->Set(data_, index, &value);
   }
-  void Add(const T& value) const { accessor_->Add(data_, &value); }
+  void Add(const T& value) const {
+    accessor_->Add(data_, &value, default_instance_);
+  }
   void RemoveLast() const { accessor_->RemoveLast(data_); }
   void SwapElements(int index1, int index2) const {
     accessor_->SwapElements(data_, index1, index2);
@@ -271,7 +274,8 @@
     if constexpr (internal::CanMakeConstSpan<T, Container>::value) {
       absl::Span<const T> span = absl::MakeConstSpan(container);
       if (!span.empty()) {
-        accessor_->AddRange(data_, span.data(), sizeof(T), span.size());
+        accessor_->AddRange(data_, span.data(), sizeof(T), span.size(),
+                            default_instance_);
       }
     } else {
       for (const auto& value : container) {
@@ -353,10 +357,12 @@
   virtual void Set(Field* PROTOBUF_NONNULL data, int index,
                    const Value* PROTOBUF_NONNULL value) const = 0;
   virtual void Add(Field* PROTOBUF_NONNULL data,
-                   const Value* PROTOBUF_NONNULL value) const = 0;
+                   const Value* PROTOBUF_NONNULL value,
+                   const Value* PROTOBUF_NULLABLE prototype) const = 0;
   virtual void AddRange(Field* PROTOBUF_NONNULL data,
                         const Value* PROTOBUF_NONNULL values, int value_size,
-                        size_t size) const = 0;
+                        size_t size,
+                        const Value* PROTOBUF_NULLABLE prototype) const = 0;
   virtual void RemoveLast(Field* PROTOBUF_NONNULL data) const = 0;
   virtual void SwapElements(Field* PROTOBUF_NONNULL data, int index1,
                             int index2) const = 0;
@@ -429,7 +435,7 @@
     // may be a generated enum type while ActualType is int32_t). To be safe
     // we make a copy to get a temporary ActualType object and use it.
     ActualType tmp = static_cast<ActualType>(value);
-    Add(data, static_cast<const Value*>(&tmp));
+    Add(data, static_cast<const Value*>(&tmp), /*prototype=*/nullptr);
   }
 
  protected:
diff --git a/src/google/protobuf/reflection_internal.h b/src/google/protobuf/reflection_internal.h
index 5947dba..f4bc1fb 100644
--- a/src/google/protobuf/reflection_internal.h
+++ b/src/google/protobuf/reflection_internal.h
@@ -15,6 +15,7 @@
 #include "absl/log/absl_check.h"
 #include "absl/strings/cord.h"
 #include "google/protobuf/map_field.h"
+#include "google/protobuf/message.h"
 #include "google/protobuf/port.h"
 #include "google/protobuf/reflection.h"
 #include "google/protobuf/repeated_field.h"
@@ -89,7 +90,8 @@
   void Set(Field* data, int index, const Value* value) const override {
     MutableRepeatedField(data)->Set(index, ConvertToT(value));
   }
-  void Add(Field* data, const Value* value) const override {
+  void Add(Field* data, const Value* value,
+           const Value* /*prototype*/) const override {
     MutableRepeatedField(data)->Add(ConvertToT(value));
   }
   void RemoveLast(Field* data) const override {
@@ -147,19 +149,20 @@
   void Set(Field* data, int index, const Value* value) const override {
     ConvertToT(value, MutableRepeatedField(data)->Mutable(index));
   }
-  void Add(Field* data, const Value* value) const override {
-    T* allocated = New(value);
+  void Add(Field* data, const Value* value,
+           const Value* prototype) const override {
+    T* allocated = New(prototype);
     ConvertToT(value, allocated);
     MutableRepeatedField(data)->AddAllocated(allocated);
   }
-  void AddRange(Field* data, const Value* values, int value_size,
-                size_t size) const override {
+  void AddRange(Field* data, const Value* values, int value_size, size_t size,
+                const Value* prototype) const override {
     auto* repeated = MutableRepeatedField(data);
     int old_size = repeated->size();
     repeated->Reserve(internal::CheckedAdd(old_size, size));
     const char* ptr = reinterpret_cast<const char*>(values);
     for (size_t i = 0; i < size; ++i) {
-      Add(data, ptr);
+      Add(data, ptr, prototype);
       ptr += value_size;
     }
   }
@@ -185,10 +188,9 @@
   }
 
   // Create a new T instance. For repeated message fields, T can be specified
-  // as google::protobuf::Message so we can't use "new T()" directly. In that case, value
-  // should be a message of the same type (it's ensured by the caller) and a
-  // new message object will be created using it.
-  virtual T* New(const Value* value) const = 0;
+  // as google::protobuf::Message so we can't use "new T()" directly. In that case,
+  // `prototype` should the prototype of the message to be created.
+  virtual T* New(const Value* prototype) const = 0;
 
   // Convert an object received by this accessor to an object that will be
   // stored in the underlying RepeatedPtrField.
@@ -222,8 +224,8 @@
     MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
   }
 
-  void AddRange(Field* data, const Value* values, int value_size,
-                size_t size) const override {
+  void AddRange(Field* data, const Value* values, int value_size, size_t size,
+                const Value* /*prototype*/) const override {
     const T* ptr = reinterpret_cast<const T*>(values);
     MutableRepeatedField(data)->Add(ptr, ptr + size);
   }
@@ -296,8 +298,8 @@
   }
 
  protected:
-  Message* New(const Value* value) const override {
-    return static_cast<const Message*>(value)->New();
+  Message* New(const Value* prototype) const override {
+    return static_cast<const Message*>(prototype)->New();
   }
   void ConvertToT(const Value* value, Message* result) const override {
     result->CopyFrom(*static_cast<const Message*>(value));
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.inc b/src/google/protobuf/repeated_field_reflection_unittest.inc
index 3dcf128..90317d7 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.inc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.inc
@@ -10,11 +10,16 @@
 // Test reflection methods for aggregate access to Repeated[Ptr]Fields.
 // This test proto2 methods on a proto2 layout.
 
+#include <cstdint>
+#include <string>
+
 #include <gtest/gtest.h>
-#include "absl/base/casts.h"
+#include "absl/log/absl_check.h"
 #include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/descriptor.h"
 #include "google/protobuf/dynamic_message.h"
-#include "google/protobuf/port.h"
+#include "google/protobuf/message.h"
 #include "google/protobuf/reflection.h"
 
 namespace google {
@@ -682,6 +687,23 @@
             refl->GetRepeatedInt32(*dynamic_message, fd_repeated_int32, 0));
 }
 
+#if GTEST_HAS_DEATH_TEST
+TEST(REFLECTION_TEST, RepeatedFieldRefAddRejectsUnrelatedMessageType) {
+  TestAllTypes m0;
+  const Reflection* refl = m0.GetReflection();
+  const Descriptor* desc = m0.GetDescriptor();
+
+  const FieldDescriptor* fd_repeated_nested_message =
+      desc->FindFieldByName("repeated_nested_message");
+  auto rf_nested_message = refl->GetMutableRepeatedFieldRef<Message>(
+      &m0, fd_repeated_nested_message);
+
+  TestAllTypes m1;
+  EXPECT_DEATH(rf_nested_message.Add(m1),
+               "Tried to copy from a message with a different type.");
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
 }  // namespace
 }  // namespace protobuf
 }  // namespace google