fix CVE-2022-1941

This commit is contained in:
changzherui 2022-10-15 12:12:20 +08:00
parent 549a6fa81e
commit 6cbad3f58c
3 changed files with 212 additions and 4 deletions

View File

@ -74,7 +74,8 @@ mindspore_add_pkg(protobuf
CMAKE_PATH cmake/ CMAKE_PATH cmake/
CMAKE_OPTION -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release CMAKE_OPTION -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release
-Dprotobuf_MSVC_STATIC_RUNTIME=OFF -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() else()
mindspore_add_pkg(protobuf mindspore_add_pkg(protobuf
VER 3.13.0 VER 3.13.0
@ -84,7 +85,8 @@ mindspore_add_pkg(protobuf
MD5 ${MD5} MD5 ${MD5}
CMAKE_PATH cmake/ CMAKE_PATH cmake/
CMAKE_OPTION -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release 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() endif()
include_directories(${protobuf_INC}) include_directories(${protobuf_INC})

View File

@ -64,7 +64,8 @@ if(APPLE)
-Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_WITH_ZLIB=OFF
-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT} -DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}
-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -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() else()
mindspore_add_pkg(protobuf_arm mindspore_add_pkg(protobuf_arm
VER 3.13.0 VER 3.13.0
@ -79,7 +80,8 @@ else()
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dprotobuf_WITH_ZLIB=OFF -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() endif()
include_directories(${protobuf_arm_INC}) include_directories(${protobuf_arm_INC})

View File

@ -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<uint8>(*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<uint64>(type_id) * 8 + 2, ptr,
- containing_type, metadata, ctx);
+
+ if (state == State::kHasType) {
+ ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(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<uint64>(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<const uint8*>(message_data.data()),
static_cast<int>(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<uint8*>(&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;