diff options
author | Роман Донченко <dpb@corrigendum.ru> | 2021-09-24 20:17:51 +0300 |
---|---|---|
committer | Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2021-10-15 04:53:03 +0000 |
commit | e116110f0cbd21c48982feadf4864218cf020264 (patch) | |
tree | a325cbbbb8c8bcf7ca528906dbf060e145bb43a2 | |
parent | cc91fd51ffdb7ea04369836abda7661f3da00364 (diff) |
jpeg: add support for dissecting inline IFD values
In many cases, the "value offset" is actually the value itself.
Handle those cases correctly.
-rw-r--r-- | epan/dissectors/file-jpeg.c | 124 |
1 files changed, 112 insertions, 12 deletions
diff --git a/epan/dissectors/file-jpeg.c b/epan/dissectors/file-jpeg.c index ff447a6b99..e3bf018295 100644 --- a/epan/dissectors/file-jpeg.c +++ b/epan/dissectors/file-jpeg.c @@ -267,17 +267,28 @@ static const value_string vals_exif_tags[] = { { 0x0000, NULL } }; -static const value_string vals_exif_types[] = { - { 0x0001, "BYTE" }, - { 0x0002, "ASCII" }, - { 0x0003, "SHORT" }, - { 0x0004, "LONG" }, - { 0x0005, "RATIONAL" }, +enum { + EXIF_TYPE_BYTE = 0x0001, + EXIF_TYPE_ASCII = 0x0002, + EXIF_TYPE_SHORT = 0x0003, + EXIF_TYPE_LONG = 0x0004, + EXIF_TYPE_RATIONAL = 0x0005, /* 0x0006 */ - { 0x0007, "UNDEFINED" }, + EXIF_TYPE_UNDEFINED = 0x0007, /* 0x0008 */ - { 0x0009, "SLONG" }, - { 0x000A, "SRATIONAL" }, + EXIF_TYPE_SLONG = 0x0009, + EXIF_TYPE_SRATIONAL = 0x000A, +}; + +static const value_string vals_exif_types[] = { + { EXIF_TYPE_BYTE, "BYTE" }, + { EXIF_TYPE_ASCII, "ASCII" }, + { EXIF_TYPE_SHORT, "SHORT" }, + { EXIF_TYPE_LONG, "LONG" }, + { EXIF_TYPE_RATIONAL, "RATIONAL" }, + { EXIF_TYPE_UNDEFINED, "UNDEFINED" }, + { EXIF_TYPE_SLONG, "SLONG" }, + { EXIF_TYPE_SRATIONAL, "SRATIONAL" }, { 0x0000, NULL } }; @@ -343,6 +354,12 @@ static gint hf_ifd_tag = -1; static gint hf_ifd_type = -1; static gint hf_ifd_count = -1; static gint hf_ifd_offset = -1; +static gint hf_ifd_value_byte = -1; +static gint hf_ifd_value_ascii = -1; +static gint hf_ifd_value_short = -1; +static gint hf_ifd_value_long = -1; +static gint hf_ifd_value_undefined = -1; +static gint hf_ifd_value_slong = -1; /* Initialize the subtree pointers */ @@ -676,13 +693,48 @@ process_app1_segment(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, guint3 proto_tree_add_item(subtree_ifd, hf_ifd_num_fields, tvb, offset, 2, encoding); offset += 2; while (num_fields-- > 0) { + guint32 field_type, value_count, value_size; + gint value_hf; + proto_tree_add_item(subtree_ifd, hf_ifd_tag, tvb, offset, 2, encoding); offset += 2; - proto_tree_add_item(subtree_ifd, hf_ifd_type, tvb, offset, 2, encoding); + proto_tree_add_item_ret_uint(subtree_ifd, hf_ifd_type, tvb, offset, 2, encoding, &field_type); offset += 2; - proto_tree_add_item(subtree_ifd, hf_ifd_count, tvb, offset, 4, encoding); + proto_tree_add_item_ret_uint(subtree_ifd, hf_ifd_count, tvb, offset, 4, encoding, &value_count); offset += 4; - proto_tree_add_item(subtree_ifd, hf_ifd_offset, tvb, offset, 4, encoding); + + switch (field_type) { + case EXIF_TYPE_BYTE: + value_size = 1; value_hf = hf_ifd_value_byte; break; + case EXIF_TYPE_ASCII: + value_size = 1; value_hf = hf_ifd_value_ascii; break; + case EXIF_TYPE_SHORT: + value_size = 2; value_hf = hf_ifd_value_short; break; + case EXIF_TYPE_LONG: + value_size = 4; value_hf = hf_ifd_value_long; break; + case EXIF_TYPE_UNDEFINED: + value_size = 1; value_hf = hf_ifd_value_undefined; break; + case EXIF_TYPE_SLONG: + value_size = 4; value_hf = hf_ifd_value_slong; break; + /* We don't need special handling for RATIONAL/SRATIONAL, + since they never fit into the offset field, + so the default branch works for them. */ + default: + value_size = 0; break; + } + + if (value_size == 0 || 4 / value_size < value_count) { + proto_tree_add_item(subtree_ifd, hf_ifd_offset, tvb, offset, 4, encoding); + } else { + /* The value(s) are small enough to fit directly in the offset field. */ + + if (value_hf == hf_ifd_value_ascii || value_hf == hf_ifd_value_undefined) + proto_tree_add_item(subtree_ifd, value_hf, tvb, offset, value_count, ENC_NA); + else + for (guint32 i = 0; i < value_count; ++i) + proto_tree_add_item(subtree_ifd, value_hf, tvb, + offset + i * value_size, value_size, encoding); + } offset += 4; } /* @@ -1282,6 +1334,54 @@ proto_register_jfif(void) HFILL } }, + { &hf_ifd_value_byte, + { "Value", + "image-jfif.ifd.value_byte", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, + HFILL + } + }, + { &hf_ifd_value_ascii, + { "Value", + "image-jfif.ifd.value_ascii", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, + HFILL + } + }, + { &hf_ifd_value_short, + { "Value", + "image-jfif.ifd.value_short", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, + HFILL + } + }, + { &hf_ifd_value_long, + { "Value", + "image-jfif.ifd.value_long", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, + HFILL + } + }, + { &hf_ifd_value_undefined, + { "Value (raw)", + "image-jfif.ifd.value_undefined", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, + HFILL + } + }, + { &hf_ifd_value_slong, + { "Value", + "image-jfif.ifd.value_slong", + FT_INT32, BASE_DEC, NULL, 0x0, + NULL, + HFILL + } + }, }; /* Setup protocol subtree array */ |