aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2018-02-07 14:07:24 -0800
committerGuy Harris <guy@alum.mit.edu>2018-02-07 22:08:32 +0000
commit32923b94a140ecbe39a419e71d828c5a1cf9bc48 (patch)
treef68c922f80f9fdc13989382cedc5e64ea3eea850
parentc0a00038246ed89bae04554b84b20ad275b10e15 (diff)
Don't crash if an IDB resolution value is too high.
When dissecting an if_tsresol option in an IDB, calculate the resolution from the base and the offset. If the result overflows, mark it as an overflow; otherwise, mark it with the units for more values than 1 microsecond. Store the calculated resolution, which we initialize to the default of 1 microsecond. When displaying time stamps in blocks, use the calculated resolution, rather than re-calculating it. If it's 0, it means the resolution is too high, so don't calculate it and end up dividing by zero. Bug: 14402 Change-Id: Idc34ededb4f7250b3604b14d4468c32f6592793f Reviewed-on: https://code.wireshark.org/review/25673 Reviewed-by: Guy Harris <guy@alum.mit.edu>
-rw-r--r--epan/dissectors/file-pcapng.c121
1 files changed, 98 insertions, 23 deletions
diff --git a/epan/dissectors/file-pcapng.c b/epan/dissectors/file-pcapng.c
index 223162aab1..6d64ccd40c 100644
--- a/epan/dissectors/file-pcapng.c
+++ b/epan/dissectors/file-pcapng.c
@@ -197,7 +197,7 @@ struct info {
struct interface_description {
guint32 link_type;
- guint8 timestamp_resolution;
+ guint64 timestamp_resolution;
guint64 timestamp_offset;
};
@@ -553,6 +553,7 @@ static gint dissect_options(proto_tree *tree, packet_info *pinfo,
gint option_length;
gint hfj_pcapng_option_code;
const guint8 *str = NULL;
+ wmem_strbuf_t *strbuf;
address addr;
address addr_mask;
const value_string *vals = NULL;
@@ -744,6 +745,12 @@ static gint dissect_options(proto_tree *tree, packet_info *pinfo,
break;
case 0x0009:
+ {
+ guint32 base;
+ guint32 exponent;
+ guint32 i;
+ guint64 resolution;
+
if (option_length != 1) {
proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length);
offset += option_length;
@@ -754,16 +761,91 @@ static gint dissect_options(proto_tree *tree, packet_info *pinfo,
value.u8 = tvb_get_guint8(tvb, offset);
offset += 1;
+ if (value.u8 & 0x80) {
+ base = 2;
+ } else {
+ base = 10;
+ }
+ exponent = value.u8 & 0x7F;
+
+ strbuf = wmem_strbuf_new(wmem_packet_scope(), "");
+ wmem_strbuf_append_printf(strbuf, "%u^-%u", base, exponent);
+ resolution = 1;
+ for (i = 0; i < exponent; i += 1)
+ resolution *= base;
if (interface_description) {
- interface_description->timestamp_resolution = value.u8;
+ interface_description->timestamp_resolution = resolution;
}
+ switch (resolution) {
+
+ case 0:
+ /* Overflow */
+ wmem_strbuf_append(strbuf, " (overflow)");
+ break;
+
+ case 1:
+ wmem_strbuf_append(strbuf, " (seconds)");
+ break;
+
+ case 10:
+ wmem_strbuf_append(strbuf, " (.1 seconds)");
+ break;
- str = wmem_strdup_printf(wmem_packet_scope(), "%s^-%u%s",
- (value.u8 & 0x80) ? "2" : "10",
- (guint32) (value.u8 & 0x7F),
- (!(value.u8 & 0x80) && value.u8 == 6) ? " (microseconds)" : ((!(value.u8 & 0x80) && value.u8 == 9) ? " (nanoseconds)" : ""));
+ case 100:
+ wmem_strbuf_append(strbuf, " (.01 seconds)");
+ break;
+
+ case 1000:
+ wmem_strbuf_append(strbuf, " (milliseconds)");
+ break;
+
+ case 10000:
+ wmem_strbuf_append(strbuf, " (.1 milliseconds)");
+ break;
+ case 100000:
+ wmem_strbuf_append(strbuf, " (.01 milliseconds)");
+ break;
+
+ case 1000000:
+ wmem_strbuf_append(strbuf, " (microseconds)");
+ break;
+
+ case 10000000:
+ wmem_strbuf_append(strbuf, " (.1 microseconds)");
+ break;
+
+ case 100000000:
+ wmem_strbuf_append(strbuf, " (.01 microseconds)");
+ break;
+
+ case 1000000000:
+ wmem_strbuf_append(strbuf, " (nanoseconds)");
+ break;
+
+ case 10000000000:
+ wmem_strbuf_append(strbuf, " (.1 nanoseconds)");
+ break;
+
+ case 100000000000:
+ wmem_strbuf_append(strbuf, " (.01 nanoseconds)");
+ break;
+
+ case 1000000000000:
+ wmem_strbuf_append(strbuf, " (picoseconds)");
+ break;
+
+ case 10000000000000:
+ wmem_strbuf_append(strbuf, " (.1 picoseconds)");
+ break;
+
+ case 100000000000000:
+ wmem_strbuf_append(strbuf, " (.01 picoseconds)");
+ break;
+ }
+ str = wmem_strbuf_finalize(strbuf);
break;
+ }
case 0x000A:
if (option_length != 4) {
proto_tree_add_expert(option_tree, pinfo, &ei_invalid_option_length, tvb, offset, option_length);
@@ -1134,9 +1216,6 @@ pcapng_add_timestamp(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
struct interface_description *interface_description;
nstime_t timestamp;
guint64 ts;
- guint32 base;
- guint32 i_resolution;
- guint64 resolution = 1;
proto_item *ti;
interface_description = (struct interface_description *) wmem_array_index(info->interfaces, interface_id);
@@ -1144,24 +1223,19 @@ pcapng_add_timestamp(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
tvb_get_guint32(tvb, offset + 4, encoding);
ts += interface_description->timestamp_offset;
- if (interface_description->timestamp_resolution == 0)
- interface_description->timestamp_resolution = 6;
- if (interface_description->timestamp_resolution & 0x80) {
- base = 2;
+ if (interface_description->timestamp_resolution == 0) {
+ /* This overflowed, so we can't calculate the time stamp */
+ pinfo->presence_flags &= ~PINFO_HAS_TS;
} else {
- base = 10;
- }
+ timestamp.secs = (time_t)(ts / interface_description->timestamp_resolution);
+ timestamp.nsecs = (int)(ts - (ts / interface_description->timestamp_resolution) * interface_description->timestamp_resolution);
- for (i_resolution = 0; i_resolution < (guint32)(interface_description->timestamp_resolution & 0x7F); i_resolution += 1)
- resolution *= base;
- timestamp.secs = (time_t)(ts / resolution);
- timestamp.nsecs = (int)(ts - (ts / resolution) * resolution);
+ ti = proto_tree_add_time(tree, hf_pcapng_timestamp, tvb, offset, 8, &timestamp);
+ PROTO_ITEM_SET_GENERATED(ti);
- ti = proto_tree_add_time(tree, hf_pcapng_timestamp, tvb, offset, 8, &timestamp);
- PROTO_ITEM_SET_GENERATED(ti);
-
- pinfo->abs_ts = timestamp;
+ pinfo->abs_ts = timestamp;
+ }
}
}
@@ -1232,6 +1306,7 @@ static gint dissect_block(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
struct interface_description interface_description;
memset(&interface_description, 0, sizeof(struct interface_description));
+ interface_description.timestamp_resolution = 1000000; /* 1 microsecond resolution is the default */
proto_item_append_text(block_item, " %u", info->interface_number);
info->interface_number += 1;