@@ -62,6 +62,15 @@ typedef struct
6262 /// \brief Array of void *pointers, indexed by their object ID
6363 /// or some other order
6464 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 ;
6574} __CPROVER_contracts_obj_set_t ;
6675
6776/// \brief Type of pointers to \ref __CPROVER_contracts_car_set_t.
@@ -261,7 +270,11 @@ __CPROVER_HIDE:;
261270 .nof_elems = 0 ,
262271 .is_empty = 1 ,
263272 .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 };
265278}
266279
267280/// \brief Initialises a \ref __CPROVER_contracts_obj_set_t object to use it
@@ -285,7 +298,61 @@ __CPROVER_HIDE:;
285298 .nof_elems = 0 ,
286299 .is_empty = 1 ,
287300 .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+ }
289356}
290357
291358/// @brief Releases resources used by \p set.
@@ -1202,7 +1269,13 @@ __CPROVER_HIDE:;
12021269 }
12031270 __CPROVER_assert (
12041271 (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 );
12061279 * ptr1 = ptr2 ;
12071280 return 1 ;
12081281 }
@@ -1211,11 +1284,21 @@ __CPROVER_HIDE:;
12111284 void * derefd = * ptr1 ;
12121285 __CPROVER_assert (
12131286 (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" );
12151288 __CPROVER_assert (
12161289 (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 ;
12191302 }
12201303}
12211304
@@ -1294,9 +1377,15 @@ __CPROVER_HIDE:;
12941377 __CPROVER_contracts_make_invalid_pointer (elem );
12951378 return 0 ;
12961379 }
1297-
12981380 void * ptr = __CPROVER_allocate (size , 0 );
12991381 * 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 );
13001389
13011390 // record the object size for non-determistic bounds checking
13021391 __CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool ();
@@ -1308,18 +1397,6 @@ __CPROVER_HIDE:;
13081397 // __CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool();
13091398 // __CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak;
13101399
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
13231400 return 1 ;
13241401 }
13251402 else if (write_set -> assume_ensures_ctx )
@@ -1357,6 +1434,13 @@ __CPROVER_HIDE:;
13571434
13581435 void * ptr = __CPROVER_allocate (size , 0 );
13591436 * 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 );
13601444
13611445 // record the object size for non-determistic bounds checking
13621446 __CPROVER_bool record_malloc = __VERIFIER_nondet___CPROVER_bool ();
@@ -1369,17 +1453,6 @@ __CPROVER_HIDE:;
13691453 __CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool ();
13701454 __CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak ;
13711455
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
13831456 return 1 ;
13841457 }
13851458 else if (write_set -> assert_requires_ctx | write_set -> assert_ensures_ctx )
@@ -1390,34 +1463,22 @@ __CPROVER_HIDE:;
13901463 (write_set -> assume_ensures_ctx == 0 ),
13911464 "only one context flag at a time" );
13921465#endif
1393- __CPROVER_contracts_obj_set_ptr_t seen = write_set -> linked_is_fresh ;
13941466 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 ;
14211482 }
14221483 else
14231484 {
@@ -1484,13 +1545,33 @@ __CPROVER_HIDE:;
14841545 __CPROVER_size_t max_offset = ub_offset - lb_offset ;
14851546 __CPROVER_assume (offset <= max_offset );
14861547 * 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 );
14871553 return 1 ;
14881554 }
14891555 else /* write_set->assert_requires_ctx | write_set->assert_ensures_ctx */
14901556 {
14911557 __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+ }
14941575 }
14951576}
14961577
0 commit comments