Missing length-check in WireFormatLite::ReadMessageNoVirtual?
63 views
Skip to first unread message
Rawler
unread,
Oct 16, 2011, 11:22:14 AM10/16/11
Reply to author
Sign in to reply to author
Forward
Sign in to forward
Delete
You do not have permission to delete messages in this group
Copy link
Report message
Sign in to report message
Show original message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Protocol Buffers
Hi,
Trying out ProtoBuffers for streaming. I was hoping to exploit some
internal ProtoBuf-code for a streaming-protocol. The streaming-
protocol is basically the same as the message-internal protocol used
by ProtoBuf:
My attempt was to simply CodedInputStream::ReadTag() +
internal::WireFormatLite::ReadMessageNoVirtual() (which should AFAIU
read a length-prefixed message). However, I hit an error that I traced
down to ReadMessageNoVirtual returning true, even when the not the
entire LENGTH of the message was available on the CodedInputStream.
For my particular example, I'll probably rewrite it to read the outer-
message length externally in CodedInputStream and have the checks
there, but couldn't this be a failing validation for embedded streams
as well? I.E. one message of say, 40 bytes claiming to include a 60-
byte sub-message?
It seems to me that particular condition could be easily checked for
by extending ReadMessageNoVirtual with a check:
uint32 length;
if (!input->ReadVarint32(&length)) return false;
+ int bytesLeft = input->BytesUntilLimit();
+ if ((bytesLeft >= 0) && (length > bytesLeft)) return false;
if (!input->IncrementRecursionDepth()) return false;
io::CodedInputStream::Limit limit = input->PushLimit(length);
Just a thought.
Eyal Farago
unread,
Oct 20, 2011, 4:08:36 PM10/20/11
Reply to author
Sign in to reply to author
Forward
Sign in to forward
Delete
You do not have permission to delete messages in this group
Copy link
Report message
Sign in to report message
Show original message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to prot...@googlegroups.com
your claims does not match the code of both CodedInputStream::PushLimit and WireFormatLite::ReadMessageNoVirtual.
please notice that there's no guarantee that the stream reached EOF once this ReamMessageNoVirtual returns, as this message may be a part of another one, my guess is that you didn't push a limit into the coded stream before calling this method.
please let me know if this is helpful,
Etal.
Rawler
unread,
Oct 28, 2011, 12:55:41 PM10/28/11
Reply to author
Sign in to reply to author
Forward
Sign in to forward
Delete
You do not have permission to delete messages in this group
Copy link
Report message
Sign in to report message
Show original message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to prot...@googlegroups.com
Yes, you are correct. I did not push a limit before. It was non-obvious this was needed, which can of course be expected in ::internal, so no worries.
When I got the effect that the code wasn't detecting premature end of stream, I assumed it was due to the return value of input->PushLimit(length) not being checked in WireFormatLite::ReadMessageNoVirtual. The comment above the ConsumedEntireMessage-check in WireFormatLite::ReadMessageNoVirtual made me believe it was just related to the deprecated group-functionality:
// Make sure that parsing stopped when the limit was hit, not at an endgroup
// tag.
Anyways since the ConsumedEntireMessage DOES in fact cover this as well, I see no problems. Sorry for the confusion.