File CVE-2022-1941.patch of Package protobuf

--- protobuf-3.14.0/src/google/protobuf/extension_set_inl.h	2024-06-17 08:34:37.710063457 +0200
+++ protobuf-3.14.0/src/google/protobuf/extension_set_inl.h.org	2024-06-17 08:30:35.432690742 +0200
@@ -206,16 +206,21 @@
     const char* ptr, const Msg* containing_type,
     internal::InternalMetadata* metadata, internal::ParseContext* ctx) {
   std::string payload;
+  uint32_t type_id;
+  enum class State { kNoTag, kHasType, kHasPayload, kDone };
+  State state = State::kNoTag;
+
-  uint32 type_id = 0;
-  bool payload_read = false;
   while (!ctx->Done(&ptr)) {
     uint32 tag = static_cast<uint8>(*ptr++);
     if (tag == WireFormatLite::kMessageSetTypeIdTag) {
       uint64 tmp;
       ptr = ParseBigVarint(ptr, &tmp);
       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+      if (state == State::kNoTag) {
+        type_id = tmp;
+	state = State::kHasType;
+      } else if (state == State::kHasPayload) {
+        type_id = tmp;
-      type_id = tmp;
-      if (payload_read) {
         ExtensionInfo extension;
         bool was_packed_on_wire;
         if (!FindExtension(2, type_id, containing_type, ctx, &extension,
@@ -241,20 +236,24 @@
           GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
                                          tmp_ctx.EndedAtLimit());
         }
+        state = State::kDone;
-        type_id = 0;
       }
     } else if (tag == WireFormatLite::kMessageSetMessageTag) {
+      if (state == State::kHasType) {
-      if (type_id != 0) {
         ptr = ParseFieldMaybeLazily(static_cast<uint64>(type_id) * 8 + 2, ptr,
                                     containing_type, metadata, ctx);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        state = State::kDone;
-        type_id = 0;
       } else {
+        std::string tmp;
         int32 size = ReadSize(&ptr);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ptr = ctx->ReadString(ptr, size, &tmp);
-        ptr = ctx->ReadString(ptr, size, &payload);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        if (state == State::kNoTag) {
+          payload = std::move(tmp);
+          state = State::kHasPayload;
+        }
-        payload_read = true;
       }
     } else {
       ptr = ReadTag(ptr - 1, &tag);
--- protobuf-3.14.0/src/google/protobuf/wire_format.cc	2024-06-17 08:38:49.003336799 +0200
+++ protobuf-3.14.0/src/google/protobuf/wire_format.cc.org	2024-06-17 08:35:18.445621561 +0200
@@ -659,9 +659,11 @@
   const char* _InternalParse(const char* ptr, internal::ParseContext* ctx) {
     // Parse a MessageSetItem
     auto metadata = reflection->MutableInternalMetadata(msg);
+    enum class State { kNoTag, kHasType, kHasPayload, kDone };
+    State state = State::kNoTag;
+
     std::string payload;
     uint32 type_id = 0;
-    bool payload_read = false;
     while (!ctx->Done(&ptr)) {
       // We use 64 bit tags in order to allow typeid's that span the whole
       // range of 32 bit numbers.
@@ -670,8 +668,11 @@
         uint64 tmp;
         ptr = ParseBigVarint(ptr, &tmp);
         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        if (state == State::kNoTag) {
+          type_id = tmp;
+          state = State::kHasType;
+        } else if (state == State::kHasPayload) {
+          type_id = tmp;
-        type_id = tmp;
-        if (payload_read) {
           const FieldDescriptor* field;
           if (ctx->data().pool == nullptr) {
             field = reflection->FindKnownExtensionByNumber(type_id);
@@ -698,17 +693,17 @@
             GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
                                            tmp_ctx.EndedAtLimit());
           }
+          state = State::kDone;
-          type_id = 0;
         }
         continue;
       } else if (tag == WireFormatLite::kMessageSetMessageTag) {
+        if (state == State::kNoTag) {
-        if (type_id == 0) {
           int32 size = ReadSize(&ptr);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
           ptr = ctx->ReadString(ptr, size, &payload);
           GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          state = State::kHasPayload;
+        } else if (state == State::kHasType) {
-          payload_read = true;
-        } else {
           // We're now parsing the payload
           const FieldDescriptor* field = nullptr;
           if (descriptor->IsExtensionNumber(type_id)) {
@@ -722,7 +717,12 @@
           ptr = WireFormat::_InternalParseAndMergeField(
               msg, ptr, ctx, static_cast<uint64>(type_id) * 8 + 2, reflection,
               field);
+          state = State::kDone;
+        } else {
+          int32_t size = ReadSize(&ptr);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          ptr = ctx->Skip(ptr, size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
-          type_id = 0;
         }
       } else {
         // An unknown field in MessageSetItem.
--- protobuf-3.14.0/src/google/protobuf/wire_format_lite.h	2024-06-17 08:43:18.156450819 +0200
+++ protobuf-3.14.0/src/google/protobuf/wire_format_lite.h.org	2024-06-17 08:39:03.671177609 +0200
@@ -1798,6 +1798,9 @@
   // we can parse it later.
   std::string message_data;
 
+  enum class State { kNoTag, kHasType, kHasPayload, kDone };
+  State state = State::kNoTag;
+
   while (true) {
     const uint32 tag = input->ReadTagNoLastTag();
     if (tag == 0) return false;
@@ -1806,26 +1809,35 @@
       case WireFormatLite::kMessageSetTypeIdTag: {
         uint32 type_id;
         if (!input->ReadVarint32(&type_id)) return false;
-        last_type_id = type_id;
 
+        if (state == State::kNoTag) {
+          last_type_id = type_id;
+          state = State::kHasType;
+        } else if (state == State::kHasPayload) {
-        if (!message_data.empty()) {
           // We saw some message data before the type_id.  Have to parse it
           // now.
           io::CodedInputStream sub_input(
               reinterpret_cast<const uint8*>(message_data.data()),
               static_cast<int>(message_data.size()));
           sub_input.SetRecursionLimit(input->RecursionBudget());
+          if (!ms.ParseField(type_id, &sub_input)) {
-          if (!ms.ParseField(last_type_id, &sub_input)) {
             return false;
           }
           message_data.clear();
+          state = State::kDone;
         }
 
         break;
       }
 
       case WireFormatLite::kMessageSetMessageTag: {
+        if (state == State::kHasType) {
+          // Already saw type_id, so we can parse this directly.
+	  if (!ms.ParseField(last_type_id, input)) {
+            return false;
+	  }
+	  state = State::kDone;
+	} else if (state == State::kNoTag) {
-        if (last_type_id == 0) {
           // We haven't seen a type_id yet.  Append this data to message_data.
           uint32 length;
           if (!input->ReadVarint32(&length)) return false;
@@ -1836,11 +1824,9 @@
           auto ptr = reinterpret_cast<uint8*>(&message_data[0]);
           ptr = io::CodedOutputStream::WriteVarint32ToArray(length, ptr);
           if (!input->ReadRaw(ptr, length)) return false;
+          state = State::kHasPayload;
         } else {
+          if (!ms.SkipField(tag, input)) return false;
-          // Already saw type_id, so we can parse this directly.
-          if (!ms.ParseField(last_type_id, input)) {
-            return false;
-          }
         }
 
         break;
openSUSE Build Service is sponsored by