Ethereal-dev: [Ethereal-dev] Patch to packet-dns to prevent looping

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Graeme Hewson <ghewson@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 11 May 2002 18:18:49 +0100
With AXFR data, it's possible for packet-dns to go into a loop if the
TCP stream isn't desegmented or if a frame was dropped.  This patch adds
some checks and throws an exception if the data doesn't make sense.


Graeme Hewson
--- packet-dns.c.orig	Sun May  5 01:16:32 2002
+++ packet-dns.c	Sat May 11 11:39:02 2002
@@ -442,6 +442,11 @@
   int component_len;
   int indir_offset;
 
+  const int min_len = 1;	/* Minimum length of encoded name (for root) */
+	/* If we're about to return a value (probably negative) which is less
+	 * than the minimum length, we're looking at bad data and we're liable
+	 * to put the dissector into a loop.  Instead we throw an exception */
+
   maxname--;	/* reserve space for the trailing '\0' */
   for (;;) {
     component_len = tvb_get_guint8(tvb, offset);
@@ -498,12 +503,15 @@
 	strcpy(name, "<Unknown extended label>");
 	/* Parsing will propably fail from here on, since the */
 	/* label length is unknown... */
-	return offset - start_offset;
+	len = offset - start_offset;
+        if (len < min_len)
+          THROW(ReportedBoundsError);
+        return len;
       }
       break;
 
     case 0x80:
-      goto error;	/* error */
+      THROW(ReportedBoundsError);
 
     case 0xc0:
       /* Pointer. */
@@ -523,6 +531,8 @@
 	 looping. */
       if (chars_processed >= data_size) {
         strcpy(name, "<Name contains a pointer that loops>");
+        if (len < min_len)
+          THROW(ReportedBoundsError);
         return len;
       }
 
@@ -531,7 +541,6 @@
     }
   }
         
-error:
   *np = '\0';
   /* If "len" is negative, we haven't seen a pointer, and thus haven't
      set the length, so set it. */
@@ -540,6 +549,8 @@
   /* Zero-length name means "root server" */
   if (*name == '\0')
     strcpy(name, "<Root>");
+  if (len < min_len)
+    THROW(ReportedBoundsError);
   return len;
 }