Skip to content

Commit 4c44cb1

Browse files
author
Mark R. Tuttle
committed
Remove all buffer length assumptions from HTTP proofs.
Also repair CBMC proof of HTTP AddHeaders method until there is a fix to diffblue/cbmc#5096 The key insight to removing buffer length assumptions is that the code accesses all buffers via pointers in the message headers, the code does not depend on the fact that buffers follow the message headers in memory (there is no pointer arithmetic to access the start of the buffers).
1 parent 1e4813c commit 4c44cb1

File tree

2 files changed

+48
-53
lines changed

2 files changed

+48
-53
lines changed

tools/cbmc/proofs/HTTP/IotHttpsClient_AddHeader/Makefile.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# A CBMC pointer is an object id followed by an offest into the object.
99
# The size of the offset is limited by the size of the object id.
1010
"CBMC_OBJECTID_BITS": "7",
11-
"CBMC_MAX_OBJECT_SIZE": "\"(UINT32_MAX>>CBMC_OBJECTID_BITS)\"",
11+
"CBMC_MAX_OBJECT_SIZE": "\"((UINT32_MAX>>CBMC_OBJECTID_BITS)>>1)\"",
1212

1313
"CBMCFLAGS":
1414
[

tools/cbmc/proofs/HTTP/global_state_HTTP.c

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,9 @@ IotHttpsRequestHandle_t allocate_IotRequestHandle();
1212
* without allocating memory.
1313
*/
1414
void *safeMalloc(size_t xWantedSize) {
15-
if(xWantedSize == 0) {
16-
return NULL;
17-
}
1815
return nondet_bool() ? malloc(xWantedSize) : NULL;
1916
}
2017

21-
/****************************************************************/
22-
23-
/* It is common for a buffer to contain a header struct followed by
24-
* user data. We optimize CBMC performance by allocating space for
25-
* the buffer using a struct with two members: the first member is the
26-
* header struct and the second member is the user data. This is
27-
* faster than just allocating a sequence of bytes large enough to
28-
* hold the header struct and the user data. We modeled
29-
* responseHandle, requestHandle and connectionHandle similarly.
30-
*/
31-
32-
// TODO: Replace this model of buffers with a model allowing
33-
// unconstrained sizes for the user data member, or at least
34-
// allowing a small set of differing sizes.
35-
36-
typedef struct _responseHandle
37-
{
38-
struct _httpsResponse RespHandle;
39-
char data[USER_DATA_SIZE];
40-
} _resHandle_t;
41-
42-
typedef struct _requestHandle
43-
{
44-
struct _httpsRequest ReqHandle;
45-
char data[USER_DATA_SIZE];
46-
} _reqHandle_t;
47-
48-
typedef struct _connectionHandle
49-
{
50-
struct _httpsConnection pConnHandle;
51-
char data[USER_DATA_SIZE];
52-
} _connHandle_t;
53-
5418
/****************************************************************
5519
* HTTP parser stubs
5620
****************************************************************/
@@ -216,7 +180,7 @@ IotHttpsConnectionInfo_t * allocate_IotConnectionInfo() {
216180
pConnInfo->pCaCert = safeMalloc(sizeof(uint32_t));
217181
pConnInfo->pClientCert = safeMalloc(sizeof(uint32_t));
218182
pConnInfo->pPrivateKey = safeMalloc(sizeof(uint32_t));
219-
pConnInfo->userBuffer.pBuffer = safeMalloc(sizeof(_connHandle_t));
183+
pConnInfo->userBuffer.pBuffer = safeMalloc(sizeof(struct _httpsConnection));
220184
}
221185
return pConnInfo;
222186
}
@@ -238,7 +202,7 @@ int is_valid_IotConnectionInfo(IotHttpsConnectionInfo_t *pConnInfo) {
238202
/* Creates a Connection Handle and assigns memory accordingly. */
239203
IotHttpsConnectionHandle_t allocate_IotConnectionHandle () {
240204
IotHttpsConnectionHandle_t pConnectionHandle =
241-
safeMalloc(sizeof(_connHandle_t));
205+
safeMalloc(sizeof(struct _httpsConnection));
242206
if(pConnectionHandle) {
243207
// network connection just points to an allocated memory object
244208
pConnectionHandle->pNetworkConnection = safeMalloc(1);
@@ -282,10 +246,13 @@ int is_valid_IotConnectionHandle(IotHttpsConnectionHandle_t handle) {
282246

283247
/* Creates a Response Handle and assigns memory accordingly. */
284248
IotHttpsResponseHandle_t allocate_IotResponseHandle() {
285-
IotHttpsResponseHandle_t pResponseHandle = safeMalloc(sizeof(_resHandle_t));
249+
IotHttpsResponseHandle_t pResponseHandle =
250+
safeMalloc(sizeof(struct _httpsResponse));
286251
if(pResponseHandle) {
287-
uint32_t len;
288-
pResponseHandle->pBody = safeMalloc(len);
252+
size_t headerLen;
253+
size_t bodyLen;
254+
pResponseHandle->pHeaders = safeMalloc(headerLen);
255+
pResponseHandle->pBody = safeMalloc(bodyLen);
289256
pResponseHandle->pHttpsConnection = allocate_IotConnectionHandle();
290257
pResponseHandle->pReadHeaderField =
291258
safeMalloc(pResponseHandle->readHeaderFieldLength);
@@ -295,6 +262,7 @@ IotHttpsResponseHandle_t allocate_IotResponseHandle() {
295262
return pResponseHandle;
296263
}
297264

265+
// ???: Should be is_stubbed
298266
IotHttpsResponseHandle_t
299267
initialize_IotResponseHandle(IotHttpsResponseHandle_t pResponseHandle) {
300268
if(pResponseHandle) {
@@ -304,26 +272,45 @@ initialize_IotResponseHandle(IotHttpsResponseHandle_t pResponseHandle) {
304272
}
305273

306274
int is_valid_IotResponseHandle(IotHttpsResponseHandle_t pResponseHandle) {
307-
int required =
275+
int required1 =
308276
__CPROVER_same_object(pResponseHandle->pHeaders,
309277
pResponseHandle->pHeadersCur) &&
310278
__CPROVER_same_object(pResponseHandle->pHeaders,
311279
pResponseHandle->pHeadersEnd);
312-
if (!required) return 0;
280+
int required2 =
281+
__CPROVER_same_object(pResponseHandle->pBody,
282+
pResponseHandle->pBodyCur) &&
283+
__CPROVER_same_object(pResponseHandle->pBody,
284+
pResponseHandle->pBodyEnd);
285+
if (!required1 || !required2) return 0;
313286

314287
int valid_headers =
315-
pResponseHandle->pHeaders == ((_resHandle_t*)pResponseHandle)->data;
316-
int valid_order =
288+
pResponseHandle->pHeaders != NULL;
289+
int valid_header_order =
317290
pResponseHandle->pHeaders <= pResponseHandle->pHeadersCur &&
318291
pResponseHandle->pHeadersCur <= pResponseHandle->pHeadersEnd;
292+
int valid_body =
293+
pResponseHandle->pBody != NULL;
294+
int valid_body_order =
295+
pResponseHandle->pBody <= pResponseHandle->pBodyCur &&
296+
pResponseHandle->pBodyCur <= pResponseHandle->pBodyEnd;
319297
int valid_parserdata =
320298
pResponseHandle->httpParserInfo.readHeaderParser.data == pResponseHandle;
321299
return
322300
valid_headers &&
323-
valid_order &&
301+
valid_header_order &&
302+
valid_body &&
303+
valid_body_order &&
324304
valid_parserdata &&
325305
// valid_order and short circuit evaluation prevents integer overflow
326-
pResponseHandle->pHeadersEnd - pResponseHandle->pHeaders <= USER_DATA_SIZE;
306+
__CPROVER_r_ok(pResponseHandle->pHeaders,
307+
pResponseHandle->pHeadersEnd - pResponseHandle->pHeaders) &&
308+
__CPROVER_w_ok(pResponseHandle->pHeaders,
309+
pResponseHandle->pHeadersEnd - pResponseHandle->pHeaders) &&
310+
__CPROVER_r_ok(pResponseHandle->pBody,
311+
pResponseHandle->pBodyEnd - pResponseHandle->pBody) &&
312+
__CPROVER_w_ok(pResponseHandle->pBody,
313+
pResponseHandle->pBodyEnd - pResponseHandle->pBody);
327314
}
328315

329316
/****************************************************************
@@ -332,12 +319,14 @@ int is_valid_IotResponseHandle(IotHttpsResponseHandle_t pResponseHandle) {
332319

333320
/* Creates a Request Handle and assigns memory accordingly. */
334321
IotHttpsRequestHandle_t allocate_IotRequestHandle() {
335-
IotHttpsRequestHandle_t pRequestHandle = safeMalloc(sizeof(_reqHandle_t));
322+
IotHttpsRequestHandle_t pRequestHandle =
323+
safeMalloc(sizeof(struct _httpsRequest));
336324
if (pRequestHandle) {
337-
uint32_t len;
325+
uint32_t headerLen;
338326
pRequestHandle->pHttpsResponse = allocate_IotResponseHandle();
339327
pRequestHandle->pHttpsConnection = allocate_IotConnectionHandle();
340-
pRequestHandle->pBody = safeMalloc(len);
328+
pRequestHandle->pHeaders = safeMalloc(headerLen);
329+
pRequestHandle->pBody = safeMalloc(pRequestHandle->bodyLength);
341330
pRequestHandle->pConnInfo = allocate_IotConnectionInfo();
342331
}
343332
return pRequestHandle;
@@ -352,18 +341,24 @@ int is_valid_IotRequestHandle(IotHttpsRequestHandle_t pRequestHandle) {
352341
if (!required) return 0;
353342

354343
int valid_headers =
355-
pRequestHandle->pHeaders == ((_reqHandle_t*)pRequestHandle)->data;
344+
pRequestHandle->pHeaders != NULL;
356345
int valid_order =
357346
pRequestHandle->pHeaders <= pRequestHandle->pHeadersCur &&
358347
pRequestHandle->pHeadersCur <= pRequestHandle->pHeadersEnd;
359348
int valid_body =
360349
pRequestHandle->pBody != NULL;
350+
int bounded_header_buffer =
351+
__CPROVER_OBJECT_SIZE(pRequestHandle->pHeaders) < CBMC_MAX_OBJECT_SIZE;
361352
return
362353
valid_headers &&
363354
valid_order &&
364355
valid_body &&
356+
bounded_header_buffer &&
365357
// valid_order and short circuit evaluation prevents integer overflow
366-
pRequestHandle->pHeadersEnd - pRequestHandle->pHeaders <= USER_DATA_SIZE;
358+
__CPROVER_r_ok(pRequestHandle->pHeaders,
359+
pRequestHandle->pHeadersEnd - pRequestHandle->pHeaders) &&
360+
__CPROVER_w_ok(pRequestHandle->pHeaders,
361+
pRequestHandle->pHeadersEnd - pRequestHandle->pHeaders);
367362
}
368363

369364
/****************************************************************

0 commit comments

Comments
 (0)