【发布时间】:2019-01-04 20:22:47
【问题描述】:
我发现了一个关于协议缓冲区的有趣问题。如果您有两条相似的消息,则可以使用 C++ API 或命令行来解析一条,就好像它是另一条一样。
limited documentation for ParseFromString 没有提到它不需要消耗所有字符串,如果不消耗也不会失败。
我曾预计 ParseFromString 无法解析 A 类型的消息,如果它与 B 类型的消息一起呈现。毕竟该消息包含额外的数据。然而,这种情况并非如此。 一个示例脚本演示了这个问题:
#!/bin/sh
cat - >./foobar.proto <<EOF
syntax = "proto3";
package demo;
message A
{
uint64 foo = 1;
};
enum flagx {
y = 0;
z = 1;
}
message B {
uint64 foolish = 1;
flagx bar = 2;
};
EOF
cat - >./mess.B.in.txtfmt <<EOF
foolish: 10
bar: y
EOF
cat - >./mess.in.txtfmt <<EOF
foo: 10
EOF
protoc --encode=demo.A foobar.proto <./mess.A.in.txtfmt >./mess.A.proto
protoc --encode=demo.B foobar.proto <./mess.B.in.txtfmt >./mess.B.proto
protoc --decode=demo.A foobar.proto >./mess.out.txtfmt <./mess.B.proto
echo "in: "
cat mess.B.in.txtfmt
echo "out: "
cat mess.out.txtfmt
echo "xxd mess.A.proto:"
xxd mess.A.proto
echo "xxd mess.B.proto:"
xxd mess.B.proto
输出是:
in:
foolish: 10
bar: 20
out:
foo: 10
xxd mess.A.proto:
00000000: 080a
xxd mess.B.proto:
00000000: 080a
所以消息 A 和 B 的二进制消息是相同的。
如果您更改协议,以便使用另一个 varint (uint64) 而不是枚举,您将获得不同的二进制消息,但 ParseFromString 仍然会成功地将较长的消息解析为较短的消息。
为了真正混淆事物,它似乎也能够将较短的消息解析为较长的消息。
这是错误还是功能?
【问题讨论】:
标签: c++ protocol-buffers