jpeg: add support for dissecting inline IFD values

In many cases, the "value offset" is actually the value itself.
Handle those cases correctly.
This commit is contained in:
Роман Донченко 2021-09-24 20:17:51 +03:00 committed by Wireshark GitLab Utility
parent cc91fd51ff
commit e116110f0c
1 changed files with 112 additions and 12 deletions

View File

@ -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 */