1// -*- c++ -*- 2// Protocol Buffers - Google's data interchange format 3// Copyright 2008 Google Inc. All rights reserved. 4// 5// Use of this source code is governed by a BSD-style 6// license that can be found in the LICENSE file or at 7// https://developers.google.com/open-source/licenses/bsd 8 9// Author: kenton@google.com (Kenton Varda) 10// Based on original Protocol Buffers design by 11// Sanjay Ghemawat, Jeff Dean, and others. 12// 13// This file needs to be included as .inc as it depends on certain macros being 14// defined prior to its inclusion. 15 16#include <fcntl.h> 17#include <sys/stat.h> 18#include <sys/types.h> 19 20#include <cmath> 21#include <functional> 22#include <limits> 23#include <vector> 24 25#ifndef _MSC_VER 26#include <unistd.h> 27#endif 28#include <fstream> 29#include <sstream> 30 31#include "google/protobuf/descriptor.pb.h" 32#include <gmock/gmock.h> 33#include "google/protobuf/testing/googletest.h" 34#include <gtest/gtest.h> 35#include "absl/log/absl_check.h" 36#include "absl/log/scoped_mock_log.h" 37#include "absl/strings/cord.h" 38#include "absl/strings/substitute.h" 39#include "google/protobuf/arena.h" 40#include "google/protobuf/descriptor.h" 41#include "google/protobuf/dynamic_message.h" 42#include "google/protobuf/generated_message_reflection.h" 43#include "google/protobuf/generated_message_tctable_impl.h" 44#include "google/protobuf/io/coded_stream.h" 45#include "google/protobuf/io/io_win32.h" 46#include "google/protobuf/io/zero_copy_stream.h" 47#include "google/protobuf/io/zero_copy_stream_impl.h" 48#include "google/protobuf/message.h" 49#include "google/protobuf/reflection_ops.h" 50#include "google/protobuf/test_util2.h" 51 52// Must be included last. 53#include "google/protobuf/port_def.inc" 54 55namespace google { 56namespace protobuf { 57 58TEST(MESSAGE_TEST_NAME, AllSetMethodsOnStringField) { 59 UNITTEST::TestAllTypes msg; 60 61 msg.set_optional_string(absl::string_view("Abcdef")); 62 EXPECT_EQ(msg.optional_string(), "Abcdef"); 63 64 msg.set_optional_string("Asciiz"); 65 EXPECT_EQ(msg.optional_string(), "Asciiz"); 66 67 msg.set_optional_string("Length delimited", 6); 68 EXPECT_EQ(msg.optional_string(), "Length"); 69 70 std::string value = "std::string value 1"; 71 msg.set_optional_string(value); 72 EXPECT_EQ(msg.optional_string(), "std::string value 1"); 73 74 value = "std::string value 2"; 75 msg.set_optional_string(std::cref(value)); 76 EXPECT_EQ(msg.optional_string(), "std::string value 2"); 77 78 value = "std::string value 3"; 79 msg.set_optional_string(std::move(value)); 80 EXPECT_EQ(msg.optional_string(), "std::string value 3"); 81} 82 83 84TEST(MESSAGE_TEST_NAME, AllAddMethodsOnRepeatedStringField) { 85 UNITTEST::TestAllTypes msg; 86 87 msg.add_repeated_string(absl::string_view("Abcdef")); 88 EXPECT_EQ(msg.repeated_string(0), "Abcdef"); 89 msg.clear_repeated_string(); 90 91 msg.add_repeated_string("Asciiz"); 92 EXPECT_EQ(msg.repeated_string(0), "Asciiz"); 93 msg.clear_repeated_string(); 94 95 msg.add_repeated_string("Length delimited", 6); 96 EXPECT_EQ(msg.repeated_string(0), "Length"); 97 msg.clear_repeated_string(); 98 99 std::string value = "std::string value 1"; 100 msg.add_repeated_string(value); 101 EXPECT_EQ(msg.repeated_string(0), "std::string value 1"); 102 msg.clear_repeated_string(); 103 104 value = "std::string value 2"; 105 msg.add_repeated_string(std::cref(value)); 106 EXPECT_EQ(msg.repeated_string(0), "std::string value 2"); 107 msg.clear_repeated_string(); 108 109 value = "std::string value 3"; 110 msg.add_repeated_string(std::move(value)); 111 EXPECT_EQ(msg.repeated_string(0), "std::string value 3"); 112 msg.clear_repeated_string(); 113} 114 115 116namespace { 117template <typename T> 118static const internal::TcParseTableBase* GetTableIfAvailable(...) { 119 return nullptr; 120} 121 122template <typename T> 123static const internal::TcParseTableBase* GetTableIfAvailable( 124 decltype(internal::TcParser::GetTable<T>())) { 125 return internal::TcParser::GetTable<T>(); 126} 127} // namespace 128 129TEST(MESSAGE_TEST_NAME, TestRegressionInlinedStringAuxIdxMismatchOnFastParser) { 130 using Proto = UNITTEST::InlinedStringIdxRegressionProto; 131 132 auto* table = GetTableIfAvailable<Proto>(nullptr); 133 // Only test when TDP is on, and we have these fields inlined. 134 if (table != nullptr && 135 table->fast_entry(1)->target() == internal::TcParser::FastSiS1) { 136 // optional string str1 = 1; 137 // The aux_idx points to the inlined_string_idx and not the actual aux_idx. 138 EXPECT_EQ(table->fast_entry(1)->bits.aux_idx(), 1); 139 // optional InlinedStringIdxRegressionProto sub = 2; 140 EXPECT_EQ(table->fast_entry(2)->bits.aux_idx(), 1); 141 // optional string str2 = 3; 142 // The aux_idx points to the inlined_string_idx and not the actual aux_idx. 143 EXPECT_EQ(table->fast_entry(3)->bits.aux_idx(), 2); 144 // optional string str3 = 4; 145 // The aux_idx points to the inlined_string_idx and not the actual aux_idx. 146 EXPECT_EQ(table->fast_entry(0)->bits.aux_idx(), 3); 147 } 148 149 std::string encoded; 150 { 151 Proto proto; 152 // We use strings longer than SSO. 153 proto.set_str1(std::string(100, 'a')); 154 proto.set_str2(std::string(100, 'a')); 155 proto.set_str3(std::string(100, 'a')); 156 encoded = proto.SerializeAsString(); 157 } 158 Arena arena; 159 auto* proto = Arena::Create<Proto>(&arena); 160 // We don't alter donation here, so it works even if the idx are bad. 161 ASSERT_TRUE(proto->ParseFromString(encoded)); 162 // Now we alter donation bits. str2's bit (#2) will be off, but its aux_idx 163 // (#3) will point to a donated string. 164 proto = Arena::Create<Proto>(&arena); 165 proto->mutable_str1(); 166 proto->mutable_str2(); 167 proto->mutable_str3(); 168 // With the bug, this breaks the cleanup list, causing UB on arena 169 // destruction. 170 ASSERT_TRUE(proto->ParseFromString(encoded)); 171} 172 173} // namespace protobuf 174} // namespace google 175 176#include "google/protobuf/port_undef.inc" 177