protobuf 如何解析(大于64MB)超大报文

来源:互联网 发布:中国移动杭州数据 编辑:程序博客网 时间:2024/06/12 19:09

为了阻止恶意用户发送超大报文,而导致int溢出或服务端为解析报文而分配大量内存致使内存耗尽,protobuf规定int溢出的默认值阈值是64MB(理论是512MB)。因此,当调用ParseFromString(str)方法时,若str的长度>64MB,返回会返回失败。

注意到protobuf中包含这样一个函数:void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold),其中有解释如下:

这里写图片描述

解决方法

    LoadDBDataProtobuf::DocumentData pDocumentData; // LoadDBDataProtobuf::DocumentData为应用程序自定义的protobuf结构    ::google::protobuf::io::ArrayInputStream input(strData.data(), strData.size()); //std::string strData,是响应报文中mTOM构造出而来    ::google::protobuf::io::CodedInputStream decoder(&input);    decoder.SetTotalBytesLimit(1024 * 1024 * 1024, 64 * 1024 * 1024);    bool success = pDocumentData.ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();    if (!success)    {        SvrResponse::instance()->setCurrentThreadReturnCode(eOtherErr, QString("protoBuf序列化出错"));        return false;    }

ZeroCopyInputStream 类

class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream{ public:    // 构造一个InputStream,返回data所指向的字节数组    // 若指定了block_size,则每次调用Next()返回不超过指定大小的数据块;否则,返回整个字节数组    ArrayInputStream(const void* data, int size, int block_size = -1);    ~ArrayInputStream();    // implements ZeroCopyInputStream ----------------------------------     bool Next(const void** data, int* size);    ......  }

CodedInputStream 类

class LIBPROTOBUF_EXPORT CodedInputStream {public:    // 构造一个从ZeroCopyInputStream读取数据的CodedInputStream对象    explicit CodedInputStream(ZeroCopyInputStream* input);    // total_bytes_limit:可读取的最大报文字节数    // warning_threshold:发出警告的最大报文字节数,若不为-1,则当读取的字节数超过warning_threshold后,stderr将会打印一条警告消息。    void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold)    // 当对报文进行解析后,必须调用ConsumedEntireMessage,以进一步判断报文是否被以正确方式读取完毕。    bool ConsumedEntireMessage()......}

ParseFromCodedStream(io::CodedInputStream* input)

功能:从给定的CodedInputStream对象中解析数据。
返回值:false,CodedInputStream格式错误或其他读错误。

原创粉丝点击