aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2017-05-05 11:46:07 +0200
committerPeter Wu <peter@lekensteyn.nl>2017-05-11 14:52:44 +0000
commit129bdb5a164a6386c35ff387e9d8f0d3d6a12dbf (patch)
tree59ff6aa1de70c20dde394ab1c19ea9c92b3df7d1
parent79eab8ca070f978415126f85b0777ab4ab02f0a2 (diff)
dns: improve loop detection in label decompression
Previously the number of allowed pointers within a message is equal to the data in a tvb (16575 in one example). This is still expensive, so implement an alternative detection mechanism that looks for a direct self-loop and limits the total pointers to about 256. Bug: 13633 Change-Id: I803873e24ab170c7ef0b881d3bdc9dfd4014de97 Link: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1206 Reviewed-on: https://code.wireshark.org/review/21507 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Martin Kaiser <wireshark@kaiser.cx> Reviewed-by: Peter Wu <peter@lekensteyn.nl>
-rw-r--r--epan/dissectors/packet-dns.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/epan/dissectors/packet-dns.c b/epan/dissectors/packet-dns.c
index 373272ea41..ec02d306ac 100644
--- a/epan/dissectors/packet-dns.c
+++ b/epan/dissectors/packet-dns.c
@@ -1134,8 +1134,7 @@ expand_dns_name(tvbuff_t *tvb, int offset, int max_len, int dns_data_offset,
int start_offset = offset;
guchar *np;
int len = -1;
- int chars_processed = 0;
- int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
+ int pointers_count = 0;
int component_len;
int indir_offset;
int maxname;
@@ -1160,7 +1159,6 @@ expand_dns_name(tvbuff_t *tvb, int offset, int max_len, int dns_data_offset,
if (component_len == 0) {
break;
}
- chars_processed++;
switch (component_len & 0xc0) {
case 0x00:
@@ -1184,7 +1182,6 @@ expand_dns_name(tvbuff_t *tvb, int offset, int max_len, int dns_data_offset,
}
component_len--;
offset++;
- chars_processed++;
}
break;
@@ -1265,7 +1262,7 @@ expand_dns_name(tvbuff_t *tvb, int offset, int max_len, int dns_data_offset,
indir_offset = dns_data_offset +
(((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
offset++;
- chars_processed++;
+ pointers_count++;
/* If "len" is negative, we are still working on the original name,
not something pointed to by a pointer, and so we should set "len"
@@ -1273,10 +1270,11 @@ expand_dns_name(tvbuff_t *tvb, int offset, int max_len, int dns_data_offset,
if (len < 0) {
len = offset - start_offset;
}
- /* If we've looked at every character in the message, this pointer
- will make us look at some character again, which means we're
- looping. */
- if (chars_processed >= data_size) {
+ /*
+ * If we find a pointer to itself, it is a trivial loop. Otherwise if we
+ * processed a large number of pointers, assume an indirect loop.
+ */
+ if (indir_offset == offset + 2 || pointers_count > MAXDNAME/4) {
*name="<Name contains a pointer that loops>";
*name_len = (guint)strlen(*name);
if (len < min_len) {