@@ -62,6 +62,15 @@ typedef struct
62
62
/// \brief Array of void *pointers, indexed by their object ID
63
63
/// or some other order
64
64
void * * elems ;
65
+ /// \brief Equal to 1 if `fresh_id` is empty, 0 otherwise.
66
+ unsigned char fresh_id_empty ;
67
+ /// \brief Demonic nondet variable ranging over the set of fresh object IDs.
68
+ __CPROVER_size_t fresh_id ;
69
+ /// \brief Equal to 1 if `ptr_pred` is empty, 0 otherwise.
70
+ unsigned char ptr_pred_empty ;
71
+ /// \brief Demonic nondet variable ranging over the set of locations storing
72
+ /// pointers on which predicates were assumed/asserted.
73
+ void * * ptr_pred ;
65
74
} __CPROVER_contracts_obj_set_t ;
66
75
67
76
/// \brief Type of pointers to \ref __CPROVER_contracts_car_set_t.
@@ -261,7 +270,11 @@ __CPROVER_HIDE:;
261
270
.nof_elems = 0 ,
262
271
.is_empty = 1 ,
263
272
.indexed_by_object_id = 1 ,
264
- .elems = __CPROVER_allocate (nof_objects * sizeof (* (set -> elems )), 1 )};
273
+ .elems = __CPROVER_allocate (nof_objects * sizeof (* (set -> elems )), 1 ),
274
+ .fresh_id_empty = 1 ,
275
+ .fresh_id = 0 ,
276
+ .ptr_pred_empty = 1 ,
277
+ .ptr_pred = 0 };
265
278
}
266
279
267
280
/// \brief Initialises a \ref __CPROVER_contracts_obj_set_t object to use it
@@ -285,7 +298,74 @@ __CPROVER_HIDE:;
285
298
.nof_elems = 0 ,
286
299
.is_empty = 1 ,
287
300
.indexed_by_object_id = 0 ,
288
- .elems = __CPROVER_allocate (max_elems * sizeof (* (set -> elems )), 1 )};
301
+ .elems = __CPROVER_allocate (max_elems * sizeof (* (set -> elems )), 1 ),
302
+ .fresh_id_empty = 1 ,
303
+ .fresh_id = 0 ,
304
+ .ptr_pred_empty = 1 ,
305
+ .ptr_pred = 0 };
306
+ }
307
+
308
+ __CPROVER_bool __CPROVER_contracts_not_seen_is_fresh (
309
+ __CPROVER_contracts_obj_set_ptr_t set ,
310
+ void * ptr )
311
+ {
312
+ __CPROVER_HIDE :;
313
+ return set -> fresh_id_empty || __CPROVER_POINTER_OBJECT (ptr ) != set -> fresh_id ;
314
+ }
315
+
316
+ void __CPROVER_contracts_record_fresh_id (
317
+ __CPROVER_contracts_obj_set_ptr_t set ,
318
+ void * ptr )
319
+ {
320
+ __CPROVER_HIDE :;
321
+ if (set -> fresh_id_empty )
322
+ {
323
+ set -> fresh_id_empty = 0 ;
324
+ set -> fresh_id = __CPROVER_POINTER_OBJECT (ptr );
325
+ }
326
+ else
327
+ {
328
+ set -> fresh_id = __VERIFIER_nondet___CPROVER_bool ()
329
+ ? __CPROVER_POINTER_OBJECT (ptr )
330
+ : set -> fresh_id ;
331
+ }
332
+ }
333
+
334
+ __CPROVER_bool __CPROVER_contracts_check_ptr_not_in_ptr_pred (
335
+ __CPROVER_contracts_obj_set_ptr_t set ,
336
+ void * * ptr )
337
+ {
338
+ __CPROVER_HIDE :;
339
+ return set -> ptr_pred_empty || ptr != set -> ptr_pred ;
340
+ }
341
+
342
+ /// \brief Resets the nondet tracker for pointer predicates in \p set.
343
+ /// Invoked right before evaluating contract ensures clauses. Since functions
344
+ /// are allowed to modify the program state, resetting the tracker allows
345
+ /// ensures clauses to establish a different pointer predicate on a pointer that
346
+ /// was already targeted by the requires clause.
347
+ void __CPROVER_contracts_obj_set_reset_ptr_pred (
348
+ __CPROVER_contracts_obj_set_ptr_t set )
349
+ {
350
+ __CPROVER_HIDE :;
351
+ set -> ptr_pred_empty = 1 ;
352
+ set -> ptr_pred = 0 ;
353
+ }
354
+
355
+ void __CPROVER_contracts_record_ptr_in_ptr_pred (
356
+ __CPROVER_contracts_obj_set_ptr_t set ,
357
+ void * * ptr )
358
+ {
359
+ __CPROVER_HIDE :;
360
+ if (set -> ptr_pred_empty )
361
+ {
362
+ set -> ptr_pred_empty = 0 ;
363
+ set -> ptr_pred = ptr ;
364
+ }
365
+ else
366
+ {
367
+ set -> ptr_pred = __VERIFIER_nondet___CPROVER_bool () ? ptr : set -> ptr_pred ;
368
+ }
289
369
}
290
370
291
371
/// @brief Releases resources used by \p set.
@@ -1202,7 +1282,13 @@ __CPROVER_HIDE:;
1202
1282
}
1203
1283
__CPROVER_assert (
1204
1284
(ptr2 == 0 ) || __CPROVER_r_ok (ptr2 , 0 ),
1205
- "pointer_equals is only called with valid pointers" );
1285
+ "__CPROVER_pointer_equals is only called with valid pointers" );
1286
+ __CPROVER_assert (
1287
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1288
+ write_set -> linked_is_fresh , ptr1 ),
1289
+ "__CPROVER_pointer_equals does not conflict with other predicate" );
1290
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1291
+ write_set -> linked_is_fresh , ptr1 );
1206
1292
* ptr1 = ptr2 ;
1207
1293
return 1 ;
1208
1294
}
@@ -1211,11 +1297,21 @@ __CPROVER_HIDE:;
1211
1297
void * derefd = * ptr1 ;
1212
1298
__CPROVER_assert (
1213
1299
(derefd == 0 ) || __CPROVER_r_ok (derefd , 0 ),
1214
- "pointer_equals is only called with valid pointers" );
1300
+ "__CPROVER_pointer_equals is only called with valid pointers" );
1215
1301
__CPROVER_assert (
1216
1302
(ptr2 == 0 ) || __CPROVER_r_ok (ptr2 , 0 ),
1217
- "pointer_equals is only called with valid pointers" );
1218
- return derefd == ptr2 ;
1303
+ "__CPROVER_pointer_equals is only called with valid pointers" );
1304
+ if (derefd != ptr2 )
1305
+ {
1306
+ return 0 ;
1307
+ }
1308
+ __CPROVER_assert (
1309
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1310
+ write_set -> linked_is_fresh , ptr1 ),
1311
+ "__CPROVER_pointer_equals does not conflict with other predicate" );
1312
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1313
+ write_set -> linked_is_fresh , ptr1 );
1314
+ return 1 ;
1219
1315
}
1220
1316
}
1221
1317
@@ -1294,9 +1390,15 @@ __CPROVER_HIDE:;
1294
1390
__CPROVER_contracts_make_invalid_pointer (elem );
1295
1391
return 0 ;
1296
1392
}
1297
-
1298
1393
void * ptr = __CPROVER_allocate (size , 0 );
1299
1394
* elem = ptr ;
1395
+ __CPROVER_assert (
1396
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1397
+ write_set -> linked_is_fresh , elem ),
1398
+ "__CPROVER_is_fresh does not conflict with other predicate" );
1399
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1400
+ write_set -> linked_is_fresh , elem );
1401
+ __CPROVER_contracts_record_fresh_id (write_set -> linked_is_fresh , ptr );
1300
1402
1301
1403
// record the object size for non-determistic bounds checking
1302
1404
__CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool ();
@@ -1308,18 +1410,6 @@ __CPROVER_HIDE:;
1308
1410
// __CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool();
1309
1411
// __CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak;
1310
1412
1311
- #ifdef __CPROVER_DFCC_DEBUG_LIB
1312
- // manually inlined below
1313
- __CPROVER_contracts_obj_set_add (write_set -> linked_is_fresh , ptr );
1314
- #else
1315
- __CPROVER_size_t object_id = __CPROVER_POINTER_OBJECT (ptr );
1316
- write_set -> linked_is_fresh -> nof_elems =
1317
- (write_set -> linked_is_fresh -> elems [object_id ] != 0 )
1318
- ? write_set -> linked_is_fresh -> nof_elems
1319
- : write_set -> linked_is_fresh -> nof_elems + 1 ;
1320
- write_set -> linked_is_fresh -> elems [object_id ] = ptr ;
1321
- write_set -> linked_is_fresh -> is_empty = 0 ;
1322
- #endif
1323
1413
return 1 ;
1324
1414
}
1325
1415
else if (write_set -> assume_ensures_ctx )
@@ -1357,6 +1447,13 @@ __CPROVER_HIDE:;
1357
1447
1358
1448
void * ptr = __CPROVER_allocate (size , 0 );
1359
1449
* elem = ptr ;
1450
+ __CPROVER_assert (
1451
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1452
+ write_set -> linked_is_fresh , elem ),
1453
+ "__CPROVER_is_fresh does not conflict with other predicate" );
1454
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1455
+ write_set -> linked_is_fresh , elem );
1456
+ __CPROVER_contracts_record_fresh_id (write_set -> linked_is_fresh , ptr );
1360
1457
1361
1458
// record the object size for non-determistic bounds checking
1362
1459
__CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool ();
@@ -1369,17 +1466,6 @@ __CPROVER_HIDE:;
1369
1466
__CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool ();
1370
1467
__CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak ;
1371
1468
1372
- #ifdef __CPROVER_DFCC_DEBUG_LIB
1373
- __CPROVER_contracts_obj_set_add (write_set -> linked_allocated , ptr );
1374
- #else
1375
- __CPROVER_size_t object_id = __CPROVER_POINTER_OBJECT (ptr );
1376
- write_set -> linked_allocated -> nof_elems =
1377
- (write_set -> linked_allocated -> elems [object_id ] != 0 )
1378
- ? write_set -> linked_allocated -> nof_elems
1379
- : write_set -> linked_allocated -> nof_elems + 1 ;
1380
- write_set -> linked_allocated -> elems [object_id ] = ptr ;
1381
- write_set -> linked_allocated -> is_empty = 0 ;
1382
- #endif
1383
1469
return 1 ;
1384
1470
}
1385
1471
else if (write_set -> assert_requires_ctx | write_set -> assert_ensures_ctx )
@@ -1390,34 +1476,22 @@ __CPROVER_HIDE:;
1390
1476
(write_set -> assume_ensures_ctx == 0 ),
1391
1477
"only one context flag at a time" );
1392
1478
#endif
1393
- __CPROVER_contracts_obj_set_ptr_t seen = write_set -> linked_is_fresh ;
1394
1479
void * ptr = * elem ;
1395
- // null pointers or already seen pointers are not fresh
1396
- #ifdef __CPROVER_DFCC_DEBUG_LIB
1397
- // manually inlined below
1398
- if ((ptr == 0 ) || (__CPROVER_contracts_obj_set_contains (seen , ptr )))
1399
- return 0 ;
1400
- #else
1401
- if (ptr == 0 )
1402
- return 0 ;
1403
-
1404
- __CPROVER_size_t object_id = __CPROVER_POINTER_OBJECT (ptr );
1405
-
1406
- if (seen -> elems [object_id ] != 0 )
1407
- return 0 ;
1408
- #endif
1409
-
1410
- #ifdef __CPROVER_DFCC_DEBUG_LIB
1411
- // manually inlined below
1412
- __CPROVER_contracts_obj_set_add (seen , ptr );
1413
- #else
1414
- seen -> nof_elems =
1415
- (seen -> elems [object_id ] != 0 ) ? seen -> nof_elems : seen -> nof_elems + 1 ;
1416
- seen -> elems [object_id ] = ptr ;
1417
- seen -> is_empty = 0 ;
1418
- #endif
1419
- // check size
1420
- return __CPROVER_r_ok (ptr , size );
1480
+ if (
1481
+ ptr != (void * )0 &&
1482
+ __CPROVER_contracts_not_seen_is_fresh (write_set -> linked_is_fresh , ptr ) &&
1483
+ __CPROVER_r_ok (ptr , size ))
1484
+ {
1485
+ __CPROVER_assert (
1486
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1487
+ write_set -> linked_is_fresh , elem ),
1488
+ "__CPROVER_is_fresh does not conflict with other predicate" );
1489
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1490
+ write_set -> linked_is_fresh , elem );
1491
+ __CPROVER_contracts_record_fresh_id (write_set -> linked_is_fresh , ptr );
1492
+ return 1 ;
1493
+ }
1494
+ return 0 ;
1421
1495
}
1422
1496
else
1423
1497
{
@@ -1484,13 +1558,33 @@ __CPROVER_HIDE:;
1484
1558
__CPROVER_size_t max_offset = ub_offset - lb_offset ;
1485
1559
__CPROVER_assume (offset <= max_offset );
1486
1560
* ptr = (char * )lb + offset ;
1561
+ __CPROVER_assert (
1562
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1563
+ write_set -> linked_is_fresh , ptr ),
1564
+ "__CPROVER_pointer_in_range_dfcc does not conflict with other predicate" );
1565
+ __CPROVER_contracts_record_ptr_in_ptr_pred (write_set -> linked_is_fresh , ptr );
1487
1566
return 1 ;
1488
1567
}
1489
1568
else /* write_set->assert_requires_ctx | write_set->assert_ensures_ctx */
1490
1569
{
1491
1570
__CPROVER_size_t offset = __CPROVER_POINTER_OFFSET (* ptr );
1492
- return __CPROVER_same_object (lb , * ptr ) && lb_offset <= offset &&
1493
- offset <= ub_offset ;
1571
+ if (
1572
+ __CPROVER_same_object (lb , * ptr ) && lb_offset <= offset &&
1573
+ offset <= ub_offset )
1574
+ {
1575
+ __CPROVER_assert (
1576
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1577
+ write_set -> linked_is_fresh , ptr ),
1578
+ "__CPROVER_pointer_in_range_dfcc does not conflict with other "
1579
+ "predicate" );
1580
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1581
+ write_set -> linked_is_fresh , ptr );
1582
+ return 1 ;
1583
+ }
1584
+ else
1585
+ {
1586
+ return 0 ;
1587
+ }
1494
1588
}
1495
1589
}
1496
1590
0 commit comments