@@ -97,6 +97,10 @@ typedef struct
97
97
__CPROVER_bool assume_ensures_ctx ;
98
98
/// \brief True iff this write set checks ensures clauses in an assertion ctx
99
99
__CPROVER_bool assert_ensures_ctx ;
100
+ /// \brief True iff dynamic allocation is allowed (default: true)
101
+ __CPROVER_bool allow_allocate ;
102
+ /// \brief True iff dynamic deallocation is allowed (default: true)
103
+ __CPROVER_bool allow_deallocate ;
100
104
} __CPROVER_contracts_write_set_t ;
101
105
102
106
/// \brief Type of pointers to \ref __CPROVER_contracts_write_set_t.
@@ -436,6 +440,8 @@ __CPROVER_HIDE:;
436
440
set -> assert_requires_ctx = assert_requires_ctx ;
437
441
set -> assume_ensures_ctx = assume_ensures_ctx ;
438
442
set -> assert_ensures_ctx = assert_ensures_ctx ;
443
+ set -> allow_allocate = 1 ;
444
+ set -> allow_deallocate = 1 ;
439
445
}
440
446
441
447
/// \brief Releases resources used by \p set.
@@ -474,6 +480,20 @@ __CPROVER_HIDE:;
474
480
// since they are owned by someone else.
475
481
}
476
482
483
+ /// \brief Forbids dynamic allocation in functions that receive that write set.
484
+ void __CPROVER_contracts_write_set_forbid_allocate (
485
+ __CPROVER_contracts_write_set_ptr_t set )
486
+ {
487
+ set -> allow_allocate = 0 ;
488
+ }
489
+
490
+ /// \brief Forbids deallocation in functions that receive that write set.
491
+ void __CPROVER_contracts_write_set_forbid_deallocate (
492
+ __CPROVER_contracts_write_set_ptr_t set )
493
+ {
494
+ set -> allow_deallocate = 0 ;
495
+ }
496
+
477
497
/// \brief Inserts a snapshot of the range starting at \p ptr of size \p size
478
498
/// at index \p idx in \p set->contract_assigns.
479
499
/// \param[inout] set The set to update
@@ -600,14 +620,35 @@ __CPROVER_HIDE:;
600
620
#endif
601
621
}
602
622
603
- /// \brief Adds the pointer \p ptr to \p set->allocated.
623
+ /// \brief Adds the dynamically allocated pointer \p ptr to \p set->allocated.
604
624
/// \param[inout] set The set to update
605
- /// \param[in] ptr Pointer to an object declared using a `DECL x` or
606
- /// `x = __CPROVER_allocate(...)` GOTO instruction.
625
+ /// \param[in] ptr Pointer to a dynamic object `x = __CPROVER_allocate(...)`.
607
626
void __CPROVER_contracts_write_set_add_allocated (
608
627
__CPROVER_contracts_write_set_ptr_t set ,
609
628
void * ptr )
610
629
{
630
+ __CPROVER_HIDE :;
631
+ __CPROVER_assert (set -> allow_allocate , "dynamic allocation is allowed" );
632
+ #if DFCC_DEBUG
633
+ // call inlined below
634
+ __CPROVER_contracts_obj_set_add (& (set -> allocated ), ptr );
635
+ #else
636
+ __CPROVER_size_t object_id = __CPROVER_POINTER_OBJECT (ptr );
637
+ set -> allocated .nof_elems = (set -> allocated .elems [object_id ] != 0 )
638
+ ? set -> allocated .nof_elems
639
+ : set -> allocated .nof_elems + 1 ;
640
+ set -> allocated .elems [object_id ] = ptr ;
641
+ set -> allocated .is_empty = 0 ;
642
+ #endif
643
+ }
644
+
645
+ /// \brief Adds the pointer \p ptr to \p set->allocated.
646
+ /// \param[inout] set The set to update
647
+ /// \param[in] ptr Pointer to an object declared using `DECL x`.
648
+ void __CPROVER_contracts_write_set_add_decl (
649
+ __CPROVER_contracts_write_set_ptr_t set ,
650
+ void * ptr )
651
+ {
611
652
__CPROVER_HIDE :;
612
653
#if DFCC_DEBUG
613
654
// call inlined below
@@ -904,8 +945,8 @@ __CPROVER_HIDE:;
904
945
/// \param[in] set Write set to check the deallocation against
905
946
/// \param[in] ptr Deallocated pointer to check set to check the deallocation
906
947
/// against
907
- /// \return True iff \p ptr is contained in \p set->contract_frees or
908
- /// \p set->allocated.
948
+ /// \return True iff deallocation is allowed and \p ptr is contained in
949
+ /// \p set->contract_frees or \p set-> allocated.
909
950
__CPROVER_bool __CPROVER_contracts_write_set_check_deallocate (
910
951
__CPROVER_contracts_write_set_ptr_t set ,
911
952
void * ptr )
@@ -924,8 +965,9 @@ __CPROVER_HIDE:;
924
965
set -> allocated .indexed_by_object_id ,
925
966
"set->allocated is indexed by object id" );
926
967
#endif
927
- return (ptr == 0 ) | (set -> contract_frees .elems [object_id ] == ptr ) |
928
- (set -> allocated .elems [object_id ] == ptr );
968
+ return (set -> allow_deallocate ) &
969
+ ((ptr == 0 ) | (set -> contract_frees .elems [object_id ] == ptr ) |
970
+ (set -> allocated .elems [object_id ] == ptr ));
929
971
}
930
972
931
973
/// \brief Checks the inclusion of the \p candidate->contract_assigns elements
0 commit comments