aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-mp4.c100
1 files changed, 71 insertions, 29 deletions
diff --git a/epan/dissectors/packet-mp4.c b/epan/dissectors/packet-mp4.c
index 1362fa7b6c..f8f4812f20 100644
--- a/epan/dissectors/packet-mp4.c
+++ b/epan/dissectors/packet-mp4.c
@@ -34,6 +34,7 @@
#include "config.h"
#include <glib.h>
+#include <epan/expert.h>
#include <epan/packet.h>
#define MAKE_TYPE_VAL(a, b, c, d) (a)<<24 | (b)<<16 | (c)<<8 | (d)
@@ -45,14 +46,19 @@ static gint ett_mp4_box = -1;
static int hf_mp4_box_size = -1;
static int hf_mp4_box_type_str = -1;
+static int hf_mp4_box_largesize = -1;
static int hf_mp4_full_box_ver = -1;
static int hf_mp4_ftyp_brand = -1;
static int hf_mp4_ftyp_ver = -1;
static int hf_mp4_ftyp_add_brand = -1;
static int hf_mp4_mfhd_seq_num = -1;
+static expert_field ei_mp4_box_too_large = EI_INIT;
+
/* a box must at least have a 32bit len field and a 32bit type */
-#define MIN_BOX_LEN 8
+#define MIN_BOX_SIZE 8
+/* an extended box has the first length field set to 1 */
+#define BOX_SIZE_EXTENDED 1
/* the box type is stored as four text characters
it is in network byte order and contains only printable characters
@@ -86,6 +92,7 @@ static int hf_mp4_mfhd_seq_num = -1;
#define BOX_TYPE_TFHD MAKE_TYPE_VAL('t', 'f', 'h', 'd')
#define BOX_TYPE_TRUN MAKE_TYPE_VAL('t', 'r', 'u', 'n')
#define BOX_TYPE_MDAT MAKE_TYPE_VAL('m', 'd', 'a', 't')
+#define BOX_TYPE_UDTA MAKE_TYPE_VAL('u', 'd', 't', 'a')
static const value_string box_types[] = {
@@ -116,14 +123,15 @@ static const value_string box_types[] = {
{ BOX_TYPE_TFHD, "Track Fragment Header Box" },
{ BOX_TYPE_TRUN, "Track Fragment Run Box" },
{ BOX_TYPE_MDAT, "Media Data Box" },
+ { BOX_TYPE_UDTA, "User Data Box" },
{ 0, NULL }
};
-static int
-dissect_mp4_mvhd_body(tvbuff_t *tvb, guint offset, guint len _U_,
+static gint
+dissect_mp4_mvhd_body(tvbuff_t *tvb, gint offset, gint len _U_,
packet_info *pinfo _U_, proto_tree *tree)
{
- guint offset_start;
+ gint offset_start;
offset_start = offset;
proto_tree_add_item(tree, hf_mp4_full_box_ver,
@@ -134,11 +142,11 @@ dissect_mp4_mvhd_body(tvbuff_t *tvb, guint offset, guint len _U_,
return offset-offset_start;
}
-static int
-dissect_mp4_mfhd_body(tvbuff_t *tvb, guint offset, guint len _U_,
+static gint
+dissect_mp4_mfhd_body(tvbuff_t *tvb, gint offset, gint len _U_,
packet_info *pinfo _U_, proto_tree *tree)
{
- guint offset_start;
+ gint offset_start;
offset_start = offset;
proto_tree_add_item(tree, hf_mp4_full_box_ver,
@@ -154,11 +162,11 @@ dissect_mp4_mfhd_body(tvbuff_t *tvb, guint offset, guint len _U_,
}
-static int
-dissect_mp4_ftyp_body(tvbuff_t *tvb, guint offset, guint len,
+static gint
+dissect_mp4_ftyp_body(tvbuff_t *tvb, gint offset, gint len,
packet_info *pinfo _U_, proto_tree *tree)
{
- guint offset_start;
+ gint offset_start;
offset_start = offset;
proto_tree_add_item(tree, hf_mp4_ftyp_brand,
@@ -177,54 +185,73 @@ dissect_mp4_ftyp_body(tvbuff_t *tvb, guint offset, guint len,
return offset-offset_start;
}
+/* dissect a box, return its (standard or extended) length or 0 for error */
static gint
dissect_mp4_box(guint32 parent_box_type _U_,
- tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+ tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree)
{
- guint offset_start;
- guint box_len;
+ gint offset_start;
+ guint64 box_size;
guint32 box_type;
guint8 *box_type_str;
- proto_item *pi;
+ proto_item *type_pi, *size_pi, *ext_size_pi = NULL;
proto_tree *box_tree;
gint ret;
+ gint body_size;
offset_start = offset;
/* the following mechanisms are not supported for now
- - extended size (size==1, largesize parameter)
- size==0, indicating that the box extends to the end of the file
- extended box types */
- box_len = tvb_get_ntohl(tvb, offset);
- if (box_len<MIN_BOX_LEN)
+ box_size = (guint64)tvb_get_ntohl(tvb, offset);
+ if (box_size!=BOX_SIZE_EXTENDED && box_size<MIN_BOX_SIZE)
return -1;
box_type = tvb_get_ntohl(tvb, offset+4);
box_type_str = tvb_get_ephemeral_string(tvb, offset+4, 4);
- pi = proto_tree_add_text(tree, tvb, offset, box_len, "%s (%s)",
+ type_pi = proto_tree_add_text(tree, tvb, offset, -1, "%s (%s)",
val_to_str_const(box_type, box_types, "unknown"), box_type_str);
- box_tree = proto_item_add_subtree(pi, ett_mp4_box);
+ box_tree = proto_item_add_subtree(type_pi, ett_mp4_box);
- proto_tree_add_item(box_tree, hf_mp4_box_size,
+ size_pi = proto_tree_add_item(box_tree, hf_mp4_box_size,
tvb, offset, 4, ENC_BIG_ENDIAN);
+ if (box_size==BOX_SIZE_EXTENDED)
+ proto_item_append_text(size_pi, " (actual size is in largesize)");
+
offset += 4;
proto_tree_add_item(box_tree, hf_mp4_box_type_str,
tvb, offset, 4, ENC_ASCII|ENC_NA);
offset += 4;
+ if (box_size==BOX_SIZE_EXTENDED) {
+ box_size = tvb_get_ntoh64(tvb, offset);
+ ext_size_pi = proto_tree_add_item(box_tree, hf_mp4_box_largesize,
+ tvb, offset, 8, ENC_BIG_ENDIAN);
+ offset += 8;
+ }
+
+ if (box_size > G_MAXINT) {
+ /* this should be ok for ext_size_pi==NULL */
+ expert_add_info(pinfo, ext_size_pi, &ei_mp4_box_too_large);
+ return -1;
+ }
+ proto_item_set_len(type_pi, (gint)box_size);
+ body_size = (gint)box_size - (offset-offset_start);
+
/* XXX - check parent box if supplied */
switch (box_type) {
case BOX_TYPE_FTYP:
- dissect_mp4_ftyp_body(tvb, offset, box_len-8, pinfo, box_tree);
+ dissect_mp4_ftyp_body(tvb, offset, body_size, pinfo, box_tree);
break;
case BOX_TYPE_MVHD:
- dissect_mp4_mvhd_body(tvb, offset, box_len-8, pinfo, box_tree);
+ dissect_mp4_mvhd_body(tvb, offset, body_size, pinfo, box_tree);
break;
case BOX_TYPE_MFHD:
- dissect_mp4_mfhd_body(tvb, offset, box_len-8, pinfo, box_tree);
+ dissect_mp4_mfhd_body(tvb, offset, body_size, pinfo, box_tree);
break;
case BOX_TYPE_MOOV:
case BOX_TYPE_MOOF:
@@ -235,7 +262,8 @@ dissect_mp4_box(guint32 parent_box_type _U_,
case BOX_TYPE_MINF:
case BOX_TYPE_MVEX:
case BOX_TYPE_DINF:
- while (offset-offset_start<box_len) {
+ case BOX_TYPE_UDTA:
+ while (offset-offset_start<(gint)box_size) {
ret = dissect_mp4_box(box_type, tvb, offset, pinfo, box_tree);
if (ret<=0)
break;
@@ -246,14 +274,14 @@ dissect_mp4_box(guint32 parent_box_type _U_,
break;
}
- return box_len;
+ return (gint)box_size;
}
static int
dissect_mp4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
- guint offset = 0;
+ gint offset = 0;
guint32 box_type;
proto_item *pi;
proto_tree *mp4_tree;
@@ -261,10 +289,11 @@ dissect_mp4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
/* to make sure that we have an mp4 file, we check that it starts with
a box of a known type
- this should be safe as long as the dissector is only called for
+ please note that we do not allow the first box to be an extended box
+ this detection should be safe as long as the dissector is only called for
the video/mp4 mime type
when we read mp4 files directly, we might need stricter checks here */
- if (tvb_reported_length(tvb)<MIN_BOX_LEN)
+ if (tvb_reported_length(tvb)<MIN_BOX_SIZE)
return 0;
box_type = tvb_get_ntohl(tvb, 4);
if (try_val_to_str(box_type, box_types) == NULL)
@@ -274,7 +303,7 @@ dissect_mp4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
col_clear(pinfo->cinfo, COL_INFO);
pi = proto_tree_add_protocol_format(tree, proto_mp4,
- tvb, 0, tvb_reported_length(tvb), "MP4");
+ tvb, 0, (gint)tvb_reported_length(tvb), "MP4");
mp4_tree = proto_item_add_subtree(pi, ett_mp4);
while (tvb_reported_length_remaining(tvb, offset) > 0) {
@@ -297,6 +326,9 @@ proto_register_mp4(void)
{ &hf_mp4_box_type_str,
{ "Box type", "mp4.box.type_str", FT_STRING, BASE_NONE,
NULL, 0, NULL, HFILL } },
+ { &hf_mp4_box_largesize,
+ { "Box size (largesize)", "mp4.box.largesize", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL } },
{ &hf_mp4_full_box_ver,
{ "Box version", "mp4.full_box.version", FT_UINT8, BASE_DEC,
NULL, 0, NULL, HFILL } },
@@ -319,10 +351,20 @@ proto_register_mp4(void)
&ett_mp4_box
};
+ static ei_register_info ei[] = {
+ { &ei_mp4_box_too_large,
+ { "mp4.box_too_large", PI_PROTOCOL, PI_WARN,
+ "box size too large, dissection of this box is not supported", EXPFILL }}
+ };
+
+ expert_module_t* expert_mp4;
+
proto_mp4 = proto_register_protocol("MP4 / ISOBMFF file format", "mp4", "mp4");
proto_register_field_array(proto_mp4, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+ expert_mp4 = expert_register_protocol(proto_mp4);
+ expert_register_field_array(expert_mp4, ei, array_length(ei));
}
void