diff options
author | Martin Kaiser <wireshark@kaiser.cx> | 2013-01-08 22:18:52 +0000 |
---|---|---|
committer | Martin Kaiser <wireshark@kaiser.cx> | 2013-01-08 22:18:52 +0000 |
commit | d3b504f33126c32850462f9aee50e507d4c59d5c (patch) | |
tree | 1e4d370ee886e1a9a0793af0093f1c77bf06c173 /epan/reassemble.c | |
parent | 697514cd353cb9e8da4f8a72cc150fc38cc6fb98 (diff) | |
download | wireshark-d3b504f33126c32850462f9aee50e507d4c59d5c.tar.gz |
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
Diffstat (limited to 'epan/reassemble.c')
-rw-r--r-- | epan/reassemble.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/epan/reassemble.c b/epan/reassemble.c index abc84dffdc..54e20b10db 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -523,7 +523,9 @@ fragment_set_tot_len(const packet_info *pinfo, const guint32 id, GHashTable *fra const 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; @@ -531,13 +533,39 @@ fragment_set_tot_len(const packet_info *pinfo, const guint32 id, GHashTable *fra 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 |