@@ -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,61 @@ __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
+ void __CPROVER_contracts_record_ptr_in_ptr_pred (
343
+ __CPROVER_contracts_obj_set_ptr_t set ,
344
+ void * * ptr )
345
+ {
346
+ __CPROVER_HIDE :;
347
+ if (set -> ptr_pred_empty )
348
+ {
349
+ set -> ptr_pred_empty = 0 ;
350
+ set -> ptr_pred = ptr ;
351
+ }
352
+ else
353
+ {
354
+ set -> ptr_pred = __VERIFIER_nondet___CPROVER_bool () ? ptr : set -> ptr_pred ;
355
+ }
289
356
}
290
357
291
358
/// @brief Releases resources used by \p set.
@@ -1202,7 +1269,13 @@ __CPROVER_HIDE:;
1202
1269
}
1203
1270
__CPROVER_assert (
1204
1271
(ptr2 == 0 ) || __CPROVER_r_ok (ptr2 , 0 ),
1205
- "pointer_equals is only called with valid pointers" );
1272
+ "__CPROVER_pointer_equals is only called with valid pointers" );
1273
+ __CPROVER_assert (
1274
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1275
+ write_set -> linked_is_fresh , ptr1 ),
1276
+ "__CPROVER_pointer_equals does not conflict with other predicate" );
1277
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1278
+ write_set -> linked_is_fresh , ptr1 );
1206
1279
* ptr1 = ptr2 ;
1207
1280
return 1 ;
1208
1281
}
@@ -1211,11 +1284,21 @@ __CPROVER_HIDE:;
1211
1284
void * derefd = * ptr1 ;
1212
1285
__CPROVER_assert (
1213
1286
(derefd == 0 ) || __CPROVER_r_ok (derefd , 0 ),
1214
- "pointer_equals is only called with valid pointers" );
1287
+ "__CPROVER_pointer_equals is only called with valid pointers" );
1215
1288
__CPROVER_assert (
1216
1289
(ptr2 == 0 ) || __CPROVER_r_ok (ptr2 , 0 ),
1217
- "pointer_equals is only called with valid pointers" );
1218
- return derefd == ptr2 ;
1290
+ "__CPROVER_pointer_equals is only called with valid pointers" );
1291
+ if (derefd != ptr2 )
1292
+ {
1293
+ return 0 ;
1294
+ }
1295
+ __CPROVER_assert (
1296
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1297
+ write_set -> linked_is_fresh , ptr1 ),
1298
+ "__CPROVER_pointer_equals does not conflict with other predicate" );
1299
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1300
+ write_set -> linked_is_fresh , ptr1 );
1301
+ return 1 ;
1219
1302
}
1220
1303
}
1221
1304
@@ -1294,9 +1377,15 @@ __CPROVER_HIDE:;
1294
1377
__CPROVER_contracts_make_invalid_pointer (elem );
1295
1378
return 0 ;
1296
1379
}
1297
-
1298
1380
void * ptr = __CPROVER_allocate (size , 0 );
1299
1381
* elem = ptr ;
1382
+ __CPROVER_assert (
1383
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1384
+ write_set -> linked_is_fresh , elem ),
1385
+ "__CPROVER_is_fresh does not conflict with other predicate" );
1386
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1387
+ write_set -> linked_is_fresh , elem );
1388
+ __CPROVER_contracts_record_fresh_id (write_set -> linked_is_fresh , ptr );
1300
1389
1301
1390
// record the object size for non-determistic bounds checking
1302
1391
__CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool ();
@@ -1308,18 +1397,6 @@ __CPROVER_HIDE:;
1308
1397
// __CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool();
1309
1398
// __CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak;
1310
1399
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
1400
return 1 ;
1324
1401
}
1325
1402
else if (write_set -> assume_ensures_ctx )
@@ -1357,6 +1434,13 @@ __CPROVER_HIDE:;
1357
1434
1358
1435
void * ptr = __CPROVER_allocate (size , 0 );
1359
1436
* elem = ptr ;
1437
+ __CPROVER_assert (
1438
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1439
+ write_set -> linked_is_fresh , elem ),
1440
+ "__CPROVER_is_fresh does not conflict with other predicate" );
1441
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1442
+ write_set -> linked_is_fresh , elem );
1443
+ __CPROVER_contracts_record_fresh_id (write_set -> linked_is_fresh , ptr );
1360
1444
1361
1445
// record the object size for non-determistic bounds checking
1362
1446
__CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool ();
@@ -1369,17 +1453,6 @@ __CPROVER_HIDE:;
1369
1453
__CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool ();
1370
1454
__CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak ;
1371
1455
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
1456
return 1 ;
1384
1457
}
1385
1458
else if (write_set -> assert_requires_ctx | write_set -> assert_ensures_ctx )
@@ -1390,34 +1463,22 @@ __CPROVER_HIDE:;
1390
1463
(write_set -> assume_ensures_ctx == 0 ),
1391
1464
"only one context flag at a time" );
1392
1465
#endif
1393
- __CPROVER_contracts_obj_set_ptr_t seen = write_set -> linked_is_fresh ;
1394
1466
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 );
1467
+ if (
1468
+ ptr != (void * )0 &&
1469
+ __CPROVER_contracts_not_seen_is_fresh (write_set -> linked_is_fresh , ptr ) &&
1470
+ __CPROVER_r_ok (ptr , size ))
1471
+ {
1472
+ __CPROVER_assert (
1473
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1474
+ write_set -> linked_is_fresh , elem ),
1475
+ "__CPROVER_is_fresh does not conflict with other predicate" );
1476
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1477
+ write_set -> linked_is_fresh , elem );
1478
+ __CPROVER_contracts_record_fresh_id (write_set -> linked_is_fresh , ptr );
1479
+ return 1 ;
1480
+ }
1481
+ return 0 ;
1421
1482
}
1422
1483
else
1423
1484
{
@@ -1484,13 +1545,33 @@ __CPROVER_HIDE:;
1484
1545
__CPROVER_size_t max_offset = ub_offset - lb_offset ;
1485
1546
__CPROVER_assume (offset <= max_offset );
1486
1547
* ptr = (char * )lb + offset ;
1548
+ __CPROVER_assert (
1549
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1550
+ write_set -> linked_is_fresh , ptr ),
1551
+ "__CPROVER_pointer_in_range_dfcc does not conflict with other predicate" );
1552
+ __CPROVER_contracts_record_ptr_in_ptr_pred (write_set -> linked_is_fresh , ptr );
1487
1553
return 1 ;
1488
1554
}
1489
1555
else /* write_set->assert_requires_ctx | write_set->assert_ensures_ctx */
1490
1556
{
1491
1557
__CPROVER_size_t offset = __CPROVER_POINTER_OFFSET (* ptr );
1492
- return __CPROVER_same_object (lb , * ptr ) && lb_offset <= offset &&
1493
- offset <= ub_offset ;
1558
+ if (
1559
+ __CPROVER_same_object (lb , * ptr ) && lb_offset <= offset &&
1560
+ offset <= ub_offset )
1561
+ {
1562
+ __CPROVER_assert (
1563
+ __CPROVER_contracts_check_ptr_not_in_ptr_pred (
1564
+ write_set -> linked_is_fresh , ptr ),
1565
+ "__CPROVER_pointer_in_range_dfcc does not conflict with other "
1566
+ "predicate" );
1567
+ __CPROVER_contracts_record_ptr_in_ptr_pred (
1568
+ write_set -> linked_is_fresh , ptr );
1569
+ return 1 ;
1570
+ }
1571
+ else
1572
+ {
1573
+ return 0 ;
1574
+ }
1494
1575
}
1495
1576
}
1496
1577
0 commit comments