diff --git a/SPECS/pytorch/CVE-2022-1941.patch b/SPECS/pytorch/CVE-2022-1941.patch new file mode 100644 index 00000000000..cd961581a22 --- /dev/null +++ b/SPECS/pytorch/CVE-2022-1941.patch @@ -0,0 +1,352 @@ +# Patch generated by Archana Choudhary +# Source: https://github.com/protocolbuffers/protobuf/commit/55815e423bb82cc828836bbd60c79c1f9a195763 + +diff --color -ruN a/third_party/protobuf/src/google/protobuf/extension_set_inl.h b/third_party/protobuf/src/google/protobuf/extension_set_inl.h +--- a/third_party/protobuf/src/google/protobuf/extension_set_inl.h 2024-03-27 22:28:55.000000000 +0000 ++++ b/third_party/protobuf/src/google/protobuf/extension_set_inl.h 2024-09-18 11:49:16.390834276 +0000 +@@ -206,16 +206,21 @@ + const char* ptr, const Msg* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + std::string payload; +- uint32 type_id = 0; +- bool payload_read = false; ++ uint32 type_id; ++ enum class State { kNoTag, kHasType, kHasPayload, kDone }; ++ State state = State::kNoTag; ++ + while (!ctx->Done(&ptr)) { + uint32 tag = static_cast(*ptr++); + if (tag == WireFormatLite::kMessageSetTypeIdTag) { + uint64 tmp; + ptr = ParseBigVarint(ptr, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); +- type_id = tmp; +- if (payload_read) { ++ if (state == State::kNoTag) { ++ type_id = tmp; ++ state = State::kHasType; ++ } else if (state == State::kHasPayload) { ++ type_id = tmp; + ExtensionInfo extension; + bool was_packed_on_wire; + if (!FindExtension(2, type_id, containing_type, ctx, &extension, +@@ -241,20 +246,24 @@ + GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) && + tmp_ctx.EndedAtLimit()); + } +- type_id = 0; ++ state = State::kDone; + } + } else if (tag == WireFormatLite::kMessageSetMessageTag) { +- if (type_id != 0) { ++ if (state == State::kHasType) { + ptr = ParseFieldMaybeLazily(static_cast(type_id) * 8 + 2, ptr, + containing_type, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); +- type_id = 0; ++ state = State::kDone; + } else { ++ std::string tmp; + int32 size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); +- ptr = ctx->ReadString(ptr, size, &payload); ++ ptr = ctx->ReadString(ptr, size, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); +- payload_read = true; ++ if (state == State::kNoTag) { ++ payload = std::move(tmp); ++ state = State::kHasPayload; ++ } + } + } else { + ptr = ReadTag(ptr - 1, &tag); +diff --color -ruN a/third_party/protobuf/src/google/protobuf/wire_format.cc b/third_party/protobuf/src/google/protobuf/wire_format.cc +--- a/third_party/protobuf/src/google/protobuf/wire_format.cc 2024-03-27 22:28:55.000000000 +0000 ++++ b/third_party/protobuf/src/google/protobuf/wire_format.cc 2024-09-18 11:49:16.390834276 +0000 +@@ -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 +672,11 @@ + uint64 tmp; + ptr = ParseBigVarint(ptr, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); +- type_id = tmp; +- if (payload_read) { ++ if (state == State::kNoTag) { ++ type_id = tmp; ++ state = State::kHasType; ++ } else if (state == State::kHasPayload) { ++ type_id = tmp; + const FieldDescriptor* field; + if (ctx->data().pool == nullptr) { + field = reflection->FindKnownExtensionByNumber(type_id); +@@ -698,17 +703,17 @@ + GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) && + tmp_ctx.EndedAtLimit()); + } +- type_id = 0; ++ state = State::kDone; + } + continue; + } else if (tag == WireFormatLite::kMessageSetMessageTag) { +- if (type_id == 0) { ++ if (state == State::kNoTag) { + int32 size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ptr = ctx->ReadString(ptr, size, &payload); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); +- payload_read = true; +- } else { ++ state = State::kHasPayload; ++ } else if (state == State::kHasType) { + // We're now parsing the payload + const FieldDescriptor* field = nullptr; + if (descriptor->IsExtensionNumber(type_id)) { +@@ -722,7 +727,12 @@ + ptr = WireFormat::_InternalParseAndMergeField( + msg, ptr, ctx, static_cast(type_id) * 8 + 2, reflection, + field); +- type_id = 0; ++ state = State::kDone; ++ } else { ++ int32 size = ReadSize(&ptr); ++ GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); ++ ptr = ctx->Skip(ptr, size); ++ GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + } else { + // An unknown field in MessageSetItem. +diff --color -ruN a/third_party/protobuf/src/google/protobuf/wire_format_lite.h b/third_party/protobuf/src/google/protobuf/wire_format_lite.h +--- a/third_party/protobuf/src/google/protobuf/wire_format_lite.h 2024-03-27 22:28:55.000000000 +0000 ++++ b/third_party/protobuf/src/google/protobuf/wire_format_lite.h 2024-09-18 11:49:16.390834276 +0000 +@@ -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,34 @@ + case WireFormatLite::kMessageSetTypeIdTag: { + uint32 type_id; + if (!input->ReadVarint32(&type_id)) return false; +- last_type_id = type_id; +- +- if (!message_data.empty()) { ++ if (state == State::kNoTag) { ++ last_type_id = type_id; ++ state = State::kHasType; ++ } else if (state == State::kHasPayload) { + // We saw some message data before the type_id. Have to parse it + // now. + io::CodedInputStream sub_input( + reinterpret_cast(message_data.data()), + static_cast(message_data.size())); + sub_input.SetRecursionLimit(input->RecursionBudget()); +- if (!ms.ParseField(last_type_id, &sub_input)) { ++ if (!ms.ParseField(type_id, &sub_input)) { + return false; + } + message_data.clear(); ++ state = State::kDone; + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { +- if (last_type_id == 0) { ++ 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) { + // We haven't seen a type_id yet. Append this data to message_data. + uint32 length; + if (!input->ReadVarint32(&length)) return false; +@@ -1836,11 +1847,9 @@ + auto ptr = reinterpret_cast(&message_data[0]); + ptr = io::CodedOutputStream::WriteVarint32ToArray(length, ptr); + if (!input->ReadRaw(ptr, length)) return false; ++ state = State::kHasPayload; + } else { +- // Already saw type_id, so we can parse this directly. +- if (!ms.ParseField(last_type_id, input)) { +- return false; +- } ++ if (!ms.SkipField(tag, input)) return false; + } + + break; +diff --color -ruN a/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc b/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc +--- a/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc 2024-03-27 22:28:55.000000000 +0000 ++++ b/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc 2024-09-18 11:49:16.394834273 +0000 +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -585,30 +586,56 @@ + EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString()); + } + +-TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { ++namespace { ++std::string BuildMessageSetItemStart() { + std::string data; + { +- unittest::TestMessageSetExtension1 message; +- message.set_i(123); +- // Build a MessageSet manually with its message content put before its +- // type_id. + io::StringOutputStream output_stream(&data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag); ++ } ++ return data; ++} ++std::string BuildMessageSetItemEnd() { ++ std::string data; ++ { ++ io::StringOutputStream output_stream(&data); ++ io::CodedOutputStream coded_output(&output_stream); ++ coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag); ++ } ++ return data; ++} ++std::string BuildMessageSetTestExtension1(int value = 123) { ++ std::string data; ++ { ++ unittest::TestMessageSetExtension1 message; ++ message.set_i(value); ++ io::StringOutputStream output_stream(&data); ++ io::CodedOutputStream coded_output(&output_stream); + // Write the message content first. + WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + &coded_output); + coded_output.WriteVarint32(message.ByteSizeLong()); + message.SerializeWithCachedSizes(&coded_output); +- // Write the type id. +- uint32 type_id = message.GetDescriptor()->extension(0)->number(); ++ } ++ return data; ++} ++std::string BuildMessageSetItemTypeId(int extension_number) { ++ std::string data; ++ { ++ io::StringOutputStream output_stream(&data); ++ io::CodedOutputStream coded_output(&output_stream); + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, +- type_id, &coded_output); +- coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag); ++ extension_number, &coded_output); + } ++ return data; ++} ++void ValidateTestMessageSet(const std::string& test_case, ++ const std::string& data) { ++ SCOPED_TRACE(test_case); + { +- proto2_wireformat_unittest::TestMessageSet message_set; ++ ::proto2_wireformat_unittest::TestMessageSet message_set; + ASSERT_TRUE(message_set.ParseFromString(data)); + + EXPECT_EQ(123, +@@ -616,10 +643,15 @@ + .GetExtension( + unittest::TestMessageSetExtension1::message_set_extension) + .i()); ++ ++ // Make sure it does not contain anything else. ++ message_set.ClearExtension( ++ unittest::TestMessageSetExtension1::message_set_extension); ++ EXPECT_EQ(message_set.SerializeAsString(), ""); + } + { + // Test parse the message via Reflection. +- proto2_wireformat_unittest::TestMessageSet message_set; ++ ::proto2_wireformat_unittest::TestMessageSet message_set; + io::CodedInputStream input(reinterpret_cast(data.data()), + data.size()); + EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set)); +@@ -631,6 +663,61 @@ + unittest::TestMessageSetExtension1::message_set_extension) + .i()); + } ++ { ++ // Test parse the message via DynamicMessage. ++ DynamicMessageFactory factory; ++ std::unique_ptr msg( ++ factory ++ .GetPrototype( ++ ::proto2_wireformat_unittest::TestMessageSet::descriptor()) ++ ->New()); ++ msg->ParseFromString(data); ++ auto* reflection = msg->GetReflection(); ++ std::vector fields; ++ reflection->ListFields(*msg, &fields); ++ ASSERT_EQ(fields.size(), 1); ++ const auto& sub = reflection->GetMessage(*msg, fields[0]); ++ reflection = sub.GetReflection(); ++ EXPECT_EQ(123, reflection->GetInt32( ++ sub, sub.GetDescriptor()->FindFieldByName("i"))); ++ } ++} ++} // namespace ++ ++TEST(WireFormatTest, ParseMessageSetWithAnyTagOrder) { ++ std::string start = BuildMessageSetItemStart(); ++ std::string end = BuildMessageSetItemEnd(); ++ std::string id = BuildMessageSetItemTypeId( ++ unittest::TestMessageSetExtension1::descriptor()->extension(0)->number()); ++ std::string message = BuildMessageSetTestExtension1(); ++ ++ ValidateTestMessageSet("id + message", start + id + message + end); ++ ValidateTestMessageSet("message + id", start + message + id + end); ++} ++ ++TEST(WireFormatTest, ParseMessageSetWithDuplicateTags) { ++ std::string start = BuildMessageSetItemStart(); ++ std::string end = BuildMessageSetItemEnd(); ++ std::string id = BuildMessageSetItemTypeId( ++ unittest::TestMessageSetExtension1::descriptor()->extension(0)->number()); ++ std::string other_id = BuildMessageSetItemTypeId(123456); ++ std::string message = BuildMessageSetTestExtension1(); ++ std::string other_message = BuildMessageSetTestExtension1(321); ++ ++ // Double id ++ ValidateTestMessageSet("id + other_id + message", ++ start + id + other_id + message + end); ++ ValidateTestMessageSet("id + message + other_id", ++ start + id + message + other_id + end); ++ ValidateTestMessageSet("message + id + other_id", ++ start + message + id + other_id + end); ++ // Double message ++ ValidateTestMessageSet("id + message + other_message", ++ start + id + message + other_message + end); ++ ValidateTestMessageSet("message + id + other_message", ++ start + message + id + other_message + end); ++ ValidateTestMessageSet("message + other_message + id", ++ start + message + other_message + id + end); + } + + void SerializeReverseOrder( diff --git a/SPECS/pytorch/pytorch.spec b/SPECS/pytorch/pytorch.spec index 45caf0a87f4..e7713f8c653 100644 --- a/SPECS/pytorch/pytorch.spec +++ b/SPECS/pytorch/pytorch.spec @@ -2,7 +2,7 @@ Summary: Tensors and Dynamic neural networks in Python with strong GPU acceleration. Name: pytorch Version: 2.0.0 -Release: 6%{?dist} +Release: 7%{?dist} License: BSD-3-Clause Vendor: Microsoft Corporation Distribution: Mariner @@ -16,6 +16,7 @@ Patch1: CVE-2024-31583.patch Patch2: CVE-2024-27319.patch Patch3: CVE-2024-31584.patch Patch4: CVE-2024-27318.patch +Patch5: CVE-2022-1941.patch BuildRequires: cmake BuildRequires: gcc @@ -88,6 +89,9 @@ cp -arf docs %{buildroot}/%{_pkgdocdir} %{_docdir}/* %changelog +* Wed Sep 18 2024 Archana Choudhary - 2.0.0-7 +- patch CVE-2022-1941 + * Wed May 15 2024 Sumedh Sharma - 2.0.0-6 - patch CVE-2024-27318