11

当我尝试解析大消息时,我收到此警告和错误。我知道默认限制超过 64MB。我现在正在使用 message.ParseFromIstream。有谁知道可以访问 CodedInputStream 对象来调用 SetTotalBytesLimit 函数?或任何其他方式来解决这个问题?

读取危险的大协议消息。如果消息大于 67108864 字节,则出于安全原因将停止解析。要增加限制(或禁用这些警告),请参阅 google/protobuf/io/coded_stream.h 中的 CodedInputStream::SetTotalBytesLimit()。

4

3 回答 3

12

正确的解决方法:您应该尝试限制 protobuf 消息的大小。请参阅: https ://developers.google.com/protocol-buffers/docs/techniques#streaming

又快又脏(不推荐阅读)的做法:在protobuf库源码的文件coded_stream.h中,修改and的值kDefaultTotalBytesLimitkDefaultTotalBytesWarningThreshold重新编译,重新安装。

于 2012-12-12T22:31:17.850 回答
9

只需阅读错误已经告诉您的函数的文档,就可以回答这个问题:

提示:如果您正在阅读本文是因为您的程序正在打印有关危险的大协议消息的警告,那么您可能会对下一步做什么感到困惑。最好的选择是更改您的设计,以便不需要过大的消息。例如,尝试将文件格式设计为包含许多小消息而不是单个大消息。如果这是不可行的,您将需要增加限制。但是,您的代码可能永远不会构造可以设置限制的 CodedInputStream。您可能通过调用 Message::ParseFromString() 之类的方法来解析消息。在这种情况下,您将需要更改您的代码以构造某种 ZeroCopyInputStream(例如 ArrayInputStream),围绕它构造一个 CodedInputStream,然后改为调用 Message::ParseFromCodedStream()。然后你可以调整限制。是的,这是更多的工作,但你正在做一些不寻常的事情。

来源

此外,遵循建议的第一部分并重新设计应用程序可能是一个非常好的主意。

于 2012-12-12T22:17:32.797 回答
4

下面是来自代码( )的注释,google/protobuf/io/coded_stream.h它为那些想知道他们所谈论的安全原因的人设置消息限制。就我而言,我无法修改我的应用程序的工作方式,因此我必须更改此限制。

这个线程很老了,但是最近深度学习受到了关注,并且库 Caffe 使用了 Protobuf,所以也许更多的人会偶然发现这个。我必须用 Caffe 做神经网络的东西,即使是最小的批量,整个网络也占用了很多内存。

  // Total Bytes Limit -----------------------------------------------
  // To prevent malicious users from sending excessively large messages
  // and causing integer overflows or memory exhaustion, CodedInputStream
  // imposes a hard limit on the total number of bytes it will read.

  // Sets the maximum number of bytes that this CodedInputStream will read
  // before refusing to continue.  To prevent integer overflows in the
  // protocol buffers implementation, as well as to prevent servers from
  // allocating enormous amounts of memory to hold parsed messages, the
  // maximum message length should be limited to the shortest length that
  // will not harm usability.  The theoretical shortest message that could
  // cause integer overflows is 512MB.  The default limit is 64MB.  Apps
  // should set shorter limits if possible.  If warning_threshold is not -1,
  // a warning will be printed to stderr after warning_threshold bytes are
  // read.  For backwards compatibility all negative values get squashed to -1,
  // as other negative values might have special internal meanings.
  // An error will always be printed to stderr if the limit is reached.
  //
  // This is unrelated to PushLimit()/PopLimit().
  //
  // Hint:  If you are reading this because your program is printing a
  //   warning about dangerously large protocol messages, you may be
  //   confused about what to do next.  The best option is to change your
  //   design such that excessively large messages are not necessary.
  //   For example, try to design file formats to consist of many small
  //   messages rather than a single large one.  If this is infeasible,
  //   you will need to increase the limit.  Chances are, though, that
  //   your code never constructs a CodedInputStream on which the limit
  //   can be set.  You probably parse messages by calling things like
  //   Message::ParseFromString().  In this case, you will need to change
  //   your code to instead construct some sort of ZeroCopyInputStream
  //   (e.g. an ArrayInputStream), construct a CodedInputStream around
  //   that, then call Message::ParseFromCodedStream() instead.  Then
  //   you can adjust the limit.  Yes, it's more work, but you're doing
  //   something unusual.
于 2016-02-03T09:00:54.813 回答