@@ -478,8 +478,10 @@ typedef struct Flags {
478478
479479/* Out of Order FIN capture */
480480typedef struct FinCapture {
481- word32 cliFinSeq ; /* client relative sequence FIN 0 is no */
482- word32 srvFinSeq ; /* server relative sequence FIN, 0 is no */
481+ word32 cliFinSeq ; /* client relative sequence FIN (may be 0) */
482+ word32 srvFinSeq ; /* server relative sequence FIN (may be 0) */
483+ byte cliHasFin ; /* client FIN captured (seq value may be 0) */
484+ byte srvHasFin ; /* server FIN captured (seq value may be 0) */
483485 byte cliCounted ; /* did we count yet, detects duplicates */
484486 byte srvCounted ; /* did we count yet, detects duplicates */
485487} FinCapture ;
@@ -5612,6 +5614,11 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
56125614 * data after the IP record for the FCS for Ethernet. */
56135615 * sslBytes = (int )(packet + ipInfo -> total - * sslFrame );
56145616
5617+ if (* sslBytes < 0 ) {
5618+ SetError (PACKET_HDR_SHORT_STR , error , NULL , 0 );
5619+ return WOLFSSL_FATAL_ERROR ;
5620+ }
5621+
56155622 /* Ensure sslBytes does not exceed the actual size. */
56165623 if (* sslBytes > (int )(length - (ipInfo -> length + tcpInfo -> length ))) {
56175624 SetError (PACKET_HDR_SHORT_STR , error , NULL , 0 );
@@ -5821,12 +5828,16 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
58215828static int AddFinCapture (SnifferSession * session , word32 sequence )
58225829{
58235830 if (session -> flags .side == WOLFSSL_SERVER_END ) {
5824- if (session -> finCapture .cliCounted == 0 )
5831+ if (session -> finCapture .cliCounted == 0 ) {
58255832 session -> finCapture .cliFinSeq = sequence ;
5833+ session -> finCapture .cliHasFin = 1 ;
5834+ }
58265835 }
58275836 else {
5828- if (session -> finCapture .srvCounted == 0 )
5837+ if (session -> finCapture .srvCounted == 0 ) {
58295838 session -> finCapture .srvFinSeq = sequence ;
5839+ session -> finCapture .srvHasFin = 1 ;
5840+ }
58305841 }
58315842 return 1 ;
58325843}
@@ -5837,6 +5848,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
58375848 int * sslBytes , const byte * * sslFrame , char * error )
58385849{
58395850 int ret = 0 ;
5851+ sword32 seqDiff ;
58405852 word32 seqStart = (session -> flags .side == WOLFSSL_SERVER_END ) ?
58415853 session -> cliSeqStart : session -> srvSeqStart ;
58425854 word32 * seqLast = (session -> flags .side == WOLFSSL_SERVER_END ) ?
@@ -5854,12 +5866,17 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
58545866 if (tcpInfo -> sequence < seqStart )
58555867 real = 0xffffffffU - seqStart + tcpInfo -> sequence + 1 ;
58565868
5869+ /* Relative sequence numbers wrap at 2^32, so order them with signed
5870+ * (RFC 1982) serial-number arithmetic; plain unsigned </> mis-handles
5871+ * the wrap boundary and would drop wrapped segments as already-seen. */
5872+ seqDiff = (sword32 )(real - * expected );
5873+
58575874 TraceRelativeSequence (* expected , real );
58585875
5859- if (real < * expected ) {
5876+ if (seqDiff < 0 ) {
58605877 int overlap = * expected - real ;
58615878
5862- if (real + * sslBytes > * expected ) {
5879+ if (( sword32 )( real + ( word32 ) * sslBytes - * expected ) > 0 ) {
58635880 #ifdef WOLFSSL_ASYNC_CRYPT
58645881 if (session -> sslServer -> error != WC_NO_ERR_TRACE (WC_PENDING_E ) &&
58655882 session -> pendSeq != tcpInfo -> sequence )
@@ -5901,7 +5918,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
59015918 }
59025919 }
59035920 else if (* sslBytes > 0 ) {
5904- if (real + * sslBytes - 1 > * seqLast ) {
5921+ if (( sword32 )( real + ( word32 ) * sslBytes - 1 - * seqLast ) > 0 ) {
59055922 /* fix segment overlap */
59065923 #ifdef DEBUG_SNIFFER
59075924 WOLFSSL * ssl = (session -> flags .side == WOLFSSL_SERVER_END ) ?
@@ -5931,7 +5948,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
59315948 session -> sslServer -> error != WC_NO_ERR_TRACE (WC_PENDING_E ) &&
59325949 session -> pendSeq != tcpInfo -> sequence &&
59335950 #endif
5934- real + * sslBytes - 1 <= * seqLast ) {
5951+ ( sword32 )( real + ( word32 ) * sslBytes - 1 - * seqLast ) <= 0 ) {
59355952 Trace (DUPLICATE_STR );
59365953 ret = 1 ;
59375954 }
@@ -5947,7 +5964,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
59475964 }
59485965 }
59495966 }
5950- else if (real > * expected ) {
5967+ else if (seqDiff > 0 ) {
59515968 Trace (OUT_OF_ORDER_STR );
59525969 if (* sslBytes > 0 ) {
59535970 int addResult = AddToReassembly (session -> flags .side , real ,
@@ -6141,7 +6158,13 @@ static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
61416158
61426159 TraceAck (real , expected );
61436160
6144- if (real > expected )
6161+ /* Relative sequence numbers wrap at 2^32; compare with signed
6162+ * (RFC 1982) serial-number arithmetic to avoid a false positive at
6163+ * the wrap boundary. Expected is still 0 when that side's SYN was
6164+ * never seen, leaving no base to be relative to, so any data being
6165+ * ACKed there is data we missed. */
6166+ if ((expected == 0 ) ? (real != 0 ) :
6167+ ((sword32 )(real - expected ) > 0 ))
61456168 return WOLFSSL_FATAL_ERROR ; /* we missed a packet, ACKing data we never saw */
61466169 }
61476170 return 0 ;
@@ -6180,6 +6203,12 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
61806203
61816204 /* adjust potential ethernet trailer */
61826205 actualLen = ipInfo -> total - ipInfo -> length - tcpInfo -> length ;
6206+ /* CheckHeaders already rejects this for the current callers; kept so the
6207+ * clamp below cannot be reached with a negative bound. */
6208+ if (actualLen < 0 ) {
6209+ SetError (PACKET_HDR_SHORT_STR , error , session , FATAL_ERROR_STATE );
6210+ return WOLFSSL_FATAL_ERROR ;
6211+ }
61836212 if (* sslBytes > actualLen ) {
61846213 * sslBytes = actualLen ;
61856214 }
@@ -6725,17 +6754,23 @@ static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
67256754 SnifferSession * session )
67266755{
67276756 int ret = 0 ;
6728- if (session -> finCapture .cliFinSeq && session -> finCapture .cliFinSeq <=
6729- session -> cliExpected ) {
6757+ /* FIN sequences are relative and wrap at 2^32, so compare "reached" with
6758+ * signed (RFC 1982) serial-number arithmetic. A dedicated has-FIN flag
6759+ * marks capture, since a relative sequence of 0 is itself a valid FIN
6760+ * position at the wrap boundary. */
6761+ if (session -> finCapture .cliHasFin &&
6762+ (sword32 )(session -> finCapture .cliFinSeq - session -> cliExpected )
6763+ <= 0 ) {
67306764 if (session -> finCapture .cliCounted == 0 ) {
67316765 session -> flags .finCount += 1 ;
67326766 session -> finCapture .cliCounted = 1 ;
67336767 TraceClientFin (session -> finCapture .cliFinSeq , session -> cliExpected );
67346768 }
67356769 }
67366770
6737- if (session -> finCapture .srvFinSeq && session -> finCapture .srvFinSeq <=
6738- session -> srvExpected ) {
6771+ if (session -> finCapture .srvHasFin &&
6772+ (sword32 )(session -> finCapture .srvFinSeq - session -> srvExpected )
6773+ <= 0 ) {
67396774 if (session -> finCapture .srvCounted == 0 ) {
67406775 session -> flags .finCount += 1 ;
67416776 session -> finCapture .srvCounted = 1 ;
0 commit comments