diff --git a/source/FreeRTOS_TCP_State_Handling.c b/source/FreeRTOS_TCP_State_Handling.c index f8e7de41c5..ecf55bae06 100644 --- a/source/FreeRTOS_TCP_State_Handling.c +++ b/source/FreeRTOS_TCP_State_Handling.c @@ -584,6 +584,8 @@ { /* Peer is requesting to stop, see if we're really finished. */ xMayClose = pdTRUE; + ulIntermediateResult = ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulCurrentSequenceNumber; + lDistance = ( int32_t ) ulIntermediateResult; /* Checks are only necessary if we haven't sent a FIN yet. */ if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED ) @@ -601,22 +603,28 @@ ( int ) bRxComplete, ( int ) bTxDone ) ); xMayClose = pdFALSE; - } - else - { - ulIntermediateResult = ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulCurrentSequenceNumber; - lDistance = ( int32_t ) ulIntermediateResult; - if( lDistance > 1 ) + /* This action is necessary to ensure proper handling of any subsequent packets that + * may arrive after the refused FIN packet. Note that we only update it when the sequence + * of FIN packet is correct. Otherwise, we wait for re-transmission. */ + if( lDistance <= 1 ) { - FreeRTOS_debug_printf( ( "Refusing FIN: Rx not complete %d (cur %u high %u)\n", - ( int ) lDistance, - ( unsigned ) ( pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ), - ( unsigned ) ( pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ) ) ); - - xMayClose = pdFALSE; + pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulFINSequenceNumber + 1U; } } + else if( lDistance > 1 ) + { + FreeRTOS_debug_printf( ( "Refusing FIN: Rx not complete %d (cur %u high %u)\n", + ( int ) lDistance, + ( unsigned ) ( pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ), + ( unsigned ) ( pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ) ) ); + + xMayClose = pdFALSE; + } + else + { + /* Empty else marker. */ + } } if( xTCPWindowLoggingLevel > 0 ) diff --git a/test/Coverity/README.md b/test/Coverity/README.md index db4579b585..8b4614eed5 100644 --- a/test/Coverity/README.md +++ b/test/Coverity/README.md @@ -1,6 +1,6 @@ # Static code analysis for FreeRTOS-Plus-TCP library This directory is made for the purpose of statically testing the MISRA C:2012 compliance of FreeRTOS+TCP using -[Synopsys Coverity](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html) static analysis tool. +[Synopsys Coverity](https://www.blackduck.com/static-analysis-tools-sast/coverity.html) static analysis tool. To that end, this directory provides a [CMake](https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/test/Coverity/CMakeLists.txt) file and [configuration files](https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/tree/main/test/Coverity/ConfigFiles) required to build an application for the tool to analyze. diff --git a/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c b/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c index b65fb12698..5b34820063 100644 --- a/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c +++ b/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c @@ -821,6 +821,47 @@ void test_prvHandleEstablished_FINNotSentRXComplete( void ) TEST_ASSERT_EQUAL( 40, xSendLength ); } +/** + * @brief Data left for receiving when receiving TCP packet with FIN/ACK. + */ +void test_prvHandleEstablished_FINNotSentRXNotCompleteNotExpectedSeq( void ) +{ + BaseType_t xSendLength = 0; + + pxSocket = &xSocket; + + pxNetworkBuffer = &xNetworkBuffer; + pxNetworkBuffer->pucEthernetBuffer = ucEthernetBuffer; + + /* Map the buffer onto the ProtocolHeader_t struct for easy access to the fields. */ + ProtocolHeaders_t * pxProtocolHeaders = ( ( ProtocolHeaders_t * ) + &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER ] ) ); + TCPHeader_t * pxTCPHeader = &pxProtocolHeaders->xTCPHeader; + TCPWindow_t * pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow; + + ulCalled = 0; + pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_FIN | tcpTCP_FLAG_ACK; + pxTCPHeader->ulSequenceNumber = FreeRTOS_htonl( 1502 ); + pxTCPHeader->usWindow = 1000; + pxSocket->u.xTCP.txStream = ( StreamBuffer_t * ) 0x12345678; + pxSocket->u.xTCP.pxHandleSent = NULL; + pxSocket->u.xTCP.bits.bFinSent = pdFALSE; + pxTCPWindow->rx.ulCurrentSequenceNumber = 1500; + + uxIPHeaderSizeSocket_IgnoreAndReturn( ipSIZE_OF_IPv4_HEADER ); + ulTCPWindowTxAck_ExpectAnyArgsAndReturn( 0 ); + prvTCPAddTxData_ExpectAnyArgs(); + xTCPWindowRxEmpty_ExpectAnyArgsAndReturn( pdFALSE ); + xTCPWindowTxDone_ExpectAnyArgsAndReturn( pdTRUE ); + prvTCPPrepareSend_ExpectAnyArgsAndReturn( 0 ); + + xSendLength = prvHandleEstablished( pxSocket, + &pxNetworkBuffer, + 0, + 0 ); + TEST_ASSERT_EQUAL( 0, xSendLength ); +} + /** * @brief Data left for receiving when receiving TCP packet with FIN/ACK. */ @@ -846,7 +887,7 @@ void test_prvHandleEstablished_FINNotSentRXNotComplete( void ) pxSocket->u.xTCP.txStream = ( StreamBuffer_t * ) 0x12345678; pxSocket->u.xTCP.pxHandleSent = NULL; pxSocket->u.xTCP.bits.bFinSent = pdFALSE; - pxTCPWindow->rx.ulCurrentSequenceNumber = 2501; + pxTCPWindow->rx.ulCurrentSequenceNumber = 1500; uxIPHeaderSizeSocket_IgnoreAndReturn( ipSIZE_OF_IPv4_HEADER ); ulTCPWindowTxAck_ExpectAnyArgsAndReturn( 0 );