@@ -97,6 +97,10 @@ typedef struct
9797 __CPROVER_bool assume_ensures_ctx ;
9898 /// \brief True iff this write set checks ensures clauses in an assertion ctx
9999 __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 ;
100104} __CPROVER_contracts_write_set_t ;
101105
102106/// \brief Type of pointers to \ref __CPROVER_contracts_write_set_t.
@@ -436,6 +440,8 @@ __CPROVER_HIDE:;
436440 set -> assert_requires_ctx = assert_requires_ctx ;
437441 set -> assume_ensures_ctx = assume_ensures_ctx ;
438442 set -> assert_ensures_ctx = assert_ensures_ctx ;
443+ set -> allow_allocate = 1 ;
444+ set -> allow_deallocate = 1 ;
439445}
440446
441447/// \brief Releases resources used by \p set.
@@ -474,6 +480,20 @@ __CPROVER_HIDE:;
474480 // since they are owned by someone else.
475481}
476482
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+
477497/// \brief Inserts a snapshot of the range starting at \p ptr of size \p size
478498/// at index \p idx in \p set->contract_assigns.
479499/// \param[inout] set The set to update
@@ -600,14 +620,35 @@ __CPROVER_HIDE:;
600620#endif
601621}
602622
603- /// \brief Adds the pointer \p ptr to \p set->allocated.
623+ /// \brief Adds the dynamically allocated pointer \p ptr to \p set->allocated.
604624/// \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(...)`.
607626void __CPROVER_contracts_write_set_add_allocated (
608627 __CPROVER_contracts_write_set_ptr_t set ,
609628 void * ptr )
610629{
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+ {
611652__CPROVER_HIDE :;
612653#if DFCC_DEBUG
613654 // call inlined below
@@ -904,8 +945,8 @@ __CPROVER_HIDE:;
904945/// \param[in] set Write set to check the deallocation against
905946/// \param[in] ptr Deallocated pointer to check set to check the deallocation
906947/// 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.
909950__CPROVER_bool __CPROVER_contracts_write_set_check_deallocate (
910951 __CPROVER_contracts_write_set_ptr_t set ,
911952 void * ptr )
@@ -924,8 +965,9 @@ __CPROVER_HIDE:;
924965 set -> allocated .indexed_by_object_id ,
925966 "set->allocated is indexed by object id" );
926967#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 ));
929971}
930972
931973/// \brief Checks the inclusion of the \p candidate->contract_assigns elements
0 commit comments