diff options
author | Bill Meier <wmeier@newsguy.com> | 2008-05-21 16:53:07 +0000 |
---|---|---|
committer | Bill Meier <wmeier@newsguy.com> | 2008-05-21 16:53:07 +0000 |
commit | bf018e2a96c5ae82a029c537b7157697ef95c905 (patch) | |
tree | e91cd01d22726c2218304a49536a5ca4a1133b10 /epan/reassemble.c | |
parent | ad761ed3fdc3ab30dbed6f5676c8ffcdc0b7eb2b (diff) | |
download | wireshark-bf018e2a96c5ae82a029c537b7157697ef95c905.tar.gz wireshark-bf018e2a96c5ae82a029c537b7157697ef95c905.tar.bz2 wireshark-bf018e2a96c5ae82a029c537b7157697ef95c905.zip |
Fix for bug #2470; (don't memcmp past end of g_malloc'd buffer).
svn path=/trunk/; revision=25343
Diffstat (limited to 'epan/reassemble.c')
-rw-r--r-- | epan/reassemble.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/epan/reassemble.c b/epan/reassemble.c index 9e678f95dc..b61ac02e5d 100644 --- a/epan/reassemble.c +++ b/epan/reassemble.c @@ -794,22 +794,19 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, int offset, /* add all data fragments */ for (dfpos=0,fd_i=fd_head;fd_i;fd_i=fd_i->next) { if (fd_i->len) { - if (fd_i->offset < dfpos) { - fd_i->flags |= FD_OVERLAP; - fd_head->flags |= FD_OVERLAP; - if ( memcmp(fd_head->data+fd_i->offset, - fd_i->data, - MIN(fd_i->len,(dfpos-fd_i->offset)) - ) ){ - fd_i->flags |= FD_OVERLAPCONFLICT; - fd_head->flags |= FD_OVERLAPCONFLICT; - } - } /* dfpos is always >= than fd_i->offset */ /* No gaps can exist here, max_loop(above) does this */ /* XXX - true? Can we get fd_i->offset+fd-i->len */ /* overflowing, for example? */ - if( fd_i->offset+fd_i->len > dfpos ) { + /* Actually: there is at least one pathological case wherein there can be fragments + on the list which are for offsets greater than max (i.e.: following a gap after max). + (Something related to "defrag_until_fin" where the fin packet has an offset less than + the highestfragment offset seen ? [Seen from a fuzz-test: bug #2470]). + So: the "overlap" compare must only be done for fragments with (offset+len) <= max + and thus within the newly g_malloc'd buffer. + */ + + if ( fd_i->offset+fd_i->len > dfpos ) { if (fd_i->offset+fd_i->len > max) g_warning("Reassemble error in frame %u: offset %u + len %u > max %u", pinfo->fd->num, fd_i->offset, @@ -821,10 +818,22 @@ fragment_add_work(fragment_data *fd_head, tvbuff_t *tvb, int offset, g_warning("Reassemble error in frame %u: dfpos %u - offset %u > len %u", pinfo->fd->num, dfpos, fd_i->offset, fd_i->len); - else + else { + if (fd_i->offset < dfpos) { + fd_i->flags |= FD_OVERLAP; + fd_head->flags |= FD_OVERLAP; + if ( memcmp(fd_head->data+fd_i->offset, + fd_i->data, + MIN(fd_i->len,(dfpos-fd_i->offset)) + ) ) { + fd_i->flags |= FD_OVERLAPCONFLICT; + fd_head->flags |= FD_OVERLAPCONFLICT; + } + } memcpy(fd_head->data+dfpos, fd_i->data+(dfpos-fd_i->offset), fd_i->len-(dfpos-fd_i->offset)); + } } else { if (fd_i->offset+fd_i->len < fd_i->offset) g_warning("Reassemble error in frame %u: offset %u + len %u < offset", |