diff --git a/cmake/external_libs/protobuf.cmake b/cmake/external_libs/protobuf.cmake index ab8a720c9ae..f8c0323b644 100644 --- a/cmake/external_libs/protobuf.cmake +++ b/cmake/external_libs/protobuf.cmake @@ -74,7 +74,8 @@ mindspore_add_pkg(protobuf CMAKE_PATH cmake/ CMAKE_OPTION -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -Dprotobuf_MSVC_STATIC_RUNTIME=OFF - PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch) + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2022-1941.patch) else() mindspore_add_pkg(protobuf VER 3.13.0 @@ -84,7 +85,8 @@ mindspore_add_pkg(protobuf MD5 ${MD5} CMAKE_PATH cmake/ CMAKE_OPTION -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release - PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch) + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2022-1941.patch) endif() include_directories(${protobuf_INC}) diff --git a/cmake/external_libs/protobuf_arm.cmake b/cmake/external_libs/protobuf_arm.cmake index 0055926da64..574ec6ba08f 100644 --- a/cmake/external_libs/protobuf_arm.cmake +++ b/cmake/external_libs/protobuf_arm.cmake @@ -64,7 +64,8 @@ if(APPLE) -Dprotobuf_WITH_ZLIB=OFF -DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} - PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch) + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2022-1941.patch) else() mindspore_add_pkg(protobuf_arm VER 3.13.0 @@ -79,7 +80,8 @@ else() -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -Dprotobuf_WITH_ZLIB=OFF - PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch) + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch + PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2022-1941.patch) endif() include_directories(${protobuf_arm_INC}) diff --git a/third_party/patch/protobuf/CVE-2022-1941.patch b/third_party/patch/protobuf/CVE-2022-1941.patch new file mode 100644 index 00000000000..7fb4c95e6ed --- /dev/null +++ b/third_party/patch/protobuf/CVE-2022-1941.patch @@ -0,0 +1,204 @@ +diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h +index 074784b96..aff050a81 100644 +--- a/src/google/protobuf/extension_set_inl.h ++++ b/src/google/protobuf/extension_set_inl.h +@@ -206,16 +206,22 @@ const char* ExtensionSet::ParseMessageSetItemTmpl( + 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_t 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 +247,26 @@ const char* ExtensionSet::ParseMessageSetItemTmpl( + 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) { +- ptr = ParseFieldMaybeLazily(static_cast(type_id) * 8 + 2, ptr, +- containing_type, metadata, ctx); ++ ++ 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 { +- int32 size = ReadSize(&ptr); ++ ++ std::string tmp; ++ int32_t 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 --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc +index 16edf2ce3..88fb09169 100644 +--- a/src/google/protobuf/wire_format.cc ++++ b/src/google/protobuf/wire_format.cc +@@ -659,9 +659,11 @@ struct WireFormat::MessageSetParser { + 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; ++ uint32_t type_id = 0; + 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 @@ struct WireFormat::MessageSetParser { + 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,18 @@ struct WireFormat::MessageSetParser { + 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) { +- int32 size = ReadSize(&ptr); ++ ++ if (state == State::kNoTag) { ++ int32_t 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 +728,12 @@ struct WireFormat::MessageSetParser { + ptr = WireFormat::_InternalParseAndMergeField( + msg, ptr, ctx, static_cast(type_id) * 8 + 2, reflection, + field); +- type_id = 0; ++ state = State::kDone; ++ } else { ++ int32_t 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 --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h +index c742fe869..4130bc531 100644 +--- a/src/google/protobuf/wire_format_lite.h ++++ b/src/google/protobuf/wire_format_lite.h +@@ -1798,6 +1798,9 @@ bool ParseMessageSetItemImpl(io::CodedInputStream* input, MS ms) { + // 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 @@ bool ParseMessageSetItemImpl(io::CodedInputStream* input, MS ms) { + 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 @@ bool ParseMessageSetItemImpl(io::CodedInputStream* input, MS ms) { + 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;