Protobuf field malformed packet for last byte of 'repeated fixed32'

asked 2023-09-13 08:05:17 +0000

updated 2023-09-13 08:12:59 +0000

Hello, I ran into an issue that in case if my protobuf message has 'repeated fixed32' on the end, this field could not be parsed correctly with Wireshark protobuf dissector, it shows 'Malformed packet' for the last byte, despite it also has 4 bytes.

If it has only one byte - it shows 'Malformed packet' for this single byte. I don't have this problem if change 'repeated fixed32' to 'bytes', but it is not suitable for me as a workaround.

Do you have any advices or maybe it is a real bug?

I'm using Wireshark ver 4.0.7 for Windows 64 bit

e.g. I meet this in a simple messages like

message Response
{
    repeated fixed32             Id = 1;
}

or bigger messages like:

message My_Cmd
{
    fixed32               field1 = 1;
    fixed32               field2 = 2;
    fixed32               field3 = 3;
    fixed32               payloadSize = 4;
    repeated fixed32 payload = 5;
}
edit retag flag offensive close merge delete

Comments

Can you post a capture file showing the issue on a public share?

grahamb gravatar imagegrahamb ( 2023-09-13 08:29:40 +0000 )edit

I'm afraid not, I can't share this capture file :( There is an upstream protocol before protobuf and after pasring header, I pass tvb to the protobuf dissector which works fine except described issue.

Cookie_with_jam gravatar imageCookie_with_jam ( 2023-09-13 08:32:31 +0000 )edit

Well, I added some debug prints and looked for the exact packet way, after some debuging I found workaround to fix my issue:

wireshark\epan\dissectors\packet-protobuf.c --> dissect_packed_repeated_field_values --> for (offset = start; offset < max_offset; offset += value_size) cycle -->

    // protobuf_dissect_field_value(subtree, tvb, offset, value_size, pinfo, ti_field, field_type,
    //     (wire_type == PROTOBUF_WIRETYPE_FIXED32 ? tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN)
    //         : tvb_get_guint64(tvb, offset, ENC_LITTLE_ENDIAN)),
    //     prepend_text, field_desc, FALSE, dumper);

    protobuf_dissect_field_value(subtree, tvb, offset, value_size, pinfo, ti_field, field_type,
        tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN),
        prepend_text, field_desc, FALSE, dumper);

(something is wrong with this ternary operator)

Otherwise it never get into the function 'protobuf_dissect_field_value' (it never went after 'TEST7' point)

TEST3  dissect_packed_repeated_field_values, field_type = 7
TEST5  dissect_packed_repeated_field_values, PROTOBUF_TYPE_FIXED32
TEST7  before calling dissect_packed_repeated_field_values --> protobuf_dissect_field_value, length = 4, value_size = 4 , wire_type == PROTOBUF_WIRETYPE_FIXED32 = 0, tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN) = 299, offset = 2
TEST8  protobuf_dissect_field_value IN
TEST9  protobuf_dissect_field_value before main operations
TEST10  protobuf_dissect_field_value before switch type, value = 299, field_type = 7
TEST1 PROTOBUF_TYPE_FIXED32 protobuf_dissect_field_value, value = 299
TEST11 ...
(more)
Cookie_with_jam gravatar imageCookie_with_jam ( 2023-09-13 09:15:30 +0000 )edit

TEST7 before calling dissect_packed_repeated_field_values --> protobuf_dissect_field_value, length = 4, value_size = 4 , wire_type == PROTOBUF_WIRETYPE_FIXED32 = 0, wire_type = 2, PROTOBUF_WIRETYPE_FIXED32 = 5, tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN) = 299, offset = 2

Something with wire_type, it is not equal to PROTOBUF_WIRETYPE_FIXED32 at that point.

Cookie_with_jam gravatar imageCookie_with_jam ( 2023-09-13 09:26:17 +0000 )edit

@grahamb

https://protobuf.dev/programming-guid... --> it says that 'packed repeated fields' has wire type = 2 and fixed32 = 5, looks like this ternary operator is incorrect here:

(wire_type == PROTOBUF_WIRETYPE_FIXED32 ? tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN)
             : tvb_get_guint64(tvb, offset, ENC_LITTLE_ENDIAN))
Cookie_with_jam gravatar imageCookie_with_jam ( 2023-09-13 10:02:20 +0000 )edit