aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorРоман Донченко <dpb@corrigendum.ru>2021-09-24 20:17:51 +0300
committerWireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2021-10-15 04:53:03 +0000
commite116110f0cbd21c48982feadf4864218cf020264 (patch)
treea325cbbbb8c8bcf7ca528906dbf060e145bb43a2
parentcc91fd51ffdb7ea04369836abda7661f3da00364 (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.c124
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 */