Skip to content

Malformed packed varints read beyond field length #3050

Open
@jrose-signal

Description

With the following protobuf

syntax = "proto3";

message RepeatedBug {
  bytes name = 1;
  repeated int32 values = 2;
  int32 id = 3;
  bytes should_never_appear = 4;
}

And the following (malformed) input:

12       // (tag 2 | Length Delimited)
01       // Length of 'values'
80       // *** Invalid truncated varint ***
18       // (tag 3 | Varint)
22       // ID value 34, which happens to be equivalent to (tag 4 | Length Delimited)
0A       // (tag 1 | Length Delimited), which happens to be equivalent to a length of 10
09       // Length of 'name'
313233   // UTF-8 Value "123456789"
343536
373839

(which can be generated by this convenient protoscope):

2:LEN {`80`}
3:VARINT 4:LEN
1:LEN {"123456789"}

Wire-Swift treats the 3:VARINT as part of the length-delimited field, and produces RepeatedBug(values: [3072], should_never_appear: "\u{09}123456789"), instead of rejecting the input as malformed. (Most instances of this bug would result in an unexpected error somewhere else, as the input stream has been desynchronized, but I managed to find this one that puns to a different "valid" structure instead.)

As far as I can tell the Kotlin implementation has the same bug, but I didn't test it. Similarly, both implementations seem vulnerable to the same issue when it's a nested message that's truncated, rather than a packed field. (It would not surprise me if these were covered by Google's protobuf conformance tests, but I didn't check that either.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions