@@ -1479,6 +1479,108 @@ void test_prvTCPSetSocketCount_NotListeningSock_HappyPath( void )
14791479 TEST_ASSERT_EQUAL ( 99 , xChildSocket .u .xTCP .usChildCount );
14801480}
14811481
1482+ /**
1483+ * @brief A child socket is being freed and the listening parent still refers to
1484+ * it. That reference must be dropped, or 'FreeRTOS_accept()' and
1485+ * 'FreeRTOS_select()' would dereference freed memory.
1486+ */
1487+ void test_prvTCPSetSocketCount_NotListeningSock_ClearsPeerSocket ( void )
1488+ {
1489+ FreeRTOS_Socket_t xSocketToDelete , xParentSocket ;
1490+ ListItem_t xIterator ;
1491+ uint16_t usLocalPort = 0x1234 ;
1492+
1493+ memset ( & xSocketToDelete , 0 , sizeof ( xSocketToDelete ) );
1494+ memset ( & xParentSocket , 0 , sizeof ( xParentSocket ) );
1495+
1496+ xSocketToDelete .ucProtocol = ( uint8_t ) FREERTOS_IPPROTO_TCP ;
1497+ xSocketToDelete .u .xTCP .eTCPState = eCLOSED ;
1498+ xSocketToDelete .usLocalPort = usLocalPort ;
1499+
1500+ xParentSocket .u .xTCP .eTCPState = eTCP_LISTEN ;
1501+ xParentSocket .usLocalPort = usLocalPort ;
1502+ xParentSocket .u .xTCP .usChildCount = 1 ;
1503+ xParentSocket .u .xTCP .pxPeerSocket = & xSocketToDelete ;
1504+
1505+ listGET_HEAD_ENTRY_ExpectAndReturn ( ( List_t * ) & ( xBoundTCPSocketsList ), ( ListItem_t * ) & ( xIterator ) );
1506+
1507+ listGET_LIST_ITEM_OWNER_ExpectAndReturn ( & xIterator , & xParentSocket );
1508+
1509+ prvTCPSetSocketCount ( & xSocketToDelete );
1510+
1511+ TEST_ASSERT_EQUAL ( NULL , xParentSocket .u .xTCP .pxPeerSocket );
1512+ TEST_ASSERT_EQUAL ( 0 , xParentSocket .u .xTCP .usChildCount );
1513+ }
1514+
1515+ /**
1516+ * @brief A child socket is being freed, but the listening parent refers to a
1517+ * different child which is still waiting to be accepted. That reference
1518+ * must survive: clearing it would lose a live connection.
1519+ */
1520+ void test_prvTCPSetSocketCount_NotListeningSock_KeepsOtherPeerSocket ( void )
1521+ {
1522+ FreeRTOS_Socket_t xSocketToDelete , xParentSocket , xPendingChild ;
1523+ ListItem_t xIterator ;
1524+ uint16_t usLocalPort = 0x1234 ;
1525+
1526+ memset ( & xSocketToDelete , 0 , sizeof ( xSocketToDelete ) );
1527+ memset ( & xParentSocket , 0 , sizeof ( xParentSocket ) );
1528+ memset ( & xPendingChild , 0 , sizeof ( xPendingChild ) );
1529+
1530+ xSocketToDelete .ucProtocol = ( uint8_t ) FREERTOS_IPPROTO_TCP ;
1531+ xSocketToDelete .u .xTCP .eTCPState = eCLOSED ;
1532+ xSocketToDelete .usLocalPort = usLocalPort ;
1533+
1534+ xParentSocket .u .xTCP .eTCPState = eTCP_LISTEN ;
1535+ xParentSocket .usLocalPort = usLocalPort ;
1536+ xParentSocket .u .xTCP .usChildCount = 2 ;
1537+ xParentSocket .u .xTCP .pxPeerSocket = & xPendingChild ;
1538+
1539+ listGET_HEAD_ENTRY_ExpectAndReturn ( ( List_t * ) & ( xBoundTCPSocketsList ), ( ListItem_t * ) & ( xIterator ) );
1540+
1541+ listGET_LIST_ITEM_OWNER_ExpectAndReturn ( & xIterator , & xParentSocket );
1542+
1543+ prvTCPSetSocketCount ( & xSocketToDelete );
1544+
1545+ TEST_ASSERT_EQUAL ( & xPendingChild , xParentSocket .u .xTCP .pxPeerSocket );
1546+ TEST_ASSERT_EQUAL ( 1 , xParentSocket .u .xTCP .usChildCount );
1547+ }
1548+
1549+ /**
1550+ * @brief The reference must be dropped even when the parent's child count has
1551+ * already reached zero, so the clean-up does not depend on the counter
1552+ * and the parent's own book-keeping staying in step.
1553+ */
1554+ void test_prvTCPSetSocketCount_NotListeningSock_ClearsPeerSocketZeroChildCount ( void )
1555+ {
1556+ FreeRTOS_Socket_t xSocketToDelete , xParentSocket ;
1557+ ListItem_t xIterator ;
1558+ uint16_t usLocalPort = 0x1234 ;
1559+
1560+ memset ( & xSocketToDelete , 0 , sizeof ( xSocketToDelete ) );
1561+ memset ( & xParentSocket , 0 , sizeof ( xParentSocket ) );
1562+
1563+ xSocketToDelete .ucProtocol = ( uint8_t ) FREERTOS_IPPROTO_TCP ;
1564+ xSocketToDelete .u .xTCP .eTCPState = eCLOSED ;
1565+ xSocketToDelete .usLocalPort = usLocalPort ;
1566+
1567+ xParentSocket .u .xTCP .eTCPState = eTCP_LISTEN ;
1568+ xParentSocket .usLocalPort = usLocalPort ;
1569+ xParentSocket .u .xTCP .usChildCount = 0 ;
1570+ xParentSocket .u .xTCP .pxPeerSocket = & xSocketToDelete ;
1571+
1572+ listGET_HEAD_ENTRY_ExpectAndReturn ( ( List_t * ) & ( xBoundTCPSocketsList ), ( ListItem_t * ) & ( xIterator ) );
1573+
1574+ listGET_LIST_ITEM_OWNER_ExpectAndReturn ( & xIterator , & xParentSocket );
1575+
1576+ listGET_NEXT_ExpectAndReturn ( & ( xIterator ), ( ListItem_t * ) & ( xBoundTCPSocketsList .xListEnd ) );
1577+
1578+ prvTCPSetSocketCount ( & xSocketToDelete );
1579+
1580+ TEST_ASSERT_EQUAL ( NULL , xParentSocket .u .xTCP .pxPeerSocket );
1581+ TEST_ASSERT_EQUAL ( 0 , xParentSocket .u .xTCP .usChildCount );
1582+ }
1583+
14821584/**
14831585 * @brief Invalid protocol.
14841586 */
0 commit comments