Skip to content

Commit af68d78

Browse files
Fix the CBMC proof of DNSgetHostByName_a (FreeRTOS#172)
* Update the proof * Uncrustify and spell check. * Update after review comments * Update after comments Co-authored-by: Gary Wicker <[email protected]>
1 parent c28847d commit af68d78

File tree

3 files changed

+117
-16
lines changed

3 files changed

+117
-16
lines changed

FreeRTOS_DNS.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@
377377
}
378378
#include "pack_struct_end.h"
379379
typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
380-
/** @brief this is for debugging only. */
381-
static struct freertos_addrinfo * pxLastInfo = NULL;
380+
/** @brief Used for additional error checking when asserts are enabled. */
381+
_static struct freertos_addrinfo * pxLastInfo = NULL;
382382

383383

384384
/**

test/cbmc/proofs/DNS/DNSgetHostByName_a/DNSgetHostByName_a_harness.c

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "FreeRTOS_UDP_IP.h"
1515
#include "FreeRTOS_DNS.h"
1616
#include "FreeRTOS_DHCP.h"
17+
#include "FreeRTOS_Routing.h"
1718
#include "NetworkBufferManagement.h"
1819
#include "NetworkInterface.h"
1920

@@ -37,6 +38,68 @@
3738
* bound the iterations of strcmp.
3839
****************************************************************/
3940

41+
/* This variable is defined in FreeRTOS_DNS.c */
42+
extern struct freertos_addrinfo * pxLastInfo;
43+
44+
/* Function Abstraction:
45+
* pxGetNetworkBufferWithDescriptor allocates a Network buffer after taking it
46+
* out of a list of network buffers maintained by the TCP stack. To prove the memory
47+
* safety of the function under test, we do not need to initialise the list - it
48+
* would make the proof more complex and deviate from its objective.
49+
* Keeping this in mind, the below stub perform some basic checks required and
50+
* allocates the required amount of memory without making any other assumptions
51+
* whatsoever.
52+
*/
53+
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
54+
TickType_t xBlockTimeTicks )
55+
{
56+
__CPROVER_assert(
57+
xRequestedSizeBytes + ipBUFFER_PADDING < CBMC_MAX_OBJECT_SIZE,
58+
"pxGetNetworkBufferWithDescriptor: request too big" );
59+
60+
/* Arbitrarily return NULL or a valid pointer. */
61+
NetworkBufferDescriptor_t * pxReturn = nondet_bool() ? NULL : malloc( sizeof( *pxReturn ) );
62+
63+
if( pxReturn != NULL )
64+
{
65+
/* Allocate the ethernet buffer. */
66+
pxReturn->pucEthernetBuffer = malloc( xRequestedSizeBytes + ipBUFFER_PADDING );
67+
68+
__CPROVER_assume( pxReturn->pucEthernetBuffer != NULL );
69+
70+
pxReturn->xDataLength = xRequestedSizeBytes;
71+
72+
/* Move the pointer ipBUFFER_PADDING (defined in FreeRTOS_IP.h) bytes
73+
* ahead. This space is used to store data by the TCP stack for its own
74+
* use whilst processing the packet. */
75+
pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
76+
}
77+
78+
return pxReturn;
79+
}
80+
81+
/* Function Abstraction:
82+
* vReleaseNetworkBufferAndDescriptor frees the memory associated with the ethernet
83+
* buffer and returns the network buffer to a list maintained by the +TCP stack. But
84+
* for the function under test, we do not need to initialise and maintain the list,
85+
* as it would make the proof unnecessarily complex.
86+
* Keeping this in mind, the stub below asserts some basic condition(s) and frees
87+
* the memory allocated by the pxGetNetworkBufferWithDescriptor stub above.
88+
*/
89+
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
90+
{
91+
__CPROVER_assert( pxNetworkBuffer != NULL,
92+
"Precondition: pxNetworkBuffer != NULL" );
93+
94+
if( pxNetworkBuffer->pucEthernetBuffer != NULL )
95+
{
96+
pxNetworkBuffer->pucEthernetBuffer -= ipBUFFER_PADDING;
97+
free( pxNetworkBuffer->pucEthernetBuffer );
98+
}
99+
100+
free( pxNetworkBuffer );
101+
}
102+
40103
/****************************************************************
41104
* Abstract prvParseDNSReply proved memory safe in ParseDNSReply.
42105
*
@@ -47,9 +110,10 @@
47110
* function.
48111
****************************************************************/
49112

50-
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
51-
size_t xBufferLength,
52-
BaseType_t xExpected )
113+
uint32_t __CPROVER_file_local_FreeRTOS_DNS_c_prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
114+
size_t xBufferLength,
115+
struct freertos_addrinfo ** ppxAddressInfo,
116+
BaseType_t xExpected )
53117
{
54118
__CPROVER_assert( pucUDPPayloadBuffer != NULL,
55119
"Precondition: pucUDPPayloadBuffer != NULL" );
@@ -67,9 +131,10 @@ uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
67131
* unconstrained data and returns and unconstrained length.
68132
****************************************************************/
69133

70-
size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
71-
const char * pcHostName,
72-
TickType_t uxIdentifier )
134+
size_t __CPROVER_file_local_FreeRTOS_DNS_c_prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
135+
const char * pcHostName,
136+
TickType_t uxIdentifier,
137+
UBaseType_t uxHostType )
73138
{
74139
__CPROVER_assert( pucUDPPayloadBuffer != NULL,
75140
"Precondition: pucUDPPayloadBuffer != NULL" );
@@ -90,24 +155,49 @@ void func( const char * pcHostName,
90155
{
91156
}
92157

158+
159+
/** A list of all network end-points. Each element has a next pointer. */
160+
extern struct xNetworkEndPoint * pxNetworkEndPoints;
161+
162+
/** A list of all network interfaces: */
163+
extern struct xNetworkInterface * pxNetworkInterfaces;
164+
165+
93166
/****************************************************************
94167
* The proof for FreeRTOS_gethostbyname_a.
95168
****************************************************************/
96-
97169
void harness()
98170
{
99171
size_t len;
100172

101-
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
102-
char * pcHostName = safeMalloc( len );
173+
__CPROVER_assume( ( len <= MAX_HOSTNAME_LEN ) && ( len > 0 ) );
103174

104-
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
105-
__CPROVER_assume( pcHostName != NULL );
106-
pcHostName[ len - 1 ] = NULL;
175+
/* Arbitrarily assign a proper memory or NULL to the hostname. */
176+
char * pcHostName = nondet_bool() ? malloc( len ) : NULL;
107177

108-
FOnDNSEvent pCallback = func;
178+
/* NULL terminate the string if the pcHostName is allocated. */
179+
if( pcHostName != NULL )
180+
{
181+
pcHostName[ len - 1 ] = NULL;
182+
}
183+
184+
/* Arbitrarily assign a NULL/valid-function to the function-pointer
185+
* being used in the callback. */
186+
FOnDNSEvent pCallback = nondet_bool() ? func : NULL;
109187
TickType_t xTimeout;
110188
void * pvSearchID;
111189

190+
/* Assume that the list of interfaces/endpoints is not initialized.
191+
* Note: These variables are defined in FreeRTOS_Routing.c in global scope.
192+
* They serve as a list to the network interfaces and the corresponding
193+
* endpoints respectively. And are defined as NULL initially. */
194+
__CPROVER_assume( pxNetworkInterfaces == NULL );
195+
__CPROVER_assume( pxNetworkEndPoints == NULL );
196+
197+
/* Assume that the last info pointer is NULL at the beginning. This is defined
198+
* in FreeRTOS_DNS.c and is used for debugging purpose. It is declared NULL
199+
* initially. */
200+
__CPROVER_assume( pxLastInfo == NULL );
201+
112202
FreeRTOS_gethostbyname_a( pcHostName, pCallback, pvSearchID, xTimeout );
113203
}

test/cbmc/proofs/DNS/DNSgetHostByName_a/Makefile.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,36 @@
66
"callback": 1,
77
"MAX_HOSTNAME_LEN": 10,
88
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
9+
"DNS_REQ_ATTEMPTS":2,
10+
"DNS_REQUEST_ATTEMPTS": "__eval {DNS_REQ_ATTEMPTS} + 1",
11+
"DNS_CACHE_ENTRIES":3,
12+
"DNS_CACHE_ENTRIES_UNWIND": "__eval {DNS_CACHE_ENTRIES} + 1",
913
"CBMCFLAGS":
1014
[
1115
"--unwind 1",
12-
"--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}",
16+
"--unwindset FreeRTOS_freeaddrinfo.0:2,__CPROVER_file_local_FreeRTOS_DNS_c_prvReadDNSCache.0:2,__CPROVER_file_local_FreeRTOS_DNS_c_prvGetHostByName.1:{DNS_REQUEST_ATTEMPTS},__CPROVER_file_local_FreeRTOS_DNS_c_prvProcessDNSCache.0:{DNS_CACHE_ENTRIES_UNWIND},prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},__CPROVER_file_local_FreeRTOS_DNS_c_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},strncpy.0:255",
1317
"--nondet-static"
1418
],
1519
"OBJS":
1620
[
1721
"$(ENTRY)_harness.goto",
1822
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/cbmc.goto",
1923
"$(FREERTOS_PLUS_TCP)/test/cbmc/stubs/freertos_api.goto",
24+
"$(FREERTOS_PLUS_TCP)/FreeRTOS_Routing.goto",
2025
"$(FREERTOS_PLUS_TCP)/FreeRTOS_DNS.goto",
2126
"$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto"
2227
],
2328
"DEF":
2429
[
2530
"ipconfigDNS_USE_CALLBACKS={callback}",
2631
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
32+
"ipconfigDNS_REQUEST_ATTEMPTS={DNS_REQ_ATTEMPTS}",
2733
# This value is defined only when ipconfigUSE_DNS_CACHE==1
2834
"ipconfigDNS_CACHE_NAME_LENGTH=254"
35+
],
36+
"OPT":
37+
[
38+
# Flag to access the static function of a file
39+
"--export-file-local-symbols"
2940
]
3041
}

0 commit comments

Comments
 (0)