From 4a75a8ccb65d76cfa69810cd94d7d11dea2bd8a6 Mon Sep 17 00:00:00 2001
From: Martin Kaiser <wireshark@kaiser.cx>
Date: Tue, 8 Jan 2013 22:18:52 +0000
Subject: [PATCH 2/6] From Evan: sanity checks before setting a packet's total
 length in fragment_set_tot_len()

(from me: check if fragments exist for the given id)

hopefully, this fixes #8111 and #8163 without causing troubles for other
protocols that use fragmentation and reassembly

svn path=/trunk/; revision=46999
---
 epan/reassemble.c |   38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/epan/reassemble.c b/epan/reassemble.c
index 73c41d2..113fa66 100644
--- a/epan/reassemble.c
+++ b/epan/reassemble.c
@@ -500,7 +500,9 @@ fragment_set_tot_len(packet_info *pinfo, guint32 id, GHashTable *fragment_table,
 			 guint32 tot_len)
 {
 	fragment_data *fd_head;
-	fragment_key key;
+	fragment_data *fd;
+	fragment_key   key;
+	guint32        max_offset = 0;
 
 	/* create key to search hash with */
 	key.src = pinfo->src;
@@ -508,13 +510,39 @@ fragment_set_tot_len(packet_info *pinfo, guint32 id, GHashTable *fragment_table,
 	key.id	= id;
 
 	fd_head = g_hash_table_lookup(fragment_table, &key);
+	if (!fd_head)
+		return;
 
-	if(fd_head){
-		fd_head->datalen = tot_len;
-		fd_head->flags |= FD_DATALEN_SET;
+	/* Verify that the length (or block sequence number) we're setting
+	 * doesn't conflict with values set by existing fragments.
+	 */
+	fd = fd_head;
+	if (fd_head->flags & FD_BLOCKSEQUENCE) {
+		while (fd) {
+			if (fd->offset > max_offset) {
+				max_offset = fd->offset;
+				DISSECTOR_ASSERT(max_offset <= tot_len);
+			}
+			fd = fd->next;
+		}
+	}
+	else {
+		while (fd) {
+			if (fd->offset + fd->len > max_offset) {
+				max_offset = fd->offset + fd->len;
+				DISSECTOR_ASSERT(max_offset <= tot_len);
+			}
+			fd = fd->next;
+		}
+	}
+
+	if (fd_head->flags & FD_DEFRAGMENTED) {
+		DISSECTOR_ASSERT(max_offset == tot_len);
 	}
 
-	return;
+	/* We got this far so the value is sane. */
+	fd_head->datalen = tot_len;
+	fd_head->flags |= FD_DATALEN_SET;
 }
 
 guint32
-- 
1.7.10.4

