CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cprover_contracts.c
Go to the documentation of this file.
1
3
4/* FUNCTION: __CPROVER_contracts_library */
5
6#ifndef __CPROVER_contracts_library_defined
7#define __CPROVER_contracts_library_defined
8
9// external dependencies
11extern const void *__CPROVER_deallocated;
12const void *__CPROVER_new_object = 0;
13extern const void *__CPROVER_memory_leak;
15#if defined(_WIN32) && defined(_M_X64)
16int __builtin_clzll(unsigned long long);
17#else
18int __builtin_clzl(unsigned long);
19#endif
22
24typedef struct
25{
27 unsigned char is_writable;
31 void *lb;
33 void *ub;
35
44
47
66
69
78
82
118
121
128{
131 ((ptr == 0) | __CPROVER_rw_ok(ptr, size)),
132 "ptr NULL or writable up to size");
135 "CAR size is less than __CPROVER_max_malloc_size");
138 !(offset > 0) | (offset + size <= __CPROVER_max_malloc_size),
139 "no offset bits overflow on CAR upper bound computation");
141 .is_writable = ptr != 0, .size = size, .lb = ptr, .ub = (char *)ptr + size};
142}
143
149 __CPROVER_size_t max_elems)
150{
152#ifdef __CPROVER_DFCC_DEBUG_LIB
155 "set writable");
156#endif
157 set->max_elems = max_elems;
158 set->elems =
159 __CPROVER_allocate(max_elems * sizeof(__CPROVER_contracts_car_t), 1);
160}
161
171 void *ptr,
172 __CPROVER_size_t size)
173{
175#ifdef __CPROVER_DFCC_DEBUG_LIB
176 __CPROVER_assert((set != 0) & (idx < set->max_elems), "no OOB access");
177#endif
179 ((ptr == 0) | __CPROVER_rw_ok(ptr, size)),
180 "ptr NULL or writable up to size");
183 "CAR size is less than __CPROVER_max_malloc_size");
186 !(offset > 0) | (offset + size <= __CPROVER_max_malloc_size),
187 "no offset bits overflow on CAR upper bound computation");
190 .is_writable = ptr != 0, .size = size, .lb = ptr, .ub = (char *)ptr + size};
191}
192
199 void *ptr)
200{
203 __CPROVER_size_t idx = set->max_elems;
206 while(idx != 0)
207 {
209 elem->is_writable = 0;
210 ++elem;
211 --idx;
212 }
213}
214
242
253{
255#ifdef __CPROVER_DFCC_DEBUG_LIB
258 "set writable");
259#endif
260 // compute the maximum number of objects that can exist in the
261 // symex state from the number of object_bits/offset_bits
262 // the number of object bits is determined by counting the number of leading
263 // zeroes of the built-in constant __CPROVER_max_malloc_size;
264#if defined(_WIN32) && defined(_M_X64)
266 __CPROVER_size_t nof_objects = 1ULL << object_bits;
267#else
268 int object_bits = __builtin_clzl(__CPROVER_max_malloc_size);
269 __CPROVER_size_t nof_objects = 1UL << object_bits;
270#endif
273 .watermark = 0,
274 .nof_elems = 0,
275 .is_empty = 1,
276 .indexed_by_object_id = 1,
277 .elems = __CPROVER_allocate(nof_objects * sizeof(*(set->elems)), 1)};
278}
279
287 __CPROVER_size_t max_elems)
288{
290#ifdef __CPROVER_DFCC_DEBUG_LIB
293 "set writable");
294#endif
296 .max_elems = max_elems,
297 .watermark = 0,
298 .nof_elems = 0,
299 .is_empty = 1,
300 .indexed_by_object_id = 0,
301 .elems = __CPROVER_allocate(max_elems * sizeof(*(set->elems)), 1)};
302}
303
306{
308#ifdef __CPROVER_DFCC_DEBUG_LIB
311 "set readable");
312 __CPROVER_assert(__CPROVER_rw_ok(&(set->elems), 0), "set->elems writable");
313#endif
315}
316
323 void *ptr)
324{
327#ifdef __CPROVER_DFCC_DEBUG_LIB
328 __CPROVER_assert(set->indexed_by_object_id, "indexed by object id");
329 __CPROVER_assert(object_id < set->max_elems, "no OOB access");
330#endif
331 set->nof_elems = set->elems[object_id] ? set->nof_elems : set->nof_elems + 1;
332 set->elems[object_id] = ptr;
333 set->is_empty = 0;
334}
335
342 void *ptr)
343{
345#ifdef __CPROVER_DFCC_DEBUG_LIB
346 __CPROVER_assert(!(set->indexed_by_object_id), "not indexed by object id");
347 __CPROVER_assert(set->watermark < set->max_elems, "no OOB access");
348#endif
349 set->nof_elems = set->watermark;
350 set->elems[set->watermark] = ptr;
351 set->watermark += 1;
352 set->is_empty = 0;
353}
354
361 void *ptr)
362{
365#ifdef __CPROVER_DFCC_DEBUG_LIB
366 __CPROVER_assert(set->indexed_by_object_id, "indexed by object id");
367 __CPROVER_assert(object_id < set->max_elems, "no OOB access");
368#endif
369 set->nof_elems = set->elems[object_id] ? set->nof_elems - 1 : set->nof_elems;
370 set->is_empty = set->nof_elems == 0;
371 set->elems[object_id] = 0;
372}
373
381 void *ptr)
382{
385#ifdef __CPROVER_DFCC_DEBUG_LIB
386 __CPROVER_assert(set->indexed_by_object_id, "indexed by object id");
387 __CPROVER_assert(object_id < set->max_elems, "no OOB access");
388#endif
389 return set->elems[object_id] != 0;
390}
391
398 void *ptr)
399{
402#ifdef __CPROVER_DFCC_DEBUG_LIB
403 __CPROVER_assert(set->indexed_by_object_id, "indexed by object id");
404 __CPROVER_assert(object_id < set->max_elems, "no OOB access");
405#endif
406 return set->elems[object_id] == ptr;
407}
408
414{
417 .is_writable = 0, .size = 0, .lb = (void *)0, .ub = (void *)0};
418 set->ptr_pred = (void **)0;
419}
420
430
451 __CPROVER_bool assume_requires_ctx,
452 __CPROVER_bool assert_requires_ctx,
453 __CPROVER_bool assume_ensures_ctx,
454 __CPROVER_bool assert_ensures_ctx,
455 __CPROVER_bool allow_allocate,
456 __CPROVER_bool allow_deallocate)
457{
459#ifdef __CPROVER_DFCC_DEBUG_LIB
462 "set writable");
463#endif
467 &(set->contract_frees));
472 set->linked_ptr_pred_ctx = 0;
473 set->linked_allocated = 0;
474 set->linked_deallocated = 0;
475 set->assume_requires_ctx = assume_requires_ctx;
476 set->assert_requires_ctx = assert_requires_ctx;
477 set->assume_ensures_ctx = assume_ensures_ctx;
478 set->assert_ensures_ctx = assert_ensures_ctx;
479 set->allow_allocate = allow_allocate;
480 set->allow_deallocate = allow_deallocate;
481}
482
486{
488#ifdef __CPROVER_DFCC_DEBUG_LIB
491 "set readable");
494 "contract_assigns writable");
497 "contract_frees writable");
500 "contract_frees_append writable");
502 __CPROVER_rw_ok(&(set->allocated.elems), 0), "allocated writable");
504 __CPROVER_rw_ok(&(set->deallocated.elems), 0), "deallocated writable");
505#endif
511 // do not free set->linked_ptr_pred_ctx->elems or
512 // set->deallocated_linked->elems since they are owned by someone else.
513}
514
530
553
576
593
599 void *ptr)
600{
602 // Preconditions will be checked if there is an actual attempt
603 // to free the pointer, don't check preemptively.
604
605 // store pointer
607#ifdef __CPROVER_DFCC_DEBUG_LIB
608 // manually inlined below
610 __CPROVER_assert(object_id < set->contract_frees.max_elems, "no OOB access");
611#else
614 : set->contract_frees.nof_elems + 1;
615 set->contract_frees.elems[object_id] = ptr;
616 set->contract_frees.is_empty = 0;
617#endif
618
619 // append pointer if available
620#ifdef __CPROVER_DFCC_DEBUG_LIB
622#else
627#endif
628}
629
635 void *ptr)
636{
638 __CPROVER_assert(set->allow_allocate, "dynamic allocation is allowed");
639#if __CPROVER_DFCC_DEBUG_LIB
640 // call inlined below
642#else
644 set->allocated.nof_elems = (set->allocated.elems[object_id] != 0)
645 ? set->allocated.nof_elems
646 : set->allocated.nof_elems + 1;
647 set->allocated.elems[object_id] = ptr;
648 set->allocated.is_empty = 0;
649#endif
650}
651
657 void *ptr)
658{
660#if __CPROVER_DFCC_DEBUG_LIB
661 // call inlined below
663#else
665 set->allocated.nof_elems = (set->allocated.elems[object_id] != 0)
666 ? set->allocated.nof_elems
667 : set->allocated.nof_elems + 1;
668 set->allocated.elems[object_id] = ptr;
669 set->allocated.is_empty = 0;
670#endif
671}
672
682 void *ptr)
683{
685#ifdef __CPROVER_DFCC_DEBUG_LIB
686 // manually inlined below
688#else
691 ? set->allocated.nof_elems - 1
692 : set->allocated.nof_elems;
693 set->allocated.is_empty = set->allocated.nof_elems == 0;
694 set->allocated.elems[object_id] = 0;
695#endif
696}
697
707 void *ptr)
708{
710#if __CPROVER_DFCC_DEBUG_LIB
711 // we record the deallocation to be able to evaluate was_freed post conditions
716 // Manually inlined below
717#else
719
720 // __CPROVER_contracts_obj_set_add
723 : set->deallocated.nof_elems + 1;
724 set->deallocated.elems[object_id] = ptr;
725 set->deallocated.is_empty = 0;
726
727 // __CPROVER_contracts_obj_set_remove
729 ? set->allocated.nof_elems - 1
730 : set->allocated.nof_elems;
731 set->allocated.is_empty = set->allocated.nof_elems == 0;
732 set->allocated.elems[object_id] = 0;
733
734 // __CPROVER_contracts_obj_set_remove
736 ? set->contract_frees.nof_elems - 1
740
741 // __CPROVER_contracts_car_set_remove
744 while(idx != 0)
745 {
747 elem->is_writable = 0;
748 ++elem;
749 --idx;
750 }
751#endif
752}
753
765
776 void *ptr,
777 __CPROVER_size_t size)
778#if __CPROVER_DFCC_DEBUG_LIB
779// manually inlined below
780{
783 ((ptr == 0) | __CPROVER_rw_ok(ptr, size)),
784 "ptr NULL or writable up to size");
785
787 (ptr == 0) | (__CPROVER_POINTER_OBJECT(ptr) < set->allocated.max_elems),
788 "no OOB access");
789
791 if(!car.is_writable)
792 return 0;
793
794 if(set->allocated.elems[__CPROVER_POINTER_OBJECT(ptr)] != 0)
795 return 1;
796
798}
799#else
800{
802# pragma CPROVER check push
803# pragma CPROVER check disable "pointer"
804# pragma CPROVER check disable "pointer-primitive"
805# pragma CPROVER check disable "unsigned-overflow"
806# pragma CPROVER check disable "signed-overflow"
807# pragma CPROVER check disable "undefined-shift"
808# pragma CPROVER check disable "conversion"
810 ((ptr == 0) | __CPROVER_rw_ok(ptr, size)),
811 "ptr NULL or writable up to size");
812
813 // the range is not writable
814 if(ptr == 0)
815 return 0;
816
817 // is ptr pointing within some a locally allocated object ?
818 if(set->allocated.elems[__CPROVER_POINTER_OBJECT(ptr)] != 0)
819 return 1;
820
821 // don't even drive symex into the rest of the function if the set is empty
822 if(set->contract_assigns.max_elems == 0)
823 return 0;
824
825 // Compute the upper bound, perform inclusion check against contract-assigns
828 "CAR size is less than __CPROVER_max_malloc_size");
829
831
833 !(offset > 0) | (offset + size <= __CPROVER_max_malloc_size),
834 "no offset bits overflow on CAR upper bound computation");
835 void *ub = (void *)((char *)ptr + size);
839
841 while(idx != 0)
842 {
843 incl |=
844 (int)elem->is_writable & (int)__CPROVER_same_object(elem->lb, ptr) &
845 (__CPROVER_POINTER_OFFSET(elem->lb) <= offset) &
847 ++elem;
848 --idx;
849 }
850 return incl;
851# pragma CPROVER check pop
852}
853#endif
854
874
894
922
941
954 void *ptr)
955{
958
959#ifdef __CPROVER_DFCC_DEBUG_LIB
962 "set->contract_frees is indexed by object id");
965 "set->allocated is indexed by object id");
966#endif
967 return (set->allow_deallocate) &
968 ((ptr == 0) | (set->contract_frees.elems[object_id] == ptr) |
969 (set->allocated.elems[object_id] == ptr));
970}
971
984{
987 __CPROVER_contracts_car_t *current = candidate->contract_assigns.elems;
988 __CPROVER_size_t idx = candidate->contract_assigns.max_elems;
990 while(idx != 0)
991 {
992 if(current->is_writable)
993 {
995 reference, current->lb, current->size);
996 }
997 --idx;
998 ++current;
999 }
1000 return incl;
1001}
1002
1015{
1017#ifdef __CPROVER_DFCC_DEBUG_LIB
1020 "reference->contract_frees is indexed by object id");
1023 "reference->allocated is indexed by object id");
1024#endif
1026 void **current = candidate->contract_frees_append.elems;
1027 __CPROVER_size_t idx = candidate->contract_frees_append.max_elems;
1028
1030 while(idx != 0)
1031 {
1032 void *ptr = *current;
1034 all_incl &= (ptr == 0) |
1035 (reference->contract_frees.elems[object_id] == ptr) |
1036 (reference->allocated.elems[object_id] == ptr);
1037 --idx;
1038 ++current;
1039 }
1040
1041 return all_incl;
1042}
1043
1050
1060{
1062 void **current = set->contract_frees_append.elems;
1065 while(idx != 0)
1066 {
1067 void *ptr = *current;
1068
1069 // call free only iff the pointer is valid preconditions are met
1070 // skip checks on r_ok, dynamic_object and pointer_offset
1071 __CPROVER_bool preconditions =
1072 (ptr == 0) |
1073 ((int)__CPROVER_r_ok(ptr, 0) & (int)__CPROVER_DYNAMIC_OBJECT(ptr) &
1074 (__CPROVER_POINTER_OFFSET(ptr) == 0));
1075 // If there is aliasing between the pointers in the freeable set,
1076 // and we attempt to free again one of the already freed pointers,
1077 // the r_ok condition above will fail, preventing us to deallocate
1078 // the same pointer twice
1079 if((ptr != 0) & preconditions & __VERIFIER_nondet___CPROVER_bool())
1080 {
1083 // also record effects in the caller write set
1084 if(target != 0)
1086 }
1087 --idx;
1088 ++current;
1089 }
1090}
1091
1098{
1100#ifdef __CPROVER_DFCC_DEBUG_LIB
1101 __CPROVER_assert(write_set != 0, "write_set not NULL");
1102#endif
1103 if((ptr_pred_ctx != 0))
1104 {
1105 write_set->linked_ptr_pred_ctx = ptr_pred_ctx;
1106 }
1107 else
1108 {
1109 write_set->linked_ptr_pred_ctx = 0;
1110 }
1111}
1112
1120{
1122#ifdef __CPROVER_DFCC_DEBUG_LIB
1124 write_set_postconditions != 0, "write_set_postconditions not NULL");
1125#endif
1126 if((write_set_to_link != 0))
1127 {
1128 write_set_postconditions->linked_allocated =
1129 &(write_set_to_link->allocated);
1130 }
1131 else
1132 {
1133 write_set_postconditions->linked_allocated = 0;
1134 }
1135}
1136
1145{
1147#ifdef __CPROVER_DFCC_DEBUG_LIB
1149 write_set_postconditions != 0, "write_set_postconditions not NULL");
1150#endif
1151 if((write_set_to_link != 0))
1152 {
1153 write_set_postconditions->linked_deallocated =
1154 &(write_set_to_link->deallocated);
1155 }
1156 else
1157 {
1158 write_set_postconditions->linked_deallocated = 0;
1159 }
1160}
1161
1168
1178{
1179#ifdef __CPROVER_DFCC_SIMPLE_INVALID_POINTER_MODEL
1180 void *dummy = __CPROVER_allocate(0, 0);
1183 *ptr = __VERIFIER_nondet___CPROVER_bool() ? dummy : (void *)0;
1184#else
1185# pragma GCC diagnostic push
1186# pragma GCC diagnostic ignored "-Wuninitialized"
1187 // We have to silence this warning to be able to generate and use an
1188 // invalid pointer.
1189 void *invalid;
1190 *ptr = invalid;
1191# pragma GCC diagnostic pop
1192#endif
1193}
1194
1211 void **ptr1,
1212 void *ptr2,
1215{
1218 (write_set != 0) & ((write_set->assume_requires_ctx == 1) |
1219 (write_set->assert_requires_ctx == 1) |
1220 (write_set->assume_ensures_ctx == 1) |
1221 (write_set->assert_ensures_ctx == 1)),
1222 "__CPROVER_is_fresh is used only in requires or ensures clauses");
1223#ifdef __CPROVER_DFCC_DEBUG_LIB
1226 "set readable");
1227#endif
1228 if(write_set->assume_requires_ctx | write_set->assume_ensures_ctx)
1229 {
1230 // SOUNDNESS: allow predicate to fail
1232 {
1234 return 0;
1235 }
1237 (ptr2 == 0) || __CPROVER_r_ok(ptr2, 0),
1238 "__CPROVER_pointer_equals is only called with valid pointers");
1240 write_set->linked_ptr_pred_ctx->ptr_pred != ptr1,
1241 "__CPROVER_pointer_equals does not conflict with other pointer "
1242 "predicate in assume context");
1243 write_set->linked_ptr_pred_ctx->ptr_pred =
1245 ? ptr1
1246 : write_set->linked_ptr_pred_ctx->ptr_pred;
1247 *ptr1 = ptr2;
1248 return 1;
1249 }
1250 else /* write_set->assert_requires_ctx | write_set->assert_ensures_ctx */
1251 {
1252 void *derefd = *ptr1;
1254 (derefd == 0) || __CPROVER_r_ok(derefd, 0),
1255 "__CPROVER_pointer_equals is only called with valid pointers");
1257 (ptr2 == 0) || __CPROVER_r_ok(ptr2, 0),
1258 "__CPROVER_pointer_equals is only called with valid pointers");
1259 if(derefd != ptr2)
1260 {
1261 return 0;
1262 }
1264 write_set->linked_ptr_pred_ctx->ptr_pred != ptr1,
1265 "__CPROVER_pointer_equals does not conflict with other pointer "
1266 "predicate in assert context");
1267 write_set->linked_ptr_pred_ctx->ptr_pred =
1269 ? ptr1
1270 : write_set->linked_ptr_pred_ctx->ptr_pred;
1271 return 1;
1272 }
1273}
1274
1291 void **elem,
1292 __CPROVER_size_t size,
1295{
1297 if(write_set->assume_requires_ctx)
1298 {
1299#ifdef __CPROVER_DFCC_DEBUG_LIB
1301 (write_set->assert_requires_ctx == 0) &
1302 (write_set->assume_ensures_ctx == 0) &
1303 (write_set->assert_ensures_ctx == 0),
1304 "only one context flag at a time");
1305#endif
1306 if(
1309 {
1310 // When --malloc-may-fail --malloc-fail-null
1311 // add implicit assumption that the size is capped
1313 }
1314 else if(
1317 {
1318 // When --malloc-may-fail --malloc-fail-assert
1319 // check if max allocation size is exceeded and
1320 // add implicit assumption that the size is capped
1323 "__CPROVER_is_fresh max allocation size exceeded");
1325 }
1326
1327 // SOUNDNESS: allow predicate to fail
1329 {
1331 return 0;
1332 }
1333 void *ptr = __CPROVER_allocate(size, 0);
1334 *elem = ptr;
1336 write_set->linked_ptr_pred_ctx->ptr_pred != elem,
1337 "__CPROVER_is_fresh does not conflict with other pointer predicate in "
1338 "assume context");
1339 write_set->linked_ptr_pred_ctx->ptr_pred =
1341 ? elem
1342 : write_set->linked_ptr_pred_ctx->ptr_pred;
1343 write_set->linked_ptr_pred_ctx->fresh_car =
1346 : write_set->linked_ptr_pred_ctx->fresh_car;
1347
1348 // record the object size for non-determistic bounds checking
1352 // do not detect memory leaks when assuming a precondition of a contract
1353 // for contract checking
1354 // __CPROVER_bool record_may_leak = __VERIFIER_nondet___CPROVER_bool();
1355 // __CPROVER_memory_leak = record_may_leak ? ptr : __CPROVER_memory_leak;
1356 return 1;
1357 }
1358 else if(write_set->assume_ensures_ctx)
1359 {
1360#ifdef __CPROVER_DFCC_DEBUG_LIB
1362 (write_set->assume_requires_ctx == 0) &
1363 (write_set->assert_requires_ctx == 0) &
1364 (write_set->assert_ensures_ctx == 0),
1365 "only one context flag at a time");
1366#endif
1367 // fail if size is too big
1368 if(
1371 {
1373 }
1374 else if(
1377 {
1380 "__CPROVER_is_fresh requires size <= __CPROVER_max_malloc_size");
1382 }
1383
1384 // SOUNDNESS: allow predicate to fail
1386 {
1388 return 0;
1389 }
1390
1391 void *ptr = __CPROVER_allocate(size, 0);
1392 *elem = ptr;
1394 write_set->linked_ptr_pred_ctx->ptr_pred != elem,
1395 "__CPROVER_is_fresh does not conflict with other pointer predicate in "
1396 "assume context");
1397 write_set->linked_ptr_pred_ctx->ptr_pred =
1399 ? elem
1400 : write_set->linked_ptr_pred_ctx->ptr_pred;
1401 write_set->linked_ptr_pred_ctx->fresh_car =
1404 : write_set->linked_ptr_pred_ctx->fresh_car;
1405
1406 // record the object size for non-determistic bounds checking
1410
1411 // detect memory leaks when is_fresh is assumed in a post condition
1412 // of a replaced contract to model a malloc performed by the function
1413 // being abstracted by the contract
1416
1417#ifdef __CPROVER_DFCC_DEBUG_LIB
1418 __CPROVER_contracts_obj_set_add(write_set->linked_allocated, ptr);
1419#else
1421 write_set->linked_allocated->nof_elems =
1422 (write_set->linked_allocated->elems[object_id] != 0)
1423 ? write_set->linked_allocated->nof_elems
1424 : write_set->linked_allocated->nof_elems + 1;
1425 write_set->linked_allocated->elems[object_id] = ptr;
1426 write_set->linked_allocated->is_empty = 0;
1427#endif
1428 return 1;
1429 }
1430 else if(write_set->assert_requires_ctx | write_set->assert_ensures_ctx)
1431 {
1432#ifdef __CPROVER_DFCC_DEBUG_LIB
1434 (write_set->assume_requires_ctx == 0) &
1435 (write_set->assume_ensures_ctx == 0),
1436 "only one context flag at a time");
1437#endif
1438 // check separation
1439 void *ptr = *elem;
1441 __CPROVER_contracts_car_t fresh_car =
1442 write_set->linked_ptr_pred_ctx->fresh_car;
1443 if(
1444 ptr != (void *)0 && __CPROVER_r_ok(ptr, size) &&
1445 (!__CPROVER_same_object(car.lb, fresh_car.lb) ||
1446 (car.ub <= fresh_car.lb) || (fresh_car.ub <= car.lb)))
1447 {
1449 write_set->linked_ptr_pred_ctx->ptr_pred != elem,
1450 "__CPROVER_is_fresh does not conflict with other pointer predicate in "
1451 "assert context");
1452 write_set->linked_ptr_pred_ctx->ptr_pred =
1454 ? elem
1455 : write_set->linked_ptr_pred_ctx->ptr_pred;
1456 write_set->linked_ptr_pred_ctx->fresh_car =
1458 ? car
1459 : write_set->linked_ptr_pred_ctx->fresh_car;
1460 return 1;
1461 }
1462 return 0;
1463 }
1464 else
1465 {
1467 0, "__CPROVER_is_fresh is only called in requires or ensures clauses");
1469 return 0; // to silence libcheck
1470 }
1471}
1472
1492 void *lb,
1493 void **ptr,
1494 void *ub,
1497{
1500 (write_set != 0) & ((write_set->assume_requires_ctx == 1) |
1501 (write_set->assert_requires_ctx == 1) |
1502 (write_set->assume_ensures_ctx == 1) |
1503 (write_set->assert_ensures_ctx == 1)),
1504 "__CPROVER_pointer_in_range_dfcc is used only in requires or ensures "
1505 "clauses");
1506 __CPROVER_assert(__CPROVER_r_ok(lb, 0), "lb pointer must be valid");
1507 __CPROVER_assert(__CPROVER_r_ok(ub, 0), "ub pointer must be valid");
1509 __CPROVER_same_object(lb, ub),
1510 "lb and ub pointers must have the same object");
1514 lb_offset <= ub_offset, "lb and ub pointers must be ordered");
1515 if(write_set->assume_requires_ctx | write_set->assume_ensures_ctx)
1516 {
1517 // SOUNDNESS: allow predicate to fail
1519 {
1521 return 0;
1522 }
1523
1524 // add nondet offset
1526
1527 // this cast is safe because we prove that ub and lb are ordered
1529 __CPROVER_assume(offset <= max_offset);
1530 *ptr = (char *)lb + offset;
1532 write_set->linked_ptr_pred_ctx->ptr_pred != ptr,
1533 "__CPROVER_pointer_in_range_dfcc does not conflict with other pointer "
1534 "predicate in assume context");
1535 write_set->linked_ptr_pred_ctx->ptr_pred =
1537 ? ptr
1538 : write_set->linked_ptr_pred_ctx->ptr_pred;
1539 return 1;
1540 }
1541 else /* write_set->assert_requires_ctx | write_set->assert_ensures_ctx */
1542 {
1544 if(
1545 __CPROVER_same_object(lb, *ptr) && lb_offset <= offset &&
1546 offset <= ub_offset)
1547 {
1549 write_set->linked_ptr_pred_ctx->ptr_pred != ptr,
1550 "__CPROVER_pointer_in_range_dfcc does not conflict with other "
1551 "predicate in assert context");
1552 write_set->linked_ptr_pred_ctx->ptr_pred =
1554 ? ptr
1555 : write_set->linked_ptr_pred_ctx->ptr_pred;
1556 return 1;
1557 }
1558 else
1559 {
1560 return 0;
1561 }
1562 }
1563}
1564
1569 __CPROVER_size_t idx)
1570{
1572#ifdef __CPROVER_DFCC_DEBUG_LIB
1573 __CPROVER_assert(write_set != 0, "write_set not NULL");
1574#endif
1575
1577 if(car.is_writable)
1578 return car.lb;
1579 else
1580 return (void *)0;
1581}
1582
1588 __CPROVER_size_t idx)
1589{
1591 __CPROVER_assert(idx < set->contract_assigns.max_elems, "no OOB access");
1593 if(car.is_writable)
1595}
1596
1601 __CPROVER_size_t idx)
1602{
1604#ifdef __CPROVER_DFCC_DEBUG_LIB
1605 __CPROVER_assert(idx < set->contract_assigns.max_elems, "no OOB access");
1606#endif
1608 if(car.is_writable)
1609 __CPROVER_havoc_slice(car.lb, car.size);
1610}
1611
1623 void *ptr,
1625{
1628 (set != 0) &
1629 ((set->assume_requires_ctx == 1) | (set->assert_requires_ctx == 1) |
1630 (set->assume_ensures_ctx == 1) | (set->assert_ensures_ctx == 1)),
1631 "__CPROVER_is_freeable is used only in requires or ensures clauses");
1632
1633 // These are all the preconditions checked by `free` of the CPROVER library
1634 __CPROVER_bool is_dynamic_object = (ptr == 0) | __CPROVER_DYNAMIC_OBJECT(ptr);
1636 (ptr == 0) | (__CPROVER_POINTER_OFFSET(ptr) == 0);
1637
1638 if((set->assume_requires_ctx == 1) || (set->assume_ensures_ctx == 1))
1639 return is_dynamic_object & has_offset_zero;
1640
1641 // these conditions cannot be used in assumptions since they involve
1642 // demonic non-determinism
1645 (ptr == 0) | (__CPROVER_deallocated != ptr);
1647 __CPROVER_bool is_not_array = (ptr == 0) | (__CPROVER_new_object != ptr) |
1649 return is_null_or_valid_pointer & is_dynamic_object & has_offset_zero &
1651}
1652
1655 void *ptr,
1657{
1660 (set != 0) &
1661 ((set->assume_ensures_ctx == 1) | (set->assert_ensures_ctx == 1)),
1662 "__CPROVER_was_freed is used only in ensures clauses");
1664 (set->linked_deallocated != 0), "linked_deallocated is not null");
1665#ifdef __CPROVER_DFCC_DEBUG_LIB
1666 // manually inlined below
1668 set->linked_deallocated, ptr);
1669#else
1671 return set->linked_deallocated->elems[object_id] == ptr;
1672#endif
1673}
1674
1681 void *ptr,
1683{
1686 set && ((set->assume_ensures_ctx == 1) | (set->assert_ensures_ctx == 1)),
1687 "__CPROVER_was_freed is used only in ensures clauses");
1688
1689 if(set->assume_ensures_ctx)
1690 {
1691#ifdef __CPROVER_DFCC_DEBUG_LIB
1692 // manually inlined below
1695 "assuming __CPROVER_was_freed(ptr) requires ptr to always exist in the "
1696 "contract's frees clause");
1697#else
1700 set->contract_frees.elems[object_id] == ptr,
1701 "assuming __CPROVER_was_freed(ptr) requires ptr to always exist in the "
1702 "contract's frees clause");
1703#endif
1704 }
1705}
1706
1716 void (**function_pointer)(void),
1717 void (*contract)(void),
1720{
1723 (set != 0) &
1724 ((set->assume_requires_ctx == 1) | (set->assert_requires_ctx == 1) |
1725 (set->assume_ensures_ctx == 1) | (set->assert_ensures_ctx == 1)),
1726 "__CPROVER_obeys_contract is used only in requires or ensures clauses");
1727 if((set->assume_requires_ctx == 1) | (set->assume_ensures_ctx == 1))
1728 {
1729 // SOUDNESS: allow predicate to fail
1731 return 0;
1734 "__CPROVER_obeys_contract does not conflict with other pointer "
1735 "predicate in assume context");
1737 ? (void **)function_pointer
1739 // must hold, assign the function pointer to the contract function
1741 return 1;
1742 }
1743 else
1744 {
1745 // in assumption contexts, the pointer gets checked for equality
1747 {
1750 "__CPROVER_obeys_contract does not conflict with other pointer "
1751 "predicate in assume context");
1755 return 1;
1756 }
1757 return 0;
1758 }
1759}
1760#endif // __CPROVER_contracts_library_defined
__CPROVER_thread_local __CPROVER_size_t __CPROVER_max_malloc_size
int __CPROVER_malloc_failure_mode
int __CPROVER_malloc_failure_mode_return_null
void * __CPROVER_allocate(__CPROVER_size_t size, __CPROVER_bool zero)
__CPROVER_bool __CPROVER_w_ok(const void *,...)
void __CPROVER_deallocate(void *)
Definition stdlib.c:670
int __CPROVER_malloc_failure_mode_assert_then_assume
__CPROVER_bool __CPROVER_rw_ok(const void *,...)
__CPROVER_bool __CPROVER_r_ok(const void *,...)
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
__CPROVER_size_t __CPROVER_OBJECT_SIZE(const void *)
void __CPROVER_assert(__CPROVER_bool assertion, const char *description)
void __CPROVER_havoc_slice(void *, __CPROVER_size_t)
__CPROVER_size_t __CPROVER_POINTER_OFFSET(const void *)
__CPROVER_size_t __CPROVER_POINTER_OBJECT(const void *)
__CPROVER_bool __CPROVER_same_object(const void *, const void *)
__CPROVER_bool __CPROVER_DYNAMIC_OBJECT(const void *)
void __CPROVER_assume(__CPROVER_bool assumption)
void __CPROVER_havoc_object(void *)
void __CPROVER_contracts_link_deallocated(__CPROVER_contracts_write_set_ptr_t write_set_postconditions, __CPROVER_contracts_write_set_ptr_t write_set_to_link)
Links write_set_to_link->deallocated to write_set_postconditions->linked_deallocated so that dealloca...
void __CPROVER_contracts_write_set_insert_object_whole(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx, void *ptr)
Inserts a snapshot of the range of bytes covering the whole object pointed to by ptr in set->contact_...
void __CPROVER_contracts_obj_set_release(__CPROVER_contracts_obj_set_ptr_t set)
Releases resources used by set.
__CPROVER_contracts_car_t __CPROVER_contracts_car_create(void *ptr, __CPROVER_size_t size)
Creates a __CPROVER_car_t struct from ptr and size.
__CPROVER_size_t __VERIFIER_nondet_size(void)
void __CPROVER_contracts_write_set_record_deallocated(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Records that an object is deallocated by adding the pointer ptr to set->deallocated.
__CPROVER_bool __CPROVER_contracts_write_set_check_havoc_object(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Checks if a havoc_object(ptr) is allowed according to set.
void __CPROVER_contracts_car_set_insert(__CPROVER_contracts_car_set_ptr_t set, __CPROVER_size_t idx, void *ptr, __CPROVER_size_t size)
Inserts a __CPROVER_contracts_car_t snapshotted from ptr and size into set at index idx.
void __CPROVER_contracts_write_set_insert_assignable(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx, void *ptr, __CPROVER_size_t size)
Inserts a snapshot of the range starting at ptr of size size at index idx in set->contract_assigns.
void __CPROVER_contracts_obj_set_remove(__CPROVER_contracts_obj_set_ptr_t set, void *ptr)
Removes ptr form set if ptr exists in set, no-op otherwise.
void __CPROVER_contracts_ptr_pred_ctx_init(__CPROVER_contracts_ptr_pred_ctx_ptr_t set)
Resets the nondet tracker for pointer predicates in set.
void __CPROVER_contracts_write_set_record_dead(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Records that an object is dead by removing the pointer ptr from set->allocated.
__CPROVER_bool __CPROVER_contracts_pointer_equals(void **ptr1, void *ptr2, __CPROVER_bool may_fail, __CPROVER_contracts_write_set_ptr_t write_set)
Implementation of the pointer_equals front-end predicate.
void __CPROVER_contracts_check_replace_ensures_was_freed_preconditions(void *ptr, __CPROVER_contracts_write_set_ptr_t set)
Asserts that ptr is found in set->contract_frees.
void * __CPROVER_contracts_write_set_havoc_get_assignable_target(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx)
Returns the start address of the conditional address range found at index idx in set->contract_assign...
void __CPROVER_contracts_obj_set_create_indexed_by_object_id(__CPROVER_contracts_obj_set_ptr_t set)
Initialises a __CPROVER_contracts_obj_set_t object to use it in "indexed by object id" mode.
__CPROVER_contracts_car_set_t * __CPROVER_contracts_car_set_ptr_t
Type of pointers to __CPROVER_contracts_car_set_t.
__CPROVER_bool __CPROVER_contracts_write_set_check_array_copy(__CPROVER_contracts_write_set_ptr_t set, void *dest)
Checks if the operation array_copy(dest, ...) is allowed according to set.
int __builtin_clzl(unsigned long)
void __CPROVER_contracts_write_set_deallocate_freeable(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_contracts_write_set_ptr_t target)
Non-deterministically call __CPROVER_contracts_free on all elements of set->contract_frees,...
void __CPROVER_contracts_write_set_havoc_object_whole(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx)
Havocs the whole object pointed to by the lower bound pointer of the element stored at index idx in s...
const void * __CPROVER_deallocated
void __CPROVER_contracts_write_set_add_decl(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Adds the pointer ptr to set->allocated.
void __CPROVER_contracts_write_set_release(__CPROVER_contracts_write_set_ptr_t set)
Releases resources used by set.
__CPROVER_bool __CPROVER_contracts_free(void *, __CPROVER_contracts_write_set_ptr_t)
Models the instrumented version of the free function.
__CPROVER_bool __CPROVER_contracts_obj_set_contains_exact(__CPROVER_contracts_obj_set_ptr_t set, void *ptr)
Checks if ptr is contained in set.
__CPROVER_bool __CPROVER_contracts_write_set_check_array_replace(__CPROVER_contracts_write_set_ptr_t set, void *dest, void *src)
Checks if the operation array_replace(dest, src) is allowed according to set.
void __CPROVER_contracts_car_set_create(__CPROVER_contracts_car_set_ptr_t set, __CPROVER_size_t max_elems)
Initialises a __CPROVER_contracts_car_set_ptr_t object.
void __CPROVER_contracts_write_set_havoc_slice(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx)
Havocs the range of bytes represented byt the element stored at index idx in set->contract_assigns,...
void __CPROVER_contracts_make_invalid_pointer(void **ptr)
Makes the given pointer invalid.
void __CPROVER_contracts_obj_set_append(__CPROVER_contracts_obj_set_ptr_t set, void *ptr)
Appends ptr to set.
void __CPROVER_contracts_link_ptr_pred_ctx(__CPROVER_contracts_write_set_ptr_t write_set, __CPROVER_contracts_ptr_pred_ctx_ptr_t ptr_pred_ctx)
Links is_fresh_set to write_set->linked_ptr_pred_ctx to share evaluation context between requires and...
void __CPROVER_contracts_ptr_pred_ctx_reset(__CPROVER_contracts_ptr_pred_ctx_ptr_t set)
Resets the nondet tracker for pointer predicates in set.
void __CPROVER_contracts_obj_set_create_append(__CPROVER_contracts_obj_set_ptr_t set, __CPROVER_size_t max_elems)
Initialises a __CPROVER_contracts_obj_set_t object to use it in "append" mode for at most max_elems e...
__CPROVER_bool __VERIFIER_nondet___CPROVER_bool(void)
__CPROVER_contracts_write_set_t * __CPROVER_contracts_write_set_ptr_t
Type of pointers to __CPROVER_contracts_write_set_t.
void __CPROVER_contracts_write_set_add_freeable(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Adds the freeable pointer ptr to set->contract_frees.
__CPROVER_bool __CPROVER_contracts_car_set_contains(__CPROVER_contracts_car_set_ptr_t set, __CPROVER_contracts_car_t candidate)
Checks if candidate is included in one of set 's elements.
__CPROVER_bool __CPROVER_contracts_was_freed(void *ptr, __CPROVER_contracts_write_set_ptr_t set)
Returns true iff the pointer ptr is found in set->deallocated.
__CPROVER_bool __CPROVER_contracts_is_freeable(void *ptr, __CPROVER_contracts_write_set_ptr_t set)
Implementation of the is_freeable front-end predicate.
__CPROVER_bool __CPROVER_contracts_obeys_contract(void(**function_pointer)(void), void(*contract)(void), __CPROVER_bool may_fail, __CPROVER_contracts_write_set_ptr_t set)
Implementation of the obeys_contract front-end predicate.
__CPROVER_bool __CPROVER_contracts_write_set_check_assigns_clause_inclusion(__CPROVER_contracts_write_set_ptr_t reference, __CPROVER_contracts_write_set_ptr_t candidate)
Checks the inclusion of the candidate->contract_assigns elements in reference->contract_assigns or re...
void __CPROVER_contracts_car_set_remove(__CPROVER_contracts_car_set_ptr_t set, void *ptr)
Invalidates all cars in the set that point into the same object as the given ptr.
__CPROVER_bool __CPROVER_contracts_write_set_check_assignment(__CPROVER_contracts_write_set_ptr_t set, void *ptr, __CPROVER_size_t size)
Checks if an assignment to the range of bytes starting at ptr and of size bytes is allowed according ...
const void * __CPROVER_memory_leak
__CPROVER_bool __CPROVER_contracts_write_set_check_deallocate(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Checks if the deallocation of ptr is allowed according to set.
void __CPROVER_contracts_obj_set_add(__CPROVER_contracts_obj_set_ptr_t set, void *ptr)
Adds the ptr to set.
__CPROVER_bool __CPROVER_contracts_is_fresh(void **elem, __CPROVER_size_t size, __CPROVER_bool may_fail, __CPROVER_contracts_write_set_ptr_t write_set)
Implementation of the is_fresh front-end predicate.
__CPROVER_contracts_ptr_pred_ctx_t * __CPROVER_contracts_ptr_pred_ctx_ptr_t
Type of pointers to __CPROVER_contracts_ptr_pred_ctx_t.
__CPROVER_contracts_obj_set_t * __CPROVER_contracts_obj_set_ptr_t
Type of pointers to __CPROVER_contracts_obj_set_t.
__CPROVER_bool __CPROVER_malloc_is_new_array
void __CPROVER_contracts_write_set_create(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t contract_assigns_size, __CPROVER_size_t contract_frees_size, __CPROVER_bool assume_requires_ctx, __CPROVER_bool assert_requires_ctx, __CPROVER_bool assume_ensures_ctx, __CPROVER_bool assert_ensures_ctx, __CPROVER_bool allow_allocate, __CPROVER_bool allow_deallocate)
Initialises a __CPROVER_contracts_write_set_t object.
__CPROVER_bool __CPROVER_contracts_write_set_check_frees_clause_inclusion(__CPROVER_contracts_write_set_ptr_t reference, __CPROVER_contracts_write_set_ptr_t candidate)
Checks the inclusion of the candidate->contract_frees elements in reference->contract_frees or refere...
const void * __CPROVER_alloca_object
void __CPROVER_contracts_write_set_insert_object_upto(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx, void *ptr, __CPROVER_size_t size)
Inserts a snapshot of the range of bytes starting at ptr of size bytes in set->contact_assigns at ind...
__CPROVER_bool __CPROVER_contracts_obj_set_contains(__CPROVER_contracts_obj_set_ptr_t set, void *ptr)
Checks if a pointer with the same object id as ptr is contained in set.
__CPROVER_bool __CPROVER_contracts_write_set_check_allocated_deallocated_is_empty(__CPROVER_contracts_write_set_ptr_t set)
Returns true iff set->deallocated is empty.
void __CPROVER_contracts_link_allocated(__CPROVER_contracts_write_set_ptr_t write_set_postconditions, __CPROVER_contracts_write_set_ptr_t write_set_to_link)
Links write_set_to_link->allocated to write_set_postconditions->linked_allocated so that allocations ...
const void * __CPROVER_new_object
void __CPROVER_contracts_write_set_insert_object_from(__CPROVER_contracts_write_set_ptr_t set, __CPROVER_size_t idx, void *ptr)
Inserts a snapshot of the range of bytes starting at ptr and extending to the end of the object in se...
__CPROVER_bool __CPROVER_contracts_pointer_in_range_dfcc(void *lb, void **ptr, void *ub, __CPROVER_bool may_fail, __CPROVER_contracts_write_set_ptr_t write_set)
Implementation of the pointer_in_range_dfcc front-end predicate.
void __CPROVER_contracts_write_set_add_allocated(__CPROVER_contracts_write_set_ptr_t set, void *ptr)
Adds the dynamically allocated pointer ptr to set->allocated.
void * __CPROVER_contracts_malloc(__CPROVER_size_t, __CPROVER_contracts_write_set_ptr_t)
Models the instrumented interface of the malloc function.
__CPROVER_bool __CPROVER_contracts_write_set_check_array_set(__CPROVER_contracts_write_set_ptr_t set, void *dest)
Checks if the operation array_set(dest, ...) is allowed according to set.
int __builtin_clzll(unsigned long long)
A set of __CPROVER_contracts_car_t.
__CPROVER_size_t max_elems
Maximum number of elements that can be stored in the set.
__CPROVER_contracts_car_t * elems
An array of car_t of size max_elems.
A conditionally writable range of bytes.
__CPROVER_size_t size
Size of the range in bytes.
void * lb
Lower bound address of the range.
void * ub
Upper bound address of the range.
unsigned char is_writable
True iff __CPROVER_w_ok(lb, size) holds at creation.
void ** elems
Array of void *pointers, indexed by their object ID or some other order.
unsigned char is_empty
True iff nof_elems is 0.
__CPROVER_size_t watermark
next usable index in elems if less than max_elems (1 + greatest used index in elems)
unsigned char indexed_by_object_id
True iff elems is indexed by the object id of the pointers.
__CPROVER_size_t nof_elems
Number of elements currently in the elems array.
__CPROVER_size_t max_elems
Maximum number of elements that can be stored in the set.
Stores context information supporting the evaluation of pointer predicates in both assume and assert ...
__CPROVER_contracts_car_t fresh_car
Runtime representation of a write set.
__CPROVER_contracts_obj_set_ptr_t linked_allocated
Object set recording the is_fresh allocations in post conditions.
__CPROVER_contracts_ptr_pred_ctx_ptr_t linked_ptr_pred_ctx
Pointer to object set supporting the is_fresh predicate checks (indexed mode)
unsigned char assume_ensures_ctx
True iff the write set checks ensures clauses in an assumption ctx.
__CPROVER_contracts_obj_set_t contract_frees
Set of freeable pointers derived from the contract (indexed mode)
__CPROVER_contracts_obj_set_t deallocated
Set of objects deallocated by the function under analysis (indexed mode)
unsigned char assume_requires_ctx
True iff the write set checks requires clauses in an assumption ctx.
__CPROVER_contracts_obj_set_ptr_t linked_deallocated
Object set recording the deallocations (used by was_freed)
__CPROVER_contracts_car_set_t contract_assigns
Set of car derived from the contract.
unsigned char assert_ensures_ctx
True iff this write set checks ensures clauses in an assertion ctx.
unsigned char assert_requires_ctx
True iff the write set checks requires clauses in an assertion ctx.
unsigned char allow_deallocate
True iff dynamic deallocation is allowed (default: true)
__CPROVER_contracts_obj_set_t allocated
Set of objects allocated by the function under analysis (indexed mode)
unsigned char allow_allocate
True iff dynamic allocation is allowed (default: true)
__CPROVER_contracts_obj_set_t contract_frees_append
Set of freeable pointers derived from the contract (append mode)