* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "common/proto_util/proto_util.h"
#include "base/err_msg.h"
#include <fstream>
#include "mmpa/mmpa_api.h"
#include "common/compile_profiling/ge_call_wrapper.h"
#include "graph/def_types.h"
#include "framework/common/util.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "common/checker.h"
namespace ge {
namespace {
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::ZeroCopyInputStream;
* kProtoReadBytesLimit and kWarningThreshold are real arguments of CodedInputStream::SetTotalBytesLimit.
* In order to prevent integer overflow and excessive memory allocation during protobuf processing,
* it is necessary to limit the length of proto message (call SetTotalBytesLimit function).
* In theory, the minimum message length that causes an integer overflow is 512MB, and the default is 64MB.
* If the limit of warning_threshold is exceeded, the exception information will be printed in stderr.
* If such an exception is encountered during operation,
* the proto file can be divided into several small files or the limit value can be increased.
*/
constexpr int32_t kProtoReadBytesLimit = INT_MAX;
constexpr size_t kMaxErrorStrLength = 128U;
}
static bool ReadProtoFromCodedInputStream(CodedInputStream &coded_stream, google::protobuf::Message *const proto) {
if (proto == nullptr) {
GELOGE(FAILED, "incorrect parameter. nullptr == proto");
return false;
}
coded_stream.SetTotalBytesLimit(kProtoReadBytesLimit);
return proto->ParseFromCodedStream(&coded_stream);
}
bool ReadProtoFromArray(const void *const data, const int32_t size, google::protobuf::Message *const proto) {
if ((proto == nullptr) || (data == nullptr) || (size == 0)) {
GELOGE(FAILED, "incorrect parameter. proto is nullptr || data is nullptr || size is 0");
return false;
}
google::protobuf::io::CodedInputStream coded_stream(PtrToPtr<void, uint8_t>(const_cast<void *>(data)), size);
return ReadProtoFromCodedInputStream(coded_stream, proto);
}
bool ReadProtoFromText(const char_t *const file, google::protobuf::Message *const message) {
FuncPerfScope func_perf_scope(__FUNCTION__, file);
if ((file == nullptr) || (message == nullptr)) {
GELOGE(FAILED, "incorrect parameter. nullptr == file || nullptr == message");
return false;
}
const std::string real_path = RealPath(file);
GE_ASSERT_TRUE(!real_path.empty(), "[Do][RealPath]Path[%s]'s realpath is empty", file);
if (GetFileLength(real_path) == -1) {
GELOGE(FAILED, "file size not valid.");
return false;
}
std::ifstream fs(real_path.c_str(), std::ifstream::in);
if (!fs.is_open()) {
char_t err_buf[kMaxErrorStrLength + 1U] = {};
const auto err_msg = mmGetErrorFormatMessage(mmGetErrorCode(), &err_buf[0], kMaxErrorStrLength);
const std::string errmsg = FormatErrnoReason(mmGetErrorCode(), err_msg);
(void)REPORT_PREDEFINED_ERR_MSG(
"E13001",
std::vector<const char *>({"file", "errmsg"}),
std::vector<const char *>({real_path.c_str(), errmsg.c_str()})
);
GELOGE(ge::FAILED, "[Open][ProtoFile]Failed, real path %s, orginal file path %s",
real_path.c_str(), file);
return false;
}
google::protobuf::io::IstreamInputStream input(&fs);
const bool ret = google::protobuf::TextFormat::Parse(&input, message);
GE_ASSERT_TRUE(ret, "[Parse][File]Through [google::protobuf::TextFormat::Parse] failed, file %s", file);
fs.close();
return ret;
}
}