summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Test/CBMC/stubs/freertos_api.c
blob: 668f8b94194ddffc99e7f736cc36b46b68a2aa0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>

/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"

#include "cbmc.h"

/****************************************************************
 * This is a collection of abstractions of methods in the FreeRTOS TCP
 * API.  The abstractions simply perform minimal validation of
 * function arguments, and return unconstrained values of the
 * appropriate type.
 ****************************************************************/

/****************************************************************
 * Abstract FreeRTOS_socket.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/socket.html
 *
 * We stub out this function to do nothing but allocate space for a
 * socket containing unconstrained data or return an error.
 ****************************************************************/

Socket_t FreeRTOS_socket( BaseType_t xDomain,
                          BaseType_t xType,
                          BaseType_t xProtocol )
{
    return nondet_bool() ?
           FREERTOS_INVALID_SOCKET : malloc( sizeof( Socket_t ) );
}

/****************************************************************
 * Abstract FreeRTOS_setsockopt.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/setsockopt.html
 ****************************************************************/

BaseType_t FreeRTOS_setsockopt( Socket_t xSocket,
                                int32_t lLevel,
                                int32_t lOptionName,
                                const void * pvOptionValue,
                                size_t uxOptionLength )
{
    __CPROVER_assert( xSocket != NULL,
                      "FreeRTOS precondition: xSocket != NULL" );
    __CPROVER_assert( pvOptionValue != NULL,
                      "FreeRTOS precondition: pvOptionValue != NULL" );
    return nondet_BaseType();
}

/****************************************************************
 * Abstract FreeRTOS_closesocket.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/close.html
 ****************************************************************/

BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
{
    __CPROVER_assert( xSocket != NULL,
                      "FreeRTOS precondition: xSocket != NULL" );
    return nondet_BaseType();
}

/****************************************************************
 * Abstract FreeRTOS_bind.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/bind.html
 ****************************************************************/

BaseType_t FreeRTOS_bind( Socket_t xSocket,
                          struct freertos_sockaddr * pxAddress,
                          socklen_t xAddressLength )
{
    __CPROVER_assert( xSocket != NULL,
                      "FreeRTOS precondition: xSocket != NULL" );
    __CPROVER_assert( pxAddress != NULL,
                      "FreeRTOS precondition: pxAddress != NULL" );
    return nondet_BaseType();
}

/****************************************************************
 * Abstract FreeRTOS_inet_addr.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/inet_addr.html
 ****************************************************************/

uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
{
    __CPROVER_assert( pcIPAddress != NULL,
                      "FreeRTOS precondition: pcIPAddress != NULL" );
    return nondet_uint32();
}

/****************************************************************
 * Abstract FreeRTOS_recvfrom.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/recvfrom.html
 *
 * We stub out this function to do nothing but allocate a buffer of
 * unconstrained size containing unconstrained data and return the
 * size (or return the size 0 if the allocation fails).
 ****************************************************************/

int32_t FreeRTOS_recvfrom( Socket_t xSocket,
                           void * pvBuffer,
                           size_t uxBufferLength,
                           BaseType_t xFlags,
                           struct freertos_sockaddr * pxSourceAddress,
                           socklen_t * pxSourceAddressLength )

{
    /****************************************************************
     * "If the zero copy calling semantics are used (the ulFlasg
     * parameter does not have the FREERTOS_ZERO_COPY bit set) then
     * pvBuffer does not point to a buffer and xBufferLength is not
     * used."  This is from the documentation.
     ****************************************************************/
    __CPROVER_assert( xFlags & FREERTOS_ZERO_COPY, "I can only do ZERO_COPY" );

    __CPROVER_assert( pvBuffer != NULL,
                      "FreeRTOS precondition: pvBuffer != NULL" );

    /****************************************************************
     * TODO: We need to check this out.
     *
     * The code calls recvfrom with these parameters NULL, it is not
     * clear from the documentation that this is allowed.
     ****************************************************************/
    #if 0
        __CPROVER_assert( pxSourceAddress != NULL,
                          "FreeRTOS precondition: pxSourceAddress != NULL" );
        __CPROVER_assert( pxSourceAddressLength != NULL,
                          "FreeRTOS precondition: pxSourceAddress != NULL" );
    #endif

    size_t payload_size;
    __CPROVER_assume( payload_size + sizeof( UDPPacket_t )
		      < CBMC_MAX_OBJECT_SIZE );

    /****************************************************************
     * TODO: We need to make this lower bound explicit in the Makefile.json
     *
     * DNSMessage_t is a typedef in FreeRTOS_DNS.c
     * sizeof(DNSMessage_t) = 6 * sizeof(uint16_t)
     ****************************************************************/
    __CPROVER_assume( payload_size >= 6 * sizeof( uint16_t ) );

    #ifdef CBMC_FREERTOS_RECVFROM_BUFFER_BOUND
        __CPROVER_assume( payload_size <= CBMC_FREERTOS_RECVFROM_BUFFER_BOUND );
    #endif

    uint32_t buffer_size = payload_size + sizeof( UDPPacket_t );
    uint8_t *buffer = safeMalloc( buffer_size );
	
    if ( buffer == NULL ) {
      buffer_size = 0;
    }
    else
    {
      buffer = buffer + sizeof( UDPPacket_t );
      buffer_size = buffer_size - sizeof( UDPPacket_t );
    }
    
    *( ( uint8_t ** ) pvBuffer ) = buffer;
    return buffer_size;
}

/****************************************************************
 * Abstract FreeRTOS_recvfrom.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/sendto.html
 ****************************************************************/

int32_t FreeRTOS_sendto( Socket_t xSocket,
                         const void * pvBuffer,
                         size_t uxTotalDataLength,
                         BaseType_t xFlags,
                         const struct freertos_sockaddr * pxDestinationAddress,
                         socklen_t xDestinationAddressLength )
{
    __CPROVER_assert( xSocket != NULL,
                      "FreeRTOS precondition: xSocket != NULL" );
    __CPROVER_assert( pvBuffer != NULL,
                      "FreeRTOS precondition: pvBuffer != NULL" );
    __CPROVER_assert( pxDestinationAddress != NULL,
                      "FreeRTOS precondition: pxDestinationAddress != NULL" );
    return nondet_int32();
}

/****************************************************************
 * Abstract FreeRTOS_GetUDPPayloadBuffer
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/FreeRTOS_GetUDPPayloadBuffer.html
 *
 * We stub out this function to do nothing but allocate a buffer of
 * unconstrained size containing unconstrained data and return a
 * pointer to the buffer (or NULL).
 ****************************************************************/

void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes,
                                     TickType_t xBlockTimeTicks )
{
    size_t size;

    __CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
    __CPROVER_assume( size >= sizeof( UDPPacket_t ) );

    uint8_t *buffer = safeMalloc( size );
    return buffer == NULL ? buffer : buffer + sizeof( UDPPacket_t );
}

/****************************************************************
 * Abstract FreeRTOS_GetUDPPayloadBuffer
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_ReleaseUDPPayloadBuffer.html
 ****************************************************************/

void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer )
{
    __CPROVER_assert( pvBuffer != NULL,
                      "FreeRTOS precondition: pvBuffer != NULL" );
    __CPROVER_assert( __CPROVER_POINTER_OFFSET( pvBuffer )
		      == sizeof( UDPPacket_t ),
                      "FreeRTOS precondition: pvBuffer offset" );

    free( pvBuffer - sizeof( UDPPacket_t ) );
}

/****************************************************************
 * Abstract pxGetNetworkBufferWithDescriptor.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/pxGetNetworkBufferWithDescriptor.html
 *
 * The real allocator take buffers off a list.
 ****************************************************************/

uint32_t GetNetworkBuffer_failure_count;

NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
                                                              TickType_t xBlockTimeTicks )
{
    __CPROVER_assert(
        xRequestedSizeBytes + ipBUFFER_PADDING < CBMC_MAX_OBJECT_SIZE,
        "pxGetNetworkBufferWithDescriptor: request too big" );

    /*
      * The semantics of this function is to wait until a buffer with
      * at least the requested number of bytes becomes available.  If a
      * timeout occurs before the buffer is available, then return a
      * NULL pointer.
      */

    NetworkBufferDescriptor_t * desc = safeMalloc( sizeof( *desc ) );

    #ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
        /*
          * This interprets the failure bound as being one greater than the
          * actual number of times GetNetworkBuffer should be allowed to
          * fail.
          *
          * This makes it possible to use the same bound for loop unrolling
          * which must be one greater than the actual number of times the
          * loop should be unwound.
          *
          * NOTE: Using this bound with --nondet-static requires setting
          * (or assuming) GetNetworkBuffer_failure_count to a value (like 0)
          * in the proof harness that won't induce an integer overflow.
          */
        GetNetworkBuffer_failure_count++;
        __CPROVER_assume(
	    IMPLIES(
	        GetNetworkBuffer_failure_count >= CBMC_GETNETWORKBUFFER_FAILURE_BOUND,
		desc != NULL ) );
    #endif

    if( desc != NULL )
    {
        /*
          * We may want to experiment with allocating space other than
          * (more than) the exact amount of space requested.
          */

        size_t size = xRequestedSizeBytes;
        __CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );

        desc->pucEthernetBuffer = safeMalloc( size );
        desc->xDataLength = desc->pucEthernetBuffer == NULL ? 0 : size;

        #ifdef CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL
            /* This may be implied by the semantics of the function. */
            __CPROVER_assume( desc->pucEthernetBuffer != NULL );
        #endif

	/* Allow method to fail again next time */
	GetNetworkBuffer_failure_count = 0;
    }

    return desc;
}

/****************************************************************
 * Abstract pxGetNetworkBufferWithDescriptor.
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vReleaseNetworkBufferAndDescriptor.html
 ****************************************************************/

void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
    __CPROVER_assert( pxNetworkBuffer != NULL,
                      "Precondition: pxNetworkBuffer != NULL" );

    if( pxNetworkBuffer->pucEthernetBuffer != NULL )
    {
        free( pxNetworkBuffer->pucEthernetBuffer );
    }

    free( pxNetworkBuffer );
}

/****************************************************************
 * Abstract FreeRTOS_GetAddressConfiguration
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_GetAddressConfiguration.html
 ****************************************************************/

void FreeRTOS_GetAddressConfiguration( uint32_t * pulIPAddress,
                                       uint32_t * pulNetMask,
                                       uint32_t * pulGatewayAddress,
                                       uint32_t * pulDNSServerAddress )
{
    if( pulIPAddress != NULL )
    {
        *pulIPAddress = nondet_unint32();
    }

    if( pulNetMask != NULL )
    {
        *pulNetMask = nondet_unint32();
    }

    if( pulGatewayAddress != NULL )
    {
        *pulGatewayAddress = nondet_unint32();
    }

    if( pulDNSServerAddress != NULL )
    {
        *pulDNSServerAddress = nondet_unint32();
    }
}

/****************************************************************/

/****************************************************************
 * This is a collection of methods that are defined by the user
 * application but are invoked by the FreeRTOS API.
 ****************************************************************/

/****************************************************************
 * Abstract FreeRTOS_GetAddressConfiguration
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vApplicationIPNetworkEventHook.html
 ****************************************************************/

void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
}

/****************************************************************
 * Abstract pcApplicationHostnameHook
 * https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html
 ****************************************************************/

const char * pcApplicationHostnameHook( void )
{
    return "hostname";
}

/****************************************************************/