Skip to content

Commit e31c44a

Browse files
committed
defrag: drop unsigned underflow in RB_NFIND search key
The seek into the fragment tree used frag_offset - 1 as the key for RB_NFIND. For the first fragment of an IP datagram frag_offset is 0 and the uint16_t subtraction wraps to 65535. The wrap is harmless in practice because no fragment can have offset 65535 (IPv4 limits the field to 8191 << 3 = 65528, and IPv6 follows the same alignment), so RB_NFIND returns NULL and the existing RB_MIN fallback walks the tree forward to reach the same end state. The path is reached by accident though, and fuzzer integer overflow sanitizers flag the wrap. Guard the RB_NFIND call with if (frag_offset > 0) so the subtraction never runs on a zero offset. The frag_offset == 0 case leaves next at NULL and falls into the existing RB_MIN fallback, which matches the prior end state on every input. The 35 defrag unit tests pass unchanged. Bug: #8232.
1 parent 367ca7f commit e31c44a

1 file changed

Lines changed: 9 additions & 4 deletions

File tree

src/defrag.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,10 +653,15 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker,
653653
ltrim = 0;
654654

655655
if (!RB_EMPTY(&tracker->fragment_tree)) {
656-
Frag key = {
657-
.offset = frag_offset - 1,
658-
};
659-
next = RB_NFIND(IP_FRAGMENTS, &tracker->fragment_tree, &key);
656+
if (frag_offset > 0) {
657+
Frag key = {
658+
.offset = frag_offset - 1,
659+
};
660+
next = RB_NFIND(IP_FRAGMENTS, &tracker->fragment_tree, &key);
661+
}
662+
/* For frag_offset == 0 the new fragment precedes every existing
663+
* fragment, so we leave next NULL and fall into the RB_MIN
664+
* fallback below. */
660665
if (next == NULL) {
661666
prev = RB_MIN(IP_FRAGMENTS, &tracker->fragment_tree);
662667
next = IP_FRAGMENTS_RB_NEXT(prev);

0 commit comments

Comments
 (0)