mirror of
https://github.com/espressif/esp-lwip.git
synced 2026-10-15 20:27:38 +00:00
ip4_reass: fix double-free of pbuf
fix mr: http://git.savannah.nongnu.org/cgit/lwip.git/commit/?id=0795e289eb2fc3460293d8d9458acdbde6db7475
This commit is contained in:
+11
-13
@@ -351,8 +351,8 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
|
||||
/* Extract length and fragment offset from current fragment */
|
||||
fraghdr = (struct ip_hdr*)new_p->payload;
|
||||
len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
|
||||
offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
|
||||
len = (u16_t)(lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4);
|
||||
offset = (u16_t)((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8);
|
||||
|
||||
/* overwrite the fragment's ip header from the pbuf with our helper struct,
|
||||
* and setup the embedded helper structure. */
|
||||
@@ -362,7 +362,11 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
iprh = (struct ip_reass_helper*)new_p->payload;
|
||||
iprh->next_pbuf = NULL;
|
||||
iprh->start = offset;
|
||||
iprh->end = offset + len;
|
||||
iprh->end = (u16_t)(offset + len);
|
||||
if (iprh->end < offset) {
|
||||
/* u16_t overflow, cannot handle this */
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
}
|
||||
|
||||
/* Iterate through until we either get to the end of the list (append),
|
||||
* or we find one with a larger offset (insert). */
|
||||
@@ -376,7 +380,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
|
||||
/* fragment overlaps with previous or following, throw away */
|
||||
goto freepbuf;
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
iprh_prev->next_pbuf = new_p;
|
||||
@@ -389,7 +393,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
if (iprh->end > iprh_tmp->start) {
|
||||
/* fragment overlaps with following, throw away */
|
||||
goto freepbuf;
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
}
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
/* fragment with the lowest offset */
|
||||
@@ -398,11 +402,11 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
break;
|
||||
} else if (iprh->start == iprh_tmp->start) {
|
||||
/* received the same datagram twice: no need to keep the datagram */
|
||||
goto freepbuf;
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
} else if (iprh->start < iprh_tmp->end) {
|
||||
/* overlap: no need to keep the new datagram */
|
||||
goto freepbuf;
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
} else {
|
||||
/* Check if the fragments received so far have no holes. */
|
||||
@@ -480,12 +484,6 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
||||
}
|
||||
/* If we come here, not all fragments were received, yet! */
|
||||
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
||||
#if IP_REASS_CHECK_OVERLAP
|
||||
freepbuf:
|
||||
ip_reass_pbufcount -= pbuf_clen(new_p);
|
||||
pbuf_free(new_p);
|
||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user