[修改] 增加freeRTOS
1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
10
kernel/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/test/cbmc/proofs/.gitignore
vendored
Normal file
10
kernel/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/test/cbmc/proofs/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# These files are generated by make_type_header_files.py
|
||||
*_datastructure.h
|
||||
|
||||
Makefile
|
||||
Makefile.common
|
||||
cbmc-batch.yaml
|
||||
**/*.txt
|
||||
**/*.goto
|
||||
|
||||
!CMakeLists.txt
|
||||
@ -0,0 +1,29 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
/*We assume that the pxGetNetworkBufferWithDescriptor function is implemented correctly and returns a valid data structure. */
|
||||
/*This is the mock to mimic the correct expected behavior. If this allocation fails, this might invalidate the proof. */
|
||||
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
|
||||
TickType_t xBlockTimeTicks )
|
||||
{
|
||||
NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) malloc( sizeof( NetworkBufferDescriptor_t ) );
|
||||
|
||||
__CPROVER_assume( pxNetworkBuffer != NULL );
|
||||
|
||||
pxNetworkBuffer->pucEthernetBuffer = malloc( xRequestedSizeBytes );
|
||||
__CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer != NULL );
|
||||
|
||||
pxNetworkBuffer->xDataLength = xRequestedSizeBytes;
|
||||
return pxNetworkBuffer;
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
vARPAgeCache();
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"ENTRY": "ARPAgeCache",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset vARPAgeCache.0:7",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
Assuming that xNetworkInterfaceOutput is memory safe,
|
||||
this harness proves the memory safety of the vARPAgeCache function.
|
||||
@ -0,0 +1,32 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
void harness()
|
||||
{
|
||||
/*
|
||||
* The assumption made here is that the buffer pointed by pucEthernetBuffer
|
||||
* is at least allocated to sizeof(ARPPacket_t) size but eventually a even larger buffer.
|
||||
* This is not checked inside vARPGenerateRequestPacket.
|
||||
*/
|
||||
uint8_t ucBUFFER_SIZE;
|
||||
|
||||
__CPROVER_assume( ucBUFFER_SIZE >= sizeof( ARPPacket_t ) && ucBUFFER_SIZE < 2 * sizeof( ARPPacket_t ) );
|
||||
void * xBuffer = malloc( ucBUFFER_SIZE );
|
||||
|
||||
__CPROVER_assume( xBuffer != NULL );
|
||||
|
||||
NetworkBufferDescriptor_t xNetworkBuffer2;
|
||||
|
||||
xNetworkBuffer2.pucEthernetBuffer = xBuffer;
|
||||
xNetworkBuffer2.xDataLength = ucBUFFER_SIZE;
|
||||
|
||||
/* vARPGenerateRequestPacket asserts buffer has room for a packet */
|
||||
__CPROVER_assume( xNetworkBuffer2.xDataLength >= sizeof( ARPPacket_t ) );
|
||||
vARPGenerateRequestPacket( &xNetworkBuffer2 );
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"ENTRY": "ARPGenerateRequestPacket",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
Given that the pointer target of xNetworkDescriptor.pucEthernetBuffer is allocated
|
||||
to the size claimed in xNetworkDescriptor.xDataLength,
|
||||
this harness proves the memory safety of ARPGenerateRequestPacket.
|
||||
@ -0,0 +1,17 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
uint32_t ulIPAddress;
|
||||
MACAddress_t xMACAddress;
|
||||
|
||||
eARPGetCacheEntry( &ulIPAddress, &xMACAddress );
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
{
|
||||
"ENTRY": "ARPGetCacheEntry",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset prvCacheLookup.0:7",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
{
|
||||
"ARPGetCacheEntry_default":[
|
||||
"ipconfigARP_STORES_REMOTE_ADDRESSES=0",
|
||||
"ipconfigUSE_LLMNR=0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ARPGetCacheEntry_LLMNR": [
|
||||
"ipconfigARP_STORES_REMOTE_ADDRESSES=0",
|
||||
"ipconfigUSE_LLMNR=1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ARPGetCacheEntry_STORE_REMOTE": [
|
||||
"ipconfigARP_STORES_REMOTE_ADDRESSES=1",
|
||||
"ipconfigUSE_LLMNR=0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ARPGetCacheEntry_REMOTE_LLMNR": [
|
||||
"ipconfigARP_STORES_REMOTE_ADDRESSES=1",
|
||||
"ipconfigUSE_LLMNR=1"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
The combined proofs in the subdirectories prove that ARPGetCacheEntry
|
||||
is memory safe for all possible combinations of ipconfigARP_STORES_REMOTE_ADDRESSES
|
||||
and ipconfigUSE_LLMNR. These are the only configuration
|
||||
parameters used inside the ARPGetCacheEntry.
|
||||
@ -0,0 +1,16 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
void harness()
|
||||
{
|
||||
MACAddress_t xMACAddress;
|
||||
uint32_t ulIPAddress;
|
||||
|
||||
eARPGetCacheEntryByMac( &xMACAddress, &ulIPAddress );
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
{
|
||||
"ENTRY": "ARPGetCacheEntryByMac",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 7",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigUSE_ARP_REVERSED_LOOKUP=1", "ipconfigARP_CACHE_ENTRIES=6"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
ARPGetCacheEntryByMac is memory safe,
|
||||
if it is enabled.
|
||||
|
||||
ARPGetCacheEntryByMac does not use multiple configurations internally.
|
||||
@ -0,0 +1,51 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
/* This pointer is maintained by the IP-task. Defined in FreeRTOS_IP.c */
|
||||
extern NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer;
|
||||
|
||||
/* This is an output function and need not be tested with this proof. */
|
||||
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
|
||||
{
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
ARPPacket_t xARPFrame;
|
||||
NetworkBufferDescriptor_t xLocalBuffer;
|
||||
uint16_t usEthernetBufferSize;
|
||||
|
||||
/* Non deterministically determine whether the pxARPWaitingNetworkBuffer will
|
||||
* point to some valid data or will it be NULL. */
|
||||
if( nondet_bool() )
|
||||
{
|
||||
/* The packet must at least be as big as an IP Packet. The size is not
|
||||
* checked in the function as the pointer is stored by the IP-task itself
|
||||
* and therefore it will always be of the required size. */
|
||||
__CPROVER_assume( usEthernetBufferSize >= sizeof( IPPacket_t ) );
|
||||
|
||||
/* Add matching data length to the network buffer descriptor. */
|
||||
__CPROVER_assume( xLocalBuffer.xDataLength == usEthernetBufferSize );
|
||||
|
||||
xLocalBuffer.pucEthernetBuffer = malloc( usEthernetBufferSize );
|
||||
|
||||
/* Since this pointer is maintained by the IP-task, either the pointer
|
||||
* pxARPWaitingNetworkBuffer will be NULL or xLocalBuffer.pucEthernetBuffer
|
||||
* will be non-NULL. */
|
||||
__CPROVER_assume( xLocalBuffer.pucEthernetBuffer != NULL );
|
||||
|
||||
pxARPWaitingNetworkBuffer = &xLocalBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxARPWaitingNetworkBuffer = NULL;
|
||||
}
|
||||
|
||||
eARPProcessPacket( &xARPFrame );
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
{
|
||||
"ENTRY": "ARPProcessPacket",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset vARPRefreshCacheEntry.0:7,memcmp.0:17,xIsIPInARPCache.0:7",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
The proofs in the subdirectories show that
|
||||
ARPProcessPacket is memory safe independent
|
||||
of the configuration value of
|
||||
ipconfigARP_USE_CLASH_DETECTION.
|
||||
@ -0,0 +1,16 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
void harness()
|
||||
{
|
||||
MACAddress_t xMACAddress;
|
||||
uint32_t ulIPAddress;
|
||||
|
||||
vARPRefreshCacheEntry( &xMACAddress, ulIPAddress );
|
||||
vARPRefreshCacheEntry( NULL, ulIPAddress );
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"ENTRY": "ARPRefreshCacheEntry",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset vARPRefreshCacheEntry.0:7,memcmp.0:17",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
{"NOT_STORE_REMOTE":["ipconfigARP_STORES_REMOTE_ADDRESSES=0"]},
|
||||
{"STORE_REMOTE":["ipconfigARP_STORES_REMOTE_ADDRESSES=1"]}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
The proofs in this directory guarantee together that
|
||||
ARPRefreshCacheEntry is memory safe independent
|
||||
of the configuration value of
|
||||
ipconfigARP_STORES_REMOTE_ADDRESSES.
|
||||
@ -0,0 +1,13 @@
|
||||
/* / * FreeRTOS includes. * / */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
vARPSendGratuitous();
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"ENTRY": "ARPSendGratuitous",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
Abstracting xQueueGenericSend away
|
||||
and including tasks.c and FreeRTOS_IP.c:
|
||||
The ARPSendGratutious function is memory safe,
|
||||
if xQueueGenericSend is memory safe.
|
||||
|
||||
queue.c is not compiled into the proof binary.
|
||||
@ -0,0 +1,12 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_ClearARP();
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
{
|
||||
"ENTRY": "ClearARP",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
This proof demonstrates the memory safety of the ClearARP function in the FreeRTOS_ARP.c file.
|
||||
No restrictions are made.
|
||||
@ -0,0 +1,58 @@
|
||||
#
|
||||
# FreeRTOS memory safety proofs with CBMC.
|
||||
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://aws.amazon.com/freertos
|
||||
# http://www.FreeRTOS.org
|
||||
#
|
||||
|
||||
{
|
||||
"ENTRY": "OutputARPRequest",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 20"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
#That is the minimal required size for an ARPPacket_t plus offset in the buffer.
|
||||
"MINIMUM_PACKET_BYTES": 50,
|
||||
"DEF":
|
||||
[
|
||||
{
|
||||
"CBMC_PROOF_ASSUMPTION_HOLDS_Packet_bytes": [
|
||||
"CBMC_PROOF_ASSUMPTION_HOLDS=1",
|
||||
"ipconfigETHERNET_MINIMUM_PACKET_BYTES={MINIMUM_PACKET_BYTES}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"CBMC_PROOF_ASSUMPTION_HOLDS_no_packet_bytes": ["CBMC_PROOF_ASSUMPTION_HOLDS=1"]
|
||||
},
|
||||
{
|
||||
"CBMC_PROOF_ASSUMPTION_DOES_NOT_HOLD": ["CBMC_PROOF_ASSUMPTION_HOLDS=0"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* FreeRTOS memory safety proofs with CBMC.
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
|
||||
ARPPacket_t xARPPacket;
|
||||
NetworkBufferDescriptor_t xNetworkBuffer;
|
||||
|
||||
/* STUB!
|
||||
* We assume that the pxGetNetworkBufferWithDescriptor function is
|
||||
* implemented correctly and returns a valid data structure.
|
||||
* This is the mock to mimic the expected behavior.
|
||||
* If this allocation fails, this might invalidate the proof.
|
||||
* FreeRTOS_OutputARPRequest calls pxGetNetworkBufferWithDescriptor
|
||||
* to get a NetworkBufferDescriptor. Then it calls vARPGenerateRequestPacket
|
||||
* passing this buffer along in the function call. vARPGenerateRequestPacket
|
||||
* casts the pointer xNetworkBuffer.pucEthernetBuffer into an ARPPacket_t pointer
|
||||
* and writes a complete ARPPacket to it. Therefore the buffer has to be at least of the size
|
||||
* of an ARPPacket to guarantee memory safety.
|
||||
*/
|
||||
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
|
||||
TickType_t xBlockTimeTicks )
|
||||
{
|
||||
#ifdef CBMC_PROOF_ASSUMPTION_HOLDS
|
||||
#if ( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 )
|
||||
xNetworkBuffer.pucEthernetBuffer = malloc( ipconfigETHERNET_MINIMUM_PACKET_BYTES );
|
||||
#else
|
||||
xNetworkBuffer.pucEthernetBuffer = malloc( xRequestedSizeBytes );
|
||||
#endif
|
||||
#else
|
||||
uint32_t malloc_size;
|
||||
__CPROVER_assert( !__CPROVER_overflow_mult( 2, xRequestedSizeBytes ) );
|
||||
__CPROVER_assume( malloc_size > 0 && malloc_size < 2 * xRequestedSizeBytes );
|
||||
xNetworkBuffer.pucEthernetBuffer = malloc( malloc_size );
|
||||
#endif
|
||||
__CPROVER_assume( xNetworkBuffer.pucEthernetBuffer != NULL );
|
||||
|
||||
xNetworkBuffer.xDataLength = xRequestedSizeBytes;
|
||||
return &xNetworkBuffer;
|
||||
}
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
uint32_t ulIPAddress;
|
||||
|
||||
FreeRTOS_OutputARPRequest( ulIPAddress );
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
This is the memory safety proof for FreeRTOS_OutputARPRequest.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* xNetworkInterfaceOutput
|
||||
|
||||
This proof checks FreeRTOS_OutputARPRequest in multiple configuration:
|
||||
|
||||
* The config_CBMC_PROOF_ASSUMPTION_HOLDS_no_packet_bytes proof
|
||||
guarantees that for a buffer allocated to xDataLength,
|
||||
the code executed by the FreeRTOS_OutputARPRequest function
|
||||
call of FreeRTOS_ARP.c is memory safe.
|
||||
* If the ipconfigETHERNET_MINIMUM_PACKET_BYTES is set and the
|
||||
buffer allocated by pxGetNetworkBufferWithDescriptor allocates
|
||||
a buffer of at least ipconfigETHERNET_MINIMUM_PACKET_BYTES,
|
||||
the config_CBMC_PROOF_ASSUMPTION_HOLDS_Packet_bytes proof
|
||||
guarantees that the code executed by the
|
||||
FreeRTOS_OutputARPRequest function call
|
||||
of FreeRTOS_ARP.c is memory safe.
|
||||
* The third configuration in the subdirectory
|
||||
config_CBMC_PROOF_ASSUMPTION_DOES_NOT_HOLD demonstrates
|
||||
that the code is not memory safe, if the allocation
|
||||
code violates our assumption.
|
||||
* All proofs mock the pxGetNetworkBufferWithDescriptor
|
||||
function for modelling the assumptions about the
|
||||
buffer management layer.
|
||||
@ -0,0 +1,14 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOSIPConfig.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_PrintARPCache();
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
{
|
||||
"ENTRY": "FreeRTOS_PrintARPCache",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 7",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigARP_CACHE_ENTRIES=6"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
FreeRTOS_PrintARPCache_harness.c is memory safe,
|
||||
assuming vLoggingPrintf is correct and memory safe.
|
||||
|
||||
FreeRTOS_PrintARPCache does not use multiple configurations.
|
||||
@ -0,0 +1,48 @@
|
||||
{
|
||||
"ENTRY": "OutputARPRequest",
|
||||
"MINIMUM_PACKET_BYTES": 50,
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind {MINIMUM_PACKET_BYTES}",
|
||||
"--unwindset xNetworkBuffersInitialise.0:3,xNetworkBuffersInitialise.1:3,vListInsert.0:3,pxGetNetworkBufferWithDescriptor.0:3,pxGetNetworkBufferWithDescriptor.1:3,vNetworkInterfaceAllocateRAMToBuffers.0:3"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/portable/BufferManagement/BufferAllocation_1.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
{
|
||||
"minimal_configuration":
|
||||
[
|
||||
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
|
||||
"configUSE_TRACE_FACILITY=0",
|
||||
"configGENERATE_RUN_TIME_STATS=0",
|
||||
"ipconfigUSE_LINKED_RX_MESSAGES=0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minimal_configuration_minimal_packet_size":
|
||||
[
|
||||
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
|
||||
"configUSE_TRACE_FACILITY=0",
|
||||
"configGENERATE_RUN_TIME_STATS=0",
|
||||
"ipconfigETHERNET_MINIMUM_PACKET_BYTES={MINIMUM_PACKET_BYTES}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minimal_configuration_linked_rx_messages":
|
||||
[
|
||||
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
|
||||
"configUSE_TRACE_FACILITY=0",
|
||||
"configGENERATE_RUN_TIME_STATS=0",
|
||||
"ipconfigUSE_LINKED_RX_MESSAGES=1"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
/* This harness is linked against
|
||||
* libraries/freertos_plus/standard/freertos_plus_tcp/source/portable/BufferManagement/BufferAllocation_1.goto
|
||||
*/
|
||||
#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_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#if ( ipconfigUSE_LLMNR == 1 )
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#endif /* ipconfigUSE_LLMNR */
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
|
||||
{
|
||||
for( int x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
|
||||
{
|
||||
NetworkBufferDescriptor_t * current = &pxNetworkBuffers[ x ];
|
||||
#if ( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 )
|
||||
current->pucEthernetBuffer = malloc( sizeof( ARPPacket_t ) + ( ipconfigETHERNET_MINIMUM_PACKET_BYTES - sizeof( ARPPacket_t ) ) );
|
||||
#else
|
||||
current->pucEthernetBuffer = malloc( sizeof( ARPPacket_t ) );
|
||||
#endif
|
||||
__CPROVER_assume( current->pucEthernetBuffer != NULL );
|
||||
current->xDataLength = sizeof( ARPPacket_t );
|
||||
}
|
||||
}
|
||||
|
||||
/* The code expects that the Semaphore creation relying on pvPortMalloc
|
||||
* is successful. This is checked by an assert statement, that gets
|
||||
* triggered when the allocation fails. Nevertheless, the code is perfectly
|
||||
* guarded against a failing Semaphore allocation. To make the assert pass,
|
||||
* it is assumed for now, that pvPortMalloc doesn't fail. Using a model allowing
|
||||
* failures of the allocation might be possible
|
||||
* after removing the assert in l.105 of BufferAllocation_1.c, from a memory
|
||||
* safety point of view. */
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
void * ptr = malloc( xWantedSize );
|
||||
|
||||
__CPROVER_assume( ptr != NULL );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is implemented by a third party.
|
||||
* After looking through a couple of samples in the demos folder, it seems
|
||||
* like the only shared contract is that you want to add the if statement
|
||||
* for releasing the buffer to the end. Apart from that, it is up to the vendor,
|
||||
* how to write this code out to the network.
|
||||
*/
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
|
||||
BaseType_t bReleaseAfterSend )
|
||||
{
|
||||
if( bReleaseAfterSend != pdFALSE )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
|
||||
}
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
BaseType_t xRes = xNetworkBuffersInitialise();
|
||||
|
||||
if( xRes == pdPASS )
|
||||
{
|
||||
uint32_t ulIPAddress;
|
||||
FreeRTOS_OutputARPRequest( ulIPAddress );
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
This is the memory safety proof for ```FreeRTOS_OutputARPRequest```
|
||||
method combined with the BufferAllocation_1.c allocation strategy.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* vPortEnterCritical
|
||||
* vPortExitCritical
|
||||
* vPortGenerateSimulatedInterrupt
|
||||
* vAssertCalled
|
||||
* xTaskGetSchedulerState
|
||||
* pvTaskIncrementMutexHeldCount
|
||||
* xTaskRemoveFromEventList
|
||||
* xTaskPriorityDisinherit
|
||||
|
||||
This proof checks ```FreeRTOS_OutputARPRequest``` in multiple configurations.
|
||||
All assume the memory safety of vNetworkInterfaceAllocateRAMToBuffers.
|
||||
* The ```config_minimal_configuration``` proof sets
|
||||
```ipconfigUSE_LINKED_RX_MESSAGES=0```.
|
||||
* The ```config_minimal_configuration_linked_rx_messages``` proof sets
|
||||
```ipconfigUSE_LINKED_RX_MESSAGES=1```.
|
||||
* The ```minimal_configuration_minimal_packet_size``` proof sets
|
||||
```ipconfigETHERNET_MINIMUM_PACKET_BYTES``` to 50.
|
||||
|
||||
All harnesses include the queue.c file, but test only for the happy path.
|
||||
@ -0,0 +1,49 @@
|
||||
{
|
||||
"ENTRY": "OutputARPRequest",
|
||||
"MINIMUM_PACKET_BYTES": 50,
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind {MINIMUM_PACKET_BYTES}",
|
||||
"--unwindset xNetworkBuffersInitialise.0:3,xNetworkBuffersInitialise.1:3,vListInsert.0:3,pxGetNetworkBufferWithDescriptor.0:3,pxGetNetworkBufferWithDescriptor.1:3,vNetworkInterfaceAllocateRAMToBuffers.0:3"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/portable/BufferManagement/BufferAllocation_2.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
{
|
||||
"minimal_configuration":
|
||||
[
|
||||
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
|
||||
"configUSE_TRACE_FACILITY=0",
|
||||
"configGENERATE_RUN_TIME_STATS=0",
|
||||
"ipconfigUSE_LINKED_RX_MESSAGES=0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minimal_configuration_minimal_packet_size":
|
||||
[
|
||||
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
|
||||
"configUSE_TRACE_FACILITY=0",
|
||||
"configGENERATE_RUN_TIME_STATS=0",
|
||||
"ipconfigETHERNET_MINIMUM_PACKET_BYTES={MINIMUM_PACKET_BYTES}",
|
||||
"ipconfigUSE_TCP=1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minimal_configuration_linked_rx_messages":
|
||||
[
|
||||
"ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS=2",
|
||||
"configUSE_TRACE_FACILITY=0",
|
||||
"configGENERATE_RUN_TIME_STATS=0",
|
||||
"ipconfigUSE_LINKED_RX_MESSAGES=1"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
/* This harness is linked against
|
||||
* libraries/freertos_plus/standard/freertos_plus_tcp/source/portable/BufferManagement/BufferAllocation_2.goto
|
||||
*/
|
||||
#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_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#if ( ipconfigUSE_LLMNR == 1 )
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#endif /* ipconfigUSE_LLMNR */
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
void * ptr = malloc( xWantedSize );
|
||||
|
||||
__CPROVER_assume( ptr != NULL );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
free( pv );
|
||||
}
|
||||
|
||||
/*
|
||||
* This function function writes a buffer to the network. We stub it
|
||||
* out here, and assume it has no side effects relevant to memory safety.
|
||||
*/
|
||||
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
|
||||
BaseType_t bReleaseAfterSend )
|
||||
{
|
||||
if( bReleaseAfterSend != pdFALSE )
|
||||
{
|
||||
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
|
||||
}
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
BaseType_t xRes = xNetworkBuffersInitialise();
|
||||
|
||||
if( xRes == pdPASS )
|
||||
{
|
||||
uint32_t ulIPAddress;
|
||||
FreeRTOS_OutputARPRequest( ulIPAddress );
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
This is the memory safety proof for FreeRTOS_OutputARPRequest
|
||||
method combined with the BufferAllocation_2.c allocation strategy.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* vPortEnterCritical
|
||||
* vPortExitCritical
|
||||
* vPortGenerateSimulatedInterrupt
|
||||
* vAssertCalled
|
||||
* xTaskGetSchedulerState
|
||||
* pvTaskIncrementMutexHeldCount
|
||||
* xTaskRemoveFromEventList
|
||||
* xTaskPriorityDisinherit
|
||||
|
||||
* pvPortMalloc
|
||||
* pvPortFree
|
||||
* xNetworkInterfaceOutput
|
||||
* vNetworkInterfaceAllocateRAMToBuffers
|
||||
|
||||
This proof disables the tracing library in the header.
|
||||
|
||||
This proof checks FreeRTOS_OutputARPRequest in multiple configuration:
|
||||
|
||||
* The proof in the directory config_minimal_configuration guarantees
|
||||
that the implementation and interaction between
|
||||
FreeRTOS_OutputARPRequest and
|
||||
FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c
|
||||
are memory save. This proof depends entirely of the implementation
|
||||
correctness of vNetworkInterfaceAllocateRAMToBuffers.
|
||||
* The proof in directory minimal_configuration_minimal_packet_size
|
||||
guarantees that using
|
||||
FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c
|
||||
along with the ipconfigETHERNET_MINIMUM_PACKET_BYTES is memory save
|
||||
as long as TCP is enabled ( ipconfigUSE_TCP 1 ) and
|
||||
ipconfigETHERNET_MINIMUM_PACKET_BYTES < sizeof( TCPPacket_t ).
|
||||
* The directory minimal_configuration_minimal_packet_size_no_tcp
|
||||
reminds that ipconfigETHERNET_MINIMUM_PACKET_BYTES must not be used
|
||||
if TCP is disabled ( ipconfigUSE_TCP 1 ) along with the
|
||||
FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c
|
||||
allocator.
|
||||
* The proof in directory
|
||||
config_minimal_configuration_linked_rx_messages guarantees that the
|
||||
ipconfigUSE_LINKED_RX_MESSAGES define does not interfere with the
|
||||
memory safety claim.
|
||||
|
||||
All harnesses include the queue.c file, but test only for the happy path.
|
||||
@ -0,0 +1,24 @@
|
||||
{
|
||||
"ENTRY": "ulARPRemoveCacheEntryByMac",
|
||||
"NUMBER_OF_CACHE_ENTRIES":6,
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
"INSTFLAGS":
|
||||
[
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigUSE_ARP_REMOVE_ENTRY=1",
|
||||
"ipconfigARP_CACHE_ENTRIES={NUMBER_OF_CACHE_ENTRIES}"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
const MACAddress_t xMACAddress;
|
||||
|
||||
/* The pointer passed to ulARPRemoveCacheEntryByMac cannot be NULL
|
||||
* (see the API definition). */
|
||||
ulARPRemoveCacheEntryByMac( &xMACAddress );
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "tasksStubs.h"
|
||||
|
||||
#ifndef TASK_STUB_COUNTER
|
||||
#define TASK_STUB_COUNTER 0;
|
||||
#endif
|
||||
|
||||
/* 5 is a magic number, but we need some number here as a default value.
|
||||
* This value is used to bound any loop depending on xTaskCheckForTimeOut
|
||||
* as a loop bound. It should be overwritten in the Makefile.json adapting
|
||||
* to the performance requirements of the harness. */
|
||||
#ifndef TASK_STUB_COUNTER_LIMIT
|
||||
#define TASK_STUB_COUNTER_LIMIT 5;
|
||||
#endif
|
||||
|
||||
|
||||
static BaseType_t xCounter = TASK_STUB_COUNTER;
|
||||
static BaseType_t xCounterLimit = TASK_STUB_COUNTER_LIMIT;
|
||||
|
||||
BaseType_t xTaskGetSchedulerState( void )
|
||||
{
|
||||
return xState;
|
||||
}
|
||||
|
||||
|
||||
/* This function is another method apart from overwriting the defines to init the max
|
||||
* loop bound. */
|
||||
void vInitTaskCheckForTimeOut( BaseType_t maxCounter,
|
||||
BaseType_t maxCounter_limit )
|
||||
{
|
||||
xCounter = maxCounter;
|
||||
xCounterLimit = maxCounter_limit;
|
||||
}
|
||||
|
||||
/* This is mostly called in a loop. For CBMC, we have to bound the loop
|
||||
* to a max limits of calls. Therefore this Stub models a nondet timeout in
|
||||
* max TASK_STUB_COUNTER_LIMIT iterations.*/
|
||||
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
||||
TickType_t * const pxTicksToWait )
|
||||
{
|
||||
++xCounter;
|
||||
|
||||
if( xCounter == xCounterLimit )
|
||||
{
|
||||
return pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nondet_basetype();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
list(APPEND cbmc_compile_options
|
||||
-m32
|
||||
)
|
||||
|
||||
list(APPEND cbmc_compile_definitions
|
||||
CBMC
|
||||
WINVER=0x400
|
||||
_CONSOLE
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
_DEBUG
|
||||
_WIN32_WINNT=0x0500
|
||||
__PRETTY_FUNCTION__=__FUNCTION__
|
||||
__free_rtos__
|
||||
)
|
||||
|
||||
list(APPEND cbmc_compile_includes
|
||||
${CMAKE_SOURCE_DIR}/Source/include
|
||||
${CMAKE_SOURCE_DIR}/Source/portable/MSVC-MingW
|
||||
${CMAKE_SOURCE_DIR}/Source/../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement
|
||||
${CMAKE_SOURCE_DIR}/Source/../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include
|
||||
${CMAKE_SOURCE_DIR}/Source/../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC
|
||||
${cbmc_dir}/include
|
||||
${cbmc_dir}/windows
|
||||
)
|
||||
|
||||
# Remove --flag for a specific proof with list(REMOVE_ITEM cbmc_flags --flag)
|
||||
list(APPEND cbmc_flags
|
||||
--32
|
||||
--bounds-check
|
||||
--pointer-check
|
||||
--div-by-zero-check
|
||||
--float-overflow-check
|
||||
--nan-check
|
||||
--nondet-static
|
||||
--pointer-overflow-check
|
||||
--signed-overflow-check
|
||||
--undefined-shift-check
|
||||
--unsigned-overflow-check
|
||||
)
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
/* 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_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* Signature of function under test
|
||||
****************************************************************/
|
||||
|
||||
BaseType_t __CPROVER_file_local_FreeRTOS_TCP_IP_c_prvCheckOptions( FreeRTOS_Socket_t * pxSocket,
|
||||
const NetworkBufferDescriptor_t * pxNetworkBuffer );
|
||||
|
||||
/****************************************************************
|
||||
* Declare the buffer size external to the harness so it can be
|
||||
* accessed by the preconditions of prvSingleStepTCPHeaderOptions, and
|
||||
* give the buffer size an unconstrained value in the harness itself.
|
||||
****************************************************************/
|
||||
size_t buffer_size;
|
||||
|
||||
/****************************************************************
|
||||
* Function contract proved correct by CheckOptionsOuter
|
||||
****************************************************************/
|
||||
|
||||
int32_t __CPROVER_file_local_FreeRTOS_TCP_IP_c_prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
|
||||
size_t uxTotalLength,
|
||||
FreeRTOS_Socket_t * const pxSocket,
|
||||
BaseType_t xHasSYNFlag )
|
||||
{
|
||||
/* CBMC model of pointers limits the size of the buffer */
|
||||
|
||||
/* Preconditions */
|
||||
__CPROVER_assert( buffer_size < CBMC_MAX_OBJECT_SIZE,
|
||||
"prvSingleStepTCPHeaderOptions: buffer_size < CBMC_MAX_OBJECT_SIZE" );
|
||||
__CPROVER_assert( 8 <= buffer_size,
|
||||
"prvSingleStepTCPHeaderOptions: 8 <= buffer_size" );
|
||||
__CPROVER_assert( pucPtr != NULL,
|
||||
"prvSingleStepTCPHeaderOptions: pucPtr != NULL" );
|
||||
__CPROVER_assert( uxTotalLength <= buffer_size,
|
||||
"prvSingleStepTCPHeaderOptions: uxTotalLength <= buffer_size" );
|
||||
__CPROVER_assert( pxSocket != NULL,
|
||||
"prvSingleStepTCPHeaderOptions: pxSocket != NULL" );
|
||||
|
||||
/* Postconditions */
|
||||
int32_t index;
|
||||
|
||||
__CPROVER_assume( ( index == -1 ) || ( index == 1 ) || ( index <= uxTotalLength ) );
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Proof of CheckOptions
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
/* Give buffer_size an unconstrained value */
|
||||
size_t buf_size;
|
||||
|
||||
buffer_size = buf_size;
|
||||
|
||||
/* pxSocket can be any socket */
|
||||
FreeRTOS_Socket_t pxSocket;
|
||||
|
||||
/* pxNetworkBuffer can be any buffer descriptor with any buffer */
|
||||
NetworkBufferDescriptor_t pxNetworkBuffer;
|
||||
|
||||
pxNetworkBuffer.pucEthernetBuffer = malloc( buffer_size );
|
||||
__CPROVER_assume( pxNetworkBuffer.pucEthernetBuffer != NULL );
|
||||
pxNetworkBuffer.xDataLength = buffer_size;
|
||||
|
||||
/****************************************************************
|
||||
* Specification and proof of CheckOptions
|
||||
****************************************************************/
|
||||
|
||||
/* CBMC model of pointers limits the size of the buffer */
|
||||
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
|
||||
|
||||
/* Bound required to bound iteration over the buffer */
|
||||
__CPROVER_assume( buffer_size <= BUFFER_SIZE );
|
||||
|
||||
/* Buffer must be big enough to hold pxTCPPacket and pxTCPHeader */
|
||||
__CPROVER_assume( buffer_size > 47 );
|
||||
|
||||
__CPROVER_file_local_FreeRTOS_TCP_IP_c_prvCheckOptions( &pxSocket, &pxNetworkBuffer );
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
{
|
||||
"ENTRY": "CheckOptions",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
" --unwindset __CPROVER_file_local_FreeRTOS_TCP_IP_c_prvCheckOptions.0:41"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_WIN.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Stream_Buffer.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
|
||||
],
|
||||
"BUFFER_SIZE": 100,
|
||||
"DEF":
|
||||
[
|
||||
"BUFFER_SIZE={BUFFER_SIZE}"
|
||||
],
|
||||
"OPT":
|
||||
[
|
||||
"--export-file-local-symbols"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
/* 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_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* Signature of function under test
|
||||
****************************************************************/
|
||||
|
||||
void prvReadSackOption( const uint8_t * const pucPtr,
|
||||
size_t uxIndex,
|
||||
FreeRTOS_Socket_t * const pxSocket );
|
||||
|
||||
/****************************************************************
|
||||
* Proof of prvReadSackOption function contract
|
||||
****************************************************************/
|
||||
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
/* pucPtr points into a buffer */
|
||||
size_t buffer_size;
|
||||
uint8_t * pucPtr = malloc( buffer_size );
|
||||
|
||||
__CPROVER_assume( pucPtr != NULL );
|
||||
|
||||
/* uxIndex in an index into the buffer */
|
||||
size_t uxIndex;
|
||||
|
||||
/* pxSocket can be any socket with some initialized values */
|
||||
FreeRTOS_Socket_t * pxSocket = malloc( sizeof( FreeRTOS_Socket_t ) );
|
||||
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
|
||||
pxSocket->u.xTCP.txStream = malloc( sizeof( StreamBuffer_t ) );
|
||||
__CPROVER_assume( pxSocket->u.xTCP.txStream != NULL );
|
||||
|
||||
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xWaitQueue );
|
||||
|
||||
if( nondet_bool() )
|
||||
{
|
||||
TCPSegment_t * segment = malloc( sizeof( TCPSegment_t ) );
|
||||
__CPROVER_assume( segment != NULL );
|
||||
listSET_LIST_ITEM_OWNER( &segment->xQueueItem, ( void * ) segment );
|
||||
vListInsertEnd( &pxSocket->u.xTCP.xTCPWindow.xWaitQueue, &segment->xQueueItem );
|
||||
}
|
||||
|
||||
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xTxSegments );
|
||||
|
||||
if( nondet_bool() )
|
||||
{
|
||||
TCPSegment_t * segment = malloc( sizeof( TCPSegment_t ) );
|
||||
__CPROVER_assume( segment != NULL );
|
||||
vListInitialiseItem( &segment->xSegmentItem );
|
||||
listSET_LIST_ITEM_OWNER( &segment->xQueueItem, ( void * ) segment );
|
||||
vListInsertEnd( &pxSocket->u.xTCP.xTCPWindow.xTxSegments, &segment->xQueueItem );
|
||||
}
|
||||
|
||||
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xPriorityQueue );
|
||||
|
||||
extern List_t xSegmentList;
|
||||
|
||||
vListInitialise( &xSegmentList );
|
||||
|
||||
/****************************************************************
|
||||
* Specification and proof of CheckOptions inner loop
|
||||
****************************************************************/
|
||||
|
||||
/* Preconditions */
|
||||
|
||||
/* CBMC model of pointers limits the size of the buffer */
|
||||
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
|
||||
|
||||
/* Both preconditions are required to avoid integer overflow in the */
|
||||
/* pointer offset of the pointer pucPtr + uxIndex + 8 */
|
||||
__CPROVER_assume( uxIndex <= buffer_size );
|
||||
__CPROVER_assume( uxIndex + 8 <= buffer_size );
|
||||
|
||||
/* Assuming quite a bit more about the initialization of pxSocket */
|
||||
__CPROVER_assume( pucPtr != NULL );
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
|
||||
prvReadSackOption( pucPtr, uxIndex, pxSocket );
|
||||
|
||||
/* No postconditions required */
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
{
|
||||
"ENTRY": "CheckOptionsInner",
|
||||
"CBMCFLAGS": [
|
||||
"--unwind 1",
|
||||
"--unwindset prvTCPWindowTxCheckAck.1:2,prvTCPWindowFastRetransmit.2:2"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_WIN.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Stream_Buffer.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
/* 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_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* Signature of the function under test
|
||||
****************************************************************/
|
||||
|
||||
int32_t __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
|
||||
size_t uxTotalLength,
|
||||
FreeRTOS_Socket_t * const pxSocket,
|
||||
BaseType_t xHasSYNFlag );
|
||||
|
||||
/****************************************************************
|
||||
* Declare the buffer size external to the harness so it can be
|
||||
* accessed by the preconditions of prvReadSackOption, and give the
|
||||
* buffer size an unconstrained value in the harness itself.
|
||||
****************************************************************/
|
||||
|
||||
size_t buffer_size;
|
||||
|
||||
/****************************************************************
|
||||
* Function contract proved correct by CheckOptionsInner
|
||||
****************************************************************/
|
||||
|
||||
void __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvReadSackOption( const uint8_t * const pucPtr,
|
||||
size_t uxIndex,
|
||||
FreeRTOS_Socket_t * const pxSocket )
|
||||
{
|
||||
/* Preconditions */
|
||||
__CPROVER_assert( buffer_size < CBMC_MAX_OBJECT_SIZE,
|
||||
"prvReadSackOption: buffer_size < CBMC_MAX_OBJECT_SIZE" );
|
||||
__CPROVER_assert( uxIndex <= buffer_size,
|
||||
"prvReadSackOption: uxIndex <= buffer_size" );
|
||||
__CPROVER_assert( uxIndex + 8 <= buffer_size,
|
||||
"prvReadSackOption: uxIndex + 8 <= buffer_size" );
|
||||
__CPROVER_assert( pucPtr != NULL,
|
||||
"prvReadSackOption: pucPtr != NULL" );
|
||||
__CPROVER_assert( pxSocket != NULL,
|
||||
"prvReadSackOption: pxSocket != NULL" );
|
||||
|
||||
/* No postconditions required */
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Proof of prvSingleStepTCPHeaderOptions function contract
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
/* Give buffer_size an unconstrained value */
|
||||
size_t buf_size;
|
||||
|
||||
buffer_size = buf_size;
|
||||
|
||||
uint8_t * pucPtr = malloc( buffer_size );
|
||||
size_t uxTotalLength;
|
||||
FreeRTOS_Socket_t * pxSocket = malloc( sizeof( FreeRTOS_Socket_t ) );
|
||||
BaseType_t xHasSYNFlag;
|
||||
|
||||
/****************************************************************
|
||||
* Specification and proof of CheckOptions outer loop
|
||||
****************************************************************/
|
||||
|
||||
/* CBMC model of pointers limits the size of the buffer */
|
||||
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
|
||||
|
||||
/* Preconditions */
|
||||
__CPROVER_assume( 8 <= buffer_size ); /* ulFirst and ulLast */
|
||||
__CPROVER_assume( pucPtr != NULL );
|
||||
__CPROVER_assume( uxTotalLength <= buffer_size );
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
|
||||
int32_t index = __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvSingleStepTCPHeaderOptions( pucPtr,
|
||||
uxTotalLength,
|
||||
pxSocket,
|
||||
xHasSYNFlag );
|
||||
|
||||
/* Postconditions */
|
||||
__CPROVER_assert( ( ( index == -1 ) || ( index == 1 ) || ( index <= uxTotalLength ) ),
|
||||
"prvSingleStepTCPHeaderOptions: index <= uxTotalLength" );
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
{
|
||||
"ENTRY": "CheckOptionsOuter",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset __CPROVER_file_local_FreeRTOS_TCP_Reception_c_prvSingleStepTCPHeaderOptions.2:32"
|
||||
],
|
||||
"OPT":
|
||||
[
|
||||
"--export-file-local-symbols"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_Reception.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_WIN.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Stream_Buffer.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* FreeRTOS memory safety proofs with CBMC.
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
/* Static members defined in FreeRTOS_DHCP.c */
|
||||
extern DHCPData_t xDHCPData;
|
||||
extern Socket_t xDHCPSocket;
|
||||
void prvCreateDHCPSocket();
|
||||
|
||||
/* Static member defined in freertos_api.c */
|
||||
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
|
||||
extern uint32_t GetNetworkBuffer_failure_count;
|
||||
#endif
|
||||
|
||||
/****************************************************************
|
||||
* The signature of the function under test.
|
||||
****************************************************************/
|
||||
|
||||
void vDHCPProcess( BaseType_t xReset,
|
||||
eDHCPState_t eExpectedState );
|
||||
|
||||
/****************************************************************
|
||||
* Abstract prvProcessDHCPReplies proved memory safe in ProcessDHCPReplies.
|
||||
****************************************************************/
|
||||
|
||||
BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
|
||||
{
|
||||
return nondet_BaseType();
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* The proof of vDHCPProcess
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
BaseType_t xReset;
|
||||
eDHCPState_t eExpectedState;
|
||||
|
||||
/****************************************************************
|
||||
* Initialize the counter used to bound the number of times
|
||||
* GetNetworkBufferWithDescriptor can fail.
|
||||
****************************************************************/
|
||||
|
||||
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
|
||||
GetNetworkBuffer_failure_count = 0;
|
||||
#endif
|
||||
|
||||
/****************************************************************
|
||||
* Assume a valid socket in most states of the DHCP state machine.
|
||||
*
|
||||
* The socket is created in the eWaitingSendFirstDiscover state.
|
||||
* xReset==True resets the state to eWaitingSendFirstDiscover.
|
||||
****************************************************************/
|
||||
|
||||
if( !( ( xDHCPData.eDHCPState == eInitialWait ) ||
|
||||
( xReset != pdFALSE ) ) )
|
||||
{
|
||||
prvCreateDHCPSocket();
|
||||
__CPROVER_assume( xDHCPSocket != NULL );
|
||||
}
|
||||
|
||||
vDHCPProcess( xReset, eExpectedState );
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
#
|
||||
# FreeRTOS memory safety proofs with CBMC.
|
||||
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://aws.amazon.com/freertos
|
||||
# http://www.FreeRTOS.org
|
||||
#
|
||||
|
||||
{
|
||||
"ENTRY": "DHCPProcess",
|
||||
|
||||
# Minimal buffer size for maximum coverage, see harness for details.
|
||||
"BUFFER_SIZE": 299,
|
||||
|
||||
# The number of times GetNetworkBufferWithDescriptor can be allowed to fail
|
||||
# (plus 1).
|
||||
"FAILURE_BOUND": 2,
|
||||
|
||||
"CBMCFLAGS": "--unwind 4 --unwindset strlen.0:11,memcmp.0:7,prvProcessDHCPReplies.0:8,prvCreatePartDHCPMessage.0:{FAILURE_BOUND} --nondet-static --flush",
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_ARP.goto"
|
||||
],
|
||||
|
||||
"DEF":
|
||||
[
|
||||
"BUFFER_SIZE={BUFFER_SIZE}",
|
||||
"CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL=1",
|
||||
"CBMC_GETNETWORKBUFFER_FAILURE_BOUND={FAILURE_BOUND}"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
This is the memory safety proof for DHCPProcess function, which is the
|
||||
function that triggers the DHCP protocol.
|
||||
|
||||
The main stubs in this proof deal with buffer management, which assume
|
||||
that the buffer is large enough to accomodate a DHCP message plus a
|
||||
few additional bytes for options (which is the last, variable-sized
|
||||
field in a DHCP message). We have abstracted away sockets, concurrency
|
||||
and third-party code. For more details, please check the comments on
|
||||
the harness file.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* FreeRTOS_sendto
|
||||
* FreeRTOS_setsockopt
|
||||
* FreeRTOS_socket
|
||||
* ulRand
|
||||
* vARPSendGratuitous
|
||||
* vApplicationIPNetworkEventHook
|
||||
* vLoggingPrintf
|
||||
* vPortEnterCritical
|
||||
* vPortExitCritical
|
||||
* vReleaseNetworkBufferAndDescriptor
|
||||
* vSocketBind
|
||||
* vSocketClose
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
"vPortEnterCritical",
|
||||
"vPortExitCritical",
|
||||
"vSocketBind",
|
||||
"vSocketClose",
|
||||
"vTaskSetTimeOutState",
|
||||
"xTaskGetTickCount",
|
||||
"xTaskGetCurrentTaskHandle",
|
||||
"xQueueGenericSend",
|
||||
"xApplicationGetRandomNumber",
|
||||
"vLoggingPrintf"
|
||||
],
|
||||
"proof-name": "DHCPProcess",
|
||||
"proof-root": "tools/cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* FreeRTOS memory safety proofs with CBMC.
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
|
||||
/*
|
||||
* The harness test proceeds to call IsDHCPSocket with an unconstrained value
|
||||
*/
|
||||
void harness()
|
||||
{
|
||||
Socket_t xSocket;
|
||||
BaseType_t xResult;
|
||||
|
||||
xResult = xIsDHCPSocket( xSocket );
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
#
|
||||
# FreeRTOS memory safety proofs with CBMC.
|
||||
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://aws.amazon.com/freertos
|
||||
# http://www.FreeRTOS.org
|
||||
#
|
||||
|
||||
{
|
||||
"ENTRY": "IsDHCPSocket",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
This is the memory safety proof for IsDCHPSocket.
|
||||
@ -0,0 +1,24 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
|
||||
/* Function prvParseDNSReply is proven to be correct separately.
|
||||
* The proof can be found here: https://github.com/aws/amazon-freertos/tree/master/tools/cbmc/proofs/ParseDNSReply */
|
||||
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
|
||||
size_t xBufferLength,
|
||||
BaseType_t xExpected )
|
||||
{
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
NetworkBufferDescriptor_t xNetworkBuffer;
|
||||
|
||||
xNetworkBuffer.pucEthernetBuffer = malloc( sizeof( UDPPacket_t ) + sizeof( DNSMessage_t ) );
|
||||
ulDNSHandlePacket( &xNetworkBuffer );
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
{
|
||||
"ENTRY": "DNShandlePacket",
|
||||
"CBMCFLAGS": "--unwind 1",
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
if( ipconfigUSE_DNS_CACHE != 0 )
|
||||
{
|
||||
FreeRTOS_dnsclear();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"ENTRY": "DNSclear",
|
||||
################################################################
|
||||
# This configuration flag uses DNS cache
|
||||
"USE_CACHE":1,
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigUSE_DNS_CACHE={USE_CACHE}"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,171 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
uint32_t FreeRTOS_dnslookup( const char * pcHostName );
|
||||
Socket_t DNS_CreateSocket( TickType_t uxReadTimeout_ticks );
|
||||
void DNS_CloseSocket( Socket_t xDNSSocket );
|
||||
void DNS_ReadReply( Socket_t xDNSSocket,
|
||||
struct freertos_sockaddr * xAddress,
|
||||
struct xDNSBuffer * pxDNSBuf );
|
||||
uint32_t DNS_SendRequest( Socket_t xDNSSocket,
|
||||
struct freertos_sockaddr * xAddress,
|
||||
struct xDNSBuffer * pxDNSBuf );
|
||||
uint32_t DNS_ParseDNSReply( uint8_t * pucUDPPayloadBuffer,
|
||||
size_t xBufferLength,
|
||||
BaseType_t xExpected );
|
||||
|
||||
/****************************************************************
|
||||
* We abstract:
|
||||
*
|
||||
* All kernel task scheduling functions since we are doing
|
||||
* sequential verification and the sequential verification of these
|
||||
* sequential primitives is done elsewhere.
|
||||
*
|
||||
* Many methods in the FreeRTOS TCP API in stubs/freertos_api.c
|
||||
*
|
||||
* DNS_ParseDNSReply proved memory safe elsewhere
|
||||
*
|
||||
* prvCreateDNSMessage
|
||||
*
|
||||
* This proof assumes the length of pcHostName is bounded by
|
||||
* MAX_HOSTNAME_LEN. We have to bound this length because we have to
|
||||
* bound the iterations of strcmp.
|
||||
****************************************************************/
|
||||
|
||||
/****************************************************************
|
||||
* Abstract DNS_ParseDNSReply proved memory safe in ParseDNSReply.
|
||||
*
|
||||
* We stub out his function to fill the payload buffer with
|
||||
* unconstrained data and return an unconstrained size.
|
||||
*
|
||||
* The function under test uses only the return value of this
|
||||
* function.
|
||||
****************************************************************/
|
||||
|
||||
uint32_t DNS_ParseDNSReply( uint8_t * pucUDPPayloadBuffer,
|
||||
size_t xBufferLength,
|
||||
BaseType_t xExpected )
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
__CPROVER_havoc_object( pucUDPPayloadBuffer );
|
||||
return size;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Abstract DNS_SendRequest
|
||||
*
|
||||
* We stub out this function with return constraint of true or false
|
||||
*
|
||||
****************************************************************/
|
||||
uint32_t DNS_SendRequest( Socket_t xDNSSocket,
|
||||
struct freertos_sockaddr * xAddress,
|
||||
struct xDNSBuffer * pxDNSBuf )
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
__CPROVER_assume( ret >= 0 );
|
||||
__CPROVER_assume( ret <= 1 );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Abstract DNS_ReadReply
|
||||
*
|
||||
* We stub out this function which returned a dns_buffer filled with random data
|
||||
*
|
||||
****************************************************************/
|
||||
void DNS_ReadReply( Socket_t xDNSSocket,
|
||||
struct freertos_sockaddr * xAddress,
|
||||
struct xDNSBuffer * pxDNSBuf )
|
||||
{
|
||||
int len;
|
||||
|
||||
pxDNSBuf->pucPayloadBuffer = safeMalloc( len );
|
||||
|
||||
pxDNSBuf->uxPayloadLength = len;
|
||||
|
||||
__CPROVER_assume( len < CBMC_MAX_OBJECT_SIZE );
|
||||
__CPROVER_assume( pxDNSBuf->pucPayloadBuffer != NULL );
|
||||
|
||||
__CPROVER_havoc_slice( pxDNSBuf->pucPayloadBuffer, pxDNSBuf->uxPayloadSize );
|
||||
}
|
||||
|
||||
|
||||
void DNS_CloseSocket( Socket_t xDNSSocket )
|
||||
{
|
||||
}
|
||||
|
||||
Socket_t DNS_CreateSocket( TickType_t uxReadTimeout_ticks )
|
||||
{
|
||||
Socket_t sock;
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
uint32_t FreeRTOS_dnslookup( const char * pcHostName )
|
||||
{
|
||||
int ret;
|
||||
|
||||
__CPROVER_assume( ret < 0xFFFF );
|
||||
__CPROVER_assume( ret > 0 );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Abstract prvCreateDNSMessage
|
||||
*
|
||||
* This function writes a header, a hostname, and a constant amount of
|
||||
* data into the payload buffer, and returns the amount of data
|
||||
* written. This abstraction just fills the entire buffer with
|
||||
* unconstrained data and returns and unconstrained length.
|
||||
****************************************************************/
|
||||
|
||||
size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
|
||||
const char * pcHostName,
|
||||
TickType_t uxIdentifier )
|
||||
{
|
||||
__CPROVER_havoc_object( pucUDPPayloadBuffer );
|
||||
size_t size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* The proof for FreeRTOS_gethostbyname.
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
size_t len;
|
||||
|
||||
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
|
||||
char * pcHostName = safeMalloc( len );
|
||||
|
||||
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
|
||||
__CPROVER_assume( pcHostName != NULL );
|
||||
pcHostName[ len - 1 ] = NULL;
|
||||
|
||||
FreeRTOS_gethostbyname( pcHostName );
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
{
|
||||
"ENTRY": "DNSgetHostByName",
|
||||
|
||||
################################################################
|
||||
# This configuration sets callback to 0.
|
||||
# It also sets MAX_HOSTNAME_LEN to 10 to bound strcmp.
|
||||
# According to the specification MAX_HOST_NAME is upto 255.
|
||||
|
||||
"callback": 0,
|
||||
"MAX_HOSTNAME_LEN": 10,
|
||||
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
|
||||
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},strcmp.0:{HOSTNAME_UNWIND},strcpy.0:{HOSTNAME_UNWIND}",
|
||||
"--unwindset prvGetHostByNameOp_WithRetry.0:{HOSTNAME_UNWIND}",
|
||||
"--nondet-static"
|
||||
],
|
||||
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto"
|
||||
],
|
||||
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigDNS_USE_CALLBACKS={callback}",
|
||||
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
"vLoggingPrintf",
|
||||
"xApplicationGetRandomNumber",
|
||||
"xTaskGetTickCount"
|
||||
],
|
||||
"proof-name": "DNSgetHostByName",
|
||||
"proof-root": "tools/cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* We abstract:
|
||||
*
|
||||
* All kernel task scheduling functions since we are doing
|
||||
* sequential verification and the sequential verification of these
|
||||
* sequential primitives is done elsewhere.
|
||||
*
|
||||
* Many methods in the FreeRTOS TCP API in stubs/freertos_api.c
|
||||
*
|
||||
* DNS_ParseDNSReply proved memory safe elsewhere
|
||||
*
|
||||
* prvCreateDNSMessage
|
||||
*
|
||||
* This proof assumes the length of pcHostName is bounded by
|
||||
* MAX_HOSTNAME_LEN. We have to bound this length because we have to
|
||||
* bound the iterations of strcmp.
|
||||
****************************************************************/
|
||||
|
||||
/****************************************************************
|
||||
* Abstract DNS_ParseDNSReply proved memory safe in ParseDNSReply.
|
||||
*
|
||||
* We stub out his function to fill the payload buffer with
|
||||
* unconstrained data and return an unconstrained size.
|
||||
*
|
||||
* The function under test uses only the return value of this
|
||||
* function.
|
||||
****************************************************************/
|
||||
|
||||
uint32_t DNS_ParseDNSReply( uint8_t * pucUDPPayloadBuffer,
|
||||
size_t xBufferLength,
|
||||
BaseType_t xExpected )
|
||||
{
|
||||
__CPROVER_assert( pucUDPPayloadBuffer != NULL,
|
||||
"Precondition: pucUDPPayloadBuffer != NULL" );
|
||||
|
||||
__CPROVER_havoc_object( pucUDPPayloadBuffer );
|
||||
return nondet_uint32();
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Abstract prvCreateDNSMessage
|
||||
*
|
||||
* This function writes a header, a hostname, and a constant amount of
|
||||
* data into the payload buffer, and returns the amount of data
|
||||
* written. This abstraction just fills the entire buffer with
|
||||
* unconstrained data and returns and unconstrained length.
|
||||
****************************************************************/
|
||||
|
||||
size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
|
||||
const char * pcHostName,
|
||||
TickType_t uxIdentifier )
|
||||
{
|
||||
__CPROVER_assert( pucUDPPayloadBuffer != NULL,
|
||||
"Precondition: pucUDPPayloadBuffer != NULL" );
|
||||
__CPROVER_assert( pcHostName != NULL,
|
||||
"Precondition: pcHostName != NULL" );
|
||||
|
||||
__CPROVER_havoc_object( pucUDPPayloadBuffer );
|
||||
return nondet_sizet();
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* A stub for a function callback.
|
||||
****************************************************************/
|
||||
|
||||
void func( const char * pcHostName,
|
||||
void * pvSearchID,
|
||||
uint32_t ulIPAddress )
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* The proof for FreeRTOS_gethostbyname_a.
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
size_t len;
|
||||
|
||||
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
|
||||
char * pcHostName = safeMalloc( len );
|
||||
|
||||
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
|
||||
__CPROVER_assume( pcHostName != NULL );
|
||||
pcHostName[ len - 1 ] = NULL;
|
||||
|
||||
FOnDNSEvent pCallback = func;
|
||||
TickType_t xTimeout;
|
||||
void * pvSearchID;
|
||||
|
||||
FreeRTOS_gethostbyname_a( pcHostName, pCallback, pvSearchID, xTimeout );
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
{
|
||||
"ENTRY": "DNSgetHostByName_a",
|
||||
################################################################
|
||||
# This configuration flag sets callback to 1. It also sets MAX_HOSTNAME_LEN to 10 and MAX_REQ_SIZE to 50 for performance issues.
|
||||
# According to the specification MAX_HOST_NAME is upto 255.
|
||||
"callback": 1,
|
||||
"MAX_HOSTNAME_LEN": 10,
|
||||
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},prvGetHostByName.0:{HOSTNAME_UNWIND},prvProcessDNSCache.0:5,strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},strcmp.0:{HOSTNAME_UNWIND},xTaskResumeAll.0:{HOSTNAME_UNWIND},xTaskResumeAll.1:{HOSTNAME_UNWIND},strcpy.0:{HOSTNAME_UNWIND}",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigDNS_USE_CALLBACKS={callback}",
|
||||
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
|
||||
# This value is defined only when ipconfigUSE_DNS_CACHE==1
|
||||
"ipconfigDNS_CACHE_NAME_LENGTH=254"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
"vLoggingPrintf",
|
||||
"xApplicationGetRandomNumber",
|
||||
"vListInsertEnd",
|
||||
"vTaskSetTimeOutState",
|
||||
"vTaskSuspendAll",
|
||||
"xTaskGetTickCount",
|
||||
"xTaskResumeAll"
|
||||
],
|
||||
"proof-name": "DNSgetHostByName_a",
|
||||
"proof-root": "tools/cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
|
||||
|
||||
/* This proof assumes the length of pcHostName is bounded by MAX_HOSTNAME_LEN. This also abstracts the concurrency. */
|
||||
|
||||
void vDNSInitialise( void );
|
||||
|
||||
void vDNSSetCallBack( const char * pcHostName,
|
||||
void * pvSearchID,
|
||||
FOnDNSEvent pCallbackFunction,
|
||||
TickType_t xTimeout,
|
||||
TickType_t xIdentifier );
|
||||
|
||||
void * safeMalloc( size_t xWantedSize ) /* Returns a NULL pointer if the wanted size is 0. */
|
||||
{
|
||||
if( xWantedSize == 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t byte;
|
||||
|
||||
return byte ? malloc( xWantedSize ) : NULL;
|
||||
}
|
||||
|
||||
/* Abstraction of xTaskCheckForTimeOut from task pool. This also abstracts the concurrency. */
|
||||
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
||||
TickType_t * const pxTicksToWait )
|
||||
{
|
||||
}
|
||||
|
||||
/* Abstraction of xTaskResumeAll from task pool. This also abstracts the concurrency. */
|
||||
BaseType_t xTaskResumeAll( void )
|
||||
{
|
||||
}
|
||||
|
||||
/* The function func mimics the callback function.*/
|
||||
void func( const char * pcHostName,
|
||||
void * pvSearchID,
|
||||
uint32_t ulIPAddress )
|
||||
{
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
vDNSInitialise(); /* We initialize the callbacklist in order to be able to check for functions that timed out. */
|
||||
size_t pvSearchID;
|
||||
FOnDNSEvent pCallback = func;
|
||||
TickType_t xTimeout;
|
||||
TickType_t xIdentifier;
|
||||
size_t len;
|
||||
|
||||
__CPROVER_assume( len >= 0 && len <= MAX_HOSTNAME_LEN );
|
||||
char * pcHostName = safeMalloc( len );
|
||||
|
||||
if( len && pcHostName )
|
||||
{
|
||||
pcHostName[ len - 1 ] = NULL;
|
||||
}
|
||||
|
||||
vDNSSetCallBack( pcHostName, &pvSearchID, pCallback, xTimeout, xIdentifier ); /* Add an item to be able to check the cancel function if the list is non-empty. */
|
||||
FreeRTOS_gethostbyname_cancel( &pvSearchID );
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
{
|
||||
"ENTRY": "DNSgetHostByName_cancel",
|
||||
################################################################
|
||||
# This configuration flag sets callback to 1. It also sets MAX_HOSTNAME_LEN to 10 for performance issues.
|
||||
# According to the specification MAX_HOST_NAME is upto 255.
|
||||
"callback": 1,
|
||||
"MAX_HOSTNAME_LEN": 10,
|
||||
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset prvProcessDNSCache.0:5,strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},vDNSCheckCallBack.0:2,strcpy.0:{HOSTNAME_UNWIND}",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigDNS_USE_CALLBACKS={callback}",
|
||||
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
|
||||
# This value is defined only when ipconfigUSE_DNS_CACHE==1
|
||||
"ipconfigDNS_CACHE_NAME_LENGTH=254"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
|
||||
/* This assumes that the length of the hostname is bounded by MAX_HOSTNAME_LEN. */
|
||||
void * safeMalloc( size_t xWantedSize )
|
||||
{
|
||||
if( xWantedSize == 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t byte;
|
||||
|
||||
return byte ? malloc( xWantedSize ) : NULL;
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
if( ipconfigUSE_DNS_CACHE != 0 )
|
||||
{
|
||||
size_t len;
|
||||
__CPROVER_assume( len >= 0 && len <= MAX_HOSTNAME_LEN );
|
||||
char * pcHostName = safeMalloc( len ); /* malloc is replaced by safeMalloc */
|
||||
|
||||
if( len && pcHostName )
|
||||
{
|
||||
pcHostName[ len - 1 ] = NULL;
|
||||
}
|
||||
|
||||
if( pcHostName ) /* guarding against NULL pointer */
|
||||
{
|
||||
FreeRTOS_dnslookup( pcHostName );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
{
|
||||
"ENTRY": "DNSlookup",
|
||||
################################################################
|
||||
# This configuration uses DNS cache and the MAX_HOSTNAME_LEN is set to 255 according to the specification
|
||||
"MAX_HOSTNAME_LEN": 255,
|
||||
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
|
||||
"USE_CACHE": 1,
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset prvProcessDNSCache.0:5,strcmp.0:{HOSTNAME_UNWIND}",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigUSE_DNS_CACHE={USE_CACHE}",
|
||||
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}"
|
||||
],
|
||||
"OPT" : "-m32"
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#
|
||||
# FreeRTOS memory safety proofs with CBMC.
|
||||
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://aws.amazon.com/freertos
|
||||
# http://www.FreeRTOS.org
|
||||
#
|
||||
|
||||
{
|
||||
"ENTRY": "SendEventToIPTask",
|
||||
"CBMCFLAGS": [
|
||||
"--unwind 1",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
This is the memory safety proof for xSendEventToIPTask, a function used
|
||||
for sending different events to IP-Task. We have abstracted away queues.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* uxQueueMessagesWaiting
|
||||
* xQueueGenericSend
|
||||
|
||||
The coverage is imperfect (97%) because xSendEventToIPTask always
|
||||
calls xSendEventStructToIPTask with xTimeout==0.
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* FreeRTOS memory safety proofs with CBMC.
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
|
||||
/* The harness test proceeds to call SendEventToIPTask with an unconstrained value */
|
||||
void harness()
|
||||
{
|
||||
eIPEvent_t eEvent;
|
||||
|
||||
xSendEventToIPTask( eEvent );
|
||||
}
|
||||
@ -0,0 +1,174 @@
|
||||
default: report
|
||||
|
||||
# ____________________________________________________________________
|
||||
# CBMC binaries
|
||||
#
|
||||
|
||||
GOTO_CC = @GOTO_CC@
|
||||
GOTO_INSTRUMENT = goto-instrument
|
||||
GOTO_ANALYZER = goto-analyzer
|
||||
VIEWER = cbmc-viewer
|
||||
|
||||
# ____________________________________________________________________
|
||||
# Variables
|
||||
#
|
||||
# Naming scheme:
|
||||
# ``````````````
|
||||
# FOO is the concatenation of the following:
|
||||
# FOO2: Set of command line
|
||||
# C_FOO: Value of $FOO common to all harnesses, set in this file
|
||||
# O_FOO: Value of $FOO specific to the OS we're running on, set in the
|
||||
# makefile for the operating system
|
||||
# H_FOO: Value of $FOO specific to a particular harness, set in the
|
||||
# makefile for that harness
|
||||
|
||||
ENTRY = $(H_ENTRY)
|
||||
OBJS = $(H_OBJS)
|
||||
|
||||
INC = \
|
||||
$(INC2) \
|
||||
$(C_INC) $(O_INC) $(H_INC) \
|
||||
# empty
|
||||
|
||||
CFLAGS = \
|
||||
$(CFLAGS2) \
|
||||
$(C_DEF) $(O_DEF) $(H_DEF) $(DEF) \
|
||||
$(C_OPT) $(O_OPT) $(H_OPT) $(OPT) \
|
||||
-m32 \
|
||||
# empty
|
||||
|
||||
CBMCFLAGS = \
|
||||
--flush \
|
||||
$(CBMCFLAGS2) \
|
||||
$(C_CBMCFLAGS) $(O_CBMCFLAGS) $(H_CBMCFLAGS) \
|
||||
# empty
|
||||
|
||||
INSTFLAGS = \
|
||||
$(INSTFLAGS2) \
|
||||
$(C_INSTFLAGS) $(O_INSTFLAGS) $(H_INSTFLAGS) \
|
||||
# empty
|
||||
|
||||
# ____________________________________________________________________
|
||||
# Rules
|
||||
#
|
||||
# Rules for patching
|
||||
|
||||
patch:
|
||||
cd $(PROOFS)/../patches && ./patch.py
|
||||
|
||||
unpatch:
|
||||
cd $(PROOFS)/../patches && ./unpatch.py
|
||||
|
||||
# ____________________________________________________________________
|
||||
# Rules
|
||||
#
|
||||
# Rules for building the CBMC harness
|
||||
|
||||
C_SOURCES = $(patsubst %.goto,%.c,$(H_OBJS_EXCEPT_HARNESS))
|
||||
|
||||
# Build each goto-binary out-of-source (i.e. in a 'gotos' directory
|
||||
# underneath each proof directory, to make it safe to build all proofs
|
||||
# in parallel
|
||||
OOS_OBJS = $(patsubst %.c,gotos/%.goto,$(C_SOURCES))
|
||||
|
||||
CWD=$(abspath .)
|
||||
|
||||
gotos/%.goto: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(GOTO_CC) @COMPILE_ONLY@ @RULE_OUTPUT@ $(INC) $(CFLAGS) @RULE_INPUT@
|
||||
|
||||
queue_datastructure.h: gotos/$(FREERTOS)/freertos_kernel/queue.goto
|
||||
python3 @TYPE_HEADER_SCRIPT@ --binary $(CWD)/gotos$(FREERTOS)/freertos_kernel/queue.goto --c-file $(FREERTOS)/freertos_kernel/queue.c
|
||||
|
||||
$(ENTRY)_harness.goto: $(ENTRY)_harness.c $(H_GENERATE_HEADER)
|
||||
$(GOTO_CC) @COMPILE_ONLY@ @RULE_OUTPUT@ $(INC) $(CFLAGS) $(ENTRY)_harness.c
|
||||
|
||||
$(ENTRY)1.goto: $(ENTRY)_harness.goto $(OOS_OBJS)
|
||||
$(GOTO_CC) @COMPILE_LINK@ @RULE_OUTPUT@ --function harness @RULE_INPUT@
|
||||
|
||||
$(ENTRY)2.goto: $(ENTRY)1.goto
|
||||
$(GOTO_INSTRUMENT) --add-library @RULE_INPUT@ @RULE_OUTPUT@ \
|
||||
> $(ENTRY)2.txt 2>&1
|
||||
|
||||
$(ENTRY)3.goto: $(ENTRY)2.goto
|
||||
$(GOTO_INSTRUMENT) --drop-unused-functions @RULE_INPUT@ @RULE_OUTPUT@ \
|
||||
> $(ENTRY)3.txt 2>&1
|
||||
|
||||
$(ENTRY)4.goto: $(ENTRY)3.goto
|
||||
$(GOTO_INSTRUMENT) $(INSTFLAGS) --slice-global-inits @RULE_INPUT@ @RULE_OUTPUT@ \
|
||||
> $(ENTRY)4.txt 2>&1
|
||||
# ____________________________________________________________________
|
||||
# After running goto-instrument to remove function bodies the unused
|
||||
# functions need to be dropped again.
|
||||
|
||||
$(ENTRY)5.goto: $(ENTRY)4.goto
|
||||
$(GOTO_INSTRUMENT) --drop-unused-functions @RULE_INPUT@ @RULE_OUTPUT@ \
|
||||
> $(ENTRY)5.txt 2>&1
|
||||
|
||||
$(ENTRY).goto: $(ENTRY)5.goto
|
||||
@CP@ @RULE_INPUT@ @RULE_OUTPUT@
|
||||
|
||||
# ____________________________________________________________________
|
||||
# Rules
|
||||
#
|
||||
# Rules for running CBMC
|
||||
|
||||
goto:
|
||||
$(MAKE) -B $(ENTRY).goto
|
||||
|
||||
# Ignore the return code for CBMC, so that we can still generate the
|
||||
# report if the proof failed. If the proof failed, we separately fail
|
||||
# the entire job using the check-cbmc-result rule.
|
||||
cbmc.txt: $(ENTRY).goto
|
||||
-cbmc $(CBMCFLAGS) $(SOLVER) --unwinding-assertions --trace @RULE_INPUT@ > $@ 2>&1
|
||||
|
||||
property.xml: $(ENTRY).goto
|
||||
cbmc $(CBMCFLAGS) --unwinding-assertions --show-properties --xml-ui @RULE_INPUT@ > $@ 2>&1
|
||||
|
||||
coverage.xml: $(ENTRY).goto
|
||||
cbmc $(CBMCFLAGS) --cover location --xml-ui @RULE_INPUT@ > $@ 2>&1
|
||||
|
||||
cbmc: cbmc.txt
|
||||
|
||||
property: property.xml
|
||||
|
||||
coverage: coverage.xml
|
||||
|
||||
report: cbmc.txt property.xml coverage.xml
|
||||
$(VIEWER) \
|
||||
--goto $(ENTRY).goto \
|
||||
--srcdir $(FREERTOS_PLUS_TCP) \
|
||||
--blddir $(FREERTOS_PLUS_TCP) \
|
||||
--htmldir html \
|
||||
--srcexclude "(.@FORWARD_SLASH@doc|.@FORWARD_SLASH@tests|.@FORWARD_SLASH@vendors)" \
|
||||
--result cbmc.txt \
|
||||
--property property.xml \
|
||||
--block coverage.xml
|
||||
|
||||
# This rule depends only on cbmc.txt and has no dependents, so it will
|
||||
# not block the report from being generated if it fails. This rule is
|
||||
# intended to fail if and only if the CBMC safety check that emits
|
||||
# cbmc.txt yielded a proof failure.
|
||||
check-cbmc-result: cbmc.txt
|
||||
grep -e "^VERIFICATION SUCCESSFUL" $^
|
||||
|
||||
# ____________________________________________________________________
|
||||
# Rules
|
||||
#
|
||||
# Rules for cleaning up
|
||||
|
||||
clean:
|
||||
@RM@ $(OBJS) $(ENTRY).goto
|
||||
@RM@ $(ENTRY)[0-9].goto $(ENTRY)[0-9].txt
|
||||
@RM@ cbmc.txt property.xml coverage.xml TAGS TAGS-*
|
||||
@RM@ *~ \#*
|
||||
@RM@ queue_datastructure.h
|
||||
|
||||
|
||||
veryclean: clean
|
||||
@RM_RECURSIVE@ html
|
||||
@RM_RECURSIVE@ gotos
|
||||
|
||||
distclean: veryclean
|
||||
cd $(PROOFS)/../patches && ./unpatch.py
|
||||
cd $(PROOFS) && ./make-remove-makefiles.py
|
||||
@ -0,0 +1,45 @@
|
||||
{
|
||||
"FREERTOS_PLUS_TCP": [ " ../../.." ],
|
||||
"PROOFS": [ "." ],
|
||||
|
||||
"DEF ": [
|
||||
"WIN32",
|
||||
"WINVER=0x400",
|
||||
"_CONSOLE",
|
||||
"_CRT_SECURE_NO_WARNINGS",
|
||||
"_DEBUG",
|
||||
"_WIN32_WINNT=0x0500",
|
||||
"__PRETTY_FUNCTION__=__FUNCTION__",
|
||||
"__free_rtos__",
|
||||
|
||||
"CBMC",
|
||||
"'configASSERT(X)=__CPROVER_assert(X,\"Assertion Error\")'",
|
||||
"'configPRECONDITION(X)=__CPROVER_assume(X)'",
|
||||
"'_static='",
|
||||
"'_volatile='"
|
||||
],
|
||||
|
||||
"INC ": [
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/portable/MSVC-MingW",
|
||||
"$(FREERTOS_PLUS_TCP)/source/include",
|
||||
"$(FREERTOS_PLUS_TCP)/source/portable/Compiler/MSVC",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/patches",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/windows",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/windows2"
|
||||
],
|
||||
|
||||
"CBMCFLAGS ": [
|
||||
"--object-bits 7",
|
||||
"--32",
|
||||
"--bounds-check",
|
||||
"--pointer-check"
|
||||
],
|
||||
|
||||
"FORWARD_SLASH": ["/"],
|
||||
|
||||
"TYPE_HEADERS": [
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.c"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
{
|
||||
"GOTO_CC": [
|
||||
"goto-cc"
|
||||
],
|
||||
"COMPILE_LINK": [
|
||||
"-o"
|
||||
],
|
||||
"COMPILE_ONLY": [
|
||||
"-c",
|
||||
"-o"
|
||||
],
|
||||
"RULE_INPUT": [
|
||||
"$^"
|
||||
],
|
||||
"RULE_OUTPUT": [
|
||||
"$@"
|
||||
],
|
||||
"RULE_GOTO": [
|
||||
"%.goto : %.c"
|
||||
],
|
||||
"INC": [
|
||||
"$(PROOFS)/../windows"
|
||||
],
|
||||
"RM": [
|
||||
"$(RM)"
|
||||
],
|
||||
"RM_RECURSIVE": [
|
||||
"$(RM) -r"
|
||||
],
|
||||
"CP": [
|
||||
"cp"
|
||||
],
|
||||
"TYPE_HEADER_SCRIPT": [
|
||||
"$(PROOFS)/make_type_header_files.py"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
{
|
||||
"DEF": [
|
||||
"WIN32"
|
||||
],
|
||||
"GOTO_CC": [
|
||||
"goto-cl"
|
||||
],
|
||||
"COMPILE_LINK": [
|
||||
"/Fe"
|
||||
],
|
||||
"COMPILE_ONLY": [
|
||||
"/c",
|
||||
"/Fo"
|
||||
],
|
||||
"RULE_INPUT": [
|
||||
"$**"
|
||||
],
|
||||
"RULE_OUTPUT": [
|
||||
"$@"
|
||||
],
|
||||
"RULE_GOTO": [
|
||||
".c.goto:"
|
||||
],
|
||||
"OPT": [
|
||||
"/wd4210",
|
||||
"/wd4127",
|
||||
"/wd4214",
|
||||
"/wd4201",
|
||||
"/wd4244",
|
||||
"/wd4310"
|
||||
],
|
||||
"RM": [
|
||||
"del"
|
||||
],
|
||||
"RM_RECURSIVE": [
|
||||
"del /s"
|
||||
],
|
||||
"CP": [
|
||||
"copy"
|
||||
],
|
||||
"TYPE_HEADER_SCRIPT": [
|
||||
"$(PROOFS)\\make_type_header_files.py"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
# The proof depends on one parameter:
|
||||
# NETWORK_BUFFER_SIZE is the size of the network buffer being parsed
|
||||
# The buffer size must be bounded because we must bound the number of
|
||||
# iterations loops iterating over the buffer.
|
||||
|
||||
{
|
||||
"ENTRY": "ParseDNSReply",
|
||||
|
||||
################################################################
|
||||
# This is the network buffer size.
|
||||
# Reasonable values are size > 12 = sizeof(xDNSMessage)
|
||||
"NETWORK_BUFFER_SIZE": 40,
|
||||
|
||||
################################################################
|
||||
# This is the size of the buffer into which the name is copied.
|
||||
# Set to any positive value.
|
||||
# In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE
|
||||
# In the proof, NAME_SIZE >= 4 required for good coverage.
|
||||
"NAME_SIZE": "10",
|
||||
|
||||
################################################################
|
||||
# Loop prvParseDNSReply.0:
|
||||
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 915
|
||||
"PARSELOOP0": "prvParseDNSReply.0",
|
||||
|
||||
# M = sizeof( DNSMessage_t ) = 12
|
||||
# U = sizeof( uint32_t) = 4
|
||||
# Loop bound is (NETWORK_BUFFER_SIZE - M) div (U+1) + 1 tight for SIZE >= M
|
||||
# Loop bound is 1 for 0 <= SIZE < M
|
||||
"PARSELOOP0_UNWIND":
|
||||
"__eval 1 if {NETWORK_BUFFER_SIZE} < 12 else ({NETWORK_BUFFER_SIZE} - 12) / 5 + 1",
|
||||
|
||||
################################################################
|
||||
# Loop prvParseDNSReply.1:
|
||||
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 989
|
||||
"PARSELOOP1": "prvParseDNSReply.1",
|
||||
|
||||
# A = sizeof( DNSAnswerRecord_t ) = 10
|
||||
# M = sizeof( DNSMessage_t ) = 12
|
||||
# U = sizeof( uint32_t) = 4
|
||||
# Loop bound is (NETWORK_BUFFER_SIZE - M - A) div (A+1) + A + 1 tight
|
||||
# for SIZE >= M + A
|
||||
# Loop bound is (NETWORK_BUFFER_SIZE - M) + 1 for M <= SIZE < M + A
|
||||
# Loop bound is 1 for 0 <= SIZE < M
|
||||
"PARSELOOP1_UNWIND":
|
||||
"__eval 1 if {NETWORK_BUFFER_SIZE} < 12 else ({NETWORK_BUFFER_SIZE} - 11 if {NETWORK_BUFFER_SIZE} < 22 else ({NETWORK_BUFFER_SIZE} - 12 - 10) / 11 + 11)",
|
||||
|
||||
################################################################
|
||||
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset {PARSELOOP0}:{PARSELOOP0_UNWIND},{PARSELOOP1}:{PARSELOOP1_UNWIND},prvProcessDNSCache.0:5"
|
||||
],
|
||||
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto"
|
||||
],
|
||||
|
||||
"DEF":
|
||||
[
|
||||
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}",
|
||||
"NAME_SIZE={NAME_SIZE}"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "list.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "FreeRTOS_DNS_Parser.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* Signature of function under test
|
||||
****************************************************************/
|
||||
|
||||
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
|
||||
size_t uxBufferLength,
|
||||
BaseType_t xExpected );
|
||||
|
||||
/****************************************************************
|
||||
* Abstraction of DNS_ReadNameField proved in ReadNameField
|
||||
****************************************************************/
|
||||
|
||||
size_t DNS_ReadNameField( const uint8_t * pucByte,
|
||||
size_t uxRemainingBytes,
|
||||
char * pcName,
|
||||
size_t uxDestLen )
|
||||
{
|
||||
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
__CPROVER_assert( NAME_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NAME_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
__CPROVER_assert( NAME_SIZE >= 4,
|
||||
"NAME_SIZE >= 4 required for good coverage." );
|
||||
|
||||
|
||||
/* Preconditions */
|
||||
__CPROVER_assert( uxRemainingBytes < CBMC_MAX_OBJECT_SIZE,
|
||||
"ReadNameField: uxRemainingBytes < CBMC_MAX_OBJECT_SIZE)" );
|
||||
__CPROVER_assert( uxDestLen < CBMC_MAX_OBJECT_SIZE,
|
||||
"ReadNameField: uxDestLen < CBMC_MAX_OBJECT_SIZE)" );
|
||||
|
||||
__CPROVER_assert( uxRemainingBytes <= NETWORK_BUFFER_SIZE,
|
||||
"ReadNameField: uxRemainingBytes <= NETWORK_BUFFER_SIZE)" );
|
||||
|
||||
/* This precondition in the function contract for prvReadNameField
|
||||
* fails because prvCheckOptions called prvReadNameField with the
|
||||
* constant value 254.
|
||||
* __CPROVER_assert(uxDestLen <= NAME_SIZE,
|
||||
* "ReadNameField: uxDestLen <= NAME_SIZE)");
|
||||
*/
|
||||
|
||||
__CPROVER_assert( pucByte != NULL,
|
||||
"ReadNameField: pucByte != NULL )" );
|
||||
__CPROVER_assert( pcName != NULL,
|
||||
"ReadNameField: pcName != NULL )" );
|
||||
|
||||
__CPROVER_assert( uxDestLen > 0,
|
||||
"ReadNameField: uxDestLen > 0)" );
|
||||
|
||||
/* Return value */
|
||||
size_t index;
|
||||
|
||||
/* Postconditions */
|
||||
__CPROVER_assume( index <= uxDestLen + 1 && index <= uxRemainingBytes );
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Abstraction of DNS_SkipNameField proved in SkipNameField
|
||||
****************************************************************/
|
||||
|
||||
size_t DNS_SkipNameField( const uint8_t * pucByte,
|
||||
size_t uxLength )
|
||||
{
|
||||
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
|
||||
|
||||
/* Preconditions */
|
||||
__CPROVER_assert( uxLength < CBMC_MAX_OBJECT_SIZE,
|
||||
"SkipNameField: uxLength < CBMC_MAX_OBJECT_SIZE)" );
|
||||
__CPROVER_assert( uxLength <= NETWORK_BUFFER_SIZE,
|
||||
"SkipNameField: uxLength <= NETWORK_BUFFER_SIZE)" );
|
||||
__CPROVER_assert( pucByte != NULL,
|
||||
"SkipNameField: pucByte != NULL)" );
|
||||
|
||||
/* Return value */
|
||||
size_t index;
|
||||
|
||||
/* Postconditions */
|
||||
__CPROVER_assume( index <= uxLength );
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Proof of prvParseDNSReply
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
size_t uxBufferLength;
|
||||
BaseType_t xExpected;
|
||||
uint8_t * pucUDPPayloadBuffer = malloc( uxBufferLength );
|
||||
|
||||
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
|
||||
__CPROVER_assume( uxBufferLength < CBMC_MAX_OBJECT_SIZE );
|
||||
__CPROVER_assume( uxBufferLength <= NETWORK_BUFFER_SIZE );
|
||||
__CPROVER_assume( pucUDPPayloadBuffer != NULL );
|
||||
|
||||
uint32_t index = prvParseDNSReply( pucUDPPayloadBuffer,
|
||||
uxBufferLength,
|
||||
xExpected );
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
# The proof depends on one parameter:
|
||||
# BUFFER_SIZE is the size of the buffer being parsed
|
||||
# The buffer size must be bounded because we must bound the number of
|
||||
# iterations loops iterating over the buffer.
|
||||
|
||||
{
|
||||
"ENTRY": "ProcessDHCPReplies",
|
||||
|
||||
################################################################
|
||||
# Buffer header: sizeof(DHCPMessage_t) = 241
|
||||
# Buffer header: sizeof(DHCPMessage_IPv4_t) = 240
|
||||
"BUFFER_HEADER": 240,
|
||||
|
||||
################################################################
|
||||
# Buffer size
|
||||
# Reasonable sizes are BUFFER_SIZE > BUFFER_HEADER
|
||||
# Sizes smaller than this causes CBMC to fail in simplify_byte_extract
|
||||
"BUFFER_SIZE": 252,
|
||||
|
||||
################################################################
|
||||
# Buffer payload
|
||||
"BUFFER_PAYLOAD": "__eval 1 if {BUFFER_SIZE} <= {BUFFER_HEADER} else {BUFFER_SIZE} - {BUFFER_HEADER} + 1",
|
||||
|
||||
################################################################
|
||||
|
||||
"CBMCFLAGS": [
|
||||
# "--nondet-static",
|
||||
"--unwind 1",
|
||||
"--unwindset memcmp.0:7,prvProcessDHCPReplies.0:{BUFFER_PAYLOAD}"
|
||||
],
|
||||
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DHCP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/portable/BufferManagement/BufferAllocation_2.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/event_groups.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto"
|
||||
],
|
||||
|
||||
"DEF":
|
||||
[
|
||||
"CBMC_DHCPMESSAGE_HEADER_SIZE={BUFFER_HEADER}",
|
||||
"CBMC_FREERTOS_RECVFROM_BUFFER_BOUND={BUFFER_SIZE}"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DHCP.h"
|
||||
#include "FreeRTOS_ARP.h"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Signature of function under test
|
||||
****************************************************************/
|
||||
|
||||
BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
|
||||
|
||||
/****************************************************************
|
||||
* The proof for FreeRTOS_gethostbyname.
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
/* Omitting model of an unconstrained xDHCPData because xDHCPData is */
|
||||
/* the source of uninitialized data only on line 647 to set a */
|
||||
/* transaction id is an outgoing message */
|
||||
|
||||
BaseType_t xExpectedMessageType;
|
||||
|
||||
prvProcessDHCPReplies( xExpectedMessageType );
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
This directory contains the proofs checked by CBMC. For each entry point of FreeRTOS-Plus-TCP tested, there is a directory that contains the test harness and cbmc configuration information needed to check the proof.
|
||||
@ -0,0 +1,55 @@
|
||||
{
|
||||
"ENTRY": "ReadNameField",
|
||||
|
||||
################################################################
|
||||
#Enable DNS callbacks or else ReadNameField is not defined
|
||||
"callbacks": "1",
|
||||
|
||||
################################################################
|
||||
# This is the network buffer size. Set to any positive value.
|
||||
"NETWORK_BUFFER_SIZE" : "10",
|
||||
|
||||
################################################################
|
||||
# This is the size of the buffer into which the name is copied.
|
||||
# Set to any positive value.
|
||||
# In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE
|
||||
# In the proof, NAME_SIZE >= 4 required for good coverage.
|
||||
"NAME_SIZE": "6",
|
||||
|
||||
################################################################
|
||||
# Loop prvReadNameField.0:
|
||||
# should be min of buffer size and name size
|
||||
# but loop must be unwound at least once, so max of this and 1+1
|
||||
"READLOOP0": "DNS_ReadNameField.0",
|
||||
"READLOOP0_UNWIND": "__eval max(2, min({NETWORK_BUFFER_SIZE}, {NAME_SIZE}+1))",
|
||||
|
||||
################################################################
|
||||
# Loop prvReadNameField.1:
|
||||
# should be min of buffer size and name size
|
||||
# but loop must be unwound at least twice, so max of this and 2+1
|
||||
"READLOOP1": "DNS_ReadNameField.1",
|
||||
"READLOOP1_UNWIND": "__eval max(3, min({NETWORK_BUFFER_SIZE}, {NAME_SIZE}))",
|
||||
|
||||
################################################################
|
||||
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset {READLOOP0}:{READLOOP0_UNWIND},{READLOOP1}:{READLOOP1_UNWIND}"
|
||||
],
|
||||
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto"
|
||||
],
|
||||
|
||||
"DEF":
|
||||
[
|
||||
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}",
|
||||
"NAME_SIZE={NAME_SIZE}",
|
||||
"ipconfigDNS_USE_CALLBACKS={callbacks}",
|
||||
"ipconfigDNS_CACHE_NAME_LENGTH=254"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "list.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* Signature of function under test
|
||||
****************************************************************/
|
||||
|
||||
size_t DNS_ReadNameField( const uint8_t * pucByte,
|
||||
size_t uxRemainingBytes,
|
||||
char * pcName,
|
||||
size_t uxDestLen );
|
||||
|
||||
/****************************************************************
|
||||
* The function under test is not defined in all configurations
|
||||
****************************************************************/
|
||||
|
||||
#if ( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
|
||||
|
||||
/* DNS_ReadNameField is defined in this configuration */
|
||||
|
||||
#else
|
||||
|
||||
/* DNS_ReadNameField is not defined in this configuration, stub it. */
|
||||
|
||||
size_t DNS_ReadNameField( const uint8_t * pucByte,
|
||||
size_t uxRemainingBytes,
|
||||
char * pcName,
|
||||
size_t uxDestLen )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* if ( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 ) */
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Proof of DNS_ReadNameField function contract
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
__CPROVER_assert( NAME_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NAME_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
|
||||
__CPROVER_assert( NAME_SIZE >= 4,
|
||||
"NAME_SIZE >= 4 required for good coverage." );
|
||||
|
||||
|
||||
size_t uxRemainingBytes;
|
||||
size_t uxDestLen;
|
||||
|
||||
uint8_t * pucByte = malloc( uxRemainingBytes );
|
||||
char * pcName = malloc( uxDestLen );
|
||||
|
||||
/* Preconditions */
|
||||
|
||||
__CPROVER_assume( uxRemainingBytes < CBMC_MAX_OBJECT_SIZE );
|
||||
__CPROVER_assume( uxDestLen < CBMC_MAX_OBJECT_SIZE );
|
||||
|
||||
__CPROVER_assume( uxRemainingBytes <= NETWORK_BUFFER_SIZE );
|
||||
__CPROVER_assume( uxDestLen <= NAME_SIZE );
|
||||
|
||||
__CPROVER_assume( pucByte != NULL );
|
||||
__CPROVER_assume( pcName != NULL );
|
||||
|
||||
/* Avoid overflow on uxSourceLen - 1U with uxSourceLen == uxRemainingBytes */
|
||||
/*__CPROVER_assume(uxRemainingBytes > 0); */
|
||||
|
||||
/* Avoid overflow on uxDestLen - 1U */
|
||||
__CPROVER_assume( uxDestLen > 0 );
|
||||
|
||||
size_t index = DNS_ReadNameField( pucByte,
|
||||
uxRemainingBytes,
|
||||
pcName,
|
||||
uxDestLen );
|
||||
|
||||
/* Postconditions */
|
||||
|
||||
__CPROVER_assert( index <= uxDestLen + 1 && index <= uxRemainingBytes,
|
||||
"DNS_ReadNameField : index <= uxDestLen+1" );
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
{
|
||||
"ENTRY": "SkipNameField",
|
||||
|
||||
################################################################
|
||||
# This is the network buffer size. This can be set to any positive value.
|
||||
"NETWORK_BUFFER_SIZE": 10,
|
||||
|
||||
################################################################
|
||||
# Loop DNS_SkipNameField.0:
|
||||
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 778
|
||||
# bound should be half network buffer size, since chunk length is at least 2
|
||||
"SKIPLOOP0": "DNS_SkipNameField.0",
|
||||
"SKIPLOOP0_UNWIND": "__eval ({NETWORK_BUFFER_SIZE} + 1) / 2",
|
||||
|
||||
################################################################
|
||||
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset {SKIPLOOP0}:{SKIPLOOP0_UNWIND}"
|
||||
],
|
||||
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_DNS_Parser.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "list.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_UDP_IP.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
#include "NetworkBufferManagement.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "IPTraceMacroDefaults.h"
|
||||
#include "FreeRTOS_DNS_Parser.h"
|
||||
|
||||
#include "cbmc.h"
|
||||
|
||||
/****************************************************************
|
||||
* Signature of function under test
|
||||
****************************************************************/
|
||||
|
||||
size_t DNS_SkipNameField( const uint8_t * pucByte,
|
||||
size_t uxLength );
|
||||
|
||||
/****************************************************************
|
||||
* Proof of DNS_SkipNameField function contract
|
||||
****************************************************************/
|
||||
|
||||
void harness()
|
||||
{
|
||||
__CPROVER_assert( NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
|
||||
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE" );
|
||||
|
||||
size_t uxLength;
|
||||
uint8_t * pucByte = malloc( uxLength );
|
||||
|
||||
/* Preconditions */
|
||||
|
||||
__CPROVER_assume( uxLength < CBMC_MAX_OBJECT_SIZE );
|
||||
__CPROVER_assume( uxLength <= NETWORK_BUFFER_SIZE );
|
||||
__CPROVER_assume( pucByte != NULL );
|
||||
|
||||
size_t index = DNS_SkipNameField( pucByte, uxLength );
|
||||
|
||||
/* Postconditions */
|
||||
|
||||
__CPROVER_assert( index <= uxLength,
|
||||
"DNS_SkipNameField: index <= uxLength" );
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
{
|
||||
"ENTRY": "vSocketBind",
|
||||
"ALLOW_SEND_WITHOUT_BIND":"1",
|
||||
"ALLOW_ETHERNET_DRIVER_FILTER":"1",
|
||||
"ALLOW_TCP":"1",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
|
||||
"$(ENTRY)_harness.goto"
|
||||
],
|
||||
"INSTFLAGS":
|
||||
[
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND={ALLOW_SEND_WITHOUT_BIND}",
|
||||
"ipconfigUSE_TCP={ALLOW_TCP}",
|
||||
"ipconfigETHERNET_DRIVER_FILTERS_PACKETS={ALLOW_ETHERNET_DRIVER_FILTER}"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
|
||||
]
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
#include "memory_assignments.c"
|
||||
|
||||
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
|
||||
|
||||
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
|
||||
{
|
||||
uint16_t usResult;
|
||||
|
||||
return usResult;
|
||||
}
|
||||
|
||||
BaseType_t xIPIsNetworkTaskReady( void )
|
||||
{
|
||||
/* Return true saying that the task is ready. */
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Random number generator provided by the application. In our case, CBMC provides
|
||||
* an indeterministic value. */
|
||||
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
|
||||
{
|
||||
__CPROVER_assert( pulNumber != NULL, "Argument to xApplicationGetRandomNumber cannot be NULL" );
|
||||
|
||||
if( nondet_bool() )
|
||||
{
|
||||
*pulNumber = nondet_uint32_t();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pulNumber = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
|
||||
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
|
||||
|
||||
struct freertos_sockaddr * pxBindAddress = safeMalloc( sizeof( struct freertos_sockaddr ) );
|
||||
|
||||
/* uxAddressLength is not used in this implementation. */
|
||||
size_t uxAddressLength;
|
||||
|
||||
BaseType_t xInternal;
|
||||
|
||||
/* Call to init the socket list. */
|
||||
vNetworkSocketsInit();
|
||||
|
||||
vSocketBind( pxSocket, pxBindAddress, uxAddressLength, xInternal );
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
{
|
||||
"ENTRY": "vSocketBind",
|
||||
"ALLOW_SEND_WITHOUT_BIND":"1",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
|
||||
"$(ENTRY)_harness.goto"
|
||||
],
|
||||
"INSTFLAGS":
|
||||
[
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND={ALLOW_SEND_WITHOUT_BIND}",
|
||||
"ipconfigUSE_TCP=1"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
|
||||
]
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
#include "memory_assignments.c"
|
||||
|
||||
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
|
||||
{
|
||||
uint16_t usResult;
|
||||
|
||||
return usResult;
|
||||
}
|
||||
|
||||
BaseType_t xIPIsNetworkTaskReady( void )
|
||||
{
|
||||
/* Return true saying that the task is ready. */
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Random number generator provided by the application. In our case, CBMC provides
|
||||
* an indeterministic value. */
|
||||
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
|
||||
{
|
||||
__CPROVER_assert( pulNumber != NULL, "Argument to xApplicationGetRandomNumber cannot be NULL" );
|
||||
|
||||
if( nondet_bool() )
|
||||
{
|
||||
*pulNumber = nondet_uint32_t();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pulNumber = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
|
||||
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
|
||||
|
||||
struct freertos_sockaddr * pxBindAddress = safeMalloc( sizeof( struct freertos_sockaddr ) );
|
||||
|
||||
/* uxAddressLength is not used in this implementation. */
|
||||
size_t uxAddressLength;
|
||||
|
||||
BaseType_t xInternal;
|
||||
|
||||
/* Call to init the socket list. */
|
||||
vNetworkSocketsInit();
|
||||
|
||||
vSocketBind( pxSocket, pxBindAddress, uxAddressLength, xInternal );
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
{
|
||||
"ENTRY": "vSocketBind",
|
||||
"ALLOW_SEND_WITHOUT_BIND":"0",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
|
||||
"$(ENTRY)_harness.goto"
|
||||
],
|
||||
"INSTFLAGS":
|
||||
[
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND={ALLOW_SEND_WITHOUT_BIND}",
|
||||
"ipconfigUSE_TCP=1"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
|
||||
]
|
||||
}
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
#include "memory_assignments.c"
|
||||
|
||||
uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
|
||||
{
|
||||
uint16_t usResult;
|
||||
|
||||
return usResult;
|
||||
}
|
||||
|
||||
BaseType_t xIPIsNetworkTaskReady( void )
|
||||
{
|
||||
/* Return true saying that the task is ready. */
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Random number generator provided by the application. In our case, CBMC provides
|
||||
* an indeterministic value. */
|
||||
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
|
||||
{
|
||||
__CPROVER_assert( pulNumber != NULL, "Argument to xApplicationGetRandomNumber cannot be NULL" );
|
||||
|
||||
if( nondet_bool() )
|
||||
{
|
||||
*pulNumber = nondet_uint32_t();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pulNumber = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
|
||||
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
|
||||
|
||||
/* malloc instead of safeMalloc since we do not allow socket without binding. */
|
||||
struct freertos_sockaddr * pxBindAddress = malloc( sizeof( struct freertos_sockaddr ) );
|
||||
|
||||
__CPROVER_assume( pxBindAddress != NULL );
|
||||
|
||||
|
||||
/* uxAddressLength is not used in this implementation. */
|
||||
size_t uxAddressLength;
|
||||
|
||||
BaseType_t xInternal;
|
||||
|
||||
/* Call to init the socket list. */
|
||||
vNetworkSocketsInit();
|
||||
|
||||
vSocketBind( pxSocket, pxBindAddress, uxAddressLength, xInternal );
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
{
|
||||
"ENTRY": "vSocketClose",
|
||||
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 2"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
|
||||
"$(ENTRY)_harness.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
{
|
||||
"UDP_Only":[
|
||||
"PROTOCOL=FREERTOS_IPPROTO_UDP",
|
||||
"ipconfigUSE_TCP=1",
|
||||
"ipconfigUSE_TCP_WIN=1",
|
||||
"ipconfigHAS_DEBUG_PRINTF=0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"TCP_Only":[
|
||||
"PROTOCOL=FREERTOS_IPPROTO_TCP",
|
||||
"ipconfigUSE_TCP=1",
|
||||
"ipconfigUSE_TCP_WIN=1",
|
||||
"ipconfigHAS_DEBUG_PRINTF=0"
|
||||
]
|
||||
}
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
#include "freertos_api.c"
|
||||
#include "memory_assignments.c"
|
||||
|
||||
/* The memory safety of vTCPWindowDestroy has already been proved in
|
||||
* proofs/TCPWin/vTCPWindowDestroy. */
|
||||
void vTCPWindowDestroy( TCPWindow_t const * xWindow )
|
||||
{
|
||||
__CPROVER_assert( xWindow != NULL, "xWindow cannot be NULL" );
|
||||
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
size_t xRequestedSizeBytes;
|
||||
TickType_t xBlockTimeTicks;
|
||||
FreeRTOS_Socket_t * pxSocket = safeMalloc( sizeof( FreeRTOS_Socket_t ) );
|
||||
|
||||
/* Socket cannot be NULL or invalid for this proof. This is allowed since vSocketClose is called by IP task only. */
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
|
||||
|
||||
/* Request a random number of bytes keeping in mind the maximum bound of CBMC. */
|
||||
__CPROVER_assume( xRequestedSizeBytes < ( CBMC_MAX_OBJECT_SIZE - ipBUFFER_PADDING ) );
|
||||
|
||||
/* Non-deterministically malloc the callback function. */
|
||||
pxSocket->pxUserWakeCallback = safeMalloc( sizeof( SocketWakeupCallback_t ) );
|
||||
|
||||
/* Non deterministically add an event group. */
|
||||
if( nondet_bool() )
|
||||
{
|
||||
pxSocket->xEventGroup = xEventGroupCreate();
|
||||
__CPROVER_assume( pxSocket->xEventGroup != NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxSocket->xEventGroup = NULL;
|
||||
}
|
||||
|
||||
/* Create and fill the socket in the bound socket list. This socket will then be
|
||||
* removed by a call to the vSocketClose. */
|
||||
List_t BoundSocketList;
|
||||
vListInitialise( &BoundSocketList );
|
||||
|
||||
/* Non-deterministically add the socket to bound socket list. */
|
||||
if( nondet_bool() )
|
||||
{
|
||||
vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
|
||||
pxSocket->xBoundSocketListItem.pxContainer = &( BoundSocketList );
|
||||
vListInsertEnd( &BoundSocketList, &( pxSocket->xBoundSocketListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxSocket->xBoundSocketListItem.pxContainer = NULL;
|
||||
}
|
||||
|
||||
/* See Configurations.json for details. Protocol can be UDP or TCP. */
|
||||
pxSocket->ucProtocol = PROTOCOL;
|
||||
|
||||
NetworkBufferDescriptor_t * NetworkBuffer;
|
||||
|
||||
/* Get a network buffer descriptor with requested bytes. See the constraints
|
||||
* on the number of requested bytes above. And block for random timer ticks. */
|
||||
if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
|
||||
{
|
||||
pxSocket->u.xTCP.rxStream = malloc( sizeof( StreamBuffer_t ) );
|
||||
pxSocket->u.xTCP.txStream = malloc( sizeof( StreamBuffer_t ) );
|
||||
|
||||
/* Non deterministically allocate/not-allocate the network buffer descriptor. */
|
||||
if( nondet_bool() )
|
||||
{
|
||||
pxSocket->u.xTCP.pxAckMessage = pxGetNetworkBufferWithDescriptor( xRequestedSizeBytes, xBlockTimeTicks );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxSocket->u.xTCP.pxAckMessage = NULL;
|
||||
}
|
||||
}
|
||||
else if( pxSocket->ucProtocol == FREERTOS_IPPROTO_UDP )
|
||||
{
|
||||
/* Initialise the waiting packet list. */
|
||||
vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
|
||||
|
||||
/* Non-deterministically either add/not-add item to the waiting packet list. */
|
||||
if( nondet_bool() )
|
||||
{
|
||||
NetworkBuffer = pxGetNetworkBufferWithDescriptor( xRequestedSizeBytes, xBlockTimeTicks );
|
||||
/* Assume non-NULL network buffer for this case. */
|
||||
__CPROVER_assume( NetworkBuffer != NULL );
|
||||
|
||||
/* Initialise the buffer list item. */
|
||||
vListInitialiseItem( &( NetworkBuffer->xBufferListItem ) );
|
||||
|
||||
/*Set the item owner as the buffer itself. */
|
||||
listSET_LIST_ITEM_OWNER( &( NetworkBuffer->xBufferListItem ), ( void * ) NetworkBuffer );
|
||||
|
||||
/* Set the container of the buffer list item as the waiting packet list. */
|
||||
NetworkBuffer->xBufferListItem.pxContainer = &( pxSocket->u.xUDP.xWaitingPacketsList );
|
||||
|
||||
/* Insert the list-item into the waiting packet list. */
|
||||
vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( NetworkBuffer->xBufferListItem ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Call to init the socket list. */
|
||||
vNetworkSocketsInit();
|
||||
|
||||
/* Call the function. */
|
||||
vSocketClose( pxSocket );
|
||||
|
||||
/* No post checking to be done. */
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
{
|
||||
"ENTRY": "vSocketWakeUpUser",
|
||||
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_Sockets.goto",
|
||||
"$(ENTRY)_harness.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigSOCKET_HAS_USER_SEMAPHORE=1",
|
||||
"ipconfigSOCKET_HAS_USER_WAKE_CALLBACK=1",
|
||||
"ipconfigSUPPORT_SELECT_FUNCTION=1",
|
||||
"configUSE_16_BIT_TICKS=0"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include",
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/proofs/utility"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,167 @@
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
#include "event_groups.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
#include "memory_assignments.c"
|
||||
|
||||
|
||||
/*********************************************************************************
|
||||
*
|
||||
* The below structure definitions are just copy pasted from the FreeRTOS-Kernel.
|
||||
* To understand the proof, you need not understand the structures and they can
|
||||
* be ignored safely.
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
/* Define the bits used by Kernel. */
|
||||
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
|
||||
|
||||
typedef struct EventGroupDef_t
|
||||
{
|
||||
EventBits_t uxEventBits;
|
||||
List_t xTasksWaitingForBits;
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t uxEventGroupNumber;
|
||||
#endif
|
||||
|
||||
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
uint8_t ucStaticallyAllocated;
|
||||
#endif
|
||||
} EventGroup_t;
|
||||
|
||||
typedef struct QueuePointers
|
||||
{
|
||||
int8_t * pcTail;
|
||||
int8_t * pcReadFrom;
|
||||
} QueuePointers_t;
|
||||
|
||||
typedef struct SemaphoreData
|
||||
{
|
||||
TaskHandle_t xMutexHolder;
|
||||
UBaseType_t uxRecursiveCallCount;
|
||||
} SemaphoreData_t;
|
||||
|
||||
typedef struct QueueDefinition
|
||||
{
|
||||
int8_t * pcHead;
|
||||
int8_t * pcWriteTo;
|
||||
|
||||
union
|
||||
{
|
||||
QueuePointers_t xQueue;
|
||||
SemaphoreData_t xSemaphore;
|
||||
} u;
|
||||
|
||||
List_t xTasksWaitingToSend;
|
||||
List_t xTasksWaitingToReceive;
|
||||
|
||||
volatile UBaseType_t uxMessagesWaiting;
|
||||
UBaseType_t uxLength;
|
||||
UBaseType_t uxItemSize;
|
||||
|
||||
volatile int8_t cRxLock;
|
||||
volatile int8_t cTxLock;
|
||||
|
||||
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
uint8_t ucStaticallyAllocated;
|
||||
#endif
|
||||
|
||||
#if ( configUSE_QUEUE_SETS == 1 )
|
||||
struct QueueDefinition * pxQueueSetContainer;
|
||||
#endif
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t uxQueueNumber;
|
||||
uint8_t ucQueueType;
|
||||
#endif
|
||||
} xQUEUE;
|
||||
|
||||
/********************************************************/
|
||||
/********* End Kernel cut-paste section *****************/
|
||||
/********************************************************/
|
||||
|
||||
|
||||
/* The memory safety of xQueueGenericSend has been proved before.
|
||||
* See github.com/FreeRTOS/FreeRTOS/FreeRTOS/Test/CBMC/proofs/Queue/QueueGenericSend.
|
||||
*/
|
||||
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
|
||||
const void * const pvItemToQueue,
|
||||
TickType_t xTicksToWait,
|
||||
const BaseType_t xCopyPosition )
|
||||
{
|
||||
BaseType_t xResult;
|
||||
|
||||
/* These asserts are copied over from the original function itself. */
|
||||
__CPROVER_assert( xQueue != NULL, "xQueue cannot be NULL" );
|
||||
__CPROVER_assert( !( ( pvItemToQueue == NULL ) && ( xQueue->uxItemSize != ( UBaseType_t ) 0U ) ),
|
||||
"If itemsize is non-zero, then pvItemToQueue cannot be NULL." );
|
||||
__CPROVER_assert( !( ( xCopyPosition == queueOVERWRITE ) && ( xQueue->uxLength != 1 ) ),
|
||||
"If length is one, then check the copy position" );
|
||||
|
||||
/* Return any random value. */
|
||||
return xResult;
|
||||
}
|
||||
|
||||
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet )
|
||||
{
|
||||
EventBits_t uxReturnBits;
|
||||
|
||||
/* The below asserts are copied over from the original function itself. */
|
||||
__CPROVER_assert( xEventGroup != NULL,
|
||||
"The event group cannot be NULL" );
|
||||
__CPROVER_assert( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0,
|
||||
"Cannot set Kernel bits" );
|
||||
|
||||
/* Return any random value. */
|
||||
return uxReturnBits;
|
||||
}
|
||||
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
|
||||
|
||||
__CPROVER_assume( pxSocket != NULL );
|
||||
__CPROVER_assume( pxSocket != FREERTOS_INVALID_SOCKET );
|
||||
|
||||
pxSocket->pxUserWakeCallback = safeMalloc( sizeof( SocketWakeupCallback_t ) );
|
||||
|
||||
pxSocket->pxSocketSet = safeMalloc( sizeof( struct xSOCKET_SET ) );
|
||||
|
||||
if( pxSocket->pxSocketSet != NULL )
|
||||
{
|
||||
pxSocket->pxSocketSet->xSelectGroup = safeMalloc( sizeof( struct EventGroupDef_t ) );
|
||||
|
||||
/* The event group cannot be NULL. */
|
||||
__CPROVER_assume( pxSocket->pxSocketSet->xSelectGroup != NULL );
|
||||
}
|
||||
|
||||
pxSocket->pxUserSemaphore = safeMalloc( sizeof( xQUEUE ) );
|
||||
|
||||
if( pxSocket->pxUserSemaphore != NULL )
|
||||
{
|
||||
/* The item size must be zero since this queue will act as a semaphore. */
|
||||
__CPROVER_assume( pxSocket->pxUserSemaphore->uxItemSize == 0 );
|
||||
}
|
||||
|
||||
pxSocket->xEventGroup = safeMalloc( sizeof( struct EventGroupDef_t ) );
|
||||
|
||||
/* Call to init the socket list. */
|
||||
vNetworkSocketsInit();
|
||||
|
||||
vSocketWakeUpUser( pxSocket );
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
#
|
||||
# FreeRTOS memory safety proofs with CBMC.
|
||||
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://aws.amazon.com/freertos
|
||||
# http://www.FreeRTOS.org
|
||||
#
|
||||
|
||||
{
|
||||
"ENTRY": "TCPHandleState",
|
||||
"TX_DRIVER":1,
|
||||
"RX_MESSAGES":1,
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--unwindset prvWinScaleFactor.0:2",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP_Utils.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP_Timers.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"ipconfigZERO_COPY_TX_DRIVER={TX_DRIVER}",
|
||||
"ipconfigUSE_LINKED_RX_MESSAGES={RX_MESSAGES}",
|
||||
"FREERTOS_TCP_ENABLE_VERIFICATION"
|
||||
],
|
||||
"INSTFLAGS":
|
||||
[
|
||||
"--remove-function-body prvTCPPrepareSend",
|
||||
"--remove-function-body prvTCPReturnPacket"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
This is the memory safety proof for prvTCPHandleState.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* prvTCPPrepareSend (proved independently)
|
||||
* prvTCPReturnPacket (proved independently)
|
||||
|
||||
* lTCPAddRxdata
|
||||
* lTCPWindowRxCheck
|
||||
* lTCPWindowTxAdd
|
||||
* ulTCPWindowTxAck
|
||||
* vTCPWindowInit
|
||||
* xTCPWindowRxEmpty
|
||||
* xTCPWindowTxDone
|
||||
|
||||
* uxStreamBufferGet
|
||||
* vReleaseNetworkBufferAndDescriptor
|
||||
* vSocketWakeUpUser
|
||||
* xTaskGetTickCount
|
||||
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* FreeRTOS memory safety proofs with CBMC.
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_TCP_IP.h"
|
||||
|
||||
#include "../../utility/memory_assignments.c"
|
||||
|
||||
/* Abstraction of xTaskGetCurrentTaskHandle */
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle( void )
|
||||
{
|
||||
static int xIsInit = 0;
|
||||
static TaskHandle_t pxCurrentTCB;
|
||||
TaskHandle_t xRandomTaskHandle; /* not initialized on purpose */
|
||||
|
||||
if( xIsInit == 0 )
|
||||
{
|
||||
pxCurrentTCB = xRandomTaskHandle;
|
||||
xIsInit = 1;
|
||||
}
|
||||
|
||||
return pxCurrentTCB;
|
||||
}
|
||||
|
||||
/* This proof assumes that prvTCPPrepareSend and prvTCPReturnPacket are correct.
|
||||
* These functions are proved to be correct separately. */
|
||||
|
||||
BaseType_t publicTCPHandleState( FreeRTOS_Socket_t * pxSocket,
|
||||
NetworkBufferDescriptor_t ** ppxNetworkBuffer );
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
|
||||
size_t socketSize = sizeof( FreeRTOS_Socket_t );
|
||||
|
||||
if( ensure_memory_is_valid( pxSocket, socketSize ) )
|
||||
{
|
||||
/* ucOptionLength is the number of valid bytes in ulOptionsData[].
|
||||
* ulOptionsData[] is initialized as uint32_t ulOptionsData[ipSIZE_TCP_OPTIONS/sizeof(uint32_t)].
|
||||
* This assumption is required for a memcpy function that copies uxOptionsLength
|
||||
* data from pxTCPHeader->ucOptdata to pxTCPWindow->ulOptionsData.*/
|
||||
__CPROVER_assume( pxSocket->u.xTCP.xTCPWindow.ucOptionLength == sizeof( uint32_t ) * ipSIZE_TCP_OPTIONS / sizeof( uint32_t ) );
|
||||
/* uxRxWinSize is initialized as size_t. This assumption is required to terminate `while(uxWinSize > 0xfffful)` loop.*/
|
||||
__CPROVER_assume( pxSocket->u.xTCP.uxRxWinSize >= 0 && pxSocket->u.xTCP.uxRxWinSize <= sizeof( size_t ) );
|
||||
/* uxRxWinSize is initialized as uint16_t. This assumption is required to terminate `while(uxWinSize > 0xfffful)` loop.*/
|
||||
__CPROVER_assume( pxSocket->u.xTCP.usMSS == sizeof( uint16_t ) );
|
||||
|
||||
if( xIsCallingFromIPTask() == pdFALSE )
|
||||
{
|
||||
__CPROVER_assume( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED );
|
||||
__CPROVER_assume( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED );
|
||||
}
|
||||
}
|
||||
|
||||
NetworkBufferDescriptor_t * pxNetworkBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated();
|
||||
size_t bufferSize = sizeof( NetworkBufferDescriptor_t );
|
||||
|
||||
if( ensure_memory_is_valid( pxNetworkBuffer, bufferSize ) )
|
||||
{
|
||||
pxNetworkBuffer->pucEthernetBuffer = safeMalloc( sizeof( TCPPacket_t ) );
|
||||
}
|
||||
|
||||
if( ensure_memory_is_valid( pxSocket, socketSize ) &&
|
||||
ensure_memory_is_valid( pxNetworkBuffer, bufferSize ) &&
|
||||
ensure_memory_is_valid( pxNetworkBuffer->pucEthernetBuffer, sizeof( TCPPacket_t ) ) &&
|
||||
ensure_memory_is_valid( pxSocket->u.xTCP.pxPeerSocket, socketSize ) )
|
||||
{
|
||||
publicTCPHandleState( pxSocket, &pxNetworkBuffer );
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#
|
||||
# FreeRTOS memory safety proofs with CBMC.
|
||||
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://aws.amazon.com/freertos
|
||||
# http://www.FreeRTOS.org
|
||||
#
|
||||
|
||||
{
|
||||
"ENTRY": "TCPPrepareSend",
|
||||
"CBMCFLAGS":
|
||||
[
|
||||
"--unwind 1",
|
||||
"--nondet-static"
|
||||
],
|
||||
"OBJS":
|
||||
[
|
||||
"$(ENTRY)_harness.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto",
|
||||
"$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto"
|
||||
],
|
||||
"DEF":
|
||||
[
|
||||
"FREERTOS_TCP_ENABLE_VERIFICATION"
|
||||
],
|
||||
"INC":
|
||||
[
|
||||
"$(FREERTOS_PLUS_TCP)/test/cbmc/include"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
This is the memory safety proof for prvTCPPrepareSend.
|
||||
|
||||
This proof is a work-in-progress. Proof assumptions are described in
|
||||
the harness. The proof also assumes the following functions are
|
||||
memory safe and have no side effects relevant to the memory safety of
|
||||
this function:
|
||||
|
||||
* ulTCPWindowTxGet
|
||||
* xTCPWindowTxDone
|
||||
|
||||
* xTaskGetTickCount
|
||||
|
||||
* uxStreamBufferGet
|
||||
* vReleaseNetworkBufferAndDescriptor
|
||||
* vSocketWakeUpUser
|
||||
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* FreeRTOS memory safety proofs with CBMC.
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_IP_Private.h"
|
||||
#include "FreeRTOS_TCP_IP.h"
|
||||
#include "FreeRTOS_Stream_Buffer.h"
|
||||
|
||||
#include "../../utility/memory_assignments.c"
|
||||
|
||||
/* This proof assumes that pxGetNetworkBufferWithDescriptor is implemented correctly. */
|
||||
int32_t publicTCPPrepareSend( FreeRTOS_Socket_t * pxSocket,
|
||||
NetworkBufferDescriptor_t ** ppxNetworkBuffer,
|
||||
UBaseType_t uxOptionsLength );
|
||||
|
||||
/* Abstraction of pxGetNetworkBufferWithDescriptor. It creates a buffer. */
|
||||
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
|
||||
TickType_t xBlockTimeTicks )
|
||||
{
|
||||
NetworkBufferDescriptor_t * pxBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated();
|
||||
size_t bufferSize = sizeof( NetworkBufferDescriptor_t );
|
||||
|
||||
if( ensure_memory_is_valid( pxBuffer, bufferSize ) )
|
||||
{
|
||||
/* The code does not expect pucEthernetBuffer to be equal to NULL if
|
||||
* pxBuffer is not NULL. */
|
||||
pxBuffer->pucEthernetBuffer = malloc( xRequestedSizeBytes );
|
||||
__CPROVER_assume( pxBuffer->pucEthernetBuffer != NULL );
|
||||
pxBuffer->xDataLength = xRequestedSizeBytes;
|
||||
}
|
||||
|
||||
return pxBuffer;
|
||||
}
|
||||
|
||||
void harness()
|
||||
{
|
||||
FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated();
|
||||
NetworkBufferDescriptor_t * pxNetworkBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated();
|
||||
size_t socketSize = sizeof( FreeRTOS_Socket_t );
|
||||
size_t bufferSize = sizeof( TCPPacket_t );
|
||||
|
||||
if( ensure_memory_is_valid( pxNetworkBuffer, sizeof( *pxNetworkBuffer ) ) )
|
||||
{
|
||||
pxNetworkBuffer->xDataLength = bufferSize;
|
||||
|
||||
/* The code does not expect pucEthernetBuffer to be equal to NULL if
|
||||
* pxNetworkBuffer is not NULL. */
|
||||
pxNetworkBuffer->pucEthernetBuffer = malloc( bufferSize );
|
||||
__CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer != NULL );
|
||||
}
|
||||
|
||||
UBaseType_t uxOptionsLength;
|
||||
|
||||
if( pxSocket )
|
||||
{
|
||||
publicTCPPrepareSend( pxSocket, &pxNetworkBuffer, uxOptionsLength );
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user