mirror of
https://github.com/FreeRTOS/FreeRTOS-Plus-TCP
synced 2025-10-24 20:29:40 +08:00
* Use CBMC XML output to enable VSCode debugger (#673) Prior to this commit, CBMC would emit logging information in plain text format, which does not contain information required for the CBMC VSCode debugger. This commit makes CBMC use XML instead of plain text. Co-authored-by: Mark Tuttle <tuttle@acm.org> * wip * wip DNSgetHostByName * wip DNSgetHostByName * fixed cbmc proof for DNS_ReadNameField * wip DNSgetHostByName_a_harness * Fix CBMC prooff for DNSgetHostByName * wip fix DNSgetHostByName_a CBMC proof * fixed cbmc target func not called issue in DNSclear * fixed cbmc target func not called issue in DNSlookup * fix DNSgetHostByName_a CBMC proof * update comments * more asserts * fixing formatting * updating as per review comments * fix dns after review comments * adding more asserts * adds more asserts * minor fix * fixing comments * fixing comments * fixing minor issue * fixing DNS_ReadReply() signature * making code more consistant * adding more asserts * making code more consistent --------- Co-authored-by: Kareem Khazem <karkhaz@amazon.com> Co-authored-by: Mark Tuttle <tuttle@acm.org>
410 lines
15 KiB
C
410 lines
15 KiB
C
/* Standard includes. */
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
/* FreeRTOS includes. */
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "queue.h"
|
|
#include "semphr.h"
|
|
|
|
/* FreeRTOS+TCP includes. */
|
|
#include "FreeRTOS_UDP_IP.h"
|
|
#include "FreeRTOS_IP.h"
|
|
#include "FreeRTOS_Sockets.h"
|
|
#include "FreeRTOS_IP_Private.h"
|
|
#include "FreeRTOS_DNS.h"
|
|
#include "NetworkBufferManagement.h"
|
|
|
|
#include "cbmc.h"
|
|
|
|
/****************************************************************
|
|
* This is a collection of abstractions of methods in the FreeRTOS TCP
|
|
* API. The abstractions simply perform minimal validation of
|
|
* function arguments, and return unconstrained values of the
|
|
* appropriate type.
|
|
****************************************************************/
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_socket.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/socket.html
|
|
*
|
|
* We stub out this function to do nothing but allocate space for a
|
|
* socket containing unconstrained data or return an error.
|
|
****************************************************************/
|
|
|
|
Socket_t FreeRTOS_socket( BaseType_t xDomain,
|
|
BaseType_t xType,
|
|
BaseType_t xProtocol )
|
|
{
|
|
if( nondet_bool() )
|
|
{
|
|
return FREERTOS_INVALID_SOCKET;
|
|
}
|
|
else
|
|
{
|
|
void * ptr = malloc( sizeof( struct xSOCKET ) );
|
|
__CPROVER_assume( ptr != NULL );
|
|
return ptr;
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_setsockopt.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/setsockopt.html
|
|
****************************************************************/
|
|
|
|
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket,
|
|
int32_t lLevel,
|
|
int32_t lOptionName,
|
|
const void * pvOptionValue,
|
|
size_t uxOptionLength )
|
|
{
|
|
__CPROVER_assert( xSocket != NULL,
|
|
"FreeRTOS precondition: xSocket != NULL" );
|
|
__CPROVER_assert( pvOptionValue != NULL,
|
|
"FreeRTOS precondition: pvOptionValue != NULL" );
|
|
return nondet_BaseType();
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_closesocket.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/close.html
|
|
****************************************************************/
|
|
|
|
BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
|
|
{
|
|
__CPROVER_assert( xSocket != NULL,
|
|
"FreeRTOS precondition: xSocket != NULL" );
|
|
return nondet_BaseType();
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_bind.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/bind.html
|
|
****************************************************************/
|
|
|
|
BaseType_t FreeRTOS_bind( Socket_t xSocket,
|
|
struct freertos_sockaddr * pxAddress,
|
|
socklen_t xAddressLength )
|
|
{
|
|
__CPROVER_assert( xSocket != NULL,
|
|
"FreeRTOS precondition: xSocket != NULL" );
|
|
__CPROVER_assert( pxAddress != NULL,
|
|
"FreeRTOS precondition: pxAddress != NULL" );
|
|
return nondet_BaseType();
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_inet_addr.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/inet_addr.html
|
|
****************************************************************/
|
|
|
|
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
|
|
{
|
|
__CPROVER_assert( pcIPAddress != NULL,
|
|
"FreeRTOS precondition: pcIPAddress != NULL" );
|
|
return nondet_uint32();
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_recvfrom.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/recvfrom.html
|
|
*
|
|
* We stub out this function to do nothing but allocate a buffer of
|
|
* unconstrained size containing unconstrained data and return the
|
|
* size (or return the size 0 if the allocation fails).
|
|
****************************************************************/
|
|
|
|
int32_t FreeRTOS_recvfrom( Socket_t xSocket,
|
|
void * pvBuffer,
|
|
size_t uxBufferLength,
|
|
BaseType_t xFlags,
|
|
struct freertos_sockaddr * pxSourceAddress,
|
|
socklen_t * pxSourceAddressLength )
|
|
|
|
{
|
|
/****************************************************************
|
|
* "If the zero copy calling semantics are used (the ulFlags
|
|
* parameter does not have the FREERTOS_ZERO_COPY bit set) then
|
|
* pvBuffer does not point to a buffer and xBufferLength is not
|
|
* used." This is from the documentation.
|
|
****************************************************************/
|
|
__CPROVER_assert( xFlags & FREERTOS_ZERO_COPY, "I can only do ZERO_COPY" );
|
|
|
|
__CPROVER_assert( pvBuffer != NULL,
|
|
"FreeRTOS precondition: pvBuffer != NULL" );
|
|
|
|
/****************************************************************
|
|
* TODO: We need to check this out.
|
|
*
|
|
* The code calls recvfrom with these parameters NULL, it is not
|
|
* clear from the documentation that this is allowed.
|
|
****************************************************************/
|
|
#if 0
|
|
__CPROVER_assert( pxSourceAddress != NULL,
|
|
"FreeRTOS precondition: pxSourceAddress != NULL" );
|
|
__CPROVER_assert( pxSourceAddressLength != NULL,
|
|
"FreeRTOS precondition: pxSourceAddress != NULL" );
|
|
#endif
|
|
|
|
size_t payload_size;
|
|
__CPROVER_assume( payload_size + sizeof( UDPPacket_t )
|
|
< CBMC_MAX_OBJECT_SIZE );
|
|
|
|
/****************************************************************
|
|
* TODO: We need to make this lower bound explicit in the Makefile.json
|
|
*
|
|
* DNSMessage_t is a typedef in FreeRTOS_DNS.c
|
|
* sizeof(DNSMessage_t) = 6 * sizeof(uint16_t)
|
|
****************************************************************/
|
|
__CPROVER_assume( payload_size >= 6 * sizeof( uint16_t ) );
|
|
|
|
#ifdef CBMC_FREERTOS_RECVFROM_BUFFER_BOUND
|
|
__CPROVER_assume( payload_size <= CBMC_FREERTOS_RECVFROM_BUFFER_BOUND );
|
|
#endif
|
|
|
|
uint32_t buffer_size = payload_size + sizeof( UDPPacket_t );
|
|
uint8_t * buffer = safeMalloc( buffer_size );
|
|
|
|
if( buffer == NULL )
|
|
{
|
|
buffer_size = 0;
|
|
}
|
|
else
|
|
{
|
|
buffer = buffer + sizeof( UDPPacket_t );
|
|
buffer_size = buffer_size - sizeof( UDPPacket_t );
|
|
}
|
|
|
|
*( ( uint8_t ** ) pvBuffer ) = buffer;
|
|
return buffer_size;
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_recvfrom.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/sendto.html
|
|
****************************************************************/
|
|
|
|
int32_t FreeRTOS_sendto( Socket_t xSocket,
|
|
const void * pvBuffer,
|
|
size_t uxTotalDataLength,
|
|
BaseType_t xFlags,
|
|
const struct freertos_sockaddr * pxDestinationAddress,
|
|
socklen_t xDestinationAddressLength )
|
|
{
|
|
__CPROVER_assert( xSocket != NULL,
|
|
"FreeRTOS precondition: xSocket != NULL" );
|
|
__CPROVER_assert( pvBuffer != NULL,
|
|
"FreeRTOS precondition: pvBuffer != NULL" );
|
|
__CPROVER_assert( pxDestinationAddress != NULL,
|
|
"FreeRTOS precondition: pxDestinationAddress != NULL" );
|
|
return nondet_int32();
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_GetUDPPayloadBuffer
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/FreeRTOS_GetUDPPayloadBuffer.html
|
|
*
|
|
* We stub out this function to do nothing but allocate a buffer of
|
|
* unconstrained size containing unconstrained data and return a
|
|
* pointer to the buffer (or NULL).
|
|
****************************************************************/
|
|
|
|
void * FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes,
|
|
TickType_t uxBlockTimeTicks,
|
|
uint8_t ucIPType )
|
|
{
|
|
size_t size;
|
|
|
|
__CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
|
|
__CPROVER_assume( size >= sizeof( UDPPacket_t ) );
|
|
|
|
uint8_t * buffer = safeMalloc( size );
|
|
|
|
return buffer == NULL ? buffer : buffer + sizeof( UDPPacket_t );
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_ReleaseUDPPayloadBuffer
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_ReleaseUDPPayloadBuffer.html
|
|
****************************************************************/
|
|
|
|
void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer )
|
|
{
|
|
__CPROVER_assert( pvBuffer != NULL,
|
|
"FreeRTOS precondition: pvBuffer != NULL" );
|
|
__CPROVER_assert( __CPROVER_POINTER_OFFSET( pvBuffer )
|
|
== sizeof( UDPPacket_t ),
|
|
"FreeRTOS precondition: pvBuffer offset" );
|
|
|
|
free( pvBuffer - sizeof( UDPPacket_t ) );
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract pxGetNetworkBufferWithDescriptor.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/pxGetNetworkBufferWithDescriptor.html
|
|
*
|
|
* The real allocator take buffers off a list.
|
|
****************************************************************/
|
|
|
|
uint32_t GetNetworkBuffer_failure_count;
|
|
|
|
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
|
|
TickType_t xBlockTimeTicks )
|
|
{
|
|
__CPROVER_assert(
|
|
xRequestedSizeBytes + ipBUFFER_PADDING < CBMC_MAX_OBJECT_SIZE,
|
|
"pxGetNetworkBufferWithDescriptor: request too big" );
|
|
|
|
/*
|
|
* The semantics of this function is to wait until a buffer with
|
|
* at least the requested number of bytes becomes available. If a
|
|
* timeout occurs before the buffer is available, then return a
|
|
* NULL pointer.
|
|
*/
|
|
|
|
NetworkBufferDescriptor_t * desc = safeMalloc( sizeof( *desc ) );
|
|
|
|
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
|
|
|
|
/*
|
|
* This interprets the failure bound as being one greater than the
|
|
* actual number of times GetNetworkBuffer should be allowed to
|
|
* fail.
|
|
*
|
|
* This makes it possible to use the same bound for loop unrolling
|
|
* which must be one greater than the actual number of times the
|
|
* loop should be unwound.
|
|
*
|
|
* NOTE: Using this bound with --nondet-static requires setting
|
|
* (or assuming) GetNetworkBuffer_failure_count to a value (like 0)
|
|
* in the proof harness that won't induce an integer overflow.
|
|
*/
|
|
GetNetworkBuffer_failure_count++;
|
|
__CPROVER_assume(
|
|
IMPLIES(
|
|
GetNetworkBuffer_failure_count >= CBMC_GETNETWORKBUFFER_FAILURE_BOUND,
|
|
desc != NULL ) );
|
|
#endif
|
|
|
|
if( desc != NULL )
|
|
{
|
|
/*
|
|
* We may want to experiment with allocating space other than
|
|
* (more than) the exact amount of space requested.
|
|
*/
|
|
|
|
size_t size = xRequestedSizeBytes;
|
|
__CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
|
|
|
|
desc->pucEthernetBuffer = safeMalloc( size );
|
|
desc->xDataLength = desc->pucEthernetBuffer == NULL ? 0 : size;
|
|
|
|
#ifdef CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL
|
|
/* This may be implied by the semantics of the function. */
|
|
__CPROVER_assume( desc->pucEthernetBuffer != NULL );
|
|
#endif
|
|
|
|
/* Allow method to fail again next time */
|
|
GetNetworkBuffer_failure_count = 0;
|
|
}
|
|
|
|
return desc;
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract pxGetNetworkBufferWithDescriptor.
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vReleaseNetworkBufferAndDescriptor.html
|
|
****************************************************************/
|
|
|
|
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
|
{
|
|
__CPROVER_assert( pxNetworkBuffer != NULL,
|
|
"Precondition: pxNetworkBuffer != NULL" );
|
|
|
|
if( pxNetworkBuffer->pucEthernetBuffer != NULL )
|
|
{
|
|
free( pxNetworkBuffer->pucEthernetBuffer );
|
|
}
|
|
|
|
free( pxNetworkBuffer );
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_GetAddressConfiguration
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_GetAddressConfiguration.html
|
|
****************************************************************/
|
|
|
|
void FreeRTOS_GetAddressConfiguration( uint32_t * pulIPAddress,
|
|
uint32_t * pulNetMask,
|
|
uint32_t * pulGatewayAddress,
|
|
uint32_t * pulDNSServerAddress )
|
|
{
|
|
if( pulIPAddress != NULL )
|
|
{
|
|
*pulIPAddress = nondet_unint32();
|
|
}
|
|
|
|
if( pulNetMask != NULL )
|
|
{
|
|
*pulNetMask = nondet_unint32();
|
|
}
|
|
|
|
if( pulGatewayAddress != NULL )
|
|
{
|
|
*pulGatewayAddress = nondet_unint32();
|
|
}
|
|
|
|
if( pulDNSServerAddress != NULL )
|
|
{
|
|
*pulDNSServerAddress = nondet_unint32();
|
|
}
|
|
}
|
|
|
|
/****************************************************************/
|
|
|
|
/****************************************************************
|
|
* This is a collection of methods that are defined by the user
|
|
* application but are invoked by the FreeRTOS API.
|
|
****************************************************************/
|
|
|
|
/****************************************************************
|
|
* Abstract FreeRTOS_GetAddressConfiguration
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vApplicationIPNetworkEventHook.html
|
|
****************************************************************/
|
|
|
|
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
|
|
{
|
|
}
|
|
|
|
/****************************************************************
|
|
* Abstract pcApplicationHostnameHook
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html
|
|
****************************************************************/
|
|
|
|
const char * pcApplicationHostnameHook( void )
|
|
{
|
|
return "hostname";
|
|
}
|
|
|
|
/****************************************************************/
|
|
|
|
|
|
/****************************************************************
|
|
* Abstract xNetworkInterfaceOutput
|
|
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Porting.html#xNetworkInterfaceOutput
|
|
****************************************************************/
|
|
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
|
|
BaseType_t bReleaseAfterSend )
|
|
{
|
|
__CPROVER_assert( pxNetworkBuffer != NULL, "The networkbuffer cannot be NULL" );
|
|
|
|
BaseType_t xReturn;
|
|
|
|
/* Return some random value. */
|
|
return xReturn;
|
|
}
|
|
|
|
/****************************************************************/
|