xref: /FreeRTOS-Plus-TCP-v4.0.0/test/cbmc/stubs/freertos_api.c (revision 2d3f4daa567ffe71aeda2e0f6d0bc02850db0627)
1 /* Standard includes. */
2 #include <stdint.h>
3 #include <stdio.h>
4 
5 /* FreeRTOS includes. */
6 #include "FreeRTOS.h"
7 #include "task.h"
8 #include "queue.h"
9 #include "semphr.h"
10 
11 /* FreeRTOS+TCP includes. */
12 #include "FreeRTOS_UDP_IP.h"
13 #include "FreeRTOS_IP.h"
14 #include "FreeRTOS_Sockets.h"
15 #include "FreeRTOS_IP_Private.h"
16 #include "FreeRTOS_DNS.h"
17 #include "NetworkBufferManagement.h"
18 
19 #include "cbmc.h"
20 
21 /****************************************************************
22 * This is a collection of abstractions of methods in the FreeRTOS TCP
23 * API.  The abstractions simply perform minimal validation of
24 * function arguments, and return unconstrained values of the
25 * appropriate type.
26 ****************************************************************/
27 
28 /****************************************************************
29 * Abstract FreeRTOS_socket.
30 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/socket.html
31 *
32 * We stub out this function to do nothing but allocate space for a
33 * socket containing unconstrained data or return an error.
34 ****************************************************************/
35 
FreeRTOS_socket(BaseType_t xDomain,BaseType_t xType,BaseType_t xProtocol)36 Socket_t FreeRTOS_socket( BaseType_t xDomain,
37                           BaseType_t xType,
38                           BaseType_t xProtocol )
39 {
40     if( nondet_bool() )
41     {
42         return FREERTOS_INVALID_SOCKET;
43     }
44     else
45     {
46         void * ptr = malloc( sizeof( struct xSOCKET ) );
47         __CPROVER_assume( ptr != NULL );
48         return ptr;
49     }
50 }
51 
52 /****************************************************************
53 * Abstract FreeRTOS_setsockopt.
54 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/setsockopt.html
55 ****************************************************************/
56 
FreeRTOS_setsockopt(Socket_t xSocket,int32_t lLevel,int32_t lOptionName,const void * pvOptionValue,size_t uxOptionLength)57 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket,
58                                 int32_t lLevel,
59                                 int32_t lOptionName,
60                                 const void * pvOptionValue,
61                                 size_t uxOptionLength )
62 {
63     __CPROVER_assert( xSocket != NULL,
64                       "FreeRTOS precondition: xSocket != NULL" );
65     __CPROVER_assert( pvOptionValue != NULL,
66                       "FreeRTOS precondition: pvOptionValue != NULL" );
67     return nondet_BaseType();
68 }
69 
70 /****************************************************************
71 * Abstract FreeRTOS_closesocket.
72 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/close.html
73 ****************************************************************/
74 
FreeRTOS_closesocket(Socket_t xSocket)75 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
76 {
77     __CPROVER_assert( xSocket != NULL,
78                       "FreeRTOS precondition: xSocket != NULL" );
79     return nondet_BaseType();
80 }
81 
82 /****************************************************************
83 * Abstract FreeRTOS_bind.
84 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/bind.html
85 ****************************************************************/
86 
FreeRTOS_bind(Socket_t xSocket,struct freertos_sockaddr * pxAddress,socklen_t xAddressLength)87 BaseType_t FreeRTOS_bind( Socket_t xSocket,
88                           struct freertos_sockaddr * pxAddress,
89                           socklen_t xAddressLength )
90 {
91     __CPROVER_assert( xSocket != NULL,
92                       "FreeRTOS precondition: xSocket != NULL" );
93     __CPROVER_assert( pxAddress != NULL,
94                       "FreeRTOS precondition: pxAddress != NULL" );
95     return nondet_BaseType();
96 }
97 
98 /****************************************************************
99 * Abstract FreeRTOS_inet_addr.
100 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/inet_addr.html
101 ****************************************************************/
102 
FreeRTOS_inet_addr(const char * pcIPAddress)103 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
104 {
105     __CPROVER_assert( pcIPAddress != NULL,
106                       "FreeRTOS precondition: pcIPAddress != NULL" );
107     return nondet_uint32();
108 }
109 
110 /****************************************************************
111 * Abstract FreeRTOS_recvfrom.
112 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/recvfrom.html
113 *
114 * We stub out this function to do nothing but allocate a buffer of
115 * unconstrained size containing unconstrained data and return the
116 * size (or return the size 0 if the allocation fails).
117 ****************************************************************/
118 
FreeRTOS_recvfrom(Socket_t xSocket,void * pvBuffer,size_t uxBufferLength,BaseType_t xFlags,struct freertos_sockaddr * pxSourceAddress,socklen_t * pxSourceAddressLength)119 int32_t FreeRTOS_recvfrom( Socket_t xSocket,
120                            void * pvBuffer,
121                            size_t uxBufferLength,
122                            BaseType_t xFlags,
123                            struct freertos_sockaddr * pxSourceAddress,
124                            socklen_t * pxSourceAddressLength )
125 
126 {
127     /****************************************************************
128     * "If the zero copy calling semantics are used (the ulFlags
129     * parameter does not have the FREERTOS_ZERO_COPY bit set) then
130     * pvBuffer does not point to a buffer and xBufferLength is not
131     * used."  This is from the documentation.
132     ****************************************************************/
133     __CPROVER_assert( xFlags & FREERTOS_ZERO_COPY, "I can only do ZERO_COPY" );
134 
135     __CPROVER_assert( pvBuffer != NULL,
136                       "FreeRTOS precondition: pvBuffer != NULL" );
137 
138     /****************************************************************
139     * TODO: We need to check this out.
140     *
141     * The code calls recvfrom with these parameters NULL, it is not
142     * clear from the documentation that this is allowed.
143     ****************************************************************/
144     #if 0
145         __CPROVER_assert( pxSourceAddress != NULL,
146                           "FreeRTOS precondition: pxSourceAddress != NULL" );
147         __CPROVER_assert( pxSourceAddressLength != NULL,
148                           "FreeRTOS precondition: pxSourceAddress != NULL" );
149     #endif
150 
151     size_t payload_size;
152     __CPROVER_assume( payload_size + sizeof( UDPPacket_t )
153                       < CBMC_MAX_OBJECT_SIZE );
154 
155     /****************************************************************
156     * TODO: We need to make this lower bound explicit in the Makefile.json
157     *
158     * DNSMessage_t is a typedef in FreeRTOS_DNS.c
159     * sizeof(DNSMessage_t) = 6 * sizeof(uint16_t)
160     ****************************************************************/
161     __CPROVER_assume( payload_size >= 6 * sizeof( uint16_t ) );
162 
163     #ifdef CBMC_FREERTOS_RECVFROM_BUFFER_BOUND
164         __CPROVER_assume( payload_size <= CBMC_FREERTOS_RECVFROM_BUFFER_BOUND );
165     #endif
166 
167     uint32_t buffer_size = payload_size + sizeof( UDPPacket_t );
168     uint8_t * buffer = safeMalloc( buffer_size );
169 
170     if( buffer == NULL )
171     {
172         buffer_size = 0;
173     }
174     else
175     {
176         buffer = buffer + sizeof( UDPPacket_t );
177         buffer_size = buffer_size - sizeof( UDPPacket_t );
178     }
179 
180     *( ( uint8_t ** ) pvBuffer ) = buffer;
181     return buffer_size;
182 }
183 
184 /****************************************************************
185 * Abstract FreeRTOS_recvfrom.
186 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/sendto.html
187 ****************************************************************/
188 
FreeRTOS_sendto(Socket_t xSocket,const void * pvBuffer,size_t uxTotalDataLength,BaseType_t xFlags,const struct freertos_sockaddr * pxDestinationAddress,socklen_t xDestinationAddressLength)189 int32_t FreeRTOS_sendto( Socket_t xSocket,
190                          const void * pvBuffer,
191                          size_t uxTotalDataLength,
192                          BaseType_t xFlags,
193                          const struct freertos_sockaddr * pxDestinationAddress,
194                          socklen_t xDestinationAddressLength )
195 {
196     __CPROVER_assert( xSocket != NULL,
197                       "FreeRTOS precondition: xSocket != NULL" );
198     __CPROVER_assert( pvBuffer != NULL,
199                       "FreeRTOS precondition: pvBuffer != NULL" );
200     __CPROVER_assert( pxDestinationAddress != NULL,
201                       "FreeRTOS precondition: pxDestinationAddress != NULL" );
202     return nondet_int32();
203 }
204 
205 /****************************************************************
206 * Abstract FreeRTOS_GetUDPPayloadBuffer
207 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/FreeRTOS_GetUDPPayloadBuffer.html
208 *
209 * We stub out this function to do nothing but allocate a buffer of
210 * unconstrained size containing unconstrained data and return a
211 * pointer to the buffer (or NULL).
212 ****************************************************************/
213 
FreeRTOS_GetUDPPayloadBuffer_Multi(size_t uxRequestedSizeBytes,TickType_t uxBlockTimeTicks,uint8_t ucIPType)214 void * FreeRTOS_GetUDPPayloadBuffer_Multi( size_t uxRequestedSizeBytes,
215                                            TickType_t uxBlockTimeTicks,
216                                            uint8_t ucIPType )
217 {
218     size_t size;
219 
220     __CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
221     __CPROVER_assume( size >= sizeof( UDPPacket_t ) );
222 
223     uint8_t * buffer = safeMalloc( size );
224 
225     return buffer == NULL ? buffer : buffer + sizeof( UDPPacket_t );
226 }
227 
228 /****************************************************************
229 * Abstract FreeRTOS_ReleaseUDPPayloadBuffer
230 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_ReleaseUDPPayloadBuffer.html
231 ****************************************************************/
232 
FreeRTOS_ReleaseUDPPayloadBuffer(void * pvBuffer)233 void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer )
234 {
235     __CPROVER_assert( pvBuffer != NULL,
236                       "FreeRTOS precondition: pvBuffer != NULL" );
237     __CPROVER_assert( __CPROVER_POINTER_OFFSET( pvBuffer )
238                       == sizeof( UDPPacket_t ),
239                       "FreeRTOS precondition: pvBuffer offset" );
240 
241     free( pvBuffer - sizeof( UDPPacket_t ) );
242 }
243 
244 /****************************************************************
245 * Abstract pxGetNetworkBufferWithDescriptor.
246 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/pxGetNetworkBufferWithDescriptor.html
247 *
248 * The real allocator take buffers off a list.
249 ****************************************************************/
250 
251 uint32_t GetNetworkBuffer_failure_count;
252 
pxGetNetworkBufferWithDescriptor(size_t xRequestedSizeBytes,TickType_t xBlockTimeTicks)253 NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
254                                                               TickType_t xBlockTimeTicks )
255 {
256     __CPROVER_assert(
257         xRequestedSizeBytes + ipBUFFER_PADDING < CBMC_MAX_OBJECT_SIZE,
258         "pxGetNetworkBufferWithDescriptor: request too big" );
259 
260     /*
261      * The semantics of this function is to wait until a buffer with
262      * at least the requested number of bytes becomes available.  If a
263      * timeout occurs before the buffer is available, then return a
264      * NULL pointer.
265      */
266 
267     NetworkBufferDescriptor_t * desc = safeMalloc( sizeof( *desc ) );
268 
269     #ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
270 
271         /*
272          * This interprets the failure bound as being one greater than the
273          * actual number of times GetNetworkBuffer should be allowed to
274          * fail.
275          *
276          * This makes it possible to use the same bound for loop unrolling
277          * which must be one greater than the actual number of times the
278          * loop should be unwound.
279          *
280          * NOTE: Using this bound with --nondet-static requires setting
281          * (or assuming) GetNetworkBuffer_failure_count to a value (like 0)
282          * in the proof harness that won't induce an integer overflow.
283          */
284         GetNetworkBuffer_failure_count++;
285         __CPROVER_assume(
286             IMPLIES(
287                 GetNetworkBuffer_failure_count >= CBMC_GETNETWORKBUFFER_FAILURE_BOUND,
288                 desc != NULL ) );
289     #endif
290 
291     if( desc != NULL )
292     {
293         /*
294          * We may want to experiment with allocating space other than
295          * (more than) the exact amount of space requested.
296          */
297 
298         size_t size = xRequestedSizeBytes;
299         __CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
300 
301         desc->pucEthernetBuffer = safeMalloc( size );
302         desc->xDataLength = desc->pucEthernetBuffer == NULL ? 0 : size;
303 
304         #ifdef CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL
305             /* This may be implied by the semantics of the function. */
306             __CPROVER_assume( desc->pucEthernetBuffer != NULL );
307         #endif
308 
309         /* Allow method to fail again next time */
310         GetNetworkBuffer_failure_count = 0;
311     }
312 
313     return desc;
314 }
315 
316 /****************************************************************
317 * Abstract pxGetNetworkBufferWithDescriptor.
318 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vReleaseNetworkBufferAndDescriptor.html
319 ****************************************************************/
320 
vReleaseNetworkBufferAndDescriptor(NetworkBufferDescriptor_t * const pxNetworkBuffer)321 void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
322 {
323     __CPROVER_assert( pxNetworkBuffer != NULL,
324                       "Precondition: pxNetworkBuffer != NULL" );
325 
326     if( pxNetworkBuffer->pucEthernetBuffer != NULL )
327     {
328         free( pxNetworkBuffer->pucEthernetBuffer );
329     }
330 
331     free( pxNetworkBuffer );
332 }
333 
334 /****************************************************************
335 * Abstract FreeRTOS_GetAddressConfiguration
336 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_GetAddressConfiguration.html
337 ****************************************************************/
338 
FreeRTOS_GetAddressConfiguration(uint32_t * pulIPAddress,uint32_t * pulNetMask,uint32_t * pulGatewayAddress,uint32_t * pulDNSServerAddress)339 void FreeRTOS_GetAddressConfiguration( uint32_t * pulIPAddress,
340                                        uint32_t * pulNetMask,
341                                        uint32_t * pulGatewayAddress,
342                                        uint32_t * pulDNSServerAddress )
343 {
344     if( pulIPAddress != NULL )
345     {
346         *pulIPAddress = nondet_unint32();
347     }
348 
349     if( pulNetMask != NULL )
350     {
351         *pulNetMask = nondet_unint32();
352     }
353 
354     if( pulGatewayAddress != NULL )
355     {
356         *pulGatewayAddress = nondet_unint32();
357     }
358 
359     if( pulDNSServerAddress != NULL )
360     {
361         *pulDNSServerAddress = nondet_unint32();
362     }
363 }
364 
365 /****************************************************************/
366 
367 /****************************************************************
368 * This is a collection of methods that are defined by the user
369 * application but are invoked by the FreeRTOS API.
370 ****************************************************************/
371 
372 /****************************************************************
373 * Abstract FreeRTOS_GetAddressConfiguration
374 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vApplicationIPNetworkEventHook.html
375 ****************************************************************/
376 
vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent)377 void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
378 {
379 }
380 
381 /****************************************************************
382 * Abstract pcApplicationHostnameHook
383 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html
384 ****************************************************************/
385 
pcApplicationHostnameHook(void)386 const char * pcApplicationHostnameHook( void )
387 {
388     return "hostname";
389 }
390 
391 /****************************************************************/
392 
393 
394 /****************************************************************
395 * Abstract xNetworkInterfaceOutput
396 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Porting.html#xNetworkInterfaceOutput
397 ****************************************************************/
xNetworkInterfaceOutput(NetworkBufferDescriptor_t * const pxNetworkBuffer,BaseType_t bReleaseAfterSend)398 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
399                                     BaseType_t bReleaseAfterSend )
400 {
401     __CPROVER_assert( pxNetworkBuffer != NULL, "The networkbuffer cannot be NULL" );
402 
403     BaseType_t xReturn;
404 
405     /* Return some random value. */
406     return xReturn;
407 }
408 
409 /****************************************************************/
410