forked from osmocom/wireshark
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>
This commit is contained in:
parent
79eab8ca07
commit
129bdb5a16
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue