├── .clang-format ├── .github └── workflows │ ├── nightly-crab-docker.yaml │ ├── test-crab-dev-docker.yaml │ └── test-crab-docker.yml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── Crab_arch.jpg ├── IKOS_LICENSE.pdf ├── LICENSE ├── README.md ├── cmake ├── Coverage.cmake ├── FindApron.cmake ├── FindCudd.cmake ├── FindElina.cmake ├── FindFLINT.cmake ├── FindGMP.cmake ├── FindGMPXX.cmake ├── FindLdd.cmake ├── FindMPFR.cmake ├── FindPPLite.cmake ├── FindSSE.cmake ├── download_apron.cmake ├── download_boxes_ldd.cmake ├── download_elina.cmake └── download_pplite.cmake ├── docker ├── buildpack-deps-crab.Dockerfile ├── buildpack-deps-crab.jammy.Dockerfile ├── crab.Dockerfile ├── crab.apron.Dockerfile ├── crab.dev.Dockerfile ├── crab.dev.apron.Dockerfile ├── crab.dev.elina.Dockerfile ├── crab.dev.pplite.Dockerfile ├── crab.elina.Dockerfile ├── crab.pplite.Dockerfile └── readme.md ├── include └── crab │ ├── analysis │ ├── abs_transformer.hpp │ ├── bwd_analyzer.hpp │ ├── dataflow │ │ ├── assertion_crawler.hpp │ │ ├── assumptions.hpp │ │ └── liveness.hpp │ ├── fwd_analyzer.hpp │ ├── fwd_bwd_params.hpp │ ├── graphs │ │ ├── cdg.hpp │ │ ├── dominance.hpp │ │ ├── sccg.hpp │ │ ├── sccg_bgl.hpp │ │ └── topo_order.hpp │ └── inter │ │ ├── bottom_up_inter_analyzer.hpp │ │ ├── inter_analyzer_api.hpp │ │ ├── inter_params.hpp │ │ ├── top_down_inter_analyzer.hpp │ │ └── top_down_inter_params.hpp │ ├── cfg │ ├── basic_block_traits.hpp │ ├── cfg.hpp │ ├── cfg_bgl.hpp │ ├── cfg_operators.hpp │ ├── cfg_to_dot.hpp │ └── type_checker.hpp │ ├── cg │ ├── cg.hpp │ └── cg_bgl.hpp │ ├── checkers │ ├── assertion.hpp │ ├── base_property.hpp │ ├── checker.hpp │ └── div_zero.hpp │ ├── config.h.cmake │ ├── domains │ ├── abstract_domain.hpp │ ├── abstract_domain_macros.def │ ├── abstract_domain_operators.hpp │ ├── abstract_domain_params.hpp │ ├── abstract_domain_specialized_traits.hpp │ ├── apron │ │ └── apron.hpp │ ├── apron_domains.hpp │ ├── array_adaptive.hpp │ ├── array_smashing.hpp │ ├── backward_assign_operations.hpp │ ├── boolean.hpp │ ├── boxes.hpp │ ├── combined_congruences.hpp │ ├── combined_domains.hpp │ ├── congruence.hpp │ ├── congruence_impl.hpp │ ├── congruences.hpp │ ├── constant.hpp │ ├── constant_domain.hpp │ ├── constant_impl.hpp │ ├── dis_interval.hpp │ ├── dis_interval_impl.hpp │ ├── dis_intervals.hpp │ ├── discrete_domains.hpp │ ├── dummy_abstract_domain.hpp │ ├── elina │ │ └── elina.hpp │ ├── elina_domains.hpp │ ├── fixed_tvpi_domain.hpp │ ├── flat_boolean_domain.hpp │ ├── generic_abstract_domain.hpp │ ├── graphs │ │ ├── adapt_sgraph.hpp │ │ ├── adapt_smap.hpp │ │ ├── graph_config.hpp │ │ ├── graph_iterators.hpp │ │ ├── graph_ops.hpp │ │ ├── graph_views.hpp │ │ ├── ht_graph.hpp │ │ ├── pt_graph.hpp │ │ ├── semiring_graph_ops.hpp │ │ ├── sparse_graph.hpp │ │ └── util │ │ │ ├── Heap.h │ │ │ ├── Vec.h │ │ │ └── reference_wrapper.hpp │ ├── interval.hpp │ ├── interval_congruence.hpp │ ├── interval_congruence_impl.hpp │ ├── interval_impl.hpp │ ├── intervals.hpp │ ├── lattice_domain.hpp │ ├── ldd │ │ ├── ldd.hpp │ │ └── ldd_print.hpp │ ├── linear_interval_solver.hpp │ ├── lookahead_widening_domain.hpp │ ├── numerical_packing.hpp │ ├── patricia_trees.hpp │ ├── powerset_domain.hpp │ ├── region │ │ ├── ghost_variable_manager.hpp │ │ ├── ghost_variables.hpp │ │ ├── region_info.hpp │ │ └── tags.hpp │ ├── region_domain.hpp │ ├── separate_domains.hpp │ ├── sign.hpp │ ├── sign_constant_domain.hpp │ ├── sign_domain.hpp │ ├── sign_impl.hpp │ ├── small_range.hpp │ ├── sparse_dbm.hpp │ ├── split_dbm.hpp │ ├── split_oct.hpp │ ├── term │ │ ├── inverse.hpp │ │ ├── simplify.hpp │ │ ├── term_expr.hpp │ │ └── term_operators.hpp │ ├── term_equiv.hpp │ ├── types.hpp │ ├── uf_domain.hpp │ ├── union_find_domain.hpp │ ├── value_partitioning_domain.hpp │ ├── wrapped_interval.hpp │ ├── wrapped_interval_domain.hpp │ └── wrapped_interval_impl.hpp │ ├── fixpoint │ ├── fixpoint_iterators_api.hpp │ ├── fixpoint_params.hpp │ ├── interleaved_fixpoint_iterator.hpp │ ├── killgen_fixpoint_iterator.hpp │ ├── thresholds.hpp │ └── wto.hpp │ ├── numbers │ ├── bignums.hpp │ ├── safeint.hpp │ └── wrapint.hpp │ ├── support │ ├── debug.hpp │ ├── os.hpp │ └── stats.hpp │ ├── transforms │ ├── dce.hpp │ ├── lower_safe_assertions.hpp │ └── transform.hpp │ └── types │ ├── indexable.hpp │ ├── linear_constraints.hpp │ ├── reference_constraints.hpp │ ├── tag.hpp │ ├── variable.hpp │ └── varname_factory.hpp ├── lib ├── CMakeLists.txt ├── abstract_domain_params.cpp ├── array_adaptive_impl.cpp ├── bignums.cpp ├── boolean.cpp ├── congruence.cpp ├── constant.cpp ├── debug.cpp ├── dis_interval.cpp ├── interval.cpp ├── interval_congruence.cpp ├── os.cpp ├── region_info.cpp ├── safeint.cpp ├── sign.cpp ├── small_range.cpp ├── stats.cpp ├── tag.cpp ├── term_operators.cpp ├── types.cpp ├── varname_factory.cpp ├── wrapint.cpp └── wrapped_interval.cpp ├── make ├── Makefile ├── Makefile.config ├── README.md ├── analysis.cpp ├── apron │ ├── Makefile │ ├── analysis.cpp │ └── domain.cpp ├── domain.cpp └── elina │ ├── Makefile │ ├── analysis.cpp │ └── domain.cpp └── tests ├── CMakeLists.txt ├── README.md ├── assertion_crawler ├── crawler-1.cc └── crawler-2.cc ├── backward ├── backward-1-apron.cc ├── backward-1-elina.cc ├── backward-2-apron.cc ├── backward-2-boxes.cc ├── backward-2-elina.cc ├── backward-3-apron.cc ├── backward-3-elina.cc ├── backward-4-apron.cc ├── backward-4-boxes.cc ├── backward-4-elina.cc ├── backward-array-1-apron.cc ├── backward-array-1.cc ├── bakhirkin-apron.cc ├── bakhirkin-elina.cc ├── unittests-backward-apron.cc ├── unittests-backward-elina.cc └── unittests-backward.cc ├── bcrab.cpp ├── bcrab.hpp ├── bcrab_inst.hpp ├── cfg └── cfg.cc ├── cg └── cg.cc ├── checkers ├── checker.cc └── entailment.cc ├── common.hpp ├── crab.cpp ├── crab.hpp ├── crab_dom.hpp ├── crab_inst.hpp ├── crab_lang.hpp ├── domains ├── apron-domains.cc ├── apron-octagons.cc ├── array_adaptive1.cc ├── array_adaptive2.cc ├── array_graph.cc.NOCOMPILE ├── array_smashing.cc ├── boxes-bug.cc ├── boxes-ldd.cc ├── boxes.cc ├── constant_domain.cc ├── disintervals.cc ├── elina-domains.cc ├── elina-octagons.cc ├── fixedtvpi.cc ├── fixedtvpi2.cc ├── flat_bool_domain1-boxes.cc ├── flat_bool_domain1.cc ├── flat_bool_domain2.cc ├── flat_bool_domain3.cc ├── flat_bool_domain4.cc ├── flat_bool_domain5-boxes.cc ├── flat_bool_domain5.cc ├── flat_bool_domain6.cc ├── flat_bool_domain7.cc ├── flat_bool_domain8.cc ├── gen_abs_dom.cc ├── intrinsics.cc ├── lookahead-widening.cc ├── nested-1.cc ├── nested-2.cc ├── nested-3.cc ├── powerset.cc ├── pplite_domains.cc ├── region │ ├── region-1.cc │ ├── region-2.cc │ ├── region-3.cc │ ├── region-4.cc │ ├── region-5.cc │ ├── region-6.cc │ ├── region-7.cc │ └── region-8.cc ├── soct-apron.cc ├── soct-elina.cc ├── soct.cc ├── sparsegraph.cc.NOCOMPILE ├── terms-1.cc ├── terms-2.cc ├── terms-3.cc ├── test1-real-apron.cc ├── test1-real.cc ├── test1.cc ├── test2-real-apron.cc ├── test2-real-boxes.cc ├── test2-real.cc ├── test2.cc ├── test3-real-apron.cc ├── test3-real-boxes.cc ├── test3-real.cc ├── test3.cc ├── test4-real-apron.cc ├── test4-real-elina.cc ├── test4.cc ├── test5.cc ├── test8.cc ├── test9.cc ├── unittests-array-adaptive.cc ├── unittests-boxes.cc ├── unittests-linear-constraints.cc ├── unittests-num-packing.cc ├── unittests-regions.cc ├── unittests-rename-apron.cc ├── unittests-rename-elina.cc ├── unittests-rename.cc ├── unittests-terms.cc.NOCOMPILE ├── unittests-uf.cc ├── unittests-union-find.cc ├── unittests-value-partitioning.cc ├── unittests-zones.cc └── wrapint │ ├── wrapint.cc │ ├── wrapped_interval_domain.cc │ └── wrapped_intervals.cc ├── expected_results.apron.out ├── expected_results.boxes.out ├── expected_results.elina.out ├── expected_results.out ├── expected_results.pplite.out ├── icrab.cpp ├── icrab.hpp ├── icrab_inst.hpp ├── inter ├── bu_inter-apron.cc ├── bu_inter.cc ├── td_inter_1-apron.cc ├── td_inter_1-elina.cc ├── td_inter_1.cc ├── td_inter_2.cc ├── td_inter_3.cc ├── td_inter_4.cc ├── td_inter_5.cc ├── td_inter_6.cc ├── td_inter_7.cc └── td_inter_8.cc ├── liveness └── live-1.cc ├── preconditions ├── precond-1-apron.cc ├── precond-1-elina.cc ├── precond-2-apron.cc └── precond-2-elina.cc ├── program_options.hpp ├── run_coverage.sh ├── run_tests.sh ├── thresholds └── thresholds.cc └── transforms ├── dce.cc └── lower_safe_assertions.cc /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | AllowShortFunctionsOnASingleLine: All 4 | IndentWidth: '2' 5 | 6 | ... 7 | -------------------------------------------------------------------------------- /.github/workflows/test-crab-dev-docker.yaml: -------------------------------------------------------------------------------- 1 | # Workflow to build and test crab dev branch 2 | 3 | name: CI-dev 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the dev branch 8 | push: 9 | branches: dev 10 | pull_request: 11 | branches: dev 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "test" 16 | test: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - name: Check out Repo 24 | uses: actions/checkout@v2 25 | with: 26 | ref: dev 27 | - name: Build crab without external libraries + run tests 28 | run: docker build --build-arg BUILD_TYPE=Release -t seahorn/crab -f docker/crab.dev.Dockerfile . 29 | - name: Build crab+apron+ldd-boxes and run tests 30 | run: docker build --build-arg BUILD_TYPE=Release -t seahorn/crab_apron_boxes -f docker/crab.dev.apron.Dockerfile . 31 | - name: Build crab+elina and run tests 32 | run: docker build --build-arg BUILD_TYPE=Release -t seahorn/crab_elina -f docker/crab.dev.elina.Dockerfile . 33 | -------------------------------------------------------------------------------- /.github/workflows/test-crab-docker.yml: -------------------------------------------------------------------------------- 1 | # Workflow to build and test crab master branch 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: master 10 | pull_request: 11 | branches: master 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "test" 16 | test: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - name: Check out Repo 24 | uses: actions/checkout@v2 25 | with: 26 | ref: master 27 | - name: Build crab without external libraries + run tests 28 | run: docker build --build-arg UBUNTU=bionic --build-arg BUILD_TYPE=Release -t seahorn/crab -f docker/crab.Dockerfile . 29 | - name: Build crab+apron+ldd-boxes and run tests 30 | run: docker build --build-arg UBUNTU=bionic --build-arg BUILD_TYPE=Release -t seahorn/crab_apron_boxes -f docker/crab.apron.Dockerfile . 31 | - name: Build crab+elina and run tests 32 | run: docker build --build-arg UBUNTU=bionic --build-arg BUILD_TYPE=Release -t seahorn/crab_elina -f docker/crab.elina.Dockerfile . 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /build-*/ 3 | /debug/ 4 | /debug-*/ 5 | /install/ 6 | /install-*/ 7 | /GPATH 8 | /GRTAGS 9 | /GTAGS 10 | *.pyc 11 | *.pyo 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | cache: apt 3 | env: 4 | matrix: 5 | - UBUNTU_DIST=xenial 6 | BUILD_TYPE=Release 7 | EXTERNAL_DOMAIN_LIB=apron 8 | - UBUNTU_DIST=bionic 9 | BUILD_TYPE=Release 10 | EXTERNAL_DOMAIN_LIB=apron 11 | # - UBUNTU_DIST=bionic 12 | # BUILD_TYPE=Coverage 13 | # EXTERNAL_DOMAIN_LIB=apron 14 | - UBUNTU_DIST=bionic 15 | BUILD_TYPE=Release 16 | EXTERNAL_DOMAIN_LIB=elina 17 | 18 | services: 19 | - docker 20 | 21 | install: true 22 | 23 | script: 24 | - docker build --build-arg BRANCH=$TRAVIS_BRANCH --build-arg UBUNTU=${UBUNTU_DIST} --build-arg BUILD_TYPE=${BUILD_TYPE} -t seahorn/crab_${EXTERNAL_DOMAIN_LIB}:${UBUNTU_DIST} -f docker/crab.${EXTERNAL_DOMAIN_LIB}.Dockerfile . 25 | 26 | - 'if [ "$TRAVIS_EVENT_TYPE" = "cron" ] ; then 27 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 28 | && docker push seahorn/crab_${EXTERNAL_DOMAIN_LIB}:${UBUNTU_DIST}; 29 | fi ' 30 | 31 | - 'if [ "$BUILD_TYPE" = "Coverage" ] ; then 32 | docker run -v $(pwd):/host -it seahorn/crab_${EXTERNAL_DOMAIN_LIB}:${UBUNTU_DIST} /bin/sh -c "bash /crab/tests/run_coverage.sh /crab/build /crab && mv /crab/build/all.info /host" && bash <(curl -s https://codecov.io/bash) -Z -f all.info; 33 | fi ' 34 | 35 | 36 | notifications: 37 | email: 38 | recipients: 39 | - navasjorgea@gmail.com 40 | on_success: always 41 | on_failure: always 42 | -------------------------------------------------------------------------------- /Crab_arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seahorn/crab/146f5399c72ff508f176e6392e490647ac657ce7/Crab_arch.jpg -------------------------------------------------------------------------------- /IKOS_LICENSE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seahorn/crab/146f5399c72ff508f176e6392e490647ac657ce7/IKOS_LICENSE.pdf -------------------------------------------------------------------------------- /cmake/FindApron.cmake: -------------------------------------------------------------------------------- 1 | #Find Apron library 2 | if (NOT APRON_FOUND) 3 | 4 | # save CMAKE_FIND_LIBRARY_SUFFIXES 5 | set(_APRON_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) 6 | 7 | #### FIXME: we cannot use apron dynamic libraries because crab 8 | #### library refers to the apron libraries located in the build 9 | #### directory instead of the ones where they will be installed. 10 | #if(NOT BUILD_CRAB_LIBS_SHARED) 11 | set(CMAKE_FIND_LIBRARY_SUFFIXES .a) 12 | #else() 13 | # set(CMAKE_FIND_LIBRARY_SUFFIXES .so .dylib) 14 | #endif() 15 | 16 | set (APRON_ROOT "" CACHE PATH "Root of Apron install.") 17 | 18 | find_package (Gmp QUIET) 19 | find_package (MPFR QUIET) 20 | 21 | find_path(APRON_INCLUDE_DIR NAMES ap_abstract0.h PATHS ${APRON_ROOT}/include) 22 | 23 | find_library(Apron_Polka_Lib NAMES polkaMPQ PATHS ${APRON_ROOT}/lib NO_DEFAULT_PATH) 24 | ## octD is faster than octMPQ 25 | find_library(Apron_Oct_Lib NAMES octD PATHS ${APRON_ROOT}/lib NO_DEFAULT_PATH) 26 | # find_library(Apron_Oct_Lib NAMES octMPQ PATHS ${APRON_ROOT}/lib) 27 | find_library(Apron_Apron_Lib NAMES apron PATHS ${APRON_ROOT}/lib NO_DEFAULT_PATH) 28 | find_library(Apron_Box_Lib NAMES boxMPQ PATHS ${APRON_ROOT}/lib NO_DEFAULT_PATH) 29 | 30 | if (HAVE_PPLITE) 31 | ## PPLite's apron wrapper 32 | find_library(Apron_PPLite_Lib 33 | NAMES ap_pplite 34 | PATHS ${APRON_ROOT}/lib NO_DEFAULT_PATH) 35 | endif() 36 | 37 | set(APRON_LIBRARY ${Apron_Box_Lib} 38 | ${Apron_Polka_Lib} ${Apron_Oct_Lib} 39 | ${Apron_Apron_Lib} ${Apron_PPLite_Lib}) 40 | 41 | message(STATUS "${APRON_LIBRARY}") 42 | include(FindPackageHandleStandardArgs) 43 | find_package_handle_standard_args (Apron 44 | REQUIRED_VARS APRON_INCLUDE_DIR APRON_LIBRARY GMP_FOUND MPFR_FOUND) 45 | 46 | set(APRON_INCLUDE_DIR ${APRON_INCLUDE_DIR} ${MPFR_INC_DIR} ${PPLITE_INCLUDE_DIRS}) 47 | set(APRON_LIBRARY ${APRON_LIBRARY} ${MPFR_LIB} ${PPLITE_LIBRARY}) 48 | 49 | mark_as_advanced(APRON_LIBRARY APRON_INCLUDE_DIR 50 | Apron_Apron_Lib Apron_Box_Lib Apron_Oct_Lib Apron_Polka_Lib 51 | Apron_PPLite_Lib) 52 | 53 | # restore CMAKE_FIND_LIBRARY_SUFFIXES 54 | set(CMAKE_FIND_LIBRARY_SUFFIXES ${_APRON_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) 55 | 56 | endif () 57 | -------------------------------------------------------------------------------- /cmake/FindCudd.cmake: -------------------------------------------------------------------------------- 1 | # Find Cudd 2 | 3 | if (NOT CUDD_ROOT) 4 | set(CUDD_ROOT "" CACHE PATH "Root of Cudd compiled source tree.") 5 | endif() 6 | 7 | find_path(CUDD_INCLUDE_DIR NAMES cudd.h PATHS ${CUDD_ROOT}/include/ldd) 8 | #find_path(CUDD_INT_INCLUDE_DIR NAMES cuddInt.h PATHS ${CUDD_ROOT}/cudd) 9 | find_path(CUDD_INT_INCLUDE_DIR NAMES cuddInt.h PATHS ${CUDD_ROOT}/include/ldd) 10 | 11 | set (CUDD_INCLUDE_DIR ${CUDD_INCLUDE_DIR} ${CUDD_INT_INCLUDE_DIR}) 12 | 13 | mark_as_advanced (CUDD_INCLUDE_DIR CUDD_INT_INCLUDE_DIR) 14 | 15 | find_library(CUDD_CUDD_LIBRARY NAMES cudd PATHS ${CUDD_ROOT}/lib) 16 | find_library(CUDD_EPD_LIBRARY NAMES epd PATHS ${CUDD_ROOT}/lib) 17 | find_library(CUDD_ST_LIBRARY NAMES st PATHS ${CUDD_ROOT}/lib) 18 | ## Hack: In some linux systems, the library /lib64/libutil.so exists 19 | ## but it has nothing to do with cudd. Even if we use NO_DEFAULT_PATH 20 | ## when CUDD_ROOT is not defined CUDD_UTIL_LIBRARY can be set to the 21 | ## wrong library. 22 | if (CUDD_CUDD_LIBRARY) 23 | find_library(CUDD_UTIL_LIBRARY util PATHS ${CUDD_ROOT}/lib NO_DEFAULT_PATH) 24 | endif() 25 | find_library(CUDD_MTR_LIBRARY NAMES mtr PATHS ${CUDD_ROOT}/lib) 26 | 27 | mark_as_advanced (CUDD_CUDD_LIBRARY CUDD_DDDMP_LIBRARY CUDD_EPD_LIBRARY 28 | CUDD_ST_LIBRARY CUDD_UTIL_LIBRARY CUDD_MTR_LIBRARY) 29 | 30 | set(CUDD_LIBRARY 31 | ${CUDD_CUDD_LIBRARY} ${CUDD_ST_LIBRARY} ${CUDD_UTIL_LIBRARY} 32 | ${CUDD_MTR_LIBRARY} ${CUDD_EPD_LIBRARY} ${CUDD_DDDMP_LIBRARY} ) 33 | mark_as_advanced (CUDD_LIBRARY) 34 | 35 | include (CheckTypeSize) 36 | check_type_size (long CMAKE_SIZEOF_LONG) 37 | #message (STATUS "sizeof (long): ${CMAKE_SIZEOF_LONG}") 38 | 39 | set (CUDD_CXXFLAGS "-DBSD -DHAVE_IEEE_754 -DSIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P} -DSIZEOF_LONG=${CMAKE_SIZEOF_LONG}") 40 | mark_as_advanced (CMAKE_SIZEOF_LONG CUDD_CXXFLAGS) 41 | 42 | include (FindPackageHandleStandardArgs) 43 | find_package_handle_standard_args(Cudd 44 | REQUIRED_VARS CUDD_LIBRARY CUDD_INCLUDE_DIR CUDD_CXXFLAGS) 45 | 46 | -------------------------------------------------------------------------------- /cmake/FindElina.cmake: -------------------------------------------------------------------------------- 1 | #Find Elina library 2 | if (NOT ELINA_FOUND) 3 | 4 | # save CMAKE_FIND_LIBRARY_SUFFIXES 5 | set(_ELINA_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) 6 | 7 | ### Elina does not produce static libraries 8 | #if(NOT BUILD_CRAB_LIBS_SHARED) 9 | # set(CMAKE_FIND_LIBRARY_SUFFIXES .a) 10 | #else() 11 | ### Elina dynamic libraries have .so extension even if they are built 12 | ### on mac osx. 13 | set(CMAKE_FIND_LIBRARY_SUFFIXES .so .dylib) 14 | #endif() 15 | 16 | set (ELINA_ROOT "" CACHE PATH "Root of Elina install.") 17 | 18 | find_package (Gmp QUIET) 19 | find_package (MPFR QUIET) 20 | 21 | find_path(ELINA_INCLUDE_DIR NAMES elina_abstract0.h PATHS ${ELINA_ROOT}/include) 22 | 23 | find_library(Elina_Poly_Lib NAMES optpoly PATHS ${ELINA_ROOT}/lib NO_DEFAULT_PATH) 24 | find_library(Elina_Opt_Oct_Lib NAMES optoct PATHS ${ELINA_ROOT}/lib NO_DEFAULT_PATH) 25 | find_library(Elina_Linearize_Lib NAMES elinalinearize PATHS ${ELINA_ROOT}/lib NO_DEFAULT_PATH) 26 | find_library(Elina_Aux_Lib NAMES elinaux PATHS ${ELINA_ROOT}/lib NO_DEFAULT_PATH) 27 | find_library(Elina_Opt_Zones_Lib NAMES optzones PATHS ${ELINA_ROOT}/lib NO_DEFAULT_PATH) 28 | find_library(Elina_Partitions_Lib NAMES partitions PATHS ${ELINA_ROOT}/lib NO_DEFAULT_PATH) 29 | 30 | set(ELINA_LIBRARY ${Elina_Poly_Lib} 31 | ${Elina_Opt_Oct_Lib} ${Elina_Linearize_Lib} ${Elina_Aux_Lib} 32 | ${Elina_Opt_Zones_Lib} ${Elina_Partitions_Lib}) 33 | 34 | include (FindPackageHandleStandardArgs) 35 | find_package_handle_standard_args (Elina 36 | REQUIRED_VARS ELINA_INCLUDE_DIR ELINA_LIBRARY GMP_FOUND MPFR_FOUND) 37 | 38 | set (ELINA_INCLUDE_DIR ${ELINA_INCLUDE_DIR} ${MPFR_INC_DIR}) 39 | set (ELINA_LIBRARY ${ELINA_LIBRARY} ${MPFR_LIB}) 40 | 41 | mark_as_advanced(ELINA_LIBRARY ELINA_INCLUDE_DIR) 42 | 43 | # restore CMAKE_FIND_LIBRARY_SUFFIXES 44 | set(CMAKE_FIND_LIBRARY_SUFFIXES ${_ELINA_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) 45 | 46 | endif () 47 | -------------------------------------------------------------------------------- /cmake/FindFLINT.cmake: -------------------------------------------------------------------------------- 1 | # Find FLINT headers and libraries. 2 | # Author: Enea Zaffanella (enea.zaffanella@unipr.it) 3 | 4 | if (NOT FLINT_FOUND) 5 | set(FLINT_ROOT "" CACHE PATH "Path to flint install directory") 6 | 7 | find_path(FLINT_INCLUDES 8 | NAMES flint/flint.h 9 | HINTS "${FLINT_ROOT}/include" 10 | DOC "Path to flint include directory" 11 | ) 12 | 13 | find_library(FLINT_LIB 14 | NAMES flint 15 | HINTS "${FLINT_ROOT}/lib" 16 | DOC "Path to flint library" 17 | ) 18 | 19 | include(FindPackageHandleStandardArgs) 20 | find_package_handle_standard_args(FLINT 21 | REQUIRED_VARS 22 | FLINT_INCLUDES 23 | FLINT_LIB 24 | VERSION_VAR 25 | FLINT_VERSION 26 | FAIL_MESSAGE 27 | "Could NOT find FLINT. Please provide -DFLINT_ROOT=/path/to/flint") 28 | endif() 29 | -------------------------------------------------------------------------------- /cmake/FindGMP.cmake: -------------------------------------------------------------------------------- 1 | # GMP_USE_STATIC_LIBS - Set to ON to force the use of static libraries. 2 | 3 | ## To switch between static and dynamic without resetting the cache 4 | # if ("${GMP_USE_STATIC_LIBS}" STREQUAL "${GMP_USE_STATIC_LIBS_LAST}") 5 | # set(GMP_USE_STATIC_LIBS_CHANGED OFF) 6 | # else () 7 | # set(GMP_USE_STATIC_LIBS_CHANGED ON) 8 | # endif() 9 | # set(GMP_USE_STATIC_LIBS_LAST "${GMP_USE_STATIC_LIBS}") 10 | # if (GMP_USE_STATIC_LIBS_CHANGED) 11 | # set(GMP_LIB "GMP_LIB-NOTFOUND") 12 | # endif() 13 | 14 | if (NOT GMP_FOUND) 15 | # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES 16 | if(GMP_USE_STATIC_LIBS ) 17 | # save CMAKE_FIND_LIBRARY_SUFFIXES 18 | set(_GMP_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) 19 | set(CMAKE_FIND_LIBRARY_SUFFIXES .a) 20 | endif() 21 | 22 | set(GMP_SEARCH_PATH "" CACHE PATH "Search path for gmp.") 23 | find_path(GMP_INCLUDE_DIR NAMES gmp.h PATHS ${GMP_SEARCH_PATH}/include) 24 | find_library(GMP_LIB NAMES gmp PATHS ${GMP_SEARCH_PATH}/lib) 25 | 26 | mark_as_advanced(GMP_SEARCH_PATH GMP_INCLUDE_DIR GMP_LIB) 27 | 28 | include (FindPackageHandleStandardArgs) 29 | find_package_handle_standard_args(GMP 30 | REQUIRED_VARS GMP_INCLUDE_DIR GMP_LIB) 31 | 32 | if(GMP_USE_STATIC_LIBS ) 33 | # restore CMAKE_FIND_LIBRARY_SUFFIXES 34 | set(CMAKE_FIND_LIBRARY_SUFFIXES ${_GMP_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) 35 | endif() 36 | 37 | endif() 38 | -------------------------------------------------------------------------------- /cmake/FindGMPXX.cmake: -------------------------------------------------------------------------------- 1 | if (NOT GMPXX_FOUND) 2 | set(GMP_SEARCH_PATH "" CACHE PATH "Search path for gmp.") 3 | find_path(GMPXX_INCLUDE_DIR NAMES gmpxx.h PATHS ${GMP_SEARCH_PATH}/include) 4 | find_library(GMPXX_LIB NAMES gmpxx PATHS ${GMP_SEARCH_PATH}/lib) 5 | 6 | include (FindPackageHandleStandardArgs) 7 | find_package_handle_standard_args(GMPXX 8 | REQUIRED_VARS GMPXX_INCLUDE_DIR GMPXX_LIB) 9 | 10 | endif() 11 | -------------------------------------------------------------------------------- /cmake/FindLdd.cmake: -------------------------------------------------------------------------------- 1 | # Find LDD 2 | if (NOT LDD_FOUND) 3 | 4 | set(LDD_ROOT "" CACHE PATH "Root of LDD compiled source tree.") 5 | 6 | #set(CUDD_ROOT ${LDD_ROOT}/cudd-2.4.2) 7 | set(CUDD_ROOT ${LDD_ROOT}) 8 | find_package (Cudd QUIET) 9 | 10 | find_path(LDD_INCLUDE_DIR NAMES ldd.h tvpi.h PATHS ${LDD_ROOT}/include/ldd) 11 | #find_path(LDD_INCLUDE_DIR NAMES ldd.h tvpi.h PATHS ${LDD_ROOT}/src/include) 12 | find_library(LDD_TVPI_LIBRARY NAMES tvpi PATHS ${LDD_ROOT}/lib) 13 | #find_library(LDD_TVPI_LIBRARY NAMES tvpi PATHS ${LDD_ROOT}/src/tvpi) 14 | find_library(LDD_LDD_LIBRARY NAMES ldd PATHS ${LDD_ROOT}/lib) 15 | #find_library(LDD_LDD_LIBRARY NAMES ldd PATHS ${LDD_ROOT}/src/ldd) 16 | 17 | set(LDD_LIBRARY ${LDD_LDD_LIBRARY} ${LDD_TVPI_LIBRARY}) 18 | include (FindPackageHandleStandardArgs) 19 | find_package_handle_standard_args(Ldd 20 | REQUIRED_VARS LDD_INCLUDE_DIR LDD_LIBRARY CUDD_FOUND) 21 | if (LDD_FOUND) 22 | set (LDD_CXXFLAGS "${CUDD_CXXFLAGS}") 23 | set(LDD_LIBRARY ${LDD_LIBRARY} ${CUDD_LIBRARY}) 24 | set (LDD_INCLUDE_DIR ${LDD_INCLUDE_DIR} ${CUDD_INCLUDE_DIR}) 25 | mark_as_advanced (LDD_INCLUDE_DIR LDD_TVPI_LIBRARY 26 | LDD_LDD_LIBRARY LDD_LIBRARY LDD_CXXFLAGS) 27 | endif () 28 | 29 | endif () 30 | -------------------------------------------------------------------------------- /cmake/FindPPLite.cmake: -------------------------------------------------------------------------------- 1 | # Find PPLite headers and libraries. 2 | # Author: Enea Zaffanella (enea.zaffanella@unipr.it) 3 | 4 | if (NOT PPLITE_FOUND) 5 | set(PPLITE_ROOT "" CACHE PATH "Path to PPLite install directory") 6 | 7 | set(PPLITE_INCLUDE_SEARCH_DIRS "") 8 | set(PPLITE_LIB_SEARCH_DIRS "") 9 | 10 | if (PPLITE_ROOT) 11 | list(APPEND PPLITE_INCLUDE_SEARCH_DIRS "${PPLITE_ROOT}/include/") 12 | list(APPEND PPLITE_LIB_SEARCH_DIRS "${PPLITE_ROOT}/lib") 13 | endif() 14 | 15 | find_package(GMP QUIET) 16 | find_package(GMPXX QUIET) 17 | find_package(FLINT QUIET) 18 | cmake_policy(SET CMP0074 NEW) 19 | 20 | find_path(PPLITE_INCLUDE_DIR 21 | NAMES pplite/pplite.hh 22 | HINTS ${PPLITE_INCLUDE_SEARCH_DIRS} 23 | DOC "Path to PPLite include directory" 24 | ) 25 | 26 | find_library(PPLITE_LIB 27 | NAMES pplite 28 | HINTS ${PPLITE_LIB_SEARCH_DIRS} 29 | DOC "Path to PPLite library" 30 | ) 31 | 32 | include(FindPackageHandleStandardArgs) 33 | find_package_handle_standard_args(PPLite 34 | REQUIRED_VARS 35 | PPLITE_INCLUDE_DIR 36 | PPLITE_LIB 37 | FLINT_FOUND 38 | GMPXX_FOUND 39 | GMP_FOUND 40 | FAIL_MESSAGE 41 | "Could NOT find PPLite. Please provide -DPPLITE_ROOT=/path/to/pplite") 42 | endif() 43 | 44 | set(PPLITE_INCLUDE_DIRS 45 | ${PPLITE_INCLUDE_DIR} 46 | ${FLINT_INCLUDE_DIR} 47 | ${GMPXX_INCLUDE_DIR} 48 | ${GMP_INCLUDE_DIR}) 49 | 50 | set(PPLITE_LIBRARY 51 | ${PPLITE_LIB} 52 | ${FLINT_LIB} 53 | ${GMPXX_LIB} 54 | ${GMP_LIB}) 55 | -------------------------------------------------------------------------------- /cmake/download_apron.cmake: -------------------------------------------------------------------------------- 1 | if (CRAB_USE_APRON) 2 | if (GIT_FOUND) 3 | 4 | if (CRAB_USE_PPLITE) 5 | SET(AP_PPLITE_OPTS -pplite-prefix ${PPLITE_ROOT} -flint-prefix ${FLINT_SEARCH_PATH}) 6 | else() 7 | SET(AP_PPLITE_OPTS -no-pplite) 8 | endif() 9 | 10 | ExternalProject_Add(apron 11 | GIT_REPOSITORY https://github.com/antoinemine/apron.git 12 | GIT_TAG e03832465bdca1888c56ecbe14dcdac0a243dce2 13 | INSTALL_DIR ${CMAKE_BINARY_DIR}/run/apron 14 | CONFIGURE_COMMAND 15 | ./configure -prefix -no-java -no-ocaml -no-ppl ${AP_PPLITE_OPTS} -gmp-prefix ${GMP_SEARCH_PATH} -mpfr-prefix ${MPFR_SEARCH_PATH} 16 | BUILD_IN_SOURCE 1 17 | BUILD_COMMAND make 18 | INSTALL_COMMAND make install 19 | LOG_CONFIGURE 1 20 | LOG_INSTALL 1 21 | LOG_BUILD 1) 22 | else () 23 | message (STATUS "Crab: could not find git. Not downloading apron") 24 | endif() 25 | endif() 26 | -------------------------------------------------------------------------------- /cmake/download_boxes_ldd.cmake: -------------------------------------------------------------------------------- 1 | if (CRAB_USE_LDD) 2 | if (GIT_FOUND) 3 | set (LDD_TAG "origin/master" CACHE STRING "ldd tag to use") 4 | set (LDD_REPO "https://github.com/seahorn/ldd.git" 5 | CACHE STRING "ldd repository") 6 | ExternalProject_Add(ldd 7 | GIT_REPOSITORY ${LDD_REPO} 8 | GIT_TAG ${LDD_TAG} 9 | PREFIX ${CMAKE_BINARY_DIR}/ldd 10 | INSTALL_DIR ${CMAKE_BINARY_DIR}/run/ldd 11 | CMAKE_ARGS 12 | -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} 13 | -DCMAKE_BUILD_TYPE:STRING=${EXT_CMAKE_BUILD_TYPE} 14 | -DCMAKE_INSTALL_PREFIX:PATH= 15 | # XXX: ldd is always compiled statically. 16 | # We add -fPIC flag so it can be linked with a shared library 17 | -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON 18 | TEST_AFTER_INSTALL 1 19 | TEST_COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_LIST_FILE} 20 | LOG_DOWNLOAD 1 21 | LOG_CONFIGURE 1 22 | LOG_BUILD 1 23 | LOG_INSTALL 1) 24 | else () 25 | message (STATUS "Crab: could not find git. Not downloading ldd") 26 | endif() 27 | endif () 28 | -------------------------------------------------------------------------------- /cmake/download_elina.cmake: -------------------------------------------------------------------------------- 1 | if (CRAB_USE_ELINA) 2 | if (GIT_FOUND) 3 | find_package(SSE) 4 | if (AVX_FOUND) 5 | set (IS_VECTOR "IS_VECTOR=-DVECTOR") 6 | else () 7 | if (SSE2_FOUND OR SSE3_FOUND OR SSSE3_FOUND OR SSE4_1_FOUND) 8 | set (IS_VECTOR "IS_VECTOR=-DVECTOR") 9 | set (IS_SSE "IS_SSE=-DSSE") 10 | message(WARNING "Crab: building elina oct with vectorized operations.") 11 | else () 12 | message(WARNING "Crab: building elina oct without vectorized operations.") 13 | endif () 14 | endif () 15 | 16 | set (ELINA_TAG "master" CACHE STRING "elina tag to use") 17 | ExternalProject_Add(elina 18 | GIT_REPOSITORY https://github.com/eth-sri/ELINA.git 19 | GIT_TAG ${ELINA_TAG} 20 | INSTALL_DIR ${CMAKE_BINARY_DIR}/run/elina 21 | CONFIGURE_COMMAND ./configure -prefix ${INSTALL_DIR} -use-vector -gmp-prefix ${GMP_SEARCH_PATH} -mpfr-prefix ${MPFR_SEARCH_PATH} 22 | BUILD_IN_SOURCE 1 23 | BUILD_COMMAND make CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${IS_VECTOR} ${IS_SSE} 24 | ELINA_PREFIX= GMP_PREFIX=${GMP_SEARCH_PATH} MPFR_PREFIX=${MPFR_SEARCH_PATH} 25 | INSTALL_COMMAND 26 | make ELINA_PREFIX= GMP_PREFIX=${GMP_SEARCH_PATH} MPFR_PREFIX=${MPFR_SEARCH_PATH} install 27 | LOG_CONFIGURE 1 28 | LOG_INSTALL 1 29 | LOG_BUILD 1) 30 | else () 31 | message (STATUS "Crab: could not find git. Not downloading elina") 32 | endif() 33 | endif() 34 | -------------------------------------------------------------------------------- /cmake/download_pplite.cmake: -------------------------------------------------------------------------------- 1 | if (CRAB_USE_PPLITE) 2 | ExternalProject_Add(pplite 3 | URL https://github.com/ezaffanella/PPLite/raw/main/releases/pplite-0.11.tar.gz 4 | INSTALL_DIR ${CMAKE_BINARY_DIR}/run/pplite 5 | CONFIGURE_COMMAND 6 | ../pplite/configure --prefix --with-gmp=${GMP_SEARCH_PATH} --with-flint=${FLINT_SEARCH_PATH} 7 | BUILD_IN_SOURCE 0 8 | BUILD_COMMAND make 9 | INSTALL_COMMAND make install 10 | LOG_CONFIGURE 1 11 | LOG_INSTALL 1 12 | LOG_BUILD 1) 13 | endif() 14 | -------------------------------------------------------------------------------- /docker/buildpack-deps-crab.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for building Crab dependencies for Ubuntu xenial and bionic. 3 | # 4 | # Arguments: 5 | # - UBUNTU: xenial, bionic 6 | # 7 | 8 | ARG UBUNTU 9 | 10 | # Pull base image. 11 | FROM buildpack-deps:$UBUNTU 12 | 13 | RUN apt-get update && \ 14 | apt-get install -yqq software-properties-common && \ 15 | add-apt-repository -y ppa:mhier/libboost-latest && \ 16 | apt-get update && \ 17 | apt-get install -yqq cmake cmake-data g++-6 \ 18 | ninja-build libstdc++6 \ 19 | libboost1.74-dev \ 20 | libgmp-dev libmpfr-dev libflint-dev \ 21 | lcov ggcov 22 | 23 | -------------------------------------------------------------------------------- /docker/buildpack-deps-crab.jammy.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for building Crab dependencies for Ubuntu 22.04 jammy 3 | # 4 | 5 | # Pull base image. 6 | FROM buildpack-deps:jammy 7 | 8 | RUN apt-get update && \ 9 | apt-get install -yqq software-properties-common && \ 10 | apt-get install -yqq build-essential && \ 11 | add-apt-repository -y ppa:mhier/libboost-latest && \ 12 | apt-get update && \ 13 | apt-get install -yqq cmake cmake-data \ 14 | ninja-build \ 15 | g++-12 \ 16 | libboost1.74-dev libboost-program-options1.74-dev \ 17 | libgmp-dev libmpfr-dev libflint-dev 18 | 19 | -------------------------------------------------------------------------------- /docker/crab.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image without external libraries. 3 | # 4 | # produces package in /crab/build 5 | # Arguments: 6 | # - UBUNTU: xenial, bionic (default) 7 | # - BUILD_TYPE: Debug, Release (default) 8 | # 9 | 10 | ARG UBUNTU 11 | 12 | # Pull base image. 13 | FROM seahorn/buildpack-deps-crab:$UBUNTU 14 | 15 | # Assume that docker-build is ran in the top-level Crab directory 16 | COPY . /crab 17 | # Re-create the build directory that might have been present in the source tree 18 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 19 | 20 | WORKDIR /crab/build 21 | 22 | ARG BUILD_TYPE 23 | # Build configuration. 24 | RUN cmake -GNinja \ 25 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 26 | -DCMAKE_INSTALL_PREFIX=run \ 27 | -DCMAKE_CXX_COMPILER=g++-6 \ 28 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 29 | -DCRAB_ENABLE_TESTS=ON \ 30 | ../ && \ 31 | cmake --build . --target install 32 | 33 | # Run tests 34 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.out /crab/build 35 | 36 | WORKDIR /crab 37 | 38 | -------------------------------------------------------------------------------- /docker/crab.apron.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image with apron and boxes libraries. 3 | # 4 | # produces package in /crab/build 5 | # Arguments: 6 | # - UBUNTU: xenial, bionic (default) 7 | # - BUILD_TYPE: Debug, Release (default) 8 | # 9 | 10 | ARG UBUNTU 11 | 12 | # Pull base image. 13 | FROM seahorn/buildpack-deps-crab:$UBUNTU 14 | 15 | # Assume that docker-build is ran in the top-level Crab directory 16 | COPY . /crab 17 | # Re-create the build directory that might have been present in the source tree 18 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 19 | WORKDIR /crab/build 20 | 21 | ARG BUILD_TYPE 22 | # Build configuration. 23 | RUN cmake -GNinja \ 24 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 25 | -DCMAKE_INSTALL_PREFIX=run \ 26 | -DCMAKE_CXX_COMPILER=g++-6 \ 27 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 28 | -DCRAB_USE_LDD=ON \ 29 | -DCRAB_USE_APRON=ON \ 30 | -DCRAB_ENABLE_TESTS=ON \ 31 | ../ && \ 32 | cmake --build . --target ldd && cmake .. && \ 33 | cmake --build . --target apron && cmake .. && \ 34 | cmake --build . --target install 35 | 36 | # Run tests 37 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.apron.out /crab/build 38 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.boxes.out /crab/build 39 | 40 | WORKDIR /crab 41 | 42 | -------------------------------------------------------------------------------- /docker/crab.dev.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image without external libraries. 3 | # 4 | # Pull base image. 5 | FROM seahorn/buildpack-deps-crab:jammy 6 | 7 | # Assume that docker-build is ran in the top-level Crab directory 8 | COPY . /crab 9 | # Re-create the build directory that might have been present in the source tree 10 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 11 | 12 | WORKDIR /crab/build 13 | 14 | ARG BUILD_TYPE 15 | # Build configuration. 16 | RUN cmake -GNinja \ 17 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 18 | -DCMAKE_INSTALL_PREFIX=run \ 19 | -DCMAKE_CXX_COMPILER=g++-12 \ 20 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 21 | -DCRAB_ENABLE_TESTS=ON \ 22 | ../ && \ 23 | cmake --build . --target install 24 | 25 | # Run tests 26 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.out /crab/build 27 | 28 | WORKDIR /crab 29 | 30 | -------------------------------------------------------------------------------- /docker/crab.dev.apron.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image with apron and boxes libraries. 3 | # 4 | 5 | # Pull base image. 6 | FROM seahorn/buildpack-deps-crab:jammy 7 | 8 | # Assume that docker-build is ran in the top-level Crab directory 9 | COPY . /crab 10 | # Re-create the build directory that might have been present in the source tree 11 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 12 | WORKDIR /crab/build 13 | 14 | ARG BUILD_TYPE 15 | # Build configuration. 16 | RUN cmake -GNinja \ 17 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 18 | -DCMAKE_INSTALL_PREFIX=run \ 19 | -DCMAKE_CXX_COMPILER=g++-12 \ 20 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 21 | -DCRAB_USE_LDD=ON \ 22 | -DCRAB_USE_APRON=ON \ 23 | -DCRAB_ENABLE_TESTS=ON \ 24 | ../ && \ 25 | cmake --build . --target ldd && cmake .. && \ 26 | cmake --build . --target apron && cmake .. && \ 27 | cmake --build . --target install 28 | 29 | # Run tests 30 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.apron.out /crab/build 31 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.boxes.out /crab/build 32 | 33 | WORKDIR /crab 34 | 35 | -------------------------------------------------------------------------------- /docker/crab.dev.elina.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image with elina library. 3 | # 4 | 5 | # Pull base image. 6 | FROM seahorn/buildpack-deps-crab:jammy 7 | 8 | # Assume that docker-build is ran in the top-level Crab directory 9 | COPY . /crab 10 | # Re-create the build directory that might have been present in the source tree 11 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 12 | WORKDIR /crab/build 13 | 14 | ARG BUILD_TYPE 15 | # Build configuration. 16 | RUN cmake -GNinja \ 17 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 18 | -DCMAKE_INSTALL_PREFIX=run \ 19 | -DCMAKE_CXX_COMPILER=g++-12 \ 20 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 21 | -DCRAB_USE_ELINA=ON \ 22 | -DCRAB_ENABLE_TESTS=ON \ 23 | ../ && \ 24 | cmake --build . --target elina && cmake .. && \ 25 | cmake --build . --target install 26 | 27 | # To find elina dynamic libraries 28 | ENV LD_LIBRARY_PATH "/crab/build/run/elina/lib:$LD_LIBRARY_PATH" 29 | 30 | # Run tests 31 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.elina.out /crab/build 32 | 33 | WORKDIR /crab 34 | 35 | -------------------------------------------------------------------------------- /docker/crab.dev.pplite.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image with pplite library. 3 | # 4 | 5 | # Pull base image. 6 | FROM seahorn/buildpack-deps-crab:jammy 7 | 8 | # Assume that docker-build is ran in the top-level Crab directory 9 | COPY . /crab 10 | # Re-create the build directory that might have been present in the source tree 11 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 12 | WORKDIR /crab/build 13 | 14 | ARG BUILD_TYPE 15 | # Build configuration. 16 | RUN cmake -GNinja \ 17 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 18 | -DCMAKE_INSTALL_PREFIX=run \ 19 | -DCMAKE_CXX_COMPILER=g++-12 \ 20 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 21 | -DCRAB_USE_APRON=ON -DCRAB_USE_PPLITE=ON \ 22 | -DCRAB_ENABLE_TESTS=ON \ 23 | ../ && \ 24 | cmake --build . --target apron && cmake .. && \ 25 | cmake --build . --target pplite && cmake .. && \ 26 | cmake --build . --target pplite_domains 27 | 28 | # Run tests 29 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.pplite.out /crab/build 30 | 31 | WORKDIR /crab 32 | 33 | -------------------------------------------------------------------------------- /docker/crab.elina.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image with elina library. 3 | # 4 | # produces package in /crab/build 5 | # Arguments: 6 | # - UBUNTU: xenial, bionic (default) 7 | # - BUILD_TYPE: Debug, Release (default) 8 | # - BRANCH: master (default) 9 | # 10 | 11 | ARG UBUNTU 12 | 13 | # Pull base image. 14 | FROM seahorn/buildpack-deps-crab:$UBUNTU 15 | 16 | # Assume that docker-build is ran in the top-level Crab directory 17 | COPY . /crab 18 | # Re-create the build directory that might have been present in the source tree 19 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 20 | WORKDIR /crab/build 21 | 22 | ARG BUILD_TYPE 23 | # Build configuration. 24 | RUN cmake -GNinja \ 25 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 26 | -DCMAKE_INSTALL_PREFIX=run \ 27 | -DCMAKE_CXX_COMPILER=g++-6 \ 28 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 29 | -DCRAB_USE_ELINA=ON \ 30 | -DCRAB_ENABLE_TESTS=ON \ 31 | ../ && \ 32 | cmake --build . --target elina && cmake .. && \ 33 | cmake --build . --target install 34 | 35 | # To find elina dynamic libraries 36 | ENV LD_LIBRARY_PATH "/crab/build/run/elina/lib:$LD_LIBRARY_PATH" 37 | 38 | # Run tests 39 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.elina.out /crab/build 40 | 41 | WORKDIR /crab 42 | 43 | -------------------------------------------------------------------------------- /docker/crab.pplite.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile for Crab image with pplite library. 3 | # 4 | # produces package in /crab/build 5 | # Arguments: 6 | # - UBUNTU: xenial, bionic (default) 7 | # - BUILD_TYPE: Debug, Release (default) 8 | # 9 | 10 | ARG UBUNTU 11 | 12 | # Pull base image. 13 | FROM seahorn/buildpack-deps-crab:$UBUNTU 14 | 15 | # Assume that docker-build is ran in the top-level Crab directory 16 | COPY . /crab 17 | # Re-create the build directory that might have been present in the source tree 18 | RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build 19 | WORKDIR /crab/build 20 | 21 | ARG BUILD_TYPE 22 | # Build configuration. 23 | RUN cmake -GNinja \ 24 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 25 | -DCMAKE_INSTALL_PREFIX=run \ 26 | -DCMAKE_CXX_COMPILER=g++-6 \ 27 | -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ 28 | -DCRAB_USE_APRON=ON -DCRAB_USE_PPLITE=ON \ 29 | -DCRAB_ENABLE_TESTS=ON \ 30 | ../ && \ 31 | cmake --build . --target apron && cmake .. && \ 32 | cmake --build . --target pplite && cmake .. && \ 33 | cmake --build . --target pplite_domains 34 | 35 | # Run tests 36 | RUN /crab/tests/run_tests.sh /crab/tests/expected_results.pplite.out /crab/build 37 | 38 | WORKDIR /crab 39 | 40 | -------------------------------------------------------------------------------- /docker/readme.md: -------------------------------------------------------------------------------- 1 | # Building Docker image for Crab dependencies # 2 | 3 | 4 | ```shell 5 | $ docker build -t seahorn/buildpack-deps-crab:bionic -f docker/buildpack-deps-crab.Dockerfile . 6 | $ docker push seahorn/buildpack-deps-crab:bionic 7 | ``` 8 | or 9 | 10 | ```shell 11 | $ docker build -t seahorn/buildpack-deps-crab:bionic -f docker/buildpack-deps-crab.jammy.Dockerfile . 12 | $ docker push seahorn/buildpack-deps-crab:jammy 13 | ``` 14 | 15 | # Building Docker image for Crab and running tests # 16 | 17 | ```shell 18 | docker build --build-arg BUILD_TYPE=Release -t seahorn/crab -f docker/crab.Dockerfile . 19 | docker run -v `pwd`:/host -it seahorn/crab:latest 20 | ``` 21 | 22 | This will automatically download all dependencies from a base image 23 | and build Crab under `/crab/build`. 24 | 25 | Crab's install directory is added to `PATH`. 26 | 27 | Build arguments (required): 28 | - BUILD_TYPE: Release, Debug 29 | 30 | -------------------------------------------------------------------------------- /include/crab/analysis/fwd_bwd_params.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace crab { 4 | namespace analyzer { 5 | 6 | /** 7 | * Class to group together all the parameters of the iterative 8 | * forward-backward analyzer 9 | **/ 10 | class fwd_bwd_parameters { 11 | // If false, then it behaves like a standard forward analyzer 12 | bool enabled_backward; 13 | // Maximum number of refinement iterations (if enabled_backward=true) 14 | unsigned max_refine_iterations; 15 | // If disabled the iterative forward-backward analyzer produces the 16 | // same invariants than a classical forward analyzer. The difference 17 | // is that it might prove more assertions. 18 | bool use_refined_invariants; 19 | 20 | public: 21 | 22 | fwd_bwd_parameters(): 23 | enabled_backward(false), 24 | max_refine_iterations(5), 25 | use_refined_invariants(false) {} 26 | 27 | bool is_enabled_backward() const { return enabled_backward; } 28 | bool& enable_backward() { return enabled_backward; } 29 | 30 | unsigned get_max_refine_iterations() const { return max_refine_iterations; } 31 | unsigned& get_max_refine_iterations() { return max_refine_iterations; } 32 | 33 | bool get_use_refined_invariants() const { return use_refined_invariants; } 34 | bool& get_use_refined_invariants() { return use_refined_invariants; } 35 | }; 36 | 37 | } // end namespace analyzer 38 | } // end namespace crab 39 | -------------------------------------------------------------------------------- /include/crab/analysis/graphs/cdg.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | //#include 5 | /* 6 | 7 | Node y is control-dependent on x if y does NOT post-dominate x but 8 | there exists a path from x to y such that all nodes in the path 9 | (different from x and y) are post-dominated by y. 10 | 11 | */ 12 | namespace crab { 13 | namespace analyzer { 14 | namespace graph_algo { 15 | 16 | // OUT: cdeps is a map from nodes to a set of nodes that 17 | // control-dependent on it. 18 | template 19 | void control_dep_graph(G g, VectorMap &cdg) { 20 | VectorMap pdf; 21 | using basic_block_t = typename G::basic_block_t; 22 | crab::analyzer::graph_algo::post_dominance(g, pdf); 23 | 24 | for (auto &kv : pdf) { 25 | for (auto v : kv.second) { 26 | auto &cdeps = cdg[v]; 27 | if (std::find(cdeps.begin(), cdeps.end(), kv.first) == cdeps.end()) { 28 | cdeps.push_back(kv.first); 29 | } 30 | } 31 | } 32 | 33 | CRAB_LOG("cdg", crab::outs() << "Control-dependence graph \n"; for (auto &kv 34 | : cdg) { 35 | crab::outs() << "{"; 36 | for (auto v : kv.second) { 37 | crab::outs() << crab::basic_block_traits::to_string(v) 38 | << ";"; 39 | } 40 | crab::outs() << "} " 41 | << " control-dependent on "; 42 | crab::outs() << crab::basic_block_traits::to_string(kv.first) 43 | << "\n"; 44 | }); 45 | } 46 | 47 | } // namespace graph_algo 48 | } // namespace analyzer 49 | } // namespace crab 50 | -------------------------------------------------------------------------------- /include/crab/analysis/graphs/topo_order.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | /* 12 | Topological order of a graph 13 | */ 14 | 15 | namespace crab { 16 | namespace analyzer { 17 | namespace graph_algo { 18 | 19 | // res contains the reverse topological order of a graph g 20 | // pre: g is a DAG. 21 | template 22 | void rev_topo_sort(const G &g, std::vector &res) { 23 | 24 | using color_map_t = 25 | std::unordered_map; 26 | using property_color_map_t = boost::associative_property_map; 27 | 28 | color_map_t colormap; 29 | 30 | for (auto const &v : boost::make_iterator_range(vertices(g))) { 31 | colormap[v] = boost::default_color_type(); 32 | } 33 | 34 | res.reserve(num_vertices(g)); 35 | 36 | boost::topological_sort(g, std::back_inserter(res), 37 | color_map(property_color_map_t(colormap))); 38 | } 39 | 40 | // res contains the topological order of g. 41 | // pre: g is a DAG. 42 | template 43 | void topo_sort(const G &g, std::vector &res) { 44 | rev_topo_sort(g, res); 45 | std::reverse(res.begin(), res.end()); 46 | } 47 | 48 | // return the reversed topological order of g with possibly cycles. 49 | // XXX: related concept but this is not Bourdoncle's WTO 50 | template std::vector weak_rev_topo_sort(G g) { 51 | std::vector sccg_order; 52 | scc_graph scc_g(g, false /*postorder within scc*/); 53 | rev_topo_sort(scc_g, sccg_order); 54 | std::vector order; 55 | for (auto &n : sccg_order) { 56 | auto &members = scc_g.get_component_members(n); 57 | order.insert(order.end(), members.begin(), members.end()); 58 | } 59 | return order; 60 | } 61 | 62 | // return the topological order of g with possibly cycles. 63 | // XXX: related concept but this is not Bourdoncle's WTO 64 | template std::vector weak_topo_sort(G g) { 65 | std::vector sccg_order; 66 | scc_graph scc_g(g, true /*preorder within scc*/); 67 | topo_sort(scc_g, sccg_order); 68 | std::vector order; 69 | for (auto &n : sccg_order) { 70 | auto &members = scc_g.get_component_members(n); 71 | order.insert(order.end(), members.begin(), members.end()); 72 | } 73 | return order; 74 | } 75 | 76 | } // end namespace graph_algo 77 | } // end namespace analyzer 78 | } // end namespace crab 79 | -------------------------------------------------------------------------------- /include/crab/analysis/inter/inter_params.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace crab { 8 | namespace analyzer { 9 | 10 | /* Parameters for the inter-procedural analyses */ 11 | template 12 | struct inter_analyzer_parameters { 13 | using cg_node_t = typename CallGraph::node_t; 14 | using cfg_t = typename cg_node_t::cfg_t; 15 | using liveness_t = live_and_dead_analysis; 16 | using liveness_map_t = std::unordered_map; 17 | 18 | inter_analyzer_parameters() 19 | : only_main_as_entry(false), widening_delay(2), 20 | descending_iters(2 /*UINT_MAX*/), thresholds_size(20 /*0*/), 21 | live_map(nullptr), 22 | run_checker(true), checker_verbosity(0), keep_cc_invariants(false), 23 | keep_invariants(true), max_call_contexts(UINT_MAX), 24 | analyze_recursive_functions(false), exact_summary_reuse(true) {} 25 | 26 | // Start the analysis from main 27 | bool only_main_as_entry; 28 | // Fixpoint parameters 29 | unsigned int widening_delay; 30 | unsigned int descending_iters; 31 | unsigned int thresholds_size; 32 | // Use liveness symbols if already available 33 | const liveness_map_t *live_map; 34 | 35 | // -- Begin parameters for top-down analysis -- // 36 | // whether interleave analysis with checking 37 | bool run_checker; 38 | unsigned checker_verbosity; 39 | // whether keep context-sensitive invariants 40 | bool keep_cc_invariants; 41 | // whether keep context-insensitive invariants 42 | bool keep_invariants; 43 | // maximum number of calling contexts per callsite 44 | unsigned int max_call_contexts; 45 | // analyze precisely recursive functions 46 | bool analyze_recursive_functions; 47 | // reuse summaries without losing precision 48 | bool exact_summary_reuse; 49 | // -- End parameters for top-down analysis -- // 50 | 51 | }; 52 | 53 | } // namespace analyzer 54 | } // namespace crab 55 | -------------------------------------------------------------------------------- /include/crab/analysis/inter/top_down_inter_params.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "inter_params.hpp" 3 | /* DEPRECATED: use inter_analyzer_parameters instead */ 4 | 5 | namespace crab { 6 | namespace analyzer { 7 | template 8 | using top_down_inter_analyzer_parameters = inter_analyzer_parameters; 9 | } // namespace analyzer 10 | } // namespace crab 11 | -------------------------------------------------------------------------------- /include/crab/cfg/basic_block_traits.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace crab { 6 | 7 | template class basic_block_traits { 8 | public: 9 | using basic_block_label_t = typename BasicBlock::basic_block_label_t; 10 | static std::string to_string(const basic_block_label_t &bb); 11 | }; 12 | 13 | } // namespace crab 14 | -------------------------------------------------------------------------------- /include/crab/cfg/cfg_operators.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace crab { 7 | namespace cfg { 8 | 9 | // To group together statements over integers or real 10 | typedef enum { 11 | BINOP_ADD, 12 | BINOP_SUB, 13 | BINOP_MUL, 14 | BINOP_SDIV, 15 | BINOP_UDIV, 16 | BINOP_SREM, 17 | BINOP_UREM, 18 | BINOP_AND, 19 | BINOP_OR, 20 | BINOP_XOR, 21 | BINOP_SHL, 22 | BINOP_LSHR, 23 | BINOP_ASHR, 24 | } binary_operation_t; 25 | 26 | typedef enum { BINOP_BAND, BINOP_BOR, BINOP_BXOR } bool_binary_operation_t; 27 | 28 | typedef enum { CAST_TRUNC, CAST_SEXT, CAST_ZEXT } cast_operation_t; 29 | 30 | inline crab::crab_os &operator<<(crab::crab_os &o, binary_operation_t op) { 31 | switch (op) { 32 | case BINOP_ADD: 33 | o << "+"; 34 | break; 35 | case BINOP_SUB: 36 | o << "-"; 37 | break; 38 | case BINOP_MUL: 39 | o << "*"; 40 | break; 41 | case BINOP_SDIV: 42 | o << "/"; 43 | break; 44 | case BINOP_UDIV: 45 | o << "/_u"; 46 | break; 47 | case BINOP_SREM: 48 | o << "%"; 49 | break; 50 | case BINOP_UREM: 51 | o << "%_u"; 52 | break; 53 | case BINOP_AND: 54 | o << "&"; 55 | break; 56 | case BINOP_OR: 57 | o << "|"; 58 | break; 59 | case BINOP_XOR: 60 | o << "^"; 61 | break; 62 | case BINOP_SHL: 63 | o << "<<"; 64 | break; 65 | case BINOP_LSHR: 66 | o << ">>_l"; 67 | break; 68 | case BINOP_ASHR: 69 | o << ">>_r"; 70 | break; 71 | // Clang complains switch already covers all values 72 | // default: 73 | // CRAB_ERROR("unexpected binary operation ", op); 74 | } 75 | return o; 76 | } 77 | 78 | inline crab::crab_os &operator<<(crab::crab_os &o, bool_binary_operation_t op) { 79 | switch (op) { 80 | case BINOP_BAND: 81 | o << "&"; 82 | break; 83 | case BINOP_BOR: 84 | o << "|"; 85 | break; 86 | case BINOP_BXOR: 87 | o << "^"; 88 | break; 89 | // Clang complains switch already covers all values 90 | //default: 91 | //CRAB_ERROR("unexpected boolean binary operation ", op); 92 | } 93 | return o; 94 | } 95 | 96 | inline crab::crab_os &operator<<(crab::crab_os &o, cast_operation_t op) { 97 | switch (op) { 98 | case CAST_TRUNC: 99 | o << "trunc"; 100 | break; 101 | case CAST_SEXT: 102 | o << "sext"; 103 | break; 104 | case CAST_ZEXT: 105 | o << "zext"; 106 | break; 107 | // Clang complains switch already covers all values 108 | //default: 109 | //CRAB_ERROR("unexpected cast operation", op); 110 | } 111 | return o; 112 | } 113 | 114 | } // end namespace cfg 115 | } // end namespace crab 116 | -------------------------------------------------------------------------------- /include/crab/config.h.cmake: -------------------------------------------------------------------------------- 1 | #ifndef _CRAB_CONFIG_H_ 2 | #define _CRAB_CONFIG_H_ 3 | 4 | /** Define whether lin-ldd is available */ 5 | #cmakedefine HAVE_LDD ${HAVE_LDD} 6 | 7 | /** Define whether apron library is available */ 8 | #cmakedefine HAVE_APRON ${HAVE_APRON} 9 | 10 | /** Define whether pplite library is available */ 11 | #cmakedefine HAVE_PPLITE ${HAVE_PPLITE} 12 | 13 | /** Define whether elina library is available */ 14 | #cmakedefine HAVE_ELINA ${HAVE_ELINA} 15 | 16 | /** Define whether disable logging for debugging purposes */ 17 | #cmakedefine NCRABLOG ${NCRABLOG} 18 | 19 | /** Define whether collecting statistics */ 20 | #cmakedefine CRAB_STATS ${CRAB_STATS} 21 | 22 | /** Use a generic wrapper for abstract domains in tests **/ 23 | #cmakedefine USE_GENERIC_WRAPPER ${USE_GENERIC_WRAPPER} 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/crab/domains/abstract_domain_operators.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* Types for abstract domain operations */ 6 | 7 | namespace crab { 8 | namespace domains { 9 | 10 | // Enumeration type for basic arithmetic operations 11 | // Do not modify the order. 12 | typedef enum { 13 | OP_ADDITION, 14 | OP_SUBTRACTION, 15 | OP_MULTIPLICATION, 16 | OP_SDIV, 17 | OP_UDIV, 18 | OP_SREM, 19 | OP_UREM 20 | } arith_operation_t; 21 | 22 | inline crab::crab_os &operator<<(crab::crab_os &o, arith_operation_t op) { 23 | switch (op) { 24 | case OP_ADDITION: 25 | o << "+"; 26 | break; 27 | case OP_SUBTRACTION: 28 | o << "-"; 29 | break; 30 | case OP_MULTIPLICATION: 31 | o << "*"; 32 | break; 33 | case OP_SDIV: 34 | o << "/"; 35 | break; 36 | case OP_UDIV: 37 | o << "/_u"; 38 | break; 39 | case OP_SREM: 40 | o << "%"; 41 | break; 42 | default: 43 | o << "%_u"; 44 | break; 45 | } 46 | return o; 47 | } 48 | 49 | // Enumeration type for bitwise operations 50 | typedef enum { 51 | OP_AND, 52 | OP_OR, 53 | OP_XOR, 54 | OP_SHL, 55 | OP_LSHR, 56 | OP_ASHR 57 | } bitwise_operation_t; 58 | 59 | inline crab::crab_os &operator<<(crab::crab_os &o, bitwise_operation_t op) { 60 | switch (op) { 61 | case OP_AND: 62 | o << "&"; 63 | break; 64 | case OP_OR: 65 | o << "|"; 66 | break; 67 | case OP_XOR: 68 | o << "^"; 69 | break; 70 | case OP_SHL: 71 | o << "<<"; 72 | break; 73 | case OP_LSHR: 74 | o << ">>_l"; 75 | break; 76 | default: 77 | o << ">>_a"; 78 | break; 79 | } 80 | return o; 81 | } 82 | 83 | // Enumeration type for cast operations 84 | typedef enum { OP_TRUNC, OP_SEXT, OP_ZEXT } int_conv_operation_t; 85 | 86 | inline crab::crab_os &operator<<(crab::crab_os &o, int_conv_operation_t op) { 87 | switch (op) { 88 | case OP_TRUNC: 89 | o << "trunc"; 90 | break; 91 | case OP_SEXT: 92 | o << "sext"; 93 | break; 94 | default: /*OP_ZEXT*/ 95 | o << "zext"; 96 | break; 97 | } 98 | return o; 99 | } 100 | 101 | // Enumeration types for boolean operations 102 | typedef enum { OP_BAND, OP_BOR, OP_BXOR } bool_operation_t; 103 | 104 | inline crab::crab_os &operator<<(crab::crab_os &o, bool_operation_t op) { 105 | switch (op) { 106 | case OP_BAND: 107 | o << "&"; 108 | break; 109 | case OP_BOR: 110 | o << "|"; 111 | break; 112 | default: /*OP_BXOR*/ 113 | o << "^"; 114 | break; 115 | } 116 | return o; 117 | } 118 | } // end namespace domains 119 | } // end namespace crab 120 | -------------------------------------------------------------------------------- /include/crab/domains/apron/apron.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ap_global0.h" 4 | #include "box.h" 5 | #include "oct.h" 6 | #include "pk.h" 7 | #include "pkeq.h" 8 | 9 | #ifdef HAVE_PPLITE 10 | #include "ap_pplite.h" 11 | #endif 12 | 13 | #include 14 | 15 | namespace crab { 16 | 17 | namespace domains { 18 | 19 | namespace apron { 20 | 21 | using ap_state = ap_abstract0_t *; 22 | using ap_state_ptr = std::shared_ptr; 23 | 24 | /** Custom deleter for ap_state_ptr */ 25 | class ap_state_deleter { 26 | private: 27 | ap_manager_t *man; 28 | 29 | public: 30 | ap_state_deleter(ap_manager_t *_m) : man(_m) {} 31 | 32 | void operator()(ap_state s) { 33 | if (s) 34 | ap_abstract0_free(man, s); 35 | } 36 | 37 | // ap_manager_t** getManager () const { return man; } 38 | }; 39 | 40 | /** Create a ap_state_ptr from ap_state */ 41 | inline ap_state_ptr apPtr(ap_manager_t *_m, ap_state _s) { 42 | if (_s) { 43 | ap_state_ptr p(_s, ap_state_deleter(_m)); 44 | return p; 45 | } 46 | CRAB_ERROR("apPtr is taking a null pointer!"); 47 | // return ap_state_ptr(); 48 | } 49 | } // namespace apron 50 | } // namespace domains 51 | } // namespace crab 52 | -------------------------------------------------------------------------------- /include/crab/domains/boolean.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* A 3-valued boolean value */ 4 | 5 | #include 6 | #include 7 | 8 | namespace crab { 9 | namespace domains { 10 | 11 | class boolean_value: public lattice_domain_api { 12 | /* 13 | Top 14 | / \ 15 | / \ 16 | True False 17 | \ / 18 | \ / 19 | Bottom 20 | */ 21 | using kind_t = enum { False = 0x0, True = 0x1, Bottom = 0x2, Top = 0x3 }; 22 | 23 | kind_t _value; 24 | 25 | boolean_value(kind_t v); 26 | 27 | public: 28 | boolean_value(); 29 | 30 | static boolean_value bottom(); 31 | 32 | static boolean_value top(); 33 | 34 | boolean_value make_top() const override; 35 | 36 | boolean_value make_bottom() const override; 37 | 38 | void set_to_top() override; 39 | 40 | void set_to_bottom() override; 41 | 42 | static boolean_value get_true(); 43 | 44 | static boolean_value get_false(); 45 | 46 | boolean_value(const boolean_value &other); 47 | 48 | boolean_value &operator=(const boolean_value &other); 49 | 50 | bool is_bottom() const override; 51 | 52 | bool is_top() const override; 53 | 54 | bool is_true() const; 55 | 56 | bool is_false() const; 57 | 58 | bool operator<=(const boolean_value &other) const override; 59 | 60 | bool operator==(const boolean_value &other) const; 61 | 62 | void operator|=(const boolean_value &other) override; 63 | 64 | boolean_value operator|(const boolean_value &other) const override; 65 | 66 | boolean_value operator&(const boolean_value &other) const override; 67 | 68 | // the lattice satisfy ACC so join is the widening 69 | boolean_value operator||(const boolean_value &other) const override; 70 | 71 | // the lattice satisfy DCC so meet is the narrowing 72 | boolean_value operator&&(const boolean_value &other) const override; 73 | 74 | boolean_value And(boolean_value other) const; 75 | 76 | boolean_value Or(boolean_value other) const; 77 | 78 | boolean_value Xor(boolean_value other) const; 79 | 80 | boolean_value Negate() const; 81 | 82 | void write(crab_os &o) const override; 83 | 84 | std::string domain_name() const override; 85 | }; // end class boolean_value 86 | 87 | inline crab_os &operator<<(crab_os &o, const boolean_value &v) { 88 | v.write(o); 89 | return o; 90 | } 91 | 92 | } //end namespace domains 93 | } //end namespace crab 94 | -------------------------------------------------------------------------------- /include/crab/domains/constant.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace crab { 9 | namespace domains { 10 | 11 | template class constant { 12 | using constant_t = constant; 13 | 14 | boost::optional m_constant; 15 | bool m_is_bottom; 16 | 17 | constant(bool is_bottom); 18 | 19 | public: 20 | constant(Number c); 21 | 22 | static constant_t bottom(); 23 | static constant_t top(); 24 | static constant_t zero(); 25 | 26 | bool is_bottom() const; 27 | bool is_top() const; 28 | 29 | bool is_constant() const; 30 | Number get_constant() const; 31 | 32 | /** lattice operations **/ 33 | bool operator<=(const constant_t &o) const; 34 | bool operator==(const constant_t &o) const; 35 | constant_t operator|(const constant_t &o) const; 36 | constant_t operator||(const constant_t &o) const; 37 | template 38 | constant_t widening_thresholds(const constant_t &o, 39 | const Thresholds &ts /*unused*/) const { 40 | return *this | o; 41 | } 42 | constant_t operator&(const constant_t &o) const; 43 | constant_t operator&&(const constant_t &o) const; 44 | 45 | /** arithmetic operations **/ 46 | constant_t Add(const constant_t &o) const; 47 | constant_t Sub(const constant_t &o) const; 48 | constant_t Mul(const constant_t &o) const; 49 | constant_t SDiv(const constant_t &o) const; 50 | constant_t SRem(const constant_t &o) const; 51 | constant_t UDiv(const constant_t &o) const; 52 | constant_t URem(const constant_t &o) const; 53 | 54 | /** bitwise operations **/ 55 | constant_t BitwiseAnd(const constant_t &o) const; 56 | constant_t BitwiseOr(const constant_t &o) const; 57 | constant_t BitwiseXor(const constant_t &o) const; 58 | constant_t BitwiseShl(const constant_t &o) const; 59 | constant_t BitwiseLShr(const constant_t &o) const; 60 | constant_t BitwiseAShr(const constant_t &o) const; 61 | 62 | void write(crab::crab_os &o) const; 63 | friend crab_os &operator<<(crab_os &o, const constant_t &c) { 64 | c.write(o); 65 | return o; 66 | } 67 | }; 68 | 69 | } // namespace domains 70 | } // namespace crab 71 | -------------------------------------------------------------------------------- /include/crab/domains/elina/elina.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma GCC diagnostic push 4 | #pragma GCC diagnostic ignored "-Wunused-function" 5 | #include "elina_abstract0.h" 6 | #include "elina_coeff.h" 7 | #include "elina_dimension.h" 8 | #include "elina_interval.h" 9 | #include "elina_lincons0.h" 10 | #include "elina_linexpr0.h" 11 | #include "elina_manager.h" 12 | #include "elina_scalar.h" 13 | #include "elina_tcons0.h" 14 | #include "elina_texpr0.h" 15 | #include "opt_oct.h" 16 | #include "opt_pk.h" 17 | #include "opt_zones.h" 18 | #pragma GCC diagnostic pop 19 | 20 | #include 21 | 22 | namespace crab { 23 | namespace domains { 24 | namespace elina { 25 | 26 | using elina_state = elina_abstract0_t *; 27 | using elina_state_ptr = boost::shared_ptr; 28 | 29 | /** Custom deleter for elina_state_ptr */ 30 | class elina_state_deleter { 31 | private: 32 | elina_manager_t *man; 33 | 34 | public: 35 | elina_state_deleter(elina_manager_t *_m) : man(_m) {} 36 | 37 | void operator()(elina_state s) { 38 | if (s) 39 | elina_abstract0_free(man, s); 40 | } 41 | }; 42 | 43 | /** Create a elina_state_ptr from elina_state */ 44 | inline elina_state_ptr elinaPtr(elina_manager_t *_m, elina_state _s) { 45 | if (_s) { 46 | elina_state_ptr p(_s, elina_state_deleter(_m)); 47 | return p; 48 | } 49 | CRAB_ERROR("elinaPtr is taking a null pointer!"); 50 | } 51 | 52 | } // namespace elina 53 | } // namespace domains 54 | } // namespace crab 55 | -------------------------------------------------------------------------------- /include/crab/domains/graphs/util/reference_wrapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace crab { 4 | // This is pretty similar to std::reference_wrapper but it allows 5 | // default constructor. 6 | template class reference_wrapper { 7 | public: 8 | using type = reference_wrapper; 9 | 10 | reference_wrapper(): m_p(nullptr) {} 11 | reference_wrapper(T &p): m_p(&p) {} 12 | 13 | reference_wrapper(const type &other) = default; 14 | type &operator=(const type &other) = default; 15 | reference_wrapper(type &&other) = default; 16 | type &operator=(type &&other) = default; 17 | 18 | T& get() const { 19 | assert(m_p); 20 | return *m_p; 21 | } 22 | private: 23 | T* m_p; 24 | }; 25 | } // end namespace 26 | -------------------------------------------------------------------------------- /include/crab/domains/lattice_domain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace crab { 7 | namespace domains { 8 | template 9 | class lattice_domain_api { 10 | public: 11 | virtual ~lattice_domain_api() {} 12 | virtual LatticeDomain make_top() const = 0; 13 | virtual LatticeDomain make_bottom() const = 0; 14 | virtual void set_to_top() = 0; 15 | virtual void set_to_bottom() = 0; 16 | virtual bool is_top() const = 0; 17 | virtual bool is_bottom() const = 0; 18 | virtual bool operator<=(const LatticeDomain &other) const = 0; 19 | virtual void operator|=(const LatticeDomain &other) = 0; 20 | virtual LatticeDomain operator|(const LatticeDomain &other) const = 0; 21 | virtual LatticeDomain operator||(const LatticeDomain &other) const = 0; 22 | virtual LatticeDomain operator&(const LatticeDomain &other) const = 0; 23 | virtual LatticeDomain operator&&(const LatticeDomain &other) const = 0; 24 | virtual void write(crab::crab_os &o) const = 0; 25 | virtual std::string domain_name() const = 0; 26 | }; 27 | } // end namespace domains 28 | } // end namespace crab 29 | -------------------------------------------------------------------------------- /include/crab/domains/region/region_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace crab { 9 | namespace domains { 10 | namespace region_domain_impl { 11 | 12 | /* This class contains any non-relational information about region 13 | variables */ 14 | class region_info { 15 | // Simple reduced product of (SmallRange x Boolean x Type) 16 | using product_t = 17 | basic_domain_product2>; 19 | 20 | product_t m_product; 21 | region_info(product_t &&product); 22 | 23 | public: 24 | region_info(); 25 | region_info(small_range count, boolean_value init, type_value type); 26 | region_info(const region_info &other) = default; 27 | region_info(region_info &&other) = default; 28 | region_info &operator=(const region_info &other) = default; 29 | region_info &operator=(region_info &&other) = default; 30 | 31 | static region_info bottom(); 32 | static region_info top(); 33 | bool is_bottom() const; 34 | bool is_top() const; 35 | 36 | // Number of references that may point to the region. 37 | small_range &refcount_val(); 38 | // Whether the region has been initialized. 39 | boolean_value &init_val(); 40 | // Type of the region. The type of a region is always known 41 | // statically except if its type is unknown. 42 | type_value &type_val(); 43 | const small_range &refcount_val() const; 44 | const boolean_value &init_val() const; 45 | const type_value &type_val() const; 46 | 47 | bool operator<=(const region_info &other) const; 48 | bool operator==(const region_info &other) const; 49 | void operator|=(const region_info &other); 50 | region_info operator|(const region_info &other) const; 51 | region_info operator||(const region_info &other) const; 52 | region_info operator&(const region_info &other) const; 53 | region_info operator&&(const region_info &other) const; 54 | void write(crab::crab_os &o) const; 55 | friend crab::crab_os &operator<<(crab::crab_os &o, region_info &dom) { 56 | dom.write(o); 57 | return o; 58 | } 59 | }; 60 | } // end namespace region_domain_impl 61 | } // end namespace domains 62 | } // end namespace crab 63 | -------------------------------------------------------------------------------- /include/crab/domains/region/tags.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace crab { 7 | namespace domains { 8 | namespace region_domain_impl { 9 | // A simple class for tags (i.e., numerical identifiers). We don't 10 | // use crab::tag because we want to have the flexibility of creating 11 | // tags without a tag manager. 12 | template class tag : public indexable { 13 | ikos::index_t m_id; 14 | 15 | public: 16 | tag(Number n) : m_id(0) { 17 | if (n < 0) { 18 | CRAB_ERROR("Cannot use negative numbers for tags"); 19 | } 20 | if (!n.fits_int64()) { 21 | CRAB_ERROR("Too large value for a tag"); 22 | } 23 | m_id = (int64_t)n; 24 | } 25 | bool operator<(const tag &as) const { return m_id < as.m_id; } 26 | bool operator==(const tag &as) const { return m_id == as.m_id; } 27 | virtual ikos::index_t index() const override { return m_id; } 28 | void write(crab_os &o) const override { o << "TAG_" << m_id; } 29 | friend crab_os &operator<<(crab_os &o, const tag &as) { 30 | as.write(o); 31 | return o; 32 | } 33 | }; /* end class tag */ 34 | } // end namespace region_domain_impl 35 | } // end namespace domains 36 | } // end namespace crab 37 | -------------------------------------------------------------------------------- /include/crab/domains/term/term_operators.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace crab { 11 | namespace domains { 12 | namespace term { 13 | 14 | class term_operator_t { 15 | uint32_t m_value; 16 | bool m_reserved; 17 | public: 18 | // used for defining constexpr crab operators 19 | constexpr term_operator_t(uint32_t value, bool is_reserved = true) 20 | : m_value(value), m_reserved(is_reserved) {} 21 | // used for defining new user operators 22 | static term_operator_t make_operator(uint32_t value); 23 | ~term_operator_t() = default; 24 | constexpr operator uint32_t() const { return m_value; } 25 | constexpr uint32_t value() const { return m_value; } 26 | constexpr bool is_reserved() const { return m_reserved;} 27 | constexpr static uint32_t first_nonreserved_value() { return 100;} 28 | friend crab::crab_os &operator<<(crab::crab_os &o, term_operator_t op); 29 | }; 30 | 31 | constexpr term_operator_t TERM_OP_ADD(0); 32 | constexpr term_operator_t TERM_OP_SUB(1); 33 | constexpr term_operator_t TERM_OP_MUL(2); 34 | constexpr term_operator_t TERM_OP_SDIV(3); 35 | constexpr term_operator_t TERM_OP_UDIV(4); 36 | constexpr term_operator_t TERM_OP_SREM(5); 37 | constexpr term_operator_t TERM_OP_UREM(6); 38 | constexpr term_operator_t TERM_OP_NOT(7); 39 | constexpr term_operator_t TERM_OP_BAND(8); 40 | constexpr term_operator_t TERM_OP_BOR(9); 41 | constexpr term_operator_t TERM_OP_BXOR(10); 42 | constexpr term_operator_t TERM_OP_AND(11); 43 | constexpr term_operator_t TERM_OP_OR(12); 44 | constexpr term_operator_t TERM_OP_XOR(13); 45 | constexpr term_operator_t TERM_OP_SHL(14); 46 | constexpr term_operator_t TERM_OP_LSHR(15); 47 | constexpr term_operator_t TERM_OP_ASHR(16); 48 | constexpr term_operator_t TERM_OP_FUNCTION(17); 49 | 50 | /* Convert between Crab operators and term domain uninterpreted functors */ 51 | term_operator_t conv2termop(arith_operation_t op); 52 | term_operator_t conv2termop(bitwise_operation_t op); 53 | term_operator_t conv2termop(bool_operation_t op); 54 | boost::optional conv2arith(term_operator_t op); 55 | boost::optional conv2bitwise(term_operator_t op); 56 | boost::optional conv2bool(term_operator_t op); 57 | } // end namespace term 58 | } // end namespace domains 59 | } // end namespace crab 60 | -------------------------------------------------------------------------------- /include/crab/domains/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* Type lattice */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace crab { 13 | namespace domains { 14 | /** 15 | * Lattice for variable types which is almost flat except regions 16 | * that can be unknown. An unknown region unifies with any other 17 | * region. 18 | * 19 | * Num = bool | int | real 20 | * Scalar = Num | reference 21 | * 22 | * -------- top 23 | * / / \ 24 | * / / region(unknown)-------- 25 | * / / | | 26 | * Scalar array(Num) region(Scalar) region(array(Num)) 27 | * | \ / | 28 | * ---------- bottom---------------------- 29 | * 30 | **/ 31 | class type_value: public lattice_domain_api { 32 | 33 | boost::optional m_type; 34 | bool m_is_bottom; 35 | 36 | type_value(bool is_bottom); 37 | 38 | public: 39 | 40 | type_value(); 41 | 42 | type_value(variable_type ty); 43 | 44 | static type_value bottom(); 45 | 46 | static type_value top(); 47 | 48 | type_value make_top() const override; 49 | 50 | type_value make_bottom() const override; 51 | 52 | void set_to_top() override; 53 | 54 | void set_to_bottom() override; 55 | 56 | bool is_bottom() const override; 57 | 58 | bool is_top() const override; 59 | 60 | bool operator<=(const type_value &o) const override; 61 | 62 | bool operator==(const type_value &o) const; 63 | 64 | void operator|=(const type_value &o) override; 65 | 66 | type_value operator|(const type_value &o) const override; 67 | 68 | type_value operator||(const type_value &o) const override; 69 | 70 | template 71 | type_value widening_thresholds(const type_value &o, 72 | const Thresholds &ts /*unused*/) const; 73 | 74 | type_value operator&(const type_value &o) const override; 75 | 76 | type_value operator&&(const type_value &o) const override; 77 | 78 | variable_type get() const; 79 | 80 | void set(variable_type ty); 81 | 82 | void write(crab::crab_os &o) const override; 83 | 84 | friend inline crab_os &operator<<(crab_os &o, const type_value &c) { 85 | c.write(o); 86 | return o; 87 | } 88 | 89 | std::string domain_name() const override; 90 | 91 | }; 92 | } // namespace domains 93 | } // namespace crab 94 | -------------------------------------------------------------------------------- /include/crab/fixpoint/fixpoint_params.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace crab { 4 | 5 | /** Class to group together all the fixpoint parameters **/ 6 | class fixpoint_parameters { 7 | // number of iterations until widening operator is called. 8 | unsigned widening_delay; 9 | // number of descending iterations. This is needed in case the 10 | // abstract domain does not implement a narrowing operator. 11 | unsigned descending_iterations; 12 | // Used to implement the technique of widening with thresholds. The 13 | // bigger is this number the slower can be the fixpoint convergence. 14 | // 15 | // The set of thresholds is currently computed by a fixed strategy 16 | // that collects at most max_thresholds per wto cycle. This 17 | // means that each wto cycle has its own set of thresholds. 18 | unsigned max_thresholds; 19 | 20 | public: 21 | 22 | fixpoint_parameters(): 23 | widening_delay(2), 24 | descending_iterations(1), 25 | // Set to 0 to disable widening with thresholds 26 | max_thresholds(0) {} 27 | 28 | unsigned get_widening_delay() const { return widening_delay; } 29 | unsigned& get_widening_delay() { return widening_delay; } 30 | 31 | unsigned get_descending_iterations() const { return descending_iterations; } 32 | unsigned& get_descending_iterations() { return descending_iterations; } 33 | 34 | unsigned get_max_thresholds() const { return max_thresholds; } 35 | unsigned& get_max_thresholds() { return max_thresholds; } 36 | }; 37 | 38 | } // end namespace crab 39 | 40 | -------------------------------------------------------------------------------- /include/crab/numbers/safeint.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Safe signed integers. 5 | **/ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #ifndef __GNUC__ 12 | #include 13 | #endif 14 | 15 | namespace crab { 16 | 17 | class safe_i64 { 18 | 19 | // Current implementation is based on 20 | // https://blog.regehr.org/archives/1139 using wider integers. 21 | 22 | #ifdef __GNUC__ 23 | // TODO/FIXME: the current code compiles assuming the type __int128 24 | // exists. Both clang and gcc supports __int128 if the targeted 25 | // architecture is x86/64, but it wont' work with 32 bits. 26 | using wideint_t = __int128; 27 | #else 28 | using wideint_t = boost::multiprecision::int128_t; 29 | #endif 30 | 31 | static int64_t get_max(); 32 | static int64_t get_min(); 33 | 34 | static int checked_add(int64_t a, int64_t b, int64_t *rp); 35 | static int checked_sub(int64_t a, int64_t b, int64_t *rp); 36 | static int checked_mul(int64_t a, int64_t b, int64_t *rp); 37 | static int checked_div(int64_t a, int64_t b, int64_t *rp); 38 | 39 | public: 40 | safe_i64(); 41 | 42 | safe_i64(int64_t num); 43 | 44 | safe_i64(ikos::z_number n); 45 | 46 | operator int64_t() const; 47 | 48 | // TODO: output parameters whether operation overflows 49 | safe_i64 operator+(safe_i64 x) const; 50 | 51 | // TODO: output parameters whether operation overflows 52 | safe_i64 operator-(safe_i64 x) const; 53 | 54 | // TODO: output parameters whether operation overflows 55 | safe_i64 operator*(safe_i64 x) const; 56 | 57 | // TODO: output parameters whether operation overflows 58 | safe_i64 operator/(safe_i64 x) const; 59 | 60 | // TODO: output parameters whether operation overflows 61 | safe_i64 operator-() const; 62 | 63 | // TODO: output parameters whether operation overflows 64 | safe_i64 &operator+=(safe_i64 x); 65 | 66 | // TODO: output parameters whether operation overflows 67 | safe_i64 &operator-=(safe_i64 x); 68 | 69 | std::size_t hash() const; 70 | 71 | bool operator==(safe_i64 x) const; 72 | 73 | bool operator!=(safe_i64 x) const; 74 | 75 | bool operator<(safe_i64 x) const; 76 | 77 | bool operator<=(safe_i64 x) const; 78 | 79 | bool operator>(safe_i64 x) const; 80 | 81 | bool operator>=(safe_i64 x) const; 82 | 83 | void write(crab::crab_os &os) const; 84 | 85 | friend crab_os &operator<<(crab_os &o, const safe_i64 &n) { 86 | n.write(o); 87 | return o; 88 | } 89 | 90 | private: 91 | int64_t m_num; 92 | }; 93 | 94 | } // end namespace crab 95 | -------------------------------------------------------------------------------- /include/crab/support/os.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace crab { 7 | 8 | // An adaptor for std::ostream that avoids polluting all crab header 9 | // files with iostream stuff 10 | class crab_os { 11 | 12 | static std::unique_ptr m_cout; 13 | static std::unique_ptr m_cerr; 14 | 15 | public: 16 | static crab_os &cout(); 17 | static crab_os &cerr(); 18 | 19 | private: 20 | std::ostream *m_os; 21 | 22 | protected: 23 | crab_os(); 24 | 25 | public: 26 | crab_os(std::ostream *os); 27 | 28 | crab_os(const crab_os &o) = delete; 29 | 30 | crab_os &operator=(const crab_os &o) = delete; 31 | 32 | virtual ~crab_os(); 33 | 34 | virtual crab_os &operator<<(char C); 35 | virtual crab_os &operator<<(unsigned char C); 36 | virtual crab_os &operator<<(signed char C); 37 | virtual crab_os &operator<<(const char *Str); 38 | virtual crab_os &operator<<(const std::string &Str); 39 | virtual crab_os &operator<<(unsigned long N); 40 | virtual crab_os &operator<<(long N); 41 | virtual crab_os &operator<<(unsigned long long N); 42 | virtual crab_os &operator<<(long long N); 43 | virtual crab_os &operator<<(const void *P); 44 | virtual crab_os &operator<<(unsigned int N); 45 | virtual crab_os &operator<<(int N); 46 | virtual crab_os &operator<<(double N); 47 | }; 48 | 49 | extern crab_os &outs(); 50 | extern crab_os &errs(); 51 | 52 | // An adaptor for std::ostringstream 53 | class crab_string_os : public crab_os { 54 | 55 | std::ostringstream *m_string_os; 56 | 57 | public: 58 | crab_string_os(); 59 | 60 | ~crab_string_os(); 61 | 62 | std::string str(); 63 | 64 | crab_os &operator<<(char C) override; 65 | crab_os &operator<<(unsigned char C) override; 66 | crab_os &operator<<(signed char C) override; 67 | crab_os &operator<<(const char *Str) override; 68 | crab_os &operator<<(const std::string &Str) override; 69 | crab_os &operator<<(unsigned long N) override; 70 | crab_os &operator<<(long N) override; 71 | crab_os &operator<<(unsigned long long N) override; 72 | crab_os &operator<<(long long N) override; 73 | crab_os &operator<<(const void *P) override; 74 | crab_os &operator<<(unsigned int N) override; 75 | crab_os &operator<<(int N) override; 76 | crab_os &operator<<(double N) override; 77 | }; 78 | 79 | } // namespace crab 80 | -------------------------------------------------------------------------------- /include/crab/support/stats.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace crab { 9 | 10 | extern bool CrabStatsFlag; 11 | void CrabEnableStats(bool v = true); 12 | 13 | class Stopwatch { 14 | long started; 15 | long finished; 16 | long timeElapsed; 17 | 18 | long systemTime() const; 19 | 20 | public: 21 | Stopwatch(); 22 | void start(); 23 | void stop(); 24 | void resume(); 25 | long getTimeElapsed() const; 26 | void Print(crab_os &out) const; 27 | double toSeconds(); 28 | }; 29 | 30 | inline crab_os &operator<<(crab_os &OS, const Stopwatch &sw) { 31 | sw.Print(OS); 32 | return OS; 33 | } 34 | 35 | class CrabStats { 36 | static std::map &getCounters(); 37 | static std::map &getTimers(); 38 | 39 | public: 40 | static void reset(); 41 | 42 | /* counters */ 43 | static unsigned get(const std::string &n); 44 | static unsigned uset(const std::string &n, unsigned v); 45 | static void count(const std::string &name); 46 | static void count_max(const std::string &name, unsigned v); 47 | 48 | /* stop watch */ 49 | static void start(const std::string &name); 50 | static void stop(const std::string &name); 51 | static void resume(const std::string &name); 52 | 53 | /** Outputs all statistics to std output */ 54 | static void Print(crab_os &OS); 55 | static void PrintBrunch(crab_os &OS); 56 | }; 57 | 58 | class ScopedCrabStats { 59 | std::string m_name; 60 | 61 | public: 62 | ScopedCrabStats(const std::string &name, bool reset = false); 63 | ~ScopedCrabStats(); 64 | }; 65 | } // namespace crab 66 | -------------------------------------------------------------------------------- /include/crab/transforms/transform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace crab { 6 | namespace transforms { 7 | 8 | /** 9 | * API for Crab Control-Flow Graph Transformations. 10 | **/ 11 | template class transform { 12 | public: 13 | virtual ~transform(){} 14 | virtual bool run(CFG &cfg) = 0; 15 | virtual std::string get_name() const = 0; 16 | }; 17 | 18 | } // namespace transforms 19 | } // namespace crab 20 | -------------------------------------------------------------------------------- /include/crab/types/indexable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace ikos { 7 | // Numerical type for indexed objects used by patricia trees 8 | using index_t = uint64_t; 9 | } // end namespace ikos 10 | 11 | namespace crab { 12 | class indexable { 13 | public: 14 | virtual ~indexable() = default; 15 | virtual ikos::index_t index() const = 0; 16 | virtual void write(crab::crab_os &o) const = 0; 17 | }; 18 | } // end namespace crab 19 | -------------------------------------------------------------------------------- /include/crab/types/tag.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /* A simple class to represent tags (i.e., labels) */ 7 | 8 | namespace crab { 9 | class crab_os; 10 | } // end namespace crab 11 | 12 | namespace crab { 13 | class tag_manager; 14 | 15 | class tag : public indexable { 16 | std::size_t m_id; 17 | explicit tag(std::size_t id); 18 | friend class tag_manager; 19 | 20 | public: 21 | tag(const tag &as) = default; 22 | tag(tag &&as) = default; 23 | tag &operator=(const tag &as) = default; 24 | tag &operator=(tag &&as) = default; 25 | bool operator<(const tag &as) const; 26 | bool operator==(const tag &as) const; 27 | virtual ikos::index_t index() const override; 28 | void write(crab_os &o) const override; 29 | friend crab_os &operator<<(crab_os &o, const tag &as) { 30 | as.write(o); 31 | return o; 32 | } 33 | }; 34 | 35 | class tag_manager { 36 | std::size_t m_id; 37 | 38 | public: 39 | tag_manager(); 40 | // create a tag 41 | tag mk_tag(); 42 | // return the number of tags 43 | std::size_t size() const; 44 | }; 45 | 46 | } // namespace crab 47 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(Crab ${CRAB_LIBS_TYPE} 2 | ##support 3 | debug.cpp 4 | stats.cpp 5 | os.cpp 6 | ##abstract domains 7 | abstract_domain_params.cpp 8 | array_adaptive_impl.cpp 9 | boolean.cpp 10 | congruence.cpp 11 | constant.cpp 12 | dis_interval.cpp 13 | interval.cpp 14 | interval_congruence.cpp 15 | region_info.cpp 16 | sign.cpp 17 | small_range.cpp 18 | term_operators.cpp 19 | types.cpp 20 | wrapped_interval.cpp 21 | ##numbers 22 | bignums.cpp 23 | safeint.cpp 24 | wrapint.cpp 25 | ##variable factory 26 | varname_factory.cpp 27 | ##types 28 | tag.cpp 29 | ) 30 | 31 | target_link_libraries(Crab ${GMP_LIB}) 32 | 33 | install(TARGETS Crab 34 | LIBRARY DESTINATION crab/lib 35 | ARCHIVE DESTINATION crab/lib) 36 | 37 | if (NOT TopLevel) 38 | ## This is ugly fix so that seahorn and crab-llvm can find Crab if 39 | ## dynamically linked. It has to do with how CMAKE_INSTALL_RPATH is 40 | ## handled by these tools. 41 | install(TARGETS Crab 42 | LIBRARY DESTINATION lib 43 | ARCHIVE DESTINATION lib) 44 | endif() 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /lib/congruence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ikos { 5 | // Default instantiations 6 | template class congruence; 7 | } // end namespace ikos 8 | -------------------------------------------------------------------------------- /lib/debug.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef NCRABLOG 4 | namespace crab { 5 | bool CrabLogFlag = false; 6 | std::set CrabLog; 7 | 8 | void CrabEnableLog(std::string x) { 9 | if (x.empty()) 10 | return; 11 | CrabLogFlag = true; 12 | CrabLog.insert(x); 13 | } 14 | } // namespace crab 15 | 16 | #else 17 | namespace crab { 18 | void CrabEnableLog(std::string x) {} 19 | } // namespace crab 20 | #endif 21 | 22 | namespace crab { 23 | unsigned CrabVerbosity = 0; 24 | void CrabEnableVerbosity(unsigned v) { CrabVerbosity = v; } 25 | 26 | bool CrabWarningFlag = true; 27 | void CrabEnableWarningMsg(bool v) { CrabWarningFlag = v; } 28 | 29 | bool CrabSanityCheckFlag = false; 30 | void CrabEnableSanityChecks(bool v) { CrabSanityCheckFlag = v; } 31 | 32 | crab_os &get_msg_stream(bool timestamp) { 33 | crab::crab_os *result = &crab::outs(); 34 | if (timestamp) { 35 | time_t now = time(0); 36 | struct tm tstruct; 37 | char buf[80]; 38 | tstruct = *localtime(&now); 39 | strftime(buf, sizeof(buf), "[%Y-%m-%d.%X] ", &tstruct); 40 | *result << buf; 41 | } 42 | return *result; 43 | } 44 | } // namespace crab 45 | -------------------------------------------------------------------------------- /lib/interval_congruence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace crab { 5 | namespace domains { 6 | // Default instantiations 7 | template class interval_congruence; 8 | } // end namespace domains 9 | } // end namespace crab 10 | -------------------------------------------------------------------------------- /lib/region_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace crab { 5 | namespace domains { 6 | namespace region_domain_impl { 7 | 8 | region_info::region_info() { m_product.set_to_top(); } 9 | 10 | region_info::region_info(region_info::product_t &&product) 11 | : m_product(std::move(product)) {} 12 | 13 | region_info::region_info(small_range count, boolean_value init, 14 | type_value type) { 15 | refcount_val() = count; 16 | init_val() = init; 17 | type_val() = type; 18 | } 19 | 20 | region_info region_info::bottom() { 21 | region_info res; 22 | res.m_product.set_to_bottom(); 23 | return res; 24 | } 25 | 26 | region_info region_info::top() { 27 | region_info res; 28 | return res; 29 | } 30 | 31 | bool region_info::is_bottom() const { return m_product.is_bottom(); } 32 | 33 | bool region_info::is_top() const { return m_product.is_top(); } 34 | 35 | small_range ®ion_info::refcount_val() { return m_product.first(); } 36 | 37 | boolean_value ®ion_info::init_val() { return m_product.second().first(); } 38 | 39 | type_value ®ion_info::type_val() { return m_product.second().second(); } 40 | 41 | const small_range ®ion_info::refcount_val() const { return m_product.first(); } 42 | 43 | const boolean_value ®ion_info::init_val() const { 44 | return m_product.second().first(); 45 | } 46 | 47 | const type_value ®ion_info::type_val() const { 48 | return m_product.second().second(); 49 | } 50 | 51 | bool region_info::operator<=(const region_info &other) const { 52 | return m_product <= other.m_product; 53 | } 54 | 55 | bool region_info::operator==(const region_info &other) const { 56 | return (operator<=(other) && other.operator<=(*this)); 57 | } 58 | 59 | void region_info::operator|=(const region_info &other) { 60 | m_product |= other.m_product; 61 | } 62 | 63 | region_info region_info::operator|(const region_info &other) const { 64 | return region_info(m_product | other.m_product); 65 | } 66 | 67 | region_info region_info::operator||(const region_info &other) const { 68 | return region_info(m_product || other.m_product); 69 | } 70 | 71 | region_info region_info::operator&(const region_info &other) const { 72 | return region_info(m_product & other.m_product); 73 | } 74 | 75 | region_info region_info::operator&&(const region_info &other) const { 76 | return region_info(m_product && other.m_product); 77 | } 78 | 79 | void region_info::write(crab::crab_os &o) const { 80 | o << "RefCount=" << refcount_val() << "," 81 | << "Init=" << init_val() << "," 82 | << "DynType=" << type_val(); 83 | } 84 | } // end namespace region_domain_impl 85 | } // end namespace domains 86 | } // end namespace crab 87 | -------------------------------------------------------------------------------- /lib/sign.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace crab { 5 | namespace domains { 6 | // Default instantiations 7 | template class sign; 8 | } // end namespace domains 9 | } // end namespace crab 10 | -------------------------------------------------------------------------------- /lib/tag.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace crab { 5 | 6 | tag::tag(size_t id) : m_id(id) {} 7 | 8 | bool tag::operator<(const tag &as) const { 9 | return m_id < as.m_id; 10 | } 11 | 12 | bool tag::operator==(const tag &as) const { 13 | return m_id == as.m_id; 14 | } 15 | 16 | ikos::index_t tag::index() const { return m_id; } 17 | 18 | void tag::write(crab_os &o) const { o << "as_" << m_id; } 19 | 20 | tag_manager::tag_manager() : m_id(0) {} 21 | 22 | tag tag_manager::mk_tag() { 23 | tag as(m_id++); 24 | return as; 25 | } 26 | 27 | size_t tag_manager::size() const { return m_id; } 28 | 29 | } // end namespace crab 30 | -------------------------------------------------------------------------------- /lib/varname_factory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace crab { 4 | namespace var_factory_impl { 5 | static const char *col_prefix_data[] = {"_x", "_y", "_z"}; 6 | const char **str_var_alloc_col::col_prefix = col_prefix_data; 7 | } // namespace var_factory_impl 8 | } // namespace crab 9 | -------------------------------------------------------------------------------- /make/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------------# 2 | # INSTRUCTIONS 3 | #------------------------------------------------------------------------------------# 4 | # 0. Define variables BOOST_ROOT and GMP_DIR in Makefile.config 5 | # 1. Type `make crab_install` 6 | # 2. Type `make all` 7 | # 3. Type `./domain` or `./analysis` 8 | #------------------------------------------------------------------------------------# 9 | 10 | include Makefile.config 11 | 12 | all: domain analysis 13 | 14 | %.o: $(CXX) $(CXXFLAGS) $< -c -o $@ 15 | 16 | domain: domain.o 17 | $(CXX) domain.o $(LDFLAGS) -o domain 18 | 19 | analysis: analysis.o 20 | $(CXX) analysis.o $(LDFLAGS) -o analysis 21 | 22 | clean: 23 | rm -f domain analysis *.a *.o 24 | -------------------------------------------------------------------------------- /make/Makefile.config: -------------------------------------------------------------------------------- 1 | BOOST_ROOT= 2 | GMP_DIR= 3 | 4 | PWD=$(shell pwd) 5 | UNAME := $(shell uname) 6 | 7 | CRAB_INSTALL=${PWD}/crab-install 8 | CRAB_LIBS = $(CRAB_INSTALL)/crab/lib/libCrab.a 9 | 10 | CXXFLAGS := \ 11 | -Wall -Wfatal-errors \ 12 | -Wno-unused-local-typedefs \ 13 | -Wno-uninitialized \ 14 | -DBSD -DHAVE_IEEE_754 -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 \ 15 | -I $(CRAB_INSTALL)/crab/include \ 16 | -I $(BOOST_ROOT)/include \ 17 | -I $(GMP_DIR)/include \ 18 | -O2 -g -std=c++11 19 | 20 | ifeq ($(UNAME),Darwin) 21 | CXXFLAGS += -Wno-nullability-completeness 22 | CXXFLAGS += -isysroot $(shell xcrun --show-sdk-path) 23 | endif 24 | 25 | LDFLAGS := $(CRAB_LIBS) 26 | LDFLAGS += -L$(GMP_DIR)/lib -lgmp 27 | 28 | .PHONY: crab_install 29 | crab_install: 30 | git clone https://github.com/seahorn/crab.git crab 31 | mkdir -p crab/build 32 | cd crab/build \ 33 | && cmake -DCMAKE_INSTALL_PREFIX=$(CRAB_INSTALL) \ 34 | -DCRAB_BUILD_LIBS_SHARED=OFF ../ \ 35 | && cmake --build . --target install 36 | -------------------------------------------------------------------------------- /make/README.md: -------------------------------------------------------------------------------- 1 | # How to use Crab via Makefile # 2 | 3 | This directory contains a sample `Makefile` and two programs: 4 | 5 | - `domain.cpp`: use Crab C++ API to create an **abstract domain 6 | object** and perform some abstract operations. 7 | 8 | - `analysis.cpp`: use Crab C++ API to create a Control Flow Graph 9 | (CFG) and an **analysis object**, and perform analysis on the CFG. 10 | 11 | There are also two subdirectories `apron` and `elina` that show how to 12 | use Apron and Elina libraries. Currently, they are not compatible with 13 | each other so that's why they must be built separately. 14 | -------------------------------------------------------------------------------- /make/apron/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------------# 2 | # INSTRUCTIONS 3 | #------------------------------------------------------------------------------------# 4 | # 0. Define variables BOOST_ROOT, GMP_DIR in Makefile.config and MPFR_DIR 5 | # 1. Type `make crab_apron_ldd_install` 6 | # 2. Type `make all` 7 | # 3. Type `./domain` or `./analysis` 8 | #------------------------------------------------------------------------------------# 9 | 10 | include ../Makefile.config 11 | 12 | MPFR_DIR= 13 | 14 | LDD_LIBS := \ 15 | $(CRAB_INSTALL)/ldd/lib/libldd.a \ 16 | $(CRAB_INSTALL)/ldd/lib/libtvpi.a \ 17 | $(CRAB_INSTALL)/ldd/lib/libcudd.a \ 18 | $(CRAB_INSTALL)/ldd/lib/libst.a \ 19 | $(CRAB_INSTALL)/ldd/lib/libutil.a \ 20 | $(CRAB_INSTALL)/ldd/lib/libmtr.a \ 21 | $(CRAB_INSTALL)/ldd/lib/libepd.a 22 | 23 | APRON_LIBS := \ 24 | $(CRAB_INSTALL)/apron/lib/libpolkaMPQ.a \ 25 | $(CRAB_INSTALL)/apron/lib/liboctD.a \ 26 | $(CRAB_INSTALL)/apron/lib/liboptoct.a \ 27 | $(CRAB_INSTALL)/apron/lib/liblinkedlistapi.a \ 28 | $(CRAB_INSTALL)/apron/lib/libapron.a \ 29 | $(CRAB_INSTALL)/apron/lib/libboxMPQ.a \ 30 | $(CRAB_INSTALL)/apron/lib/libitvMPQ.a 31 | 32 | CXXFLAGS += \ 33 | -I $(MPFR_DIR)/include \ 34 | -I $(CRAB_INSTALL)/ldd/include/ldd \ 35 | -I $(CRAB_INSTALL)/apron/include 36 | 37 | LDFLAGS += $(LDD_LIBS) $(APRON_LIBS) 38 | LDFLAGS += -L$(MPFR_DIR)/lib -lmpfr 39 | 40 | 41 | all: domain analysis 42 | 43 | %.o: $(CXX) $(CXXFLAGS) $< -c -o $@ 44 | 45 | domain: domain.o 46 | $(CXX) domain.o $(LDFLAGS) -o domain 47 | 48 | analysis: analysis.o 49 | $(CXX) analysis.o $(LDFLAGS) -o analysis 50 | 51 | clean: 52 | rm -f domain analysis *.a *.o 53 | 54 | .PHONY: crab_apron_ldd_install 55 | crab_apron_ldd_install: 56 | git clone https://github.com/seahorn/crab.git crab 57 | mkdir -p crab/build 58 | @echo "Installing crab+apron+ldd in ${CRAB_INSTALL} ... " 59 | cd crab/build \ 60 | && cmake -DCMAKE_INSTALL_PREFIX=$(CRAB_INSTALL) -DCRAB_BUILD_LIBS_SHARED=OFF \ 61 | -DCRAB_USE_LDD=ON -DCRAB_USE_APRON=ON ../ \ 62 | && cmake --build . --target ldd && cmake ../ \ 63 | && cmake --build . --target apron && cmake ../ \ 64 | && cmake --build . --target install 65 | 66 | -------------------------------------------------------------------------------- /make/apron/domain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Abstract domains 10 | #include 11 | #include 12 | 13 | using namespace crab; 14 | using namespace ikos; 15 | 16 | // A variable factory based on strings 17 | using variable_factory_t = var_factory_impl::str_variable_factory; 18 | namespace crab { 19 | template<> 20 | class variable_name_traits { 21 | public: 22 | static std::string to_string(std::string varname) { 23 | return varname; 24 | } 25 | }; 26 | } // end namespace crab 27 | // Expressions 28 | using varname_t = typename variable_factory_t::varname_t; 29 | using var_t = variable; 30 | using lin_exp_t = linear_expression; 31 | using lin_cst_t = linear_constraint ; 32 | using lin_cst_sys_t = linear_constraint_system ; 33 | 34 | ///////// Begin Crab Abstract Domains ///////////// 35 | using interval_domain_t = interval_domain; 36 | using pk_domain_t = domains::apron_domain; 38 | ///////// End Crab Abstract Domains ///////////// 39 | 40 | int main(int argc, char**argv) { 41 | 42 | variable_factory_t vfac; 43 | var_t x(vfac["x"], INT_TYPE, 32); 44 | var_t y(vfac["y"], INT_TYPE, 32); 45 | var_t z(vfac["z"], INT_TYPE, 32); 46 | 47 | { 48 | outs() << "Example using intervals\n"; 49 | interval_domain_t inv1, inv2; 50 | inv1.assign(x, 5); 51 | inv1.assign(y, 10); 52 | outs() << "inv1=" << inv1 << "\n"; 53 | inv2.assign(x, 10); 54 | inv2.assign(y, 20); 55 | outs() << "inv2=" << inv1 << "\n"; 56 | interval_domain_t inv3 = inv1 | inv2; 57 | inv3.apply(domains::OP_ADDITION, z, x, y); 58 | outs() << "inv1 | inv2 = " << inv3 << "\n"; 59 | } 60 | 61 | { 62 | outs() << "Example using polyhedra\n"; 63 | pk_domain_t inv1, inv2; 64 | inv1.assign(x, 5); 65 | inv1.assign(y, 10); 66 | outs() << "inv1=" << inv1 << "\n"; 67 | inv2.assign(x, 10); 68 | inv2.assign(y, 20); 69 | outs() << "inv2=" << inv1 << "\n"; 70 | pk_domain_t inv3 = inv1 | inv2; 71 | inv3.apply(domains::OP_ADDITION, z, x, y); 72 | outs() << "inv1 | inv2 = " << inv3 << "\n"; 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /make/domain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Abstract domains 10 | #include 11 | #include 12 | 13 | using namespace crab; 14 | using namespace ikos; 15 | 16 | // A variable factory based on strings 17 | using variable_factory_t = var_factory_impl::str_variable_factory; 18 | namespace crab { 19 | template<> 20 | class variable_name_traits { 21 | public: 22 | static std::string to_string(std::string varname) { 23 | return varname; 24 | } 25 | }; 26 | } //end namespace crab 27 | // Expressions 28 | using varname_t = typename variable_factory_t::varname_t; 29 | using var_t = variable; 30 | using lin_exp_t = linear_expression; 31 | using lin_cst_t = linear_constraint ; 32 | using lin_cst_sys_t = linear_constraint_system ; 33 | 34 | ///////// Begin Crab Abstract Domains ///////////// 35 | using interval_domain_t = interval_domain; 36 | using zones_domain_t = domains::split_dbm_domain; 37 | ///////// End Crab Abstract Domains ///////////// 38 | 39 | int main(int argc, char**argv) { 40 | 41 | variable_factory_t vfac; 42 | var_t x(vfac["x"], INT_TYPE, 32); 43 | var_t y(vfac["y"], INT_TYPE, 32); 44 | var_t z(vfac["z"], INT_TYPE, 32); 45 | 46 | { 47 | outs() << "Example using intervals\n"; 48 | interval_domain_t inv1, inv2; 49 | inv1.assign(x, 5); 50 | inv1.assign(y, 10); 51 | outs() << "inv1=" << inv1 << "\n"; 52 | inv2.assign(x, 10); 53 | inv2.assign(y, 20); 54 | outs() << "inv2=" << inv1 << "\n"; 55 | interval_domain_t inv3 = inv1 | inv2; 56 | inv3.apply(domains::OP_ADDITION, z, x, y); 57 | outs() << "inv1 | inv2 = " << inv3 << "\n"; 58 | } 59 | 60 | { 61 | outs() << "Example using zones\n"; 62 | zones_domain_t inv1, inv2; 63 | inv1.assign(x, 5); 64 | inv1.assign(y, 10); 65 | outs() << "inv1=" << inv1 << "\n"; 66 | inv2.assign(x, 10); 67 | inv2.assign(y, 20); 68 | outs() << "inv2=" << inv1 << "\n"; 69 | zones_domain_t inv3 = inv1 | inv2; 70 | inv3.apply(domains::OP_ADDITION, z, x, y); 71 | outs() << "inv1 | inv2 = " << inv3 << "\n"; 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /make/elina/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------------# 2 | # INSTRUCTIONS 3 | #------------------------------------------------------------------------------------# 4 | # 0. Define variables BOOST_ROOT, GMP_DIR in Makefile.config and MPFR_DIR 5 | # 1. Type `make crab_elina_install` 6 | # 2. Type `make all` 7 | # 3. Type `./domain` or `./analysis` 8 | #------------------------------------------------------------------------------------# 9 | 10 | include ../Makefile.config 11 | 12 | MPFR_DIR= 13 | 14 | # Elina shared libraries have extension .so even on mac 15 | ELINA_LIBS := \ 16 | $(CRAB_INSTALL)/elina/lib/libelinalinearize.so \ 17 | $(CRAB_INSTALL)/elina/lib/libelinaux.so \ 18 | $(CRAB_INSTALL)/elina/lib/liboptoct.so \ 19 | $(CRAB_INSTALL)/elina/lib/liboptpoly.so \ 20 | $(CRAB_INSTALL)/elina/lib/liboptzones.so \ 21 | $(CRAB_INSTALL)/elina/lib/libpartitions.so \ 22 | $(CRAB_INSTALL)/elina/lib/libzonotope.so 23 | 24 | CXXFLAGS += \ 25 | -I $(MPFR_DIR)/include \ 26 | -I $(CRAB_INSTALL)/elina/include 27 | 28 | LDFLAGS += $(ELINA_LIBS) 29 | LDFLAGS += -L$(MPFR_DIR)/lib -lmpfr 30 | 31 | # Lookup paths for crab and elina shared libraries 32 | LDFLAGS += -Wl,-rpath,$(CRAB_INSTALL)/crab/lib/,-rpath,$(CRAB_INSTALL)/elina/lib/ 33 | ifeq ($(UNAME),Linux) 34 | LDFLAGS += -Wl,--disable-new-dtags 35 | endif 36 | 37 | all: domain analysis 38 | # Ugly hack: add elina lib directory to rpath is not enough 39 | @echo "Compilation done. \nType \"export LD_LIBRARY_PATH=$(CRAB_INSTALL)/elina/lib\"" 40 | 41 | %.o: $(CXX) $(CXXFLAGS) $< -c -o $@ 42 | 43 | domain: domain.o 44 | $(CXX) domain.o $(LDFLAGS) -o domain 45 | 46 | analysis: analysis.o 47 | $(CXX) analysis.o $(LDFLAGS) -o analysis 48 | 49 | clean: 50 | rm -f domain analysis *.a *.o 51 | 52 | .PHONY: crab_elina_install 53 | crab_elina_install: 54 | git clone https://github.com/seahorn/crab.git crab -b dev 55 | mkdir -p crab/build 56 | cd crab/build \ 57 | && cmake -DCMAKE_INSTALL_PREFIX=$(CRAB_INSTALL) -DCRAB_BUILD_LIBS_SHARED=OFF \ 58 | -DCRAB_USE_ELINA=ON ../ \ 59 | && cmake --build . --target elina && cmake ../ \ 60 | && cmake --build . --target install 61 | -------------------------------------------------------------------------------- /make/elina/domain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Abstract domains 10 | #include 11 | #include 12 | 13 | using namespace crab; 14 | using namespace ikos; 15 | 16 | // A variable factory based on strings 17 | using variable_factory_t = var_factory_impl::str_variable_factory; 18 | namespace crab { 19 | template<> 20 | class variable_name_traits { 21 | public: 22 | static std::string to_string(std::string varname) { 23 | return varname; 24 | } 25 | }; 26 | } // end namespace crab 27 | // Expressions 28 | using varname_t = typename variable_factory_t::varname_t; 29 | using var_t = variable; 30 | using lin_exp_t = linear_expression; 31 | using lin_cst_t = linear_constraint ; 32 | using lin_cst_sys_t = linear_constraint_system ; 33 | 34 | ///////// Begin Crab Abstract Domains ///////////// 35 | using interval_domain_t = interval_domain; 36 | using pk_domain_t = domains::elina_domain; 38 | ///////// End Crab Abstract Domains ///////////// 39 | 40 | int main(int argc, char**argv) { 41 | 42 | variable_factory_t vfac; 43 | var_t x(vfac["x"], INT_TYPE, 32); 44 | var_t y(vfac["y"], INT_TYPE, 32); 45 | var_t z(vfac["z"], INT_TYPE, 32); 46 | 47 | { 48 | outs() << "Example using intervals\n"; 49 | interval_domain_t inv1, inv2; 50 | inv1.assign(x, 5); 51 | inv1.assign(y, 10); 52 | outs() << "inv1=" << inv1 << "\n"; 53 | inv2.assign(x, 10); 54 | inv2.assign(y, 20); 55 | outs() << "inv2=" << inv1 << "\n"; 56 | interval_domain_t inv3 = inv1 | inv2; 57 | inv3.apply(domains::OP_ADDITION, z, x, y); 58 | outs() << "inv1 | inv2 = " << inv3 << "\n"; 59 | } 60 | 61 | { 62 | outs() << "Example using polyhedra\n"; 63 | pk_domain_t inv1, inv2; 64 | inv1.assign(x, 5); 65 | inv1.assign(y, 10); 66 | outs() << "inv1=" << inv1 << "\n"; 67 | inv2.assign(x, 10); 68 | inv2.assign(y, 20); 69 | outs() << "inv2=" << inv1 << "\n"; 70 | pk_domain_t inv3 = inv1 | inv2; 71 | inv3.apply(domains::OP_ADDITION, z, x, y); 72 | outs() << "inv1 | inv2 = " << inv3 << "\n"; 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(IntraCrab ${CRAB_LIBS_TYPE} crab.cpp) 2 | target_link_libraries(IntraCrab ${CRAB_LIBS}) 3 | add_library(InterCrab ${CRAB_LIBS_TYPE} icrab.cpp) 4 | target_link_libraries(InterCrab ${CRAB_LIBS}) 5 | add_library(BackwardCrab ${CRAB_LIBS_TYPE} bcrab.cpp) 6 | target_link_libraries(BackwardCrab ${CRAB_LIBS}) 7 | 8 | function (AddTest testSrc dirName) 9 | #Extract the filename without an extension (NAME_WE) 10 | get_filename_component(testName ${testSrc} NAME_WE) 11 | #Add compile target 12 | add_executable(${testName} ${testSrc} ) 13 | #link with crab libraries 14 | if (${dirName} MATCHES "inter") 15 | target_link_libraries(${testName} ${Boost_PROGRAM_OPTIONS_LIBRARY} InterCrab) 16 | elseif (${dirName} MATCHES "backward") 17 | target_link_libraries(${testName} ${Boost_PROGRAM_OPTIONS_LIBRARY} BackwardCrab) 18 | else () 19 | target_link_libraries(${testName} ${Boost_PROGRAM_OPTIONS_LIBRARY} IntraCrab) 20 | endif () 21 | #move testing binaries into a ${TEST_DIR} directory 22 | set_target_properties(${testName} PROPERTIES 23 | RUNTIME_OUTPUT_DIRECTORY ${TEST_DIR}) 24 | #Finally add it to test execution 25 | add_test(NAME ${testName} 26 | WORKING_DIRECTORY ${TEST_DIR} 27 | COMMAND ${TEST_DIR}/${testName} --disable-warnings) 28 | endfunction() 29 | 30 | set(EXCLUDE_FILES 31 | "" 32 | ) 33 | 34 | function (AddTestDir dirName) 35 | file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${dirName}/*.cc) 36 | foreach(testSrc ${TEST_SRCS}) 37 | if (${testSrc} IN_LIST EXCLUDE_FILES) 38 | message (STATUS " ##### Excluding ${testSrc} from compilation") 39 | else() 40 | AddTest (${testSrc} ${dirName}) 41 | endif() 42 | endforeach(testSrc) 43 | endfunction () 44 | 45 | AddTestDir(assertion_crawler) 46 | AddTestDir(domains) 47 | AddTestDir(domains/wrapint) 48 | AddTestDir(domains/region) 49 | AddTestDir(transforms) 50 | AddTestDir(inter) 51 | AddTestDir(cg) 52 | AddTestDir(cfg) 53 | AddTestDir(thresholds) 54 | AddTestDir(checkers) 55 | AddTestDir(backward) 56 | AddTestDir(preconditions) 57 | AddTestDir(liveness) 58 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Add a test for a new abstract domain (for developers) # 2 | 3 | 1. Include the header file in `crab_dom.hpp`: 4 | 5 | #include 6 | 7 | 2. Create an instantiation of the `run` function for the new domain: 8 | 9 | Z_RUNNER(crab::domain_impl::z_wrapped_interval_domain_t) 10 | 11 | The `run` function should be called from your test (see step 3). 12 | 13 | If the domain is defined over rational instead of integers then use 14 | 15 | Q_RUNNER(...) 16 | 17 | 3. Add your test `wrapped_interval_domain_test.cc`. You can use 18 | `domains/test1.cc` as a template. 19 | 20 | 4. Include the directory where your test is located in 21 | `CMakeLists.txt`. For instance, if your test is under a 22 | subdirectory called `domains/wrapint`: 23 | 24 | AddTestDir(domains) 25 | ... 26 | AddTestDir (domains/wrapint) # directory where your test is located 27 | 28 | Of course, if you put your test in the rest of the above directories 29 | you can skip step 4. 30 | 31 | **IMPORTANT:** Tests are only compiled if option `-DCRAB_ENABLE_TESTS=ON` 32 | is enabled in the `cmake` command. 33 | 34 | -------------------------------------------------------------------------------- /tests/backward/backward-1-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Example from Monniaux's slides. 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 18 | // entry and exit block 19 | auto cfg = new z_cfg_t("entry", "bb3"); 20 | // adding blocks 21 | z_basic_block_t &entry = cfg->insert("entry"); 22 | z_basic_block_t &bb1 = cfg->insert("bb1"); 23 | z_basic_block_t &bb2 = cfg->insert("bb2"); 24 | z_basic_block_t &bb3 = cfg->insert("bb3"); 25 | // adding control flow 26 | entry >> bb1; 27 | entry >> bb2; 28 | bb1 >> bb3; 29 | bb2 >> bb3; 30 | 31 | // adding statements 32 | bb1.assume(x >= 0); 33 | bb1.assign(y, x); 34 | 35 | bb2.assume(x <= -1); 36 | bb2.assign(tmp, 0); 37 | bb2.sub(y, tmp, x); 38 | 39 | bb3.assume(y >= 1); 40 | bb3.assertion(x != 0); 41 | 42 | return cfg; 43 | } 44 | 45 | int main(int argc, char **argv) { 46 | #ifdef HAVE_APRON 47 | bool stats_enabled = false; 48 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 49 | return 0; 50 | } 51 | variable_factory_t vfac; 52 | z_cfg_t *cfg = prog(vfac); 53 | crab::outs() << *cfg << "\n"; 54 | 55 | // A forward+backward analysis should prove the assertion holds. 56 | 57 | z_box_apron_domain_t initial_states; 58 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 59 | 20, stats_enabled); 60 | 61 | // free the CFG 62 | delete cfg; 63 | #endif 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tests/backward/backward-1-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Example from Monniaux's slides. 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 18 | // entry and exit block 19 | auto cfg = new z_cfg_t("entry", "bb3"); 20 | // adding blocks 21 | z_basic_block_t &entry = cfg->insert("entry"); 22 | z_basic_block_t &bb1 = cfg->insert("bb1"); 23 | z_basic_block_t &bb2 = cfg->insert("bb2"); 24 | z_basic_block_t &bb3 = cfg->insert("bb3"); 25 | // adding control flow 26 | entry >> bb1; 27 | entry >> bb2; 28 | bb1 >> bb3; 29 | bb2 >> bb3; 30 | 31 | // adding statements 32 | bb1.assume(x >= 0); 33 | bb1.assign(y, x); 34 | 35 | bb2.assume(x <= -1); 36 | bb2.assign(tmp, 0); 37 | bb2.sub(y, tmp, x); 38 | 39 | bb3.assume(y >= 1); 40 | bb3.assertion(x != 0); 41 | 42 | return cfg; 43 | } 44 | 45 | int main(int argc, char **argv) { 46 | #ifdef HAVE_ELINA 47 | bool stats_enabled = false; 48 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 49 | return 0; 50 | } 51 | variable_factory_t vfac; 52 | z_cfg_t *cfg = prog(vfac); 53 | crab::outs() << *cfg << "\n"; 54 | 55 | // A forward+backward analysis should prove the assertion holds. 56 | z_oct_elina_domain_t initial_states; 57 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 58 | 20, stats_enabled); 59 | 60 | // free the CFG 61 | delete cfg; 62 | #endif 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tests/backward/backward-2-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Modified version from Rival'05 paper 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 18 | // entry and exit block 19 | auto cfg = new z_cfg_t("entry", "bb3"); 20 | // adding blocks 21 | z_basic_block_t &entry = cfg->insert("entry"); 22 | z_basic_block_t &bb1 = cfg->insert("bb1"); 23 | z_basic_block_t &bb2 = cfg->insert("bb2"); 24 | z_basic_block_t &bb3 = cfg->insert("bb3"); 25 | // adding control flow 26 | entry >> bb1; 27 | entry >> bb2; 28 | bb1 >> bb3; 29 | bb2 >> bb3; 30 | 31 | // adding statements 32 | bb1.assume(x >= 1); 33 | bb1.assign(y, x); 34 | 35 | bb2.assume(x <= 0); 36 | bb2.assign(tmp, 0); 37 | bb2.sub(y, tmp, x); 38 | 39 | bb3.assume(y >= 6); 40 | bb3.assertion(x <= 5); 41 | bb3.assertion(x >= -5); 42 | return cfg; 43 | } 44 | 45 | int main(int argc, char **argv) { 46 | #ifdef HAVE_APRON 47 | bool stats_enabled = false; 48 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 49 | return 0; 50 | } 51 | variable_factory_t vfac; 52 | z_cfg_t *cfg = prog(vfac); 53 | crab::outs() << *cfg << "\n"; 54 | 55 | // A forward+backward analysis cannot prove the two assertion holds, 56 | // even used disjunctive boxes. 57 | // - for classical intervals, we lose all information going 58 | // backwards after the assert(x<=5) 59 | // - for disjunctive intervals, we can keep that error can happen 60 | // either x <= -6 or x >= 6. However, when going backwards 61 | // through blocks bb1 and bb2 one of the two constraints is true 62 | // so we never infer bottom. 63 | 64 | z_box_apron_domain_t initial_states; 65 | z_var x(vfac["x"], crab::INT_TYPE, 32); 66 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 67 | 20, stats_enabled); 68 | // free the CFG 69 | delete cfg; 70 | #endif 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /tests/backward/backward-2-boxes.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Modified version from Rival'05 paper 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 18 | // entry and exit block 19 | auto cfg = new z_cfg_t("entry", "bb3"); 20 | // adding blocks 21 | z_basic_block_t &entry = cfg->insert("entry"); 22 | z_basic_block_t &bb1 = cfg->insert("bb1"); 23 | z_basic_block_t &bb2 = cfg->insert("bb2"); 24 | z_basic_block_t &bb3 = cfg->insert("bb3"); 25 | // adding control flow 26 | entry >> bb1; 27 | entry >> bb2; 28 | bb1 >> bb3; 29 | bb2 >> bb3; 30 | 31 | // adding statements 32 | bb1.assume(x >= 1); 33 | bb1.assign(y, x); 34 | 35 | bb2.assume(x <= 0); 36 | bb2.assign(tmp, 0); 37 | bb2.sub(y, tmp, x); 38 | 39 | bb3.assume(y >= 6); 40 | bb3.assertion(x <= 5); 41 | bb3.assertion(x >= -5); 42 | return cfg; 43 | } 44 | 45 | int main(int argc, char **argv) { 46 | #ifdef HAVE_LDD 47 | bool stats_enabled = false; 48 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 49 | return 0; 50 | } 51 | variable_factory_t vfac; 52 | z_cfg_t *cfg = prog(vfac); 53 | crab::outs() << *cfg << "\n"; 54 | 55 | // A forward+backward analysis cannot prove the two assertion holds, 56 | // even used disjunctive boxes. 57 | // - for classical intervals, we lose all information going 58 | // backwards after the assert(x<=5) 59 | // - for disjunctive intervals, we can keep that error can happen 60 | // either x <= -6 or x >= 6. However, when going backwards 61 | // through blocks bb1 and bb2 one of the two constraints is true 62 | // so we never infer bottom. 63 | 64 | z_boxes_domain_t initial_states; 65 | z_var x(vfac["x"], crab::INT_TYPE, 32); 66 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 20, 67 | stats_enabled); 68 | 69 | // free the CFG 70 | delete cfg; 71 | #endif 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/backward/backward-2-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Modified version from Rival'05 paper 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 18 | // entry and exit block 19 | auto cfg = new z_cfg_t("entry", "bb3"); 20 | // adding blocks 21 | z_basic_block_t &entry = cfg->insert("entry"); 22 | z_basic_block_t &bb1 = cfg->insert("bb1"); 23 | z_basic_block_t &bb2 = cfg->insert("bb2"); 24 | z_basic_block_t &bb3 = cfg->insert("bb3"); 25 | // adding control flow 26 | entry >> bb1; 27 | entry >> bb2; 28 | bb1 >> bb3; 29 | bb2 >> bb3; 30 | 31 | // adding statements 32 | bb1.assume(x >= 1); 33 | bb1.assign(y, x); 34 | 35 | bb2.assume(x <= 0); 36 | bb2.assign(tmp, 0); 37 | bb2.sub(y, tmp, x); 38 | 39 | bb3.assume(y >= 6); 40 | bb3.assertion(x <= 5); 41 | bb3.assertion(x >= -5); 42 | return cfg; 43 | } 44 | 45 | int main(int argc, char **argv) { 46 | #ifdef HAVE_ELINA 47 | bool stats_enabled = false; 48 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 49 | return 0; 50 | } 51 | variable_factory_t vfac; 52 | z_cfg_t *cfg = prog(vfac); 53 | crab::outs() << *cfg << "\n"; 54 | 55 | // A forward+backward analysis cannot prove the two assertion holds, 56 | // even used disjunctive boxes. 57 | // - for classical intervals, we lose all information going 58 | // backwards after the assert(x<=5) 59 | // - for disjunctive intervals, we can keep that error can happen 60 | // either x <= -6 or x >= 6. However, when going backwards 61 | // through blocks bb1 and bb2 one of the two constraints is true 62 | // so we never infer bottom. 63 | 64 | z_oct_elina_domain_t initial_states; 65 | z_var x(vfac["x"], crab::INT_TYPE, 32); 66 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 67 | 20, stats_enabled); 68 | 69 | // free the CFG 70 | delete cfg; 71 | #endif 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/backward/backward-3-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | // Defining program variables 13 | z_var x(vfac["x"], crab::INT_TYPE, 32); 14 | z_var y(vfac["y"], crab::INT_TYPE, 32); 15 | // entry and exit block 16 | auto cfg = new z_cfg_t("bb1", "bb4"); 17 | // adding blocks 18 | z_basic_block_t &bb1 = cfg->insert("bb1"); 19 | z_basic_block_t &bb2 = cfg->insert("bb2"); 20 | z_basic_block_t &bb3 = cfg->insert("bb3"); 21 | z_basic_block_t &bb4 = cfg->insert("bb4"); 22 | // adding control flow 23 | bb1 >> bb2; 24 | bb2 >> bb3; 25 | bb3 >> bb2; 26 | bb2 >> bb4; 27 | 28 | // adding statements 29 | bb1.assign(x, 0); 30 | bb1.assign(y, 0); 31 | bb3.assume(x <= 99); 32 | bb3.add(x, x, 1); 33 | bb3.add(y, y, 1); 34 | bb4.assume(x >= 100); 35 | bb4.assertion(y <= 100); 36 | return cfg; 37 | } 38 | 39 | int main(int argc, char **argv) { 40 | #ifdef HAVE_APRON 41 | bool stats_enabled = false; 42 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 43 | return 0; 44 | } 45 | variable_factory_t vfac; 46 | z_cfg_t *cfg = prog(vfac); 47 | crab::outs() << *cfg << "\n"; 48 | 49 | z_box_apron_domain_t initial_states; 50 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 51 | 20, stats_enabled); 52 | 53 | // free the CFG 54 | delete cfg; 55 | #endif 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /tests/backward/backward-3-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | // Defining program variables 13 | z_var x(vfac["x"], crab::INT_TYPE, 32); 14 | z_var y(vfac["y"], crab::INT_TYPE, 32); 15 | // entry and exit block 16 | auto cfg = new z_cfg_t("bb1", "bb4"); 17 | // adding blocks 18 | z_basic_block_t &bb1 = cfg->insert("bb1"); 19 | z_basic_block_t &bb2 = cfg->insert("bb2"); 20 | z_basic_block_t &bb3 = cfg->insert("bb3"); 21 | z_basic_block_t &bb4 = cfg->insert("bb4"); 22 | // adding control flow 23 | bb1 >> bb2; 24 | bb2 >> bb3; 25 | bb3 >> bb2; 26 | bb2 >> bb4; 27 | 28 | // adding statements 29 | bb1.assign(x, 0); 30 | bb1.assign(y, 0); 31 | bb3.assume(x <= 99); 32 | bb3.add(x, x, 1); 33 | bb3.add(y, y, 1); 34 | bb4.assume(x >= 100); 35 | bb4.assertion(y <= 100); 36 | return cfg; 37 | } 38 | 39 | int main(int argc, char **argv) { 40 | #ifdef HAVE_ELINA 41 | bool stats_enabled = false; 42 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 43 | return 0; 44 | } 45 | variable_factory_t vfac; 46 | z_cfg_t *cfg = prog(vfac); 47 | crab::outs() << *cfg << "\n"; 48 | 49 | z_oct_elina_domain_t initial_states; 50 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 51 | 20, stats_enabled); 52 | 53 | // free the CFG 54 | delete cfg; 55 | #endif 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/backward/backward-4-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | // Defining program variables 13 | z_var x(vfac["x"], crab::INT_TYPE, 32); 14 | // entry and exit block 15 | auto cfg = new z_cfg_t("bb1", "bb4"); 16 | // adding blocks 17 | z_basic_block_t &bb1 = cfg->insert("bb1"); 18 | z_basic_block_t &bb2 = cfg->insert("bb2"); 19 | z_basic_block_t &bb3 = cfg->insert("bb3"); 20 | z_basic_block_t &bb4 = cfg->insert("bb4"); 21 | // adding control flow 22 | bb1 >> bb2; 23 | bb2 >> bb3; 24 | bb3 >> bb2; 25 | bb2 >> bb4; 26 | 27 | // adding statements 28 | bb1.assign(x, 0); 29 | bb3.assume(x <= 99); 30 | bb3.add(x, x, 1); 31 | bb4.assume(x >= 100); 32 | bb4.assertion(x <= 100); 33 | return cfg; 34 | } 35 | 36 | int main(int argc, char **argv) { 37 | #ifdef HAVE_APRON 38 | bool stats_enabled = false; 39 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 40 | return 0; 41 | } 42 | variable_factory_t vfac; 43 | z_cfg_t *cfg = prog(vfac); 44 | crab::outs() << *cfg << "\n"; 45 | 46 | z_box_apron_domain_t initial_states; 47 | // no thresholds, no narrowing 48 | backward_run(cfg, cfg->entry(), initial_states, 1, 0, 49 | 0, stats_enabled); 50 | 51 | // free the CFG 52 | delete cfg; 53 | #endif 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tests/backward/backward-4-boxes.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | // Defining program variables 13 | z_var x(vfac["x"], crab::INT_TYPE, 32); 14 | // entry and exit block 15 | auto cfg = new z_cfg_t("bb1", "bb4"); 16 | // adding blocks 17 | z_basic_block_t &bb1 = cfg->insert("bb1"); 18 | z_basic_block_t &bb2 = cfg->insert("bb2"); 19 | z_basic_block_t &bb3 = cfg->insert("bb3"); 20 | z_basic_block_t &bb4 = cfg->insert("bb4"); 21 | // adding control flow 22 | bb1 >> bb2; 23 | bb2 >> bb3; 24 | bb3 >> bb2; 25 | bb2 >> bb4; 26 | 27 | // adding statements 28 | bb1.assign(x, 0); 29 | bb3.assume(x <= 99); 30 | bb3.add(x, x, 1); 31 | bb4.assume(x >= 100); 32 | bb4.assertion(x <= 100); 33 | return cfg; 34 | } 35 | 36 | int main(int argc, char **argv) { 37 | #ifdef HAVE_LDD 38 | bool stats_enabled = false; 39 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 40 | return 0; 41 | } 42 | variable_factory_t vfac; 43 | z_cfg_t *cfg = prog(vfac); 44 | crab::outs() << *cfg << "\n"; 45 | 46 | z_boxes_domain_t initial_states; 47 | // no thresholds, no narrowing 48 | backward_run(cfg, cfg->entry(), initial_states, 1, 0, 0, 49 | stats_enabled); 50 | 51 | // free the CFG 52 | delete cfg; 53 | #endif 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tests/backward/backward-4-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | // Defining program variables 13 | z_var x(vfac["x"], crab::INT_TYPE, 32); 14 | // entry and exit block 15 | auto cfg = new z_cfg_t("bb1", "bb4"); 16 | // adding blocks 17 | z_basic_block_t &bb1 = cfg->insert("bb1"); 18 | z_basic_block_t &bb2 = cfg->insert("bb2"); 19 | z_basic_block_t &bb3 = cfg->insert("bb3"); 20 | z_basic_block_t &bb4 = cfg->insert("bb4"); 21 | // adding control flow 22 | bb1 >> bb2; 23 | bb2 >> bb3; 24 | bb3 >> bb2; 25 | bb2 >> bb4; 26 | 27 | // adding statements 28 | bb1.assign(x, 0); 29 | bb3.assume(x <= 99); 30 | bb3.add(x, x, 1); 31 | bb4.assume(x >= 100); 32 | bb4.assertion(x <= 100); 33 | return cfg; 34 | } 35 | 36 | int main(int argc, char **argv) { 37 | #ifdef HAVE_ELINA 38 | bool stats_enabled = false; 39 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 40 | return 0; 41 | } 42 | variable_factory_t vfac; 43 | z_cfg_t *cfg = prog(vfac); 44 | crab::outs() << *cfg << "\n"; 45 | 46 | z_oct_elina_domain_t initial_states; 47 | // no thresholds, no narrowing 48 | backward_run(cfg, cfg->entry(), initial_states, 1, 0, 49 | 0, stats_enabled); 50 | 51 | // free the CFG 52 | delete cfg; 53 | #endif 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tests/backward/backward-array-1-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Example from Monniaux's slides using arrays 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var a(vfac["M"], crab::ARR_INT_TYPE); 16 | z_var x(vfac["x"], crab::INT_TYPE, 32); 17 | z_var y(vfac["y"], crab::INT_TYPE, 32); 18 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 19 | // entry and exit block 20 | auto cfg = new z_cfg_t("entry", "bb3"); 21 | // adding blocks 22 | z_basic_block_t &entry = cfg->insert("entry"); 23 | z_basic_block_t &bb1 = cfg->insert("bb1"); 24 | z_basic_block_t &bb2 = cfg->insert("bb2"); 25 | z_basic_block_t &bb3 = cfg->insert("bb3"); 26 | // adding control flow 27 | entry >> bb1; 28 | entry >> bb2; 29 | bb1 >> bb3; 30 | bb2 >> bb3; 31 | 32 | // adding statements 33 | entry.array_load(x, a, 0, 4); 34 | 35 | bb1.assume(x >= 0); 36 | bb1.array_store(a, 4, x, 4); 37 | 38 | bb2.assume(x <= -1); 39 | bb2.assign(tmp, 0); 40 | bb2.sub(y, tmp, x); 41 | bb2.array_store(a, 4, y, 4); 42 | 43 | bb3.array_load(y, a, 4, 4); 44 | bb3.assume(y >= 1); 45 | bb3.assertion(x != 0); 46 | 47 | /* 48 | entry: 49 | x = array_load(M,0,sz=4); 50 | goto bb1,bb2; 51 | bb1: 52 | assume(-x <= 0); 53 | // {x=0, x>=1} => BOT 54 | array_store(M,4,x,sz=4); 55 | // {x = 0 , M[4] >= 1} 56 | goto bb3; 57 | 58 | bb2: 59 | assume(x <= -1); 60 | tmp = 0; 61 | y = tmp-x; 62 | array_store(M,4,y,sz=4); 63 | // {x = 0 , M[4] >= 1} ==> BOT (x = 0 and x <= -1 ) 64 | goto bb3; 65 | 66 | bb3: 67 | // {x = 0 , M[4] >= 1} 68 | y = array_load(M,4,sz=4); 69 | // {x = 0 , y >= 1} 70 | assume(-y <= -1); 71 | // {x = 0} 72 | assert(x != 0); 73 | */ 74 | return cfg; 75 | } 76 | 77 | int main(int argc, char **argv) { 78 | #ifdef HAVE_APRON 79 | bool stats_enabled = false; 80 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 81 | return 0; 82 | } 83 | variable_factory_t vfac; 84 | z_cfg_t *cfg = prog(vfac); 85 | crab::outs() << *cfg << "\n"; 86 | 87 | // A forward+backward analysis should prove the assertion holds. 88 | z_aa_box_apron_t initial_states; 89 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 20, 90 | stats_enabled); 91 | 92 | // free the CFG 93 | delete cfg; 94 | #endif 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /tests/backward/backward-array-1.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // Example from Monniaux's slides using arrays 5 | 6 | using namespace std; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | /* Example of how to build a CFG */ 12 | z_cfg_t *prog(variable_factory_t &vfac) { 13 | 14 | // Defining program variables 15 | z_var a(vfac["M"], crab::ARR_INT_TYPE); 16 | z_var x(vfac["x"], crab::INT_TYPE, 32); 17 | z_var y(vfac["y"], crab::INT_TYPE, 32); 18 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 19 | // entry and exit block 20 | auto cfg = new z_cfg_t("entry", "bb3"); 21 | // adding blocks 22 | z_basic_block_t &entry = cfg->insert("entry"); 23 | z_basic_block_t &bb1 = cfg->insert("bb1"); 24 | z_basic_block_t &bb2 = cfg->insert("bb2"); 25 | z_basic_block_t &bb3 = cfg->insert("bb3"); 26 | // adding control flow 27 | entry >> bb1; 28 | entry >> bb2; 29 | bb1 >> bb3; 30 | bb2 >> bb3; 31 | 32 | // adding statements 33 | entry.array_load(x, a, 0, 4); 34 | 35 | bb1.assume(x >= 0); 36 | bb1.array_store(a, 4, x, 4); 37 | 38 | bb2.assume(x <= -1); 39 | bb2.assign(tmp, 0); 40 | bb2.sub(y, tmp, x); 41 | bb2.array_store(a, 4, y, 4); 42 | 43 | bb3.array_load(y, a, 4, 4); 44 | bb3.assume(y >= 1); 45 | bb3.assertion(x != 0); 46 | 47 | /* 48 | entry: 49 | x = array_load(M,0,sz=4); 50 | goto bb1,bb2; 51 | bb1: 52 | assume(-x <= 0); 53 | // {x=0, x>=1} => BOT 54 | array_store(M,4,x,sz=4); 55 | // {x = 0 , M[4] >= 1} 56 | goto bb3; 57 | 58 | bb2: 59 | assume(x <= -1); 60 | tmp = 0; 61 | y = tmp-x; 62 | array_store(M,4,y,sz=4); 63 | // {x = 0 , M[4] >= 1} ==> BOT (x = 0 and x <= -1 ) 64 | goto bb3; 65 | 66 | bb3: 67 | // {x = 0 , M[4] >= 1} 68 | y = array_load(M,4,sz=4); 69 | // {x = 0 , y >= 1} 70 | assume(-y <= -1); 71 | // {x = 0} 72 | assert(x != 0); 73 | */ 74 | return cfg; 75 | } 76 | 77 | int main(int argc, char **argv) { 78 | bool stats_enabled = false; 79 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 80 | return 0; 81 | } 82 | variable_factory_t vfac; 83 | z_cfg_t *cfg = prog(vfac); 84 | crab::outs() << *cfg << "\n"; 85 | 86 | // A forward+backward analysis should prove the assertion holds. 87 | z_aa_int_t initial_states; 88 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 20, 89 | stats_enabled); 90 | 91 | // free the CFG 92 | delete cfg; 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /tests/backward/bakhirkin-apron.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Fig.5 from SAS'17 paper "Combining Forward and Backward Abstract 3 | Interpretation of Horn Clauses" by Bakhirkin and Monniaux. 4 | */ 5 | 6 | #include "../common.hpp" 7 | #include "../program_options.hpp" 8 | 9 | using namespace std; 10 | using namespace crab::cfg; 11 | using namespace crab::cfg_impl; 12 | using namespace crab::domain_impl; 13 | 14 | /* Example of how to build a CFG */ 15 | z_cfg_t *prog(variable_factory_t &vfac) { 16 | 17 | // Defining program variables 18 | z_var x(vfac["x"], crab::INT_TYPE, 32); 19 | z_var y(vfac["y"], crab::INT_TYPE, 32); 20 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 21 | // entry and exit block 22 | auto cfg = new z_cfg_t("entry", "ret"); 23 | // adding blocks 24 | z_basic_block_t &entry = cfg->insert("entry"); 25 | z_basic_block_t &header1 = cfg->insert("header1"); 26 | z_basic_block_t &body1 = cfg->insert("body1"); 27 | z_basic_block_t &exit1 = cfg->insert("exit1"); 28 | z_basic_block_t &ifxpos = cfg->insert("ifxpos"); 29 | z_basic_block_t &header2 = cfg->insert("header2"); 30 | z_basic_block_t &body2 = cfg->insert("body2"); 31 | z_basic_block_t &exit2 = cfg->insert("exit2"); 32 | z_basic_block_t &ret = cfg->insert("ret"); 33 | 34 | // adding control flow 35 | entry >> header1; 36 | header1 >> body1; 37 | body1 >> header1; 38 | header1 >> exit1; 39 | exit1 >> ifxpos; 40 | exit1 >> ret; 41 | ifxpos >> header2; 42 | header2 >> body2; 43 | body2 >> header2; 44 | header2 >> exit2; 45 | exit2 >> ret; 46 | 47 | /* 48 | x=0;y=*; 49 | while(*) 50 | x += y; 51 | if (x>0) { 52 | while(*) 53 | y += x; 54 | assert(y>=0); 55 | } 56 | */ 57 | entry.assign(x, 0); 58 | body1.add(x, x, y); 59 | ifxpos.assume(x >= 1); 60 | body2.add(y, y, x); 61 | exit2.assertion(y >= 0); 62 | return cfg; 63 | } 64 | 65 | int main(int argc, char **argv) { 66 | #ifdef HAVE_APRON 67 | bool stats_enabled = false; 68 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 69 | return 0; 70 | } 71 | variable_factory_t vfac; 72 | z_cfg_t *cfg = prog(vfac); 73 | crab::outs() << *cfg << "\n"; 74 | 75 | { 76 | z_box_apron_domain_t initial_states; 77 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 78 | 20, stats_enabled); 79 | } 80 | 81 | { 82 | z_pk_apron_domain_t initial_states; 83 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 84 | 20, stats_enabled); 85 | } 86 | 87 | // free the CFG 88 | delete cfg; 89 | #endif 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /tests/backward/bakhirkin-elina.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Fig.5 from SAS'17 paper "Combining Forward and Backward Abstract 3 | Interpretation of Horn Clauses" by Bakhirkin and Monniaux. 4 | */ 5 | 6 | #include "../common.hpp" 7 | #include "../program_options.hpp" 8 | 9 | using namespace std; 10 | using namespace crab::cfg; 11 | using namespace crab::cfg_impl; 12 | using namespace crab::domain_impl; 13 | 14 | /* Example of how to build a CFG */ 15 | z_cfg_t *prog(variable_factory_t &vfac) { 16 | 17 | // Defining program variables 18 | z_var x(vfac["x"], crab::INT_TYPE, 32); 19 | z_var y(vfac["y"], crab::INT_TYPE, 32); 20 | z_var tmp(vfac["tmp"], crab::INT_TYPE, 32); 21 | // entry and exit block 22 | auto cfg = new z_cfg_t("entry", "ret"); 23 | // adding blocks 24 | z_basic_block_t &entry = cfg->insert("entry"); 25 | z_basic_block_t &header1 = cfg->insert("header1"); 26 | z_basic_block_t &body1 = cfg->insert("body1"); 27 | z_basic_block_t &exit1 = cfg->insert("exit1"); 28 | z_basic_block_t &ifxpos = cfg->insert("ifxpos"); 29 | z_basic_block_t &header2 = cfg->insert("header2"); 30 | z_basic_block_t &body2 = cfg->insert("body2"); 31 | z_basic_block_t &exit2 = cfg->insert("exit2"); 32 | z_basic_block_t &ret = cfg->insert("ret"); 33 | 34 | // adding control flow 35 | entry >> header1; 36 | header1 >> body1; 37 | body1 >> header1; 38 | header1 >> exit1; 39 | exit1 >> ifxpos; 40 | exit1 >> ret; 41 | ifxpos >> header2; 42 | header2 >> body2; 43 | body2 >> header2; 44 | header2 >> exit2; 45 | exit2 >> ret; 46 | 47 | /* 48 | x=0;y=*; 49 | while(*) 50 | x += y; 51 | if (x>0) { 52 | while(*) 53 | y += x; 54 | assert(y>=0); 55 | } 56 | */ 57 | entry.assign(x, 0); 58 | body1.add(x, x, y); 59 | ifxpos.assume(x >= 1); 60 | body2.add(y, y, x); 61 | exit2.assertion(y >= 0); 62 | return cfg; 63 | } 64 | 65 | int main(int argc, char **argv) { 66 | #ifdef HAVE_ELINA 67 | bool stats_enabled = false; 68 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 69 | return 0; 70 | } 71 | variable_factory_t vfac; 72 | z_cfg_t *cfg = prog(vfac); 73 | crab::outs() << *cfg << "\n"; 74 | 75 | z_oct_elina_domain_t initial_states; 76 | backward_run(cfg, cfg->entry(), initial_states, 1, 2, 77 | 20, stats_enabled); 78 | // free the CFG 79 | delete cfg; 80 | #endif 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /tests/backward/unittests-backward-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | int main(int argc, char **argv) { 10 | #ifdef HAVE_APRON 11 | bool stats_enabled = false; 12 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 13 | return 0; 14 | } 15 | variable_factory_t vfac; 16 | z_var M(vfac["M"], crab::ARR_INT_TYPE); 17 | z_var x(vfac["x"], crab::INT_TYPE, 32); 18 | z_var y(vfac["y"], crab::INT_TYPE, 32); 19 | z_var z(vfac["z"], crab::INT_TYPE, 32); 20 | 21 | { // backward array load 22 | z_aa_box_apron_t pre, inv; 23 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 24 | pre += (y >= 1); 25 | pre.backward_array_load(y, M, 4, 4, inv); 26 | crab::outs() << "EXPECTED: {M[4..7] >= 1} \n"; 27 | crab::outs() << "RESULT: " << pre << "\n"; 28 | } 29 | 30 | crab::outs() << "============================\n"; 31 | 32 | { // backward array store 33 | z_aa_box_apron_t pre, inv; 34 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 35 | pre += (x >= 2); 36 | pre += (y >= 1); 37 | /// pre += (z >= -10); 38 | pre.array_store(M, 4, 4, x, false); 39 | pre.backward_array_store(M, 4, 4, z, false, inv); 40 | crab::outs() << "EXPECTED: {z >= 2, ...}\n"; 41 | crab::outs() << "RESULT: " << pre << "\n"; 42 | } 43 | 44 | crab::outs() << "============================\n"; 45 | 46 | { // backward array store 47 | z_aa_box_apron_t pre, inv; 48 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 49 | pre += (x >= 2); 50 | pre += (y >= 1); 51 | pre += (z == -10); 52 | pre.array_store(M, 4, 4, x, false); 53 | pre.backward_array_store(M, 4, 4, z, false, inv); 54 | crab::outs() << "EXPECTED: _|_\n"; 55 | crab::outs() << "RESULT: " << pre << "\n"; 56 | } 57 | 58 | crab::outs() << "============================\n"; 59 | 60 | { // backward array store 61 | z_aa_box_apron_t pre, inv; 62 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 63 | pre += (x >= 2); 64 | pre += (y >= 1); 65 | pre.array_store(M, 4, 4, x, false); 66 | pre.backward_array_store(M, 4, 4, y, false, inv); 67 | crab::outs() << "EXPECTED: {y >= 2, ...}\n"; 68 | crab::outs() << "RESULT: " << pre << "\n"; 69 | } 70 | #endif 71 | 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/backward/unittests-backward-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | int main(int argc, char **argv) { 10 | #ifdef HAVE_ELINA 11 | #if 0 12 | bool stats_enabled = false; 13 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 14 | return 0; 15 | } 16 | variable_factory_t vfac; 17 | z_var M(vfac["M"], crab::ARR_INT_TYPE); 18 | z_var x(vfac["x"], crab::INT_TYPE, 32); 19 | z_var y(vfac["y"], crab::INT_TYPE, 32); 20 | z_var z(vfac["z"], crab::INT_TYPE, 32); 21 | 22 | 23 | { // backward array load 24 | z_aa_zones_elina_t pre, inv; 25 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 26 | pre += (y >= 1); 27 | pre.backward_array_load(y, M, 4, 4, inv); 28 | crab::outs() << "EXPECTED: {M[4..7] >= 1} \n"; 29 | crab::outs() << "RESULT: " << pre << "\n"; 30 | } 31 | 32 | crab::outs() << "============================\n"; 33 | 34 | { // backward array store 35 | z_aa_zones_elina_t pre, inv; 36 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 37 | pre += (x >= 2); 38 | pre += (y >= 1); 39 | ///pre += (z >= -10); 40 | pre.array_store(M, 4, 4, x, false); 41 | pre.backward_array_store(M, 4, 4, z, false, inv); 42 | crab::outs() << "EXPECTED: {z >= 2, ...}\n"; 43 | crab::outs() << "RESULT: " << pre << "\n"; 44 | } 45 | 46 | crab::outs() << "============================\n"; 47 | 48 | { // backward array store 49 | z_aa_zones_elina_t pre, inv; 50 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 51 | pre += (x >= 2); 52 | pre += (y >= 1); 53 | pre += (z == -10); 54 | pre.array_store(M, 4, 4, x, false); 55 | pre.backward_array_store(M, 4, 4, z, false, inv); 56 | crab::outs() << "EXPECTED: _|_\n"; 57 | crab::outs() << "RESULT: " << pre << "\n"; 58 | } 59 | 60 | crab::outs() << "============================\n"; 61 | 62 | { // backward array store 63 | z_aa_zones_elina_t pre, inv; 64 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 65 | pre += (x >= 2); 66 | pre += (y >= 1); 67 | pre.array_store(M, 4, 4, x, false); 68 | pre.backward_array_store(M, 4, 4, y, false, inv); 69 | crab::outs() << "EXPECTED: {y >= 2, ...}\n"; 70 | crab::outs() << "RESULT: " << pre << "\n"; 71 | } 72 | #endif 73 | #endif 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /tests/backward/unittests-backward.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | int main(int argc, char **argv) { 10 | bool stats_enabled = false; 11 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 12 | return 0; 13 | } 14 | variable_factory_t vfac; 15 | z_var M(vfac["M"], crab::ARR_INT_TYPE); 16 | z_var x(vfac["x"], crab::INT_TYPE, 32); 17 | z_var y(vfac["y"], crab::INT_TYPE, 32); 18 | z_var z(vfac["z"], crab::INT_TYPE, 32); 19 | 20 | { // backward array load 21 | z_aa_int_t pre, inv; 22 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 23 | pre += (y >= 1); 24 | pre.backward_array_load(y, M, 4, 4, inv); 25 | crab::outs() << "EXPECTED: {M[4..7] >= 1} \n"; 26 | crab::outs() << "RESULT: " << pre << "\n"; 27 | } 28 | 29 | crab::outs() << "============================\n"; 30 | 31 | { // backward array store 32 | z_aa_int_t pre, inv; 33 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 34 | pre += (x >= 2); 35 | pre += (y >= 1); 36 | /// pre += (z >= -10); 37 | pre.array_store(M, 4, 4, x, false); 38 | pre.backward_array_store(M, 4, 4, z, false, inv); 39 | crab::outs() << "EXPECTED: {z >= 2, ...}\n"; 40 | crab::outs() << "RESULT: " << pre << "\n"; 41 | } 42 | 43 | crab::outs() << "============================\n"; 44 | 45 | { // backward array store 46 | z_aa_int_t pre, inv; 47 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 48 | pre += (x >= 2); 49 | pre += (y >= 1); 50 | pre += (z == -10); 51 | pre.array_store(M, 4, 4, x, false); 52 | pre.backward_array_store(M, 4, 4, z, false, inv); 53 | crab::outs() << "EXPECTED: _|_\n"; 54 | crab::outs() << "RESULT: " << pre << "\n"; 55 | } 56 | 57 | crab::outs() << "============================\n"; 58 | 59 | { // backward array store 60 | z_aa_int_t pre, inv; 61 | crab::outs() << "Test using " << pre.domain_name() << "\n"; 62 | pre += (x >= 2); 63 | pre += (y >= 1); 64 | pre.array_store(M, 4, 4, x, false); 65 | pre.backward_array_store(M, 4, 4, y, false, inv); 66 | crab::outs() << "EXPECTED: {y >= 2, ...}\n"; 67 | crab::outs() << "RESULT: " << pre << "\n"; 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /tests/bcrab.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __CRAB_BACKWARD_ANALYZERS__ 2 | #define __CRAB_BACKWARD_ANALYZERS__ 3 | 4 | #include "./crab_lang.hpp" 5 | #include "./crab_dom.hpp" 6 | 7 | template 8 | extern void z_backward_run(crab::cfg_impl::z_cfg_t *cfg, 9 | crab::cfg_impl::basic_block_label_t entry, 10 | Dom initial_states, unsigned widening, 11 | unsigned narrowing, unsigned jump_set_size, 12 | bool enable_stats); 13 | 14 | template 15 | void backward_run(crab::cfg_impl::z_cfg_t *cfg, 16 | crab::cfg_impl::basic_block_label_t entry, Dom initial_states, 17 | unsigned widening, unsigned narrowing, unsigned jump_set_size, 18 | bool enable_stats) { 19 | #ifdef USE_GENERIC_WRAPPER 20 | using namespace crab::domain_impl; 21 | z_abs_domain_t init(initial_states); 22 | z_backward_run(cfg, entry, init, widening, narrowing, jump_set_size, 23 | enable_stats); 24 | #else 25 | z_backward_run(cfg, entry, initial_states, widening, narrowing, jump_set_size, 26 | enable_stats); 27 | #endif 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tests/bcrab_inst.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Here all explicit instantiations 3 | 4 | #define Z_BWD_RUNNER(DOM) \ 5 | template void z_backward_run(crab::cfg_impl::z_cfg_t *, \ 6 | crab::cfg_impl::basic_block_label_t, DOM, \ 7 | unsigned, unsigned, unsigned, bool); 8 | 9 | #ifdef USE_GENERIC_WRAPPER 10 | Z_BWD_RUNNER(crab::domain_impl::z_abs_domain_t) 11 | #else 12 | Z_BWD_RUNNER(crab::domain_impl::z_interval_domain_t) 13 | Z_BWD_RUNNER(crab::domain_impl::z_boxes_domain_t) 14 | Z_BWD_RUNNER(crab::domain_impl::z_box_apron_domain_t) 15 | Z_BWD_RUNNER(crab::domain_impl::z_oct_apron_domain_t) 16 | Z_BWD_RUNNER(crab::domain_impl::z_pk_apron_domain_t) 17 | Z_BWD_RUNNER(crab::domain_impl::z_oct_elina_domain_t) 18 | Z_BWD_RUNNER(crab::domain_impl::z_aa_int_t) 19 | Z_BWD_RUNNER(crab::domain_impl::z_aa_box_apron_t) 20 | Z_BWD_RUNNER(crab::domain_impl::z_aa_zones_elina_t) 21 | #endif 22 | -------------------------------------------------------------------------------- /tests/checkers/entailment.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | #include "crab/domains/abstract_domain_specialized_traits.hpp" 4 | 5 | using namespace std; 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | template void check_entailment(Dom inv, const z_lin_cst_t &cst) { 11 | bool r = inv.entails(cst); 12 | if (r) { 13 | crab::outs() << inv << " entails " << cst << "\n"; 14 | } else { 15 | crab::outs() << inv << " does not entail " << cst << "\n"; 16 | } 17 | } 18 | 19 | int main(int argc, char **argv) { 20 | 21 | bool stats_enabled = false; 22 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 23 | return 0; 24 | } 25 | variable_factory_t vfac; 26 | z_var x(vfac["x"], crab::INT_TYPE, 32); 27 | z_var y(vfac["y"], crab::INT_TYPE, 32); 28 | 29 | z_sdbm_domain_t inv1; 30 | inv1 += crab::cfg_impl::z_lin_cst_t(x >= 5); 31 | inv1 += crab::cfg_impl::z_lin_cst_t(x <= 10); 32 | crab::cfg_impl::z_lin_cst_t c1(x == 7); 33 | crab::cfg_impl::z_lin_cst_t c2(x == 11); 34 | check_entailment(inv1, c1); 35 | check_entailment(inv1, c2); 36 | 37 | z_sdbm_domain_t inv2; 38 | inv2 += crab::cfg_impl::z_lin_cst_t(x == 5); 39 | inv2 += crab::cfg_impl::z_lin_cst_t(y >= 0); 40 | inv2 += crab::cfg_impl::z_lin_cst_t(y <= 10); 41 | crab::cfg_impl::z_lin_cst_t c3(x == 5); 42 | crab::cfg_impl::z_lin_cst_t c4(x == 7); 43 | crab::cfg_impl::z_lin_cst_t c5(y != 42); 44 | check_entailment(inv2, c3); 45 | check_entailment(inv2, c4); 46 | check_entailment(inv2, c5); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests/common.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __TESTS_COMMON__ 2 | #define __TESTS_COMMON__ 3 | 4 | #include "./bcrab.hpp" 5 | #include "./crab.hpp" 6 | #include "./crab_dom.hpp" 7 | #include "./crab_lang.hpp" 8 | #include "./icrab.hpp" 9 | 10 | #endif /*__TESTS_COMMON__*/ 11 | -------------------------------------------------------------------------------- /tests/domains/flat_bool_domain2.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* 10 | * Crab distinguishes between integer and booleans. 11 | * Example of program with booleans 12 | */ 13 | 14 | z_cfg_t *prog(variable_factory_t &vfac) { 15 | 16 | /* 17 | i := 0; 18 | n := *; 19 | b := (n == 10); 20 | assume(b); 21 | while (i <= n) { 22 | i++; 23 | } 24 | assert(i == 10); 25 | */ 26 | 27 | // Defining program variables 28 | z_var i(vfac["i"], crab::INT_TYPE, 32); 29 | z_var b(vfac["b"], crab::BOOL_TYPE, 1); 30 | z_var n(vfac["n"], crab::INT_TYPE, 32); 31 | 32 | // entry and exit block 33 | auto cfg = new z_cfg_t("entry", "ret"); 34 | // adding blocks 35 | z_basic_block_t &entry = cfg->insert("entry"); 36 | z_basic_block_t &bb1 = cfg->insert("bb1"); 37 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 38 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 39 | z_basic_block_t &bb2 = cfg->insert("bb2"); 40 | z_basic_block_t &ret = cfg->insert("ret"); 41 | // adding control flow 42 | entry >> bb1; 43 | bb1 >> bb1_t; 44 | bb1 >> bb1_f; 45 | bb1_t >> bb2; 46 | bb2 >> bb1; 47 | bb1_f >> ret; 48 | // adding statements 49 | entry.assign(i, z_number(0)); 50 | entry.havoc(n); 51 | entry.bool_assign(b, n == z_number(10)); 52 | // entry.assign(n, z_number(1)); 53 | entry.bool_assume(b); 54 | bb1_t.assume(i <= n); 55 | bb2.add(i, i, 1); 56 | bb1_f.assume(i >= n + 1); 57 | ret.assertion(i == z_number(10)); 58 | 59 | return cfg; 60 | } 61 | 62 | /* Example of how to infer invariants from the above CFG */ 63 | int main(int argc, char **argv) { 64 | bool stats_enabled = false; 65 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 66 | return 0; 67 | } 68 | variable_factory_t vfac; 69 | // precise 70 | z_cfg_t *cfg = prog(vfac); 71 | crab::outs() << *cfg << "\n"; 72 | z_bool_interval_domain_t init; 73 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 74 | delete cfg; 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /tests/domains/flat_bool_domain3.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* 10 | * Crab distinguishes between integer and booleans. 11 | * Example of program with booleans 12 | */ 13 | 14 | z_cfg_t *prog(variable_factory_t &vfac) { 15 | 16 | /* 17 | i := 0; 18 | n := *; 19 | b := (n == 10) 20 | if (*) { 21 | n : = 1; 22 | } 23 | assume(b); 24 | while (i <= n) { 25 | i++; 26 | } 27 | assert(i == 10); 28 | */ 29 | 30 | // Defining program variables 31 | z_var i(vfac["i"], crab::INT_TYPE, 32); 32 | z_var b(vfac["b"], crab::BOOL_TYPE, 1); 33 | z_var n(vfac["n"], crab::INT_TYPE, 32); 34 | 35 | // entry and exit block 36 | auto cfg = new z_cfg_t("entry", "ret"); 37 | // adding blocks 38 | z_basic_block_t &entry = cfg->insert("entry"); 39 | z_basic_block_t &bb0 = cfg->insert("bb0"); 40 | z_basic_block_t &entry_cnt = cfg->insert("entry_cnt"); 41 | z_basic_block_t &bb1 = cfg->insert("bb1"); 42 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 43 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 44 | z_basic_block_t &bb2 = cfg->insert("bb2"); 45 | z_basic_block_t &ret = cfg->insert("ret"); 46 | // adding control flow 47 | entry >> bb0; 48 | bb0 >> entry_cnt; 49 | entry >> entry_cnt; 50 | entry_cnt >> bb1; 51 | bb1 >> bb1_t; 52 | bb1 >> bb1_f; 53 | bb1_t >> bb2; 54 | bb2 >> bb1; 55 | bb1_f >> ret; 56 | // adding statements 57 | entry.assign(i, z_number(0)); 58 | entry.havoc(n); 59 | entry.bool_assign(b, n == z_number(10)); 60 | bb0.assign(n, z_number(1)); 61 | entry_cnt.bool_assume(b); 62 | bb1_t.assume(i <= n); 63 | bb2.add(i, i, 1); 64 | bb1_f.assume(i >= n + 1); 65 | ret.assertion(i == 10); 66 | 67 | return cfg; 68 | } 69 | 70 | /* Example of how to infer invariants from the above CFG */ 71 | int main(int argc, char **argv) { 72 | bool stats_enabled = false; 73 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 74 | return 0; 75 | } 76 | variable_factory_t vfac; 77 | // imprecise 78 | z_cfg_t *cfg = prog(vfac); 79 | crab::outs() << *cfg << "\n"; 80 | z_bool_interval_domain_t init; 81 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 82 | delete cfg; 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /tests/domains/flat_bool_domain4.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog(variable_factory_t &vfac) { 10 | 11 | /* 12 | i, n: 64 integer 13 | n1 : 32 integer 14 | 15 | i := 0; 16 | n := *; 17 | n1 := truncate(n); 18 | b1 := (n1 == 9); 19 | assume(b1); 20 | while (i <= n) { 21 | i++; 22 | } 23 | assert(i == 10); 24 | */ 25 | 26 | // Defining program variables 27 | z_var i(vfac["i"], crab::INT_TYPE, 64); 28 | z_var b1(vfac["b1"], crab::BOOL_TYPE, 1); 29 | z_var n(vfac["n"], crab::INT_TYPE, 64); 30 | z_var n1(vfac["n1"], crab::INT_TYPE, 32); 31 | 32 | // entry and exit block 33 | auto cfg = new z_cfg_t("entry", "ret"); 34 | // adding blocks 35 | z_basic_block_t &entry = cfg->insert("entry"); 36 | z_basic_block_t &bb1 = cfg->insert("bb1"); 37 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 38 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 39 | z_basic_block_t &bb2 = cfg->insert("bb2"); 40 | z_basic_block_t &ret = cfg->insert("ret"); 41 | // adding control flow 42 | entry >> bb1; 43 | bb1 >> bb1_t; 44 | bb1 >> bb1_f; 45 | bb1_t >> bb2; 46 | bb2 >> bb1; 47 | bb1_f >> ret; 48 | // adding statements 49 | entry.assign(i, z_number(0)); 50 | entry.havoc(n); 51 | entry.truncate(n, n1); 52 | entry.bool_assign(b1, n1 == z_number(9)); 53 | entry.bool_assume(b1); 54 | bb1_t.assume(i <= n); 55 | bb2.add(i, i, 1); 56 | bb1_f.assume(i >= n + 1); 57 | ret.assertion(i == 10); 58 | 59 | return cfg; 60 | } 61 | 62 | /* Example of how to infer invariants from the above CFG */ 63 | int main(int argc, char **argv) { 64 | bool stats_enabled = false; 65 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 66 | return 0; 67 | } 68 | variable_factory_t vfac; 69 | z_cfg_t *cfg = prog(vfac); 70 | crab::outs() << *cfg << "\n"; 71 | 72 | { 73 | z_bool_interval_domain_t init; 74 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 75 | } 76 | { 77 | z_bool_num_domain_t init; 78 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 79 | } 80 | 81 | // free the CFG 82 | delete cfg; 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /tests/domains/flat_bool_domain6.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | int main(int argc, char **argv) { 10 | bool stats_enabled = false; 11 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 12 | return 0; 13 | } 14 | /* 15 | 16 | bb1: 17 | havoc(b1) 18 | havoc(b2) 19 | b3 = b1&_b2; 20 | assume(b3); 21 | b4 = b1&_b3; 22 | goto bb2, bb4; 23 | bb2: 24 | assume(b4); 25 | goto bb3; 26 | bb4: 27 | assume(not(b4)); 28 | assume(false); 29 | goto bb3; 30 | bb3: 31 | assert(b2) 32 | assert(b4) 33 | */ 34 | 35 | variable_factory_t vfac; 36 | // entry and exit block 37 | z_cfg_t cfg("bb1", "bb3"); 38 | // adding blocks 39 | z_basic_block_t &bb1 = cfg.insert("bb1"); 40 | z_basic_block_t &bb2 = cfg.insert("bb2"); 41 | z_basic_block_t &bb3 = cfg.insert("bb3"); 42 | z_basic_block_t &bb4 = cfg.insert("bb4"); 43 | // adding control flow 44 | bb1 >> bb2; 45 | bb1 >> bb4; 46 | bb2 >> bb3; 47 | bb4 >> bb3; 48 | z_var b1(vfac["b1"], crab::BOOL_TYPE, 1); 49 | z_var b2(vfac["b2"], crab::BOOL_TYPE, 1); 50 | z_var b3(vfac["b3"], crab::BOOL_TYPE, 1); 51 | z_var b4(vfac["b4"], crab::BOOL_TYPE, 1); 52 | // adding statements 53 | bb1.havoc(b1); 54 | bb1.havoc(b2); 55 | bb1.bool_and(b3, b1, b2); 56 | bb1.bool_assume(b3); 57 | bb1.bool_and(b4, b1, b3); 58 | ///// 59 | bb2.bool_assume(b4); 60 | ///// 61 | bb4.bool_not_assume(b4); 62 | bb4.assume(z_lin_cst_t::get_false()); 63 | ///// 64 | bb3.bool_assert(b2); 65 | bb3.bool_assert(b4); 66 | 67 | z_bool_num_domain_t init; 68 | run_and_check(&cfg, cfg.entry(), init, false, 1, 2, 20, stats_enabled); 69 | 70 | return 0; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /tests/domains/flat_bool_domain7.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | int main(int argc, char **argv) { 10 | bool stats_enabled = false; 11 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 12 | return 0; 13 | } 14 | /* 15 | bb: 16 | assume(x >= 0) 17 | b1 = (y = 1); 18 | b2 = (x >= 0); 19 | b3 = (x <= 10); 20 | b4 = true; 21 | b5 = ite(b2,b3,b4); 22 | b6 = b1 & b5; 23 | assume(b6); 24 | exit 25 | assert(y == 1); 26 | assert(x >= 0); 27 | assert(x <= 10); 28 | */ 29 | 30 | variable_factory_t vfac; 31 | // entry and exit block 32 | z_cfg_t cfg("entry", "exit"); 33 | // adding blocks 34 | z_basic_block_t &entry = cfg.insert("entry"); 35 | z_basic_block_t &exit = cfg.insert("exit"); 36 | // adding control flow 37 | entry >> exit; 38 | z_var b1(vfac["b1"], crab::BOOL_TYPE, 1); 39 | z_var b2(vfac["b2"], crab::BOOL_TYPE, 1); 40 | z_var b3(vfac["b3"], crab::BOOL_TYPE, 1); 41 | z_var b4(vfac["b4"], crab::BOOL_TYPE, 1); 42 | z_var b5(vfac["b5"], crab::BOOL_TYPE, 1); 43 | z_var b6(vfac["b6"], crab::BOOL_TYPE, 1); 44 | z_var x(vfac["x"], crab::INT_TYPE, 32); 45 | z_var y(vfac["y"], crab::INT_TYPE, 32); 46 | 47 | 48 | // adding statements 49 | entry.assume(z_lin_exp_t(x) >= 0); 50 | entry.bool_assign(b1, z_lin_exp_t(y) == 1); 51 | entry.bool_assign(b2, z_lin_exp_t(x) >= 0); 52 | entry.bool_assign(b3, z_lin_exp_t(x) <= 10); 53 | entry.bool_assign(b4, z_lin_cst_t::get_true()); 54 | entry.bool_select(b5, b2, b3, b4); 55 | entry.bool_and(b6, b1, b5); 56 | entry.bool_assume(b6); 57 | 58 | // All assertions are OK 59 | exit.assertion(z_lin_exp_t(y) >= 1); 60 | exit.assertion(z_lin_exp_t(x) >= 0); 61 | exit.assertion(z_lin_exp_t(x) <= 10); 62 | z_bool_num_domain_t init; 63 | run_and_check(&cfg, cfg.entry(), init, false, 1, 2, 20, stats_enabled); 64 | 65 | return 0; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /tests/domains/flat_bool_domain8.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog1(variable_factory_t &vfac) { 10 | /* 11 | entry: 12 | havoc(x) 13 | havoc(y) 14 | b1 = x <= y 15 | assume(b1) 16 | assume(y >= 0) 17 | goto bb1, bb2 18 | bb1: 19 | assume x >= 0 20 | b2 = item(y <= -1, true, b1) 21 | goto exit 22 | bb2 23 | assume x <= -1 24 | b2 = item(y <= -1, b1, false) 25 | goto exit 26 | exit: 27 | assert(b2) // EXPECTED FALSE (e.g., x=-1, y=1) 28 | */ 29 | 30 | // entry and exit block 31 | auto cfg = new z_cfg_t("entry", "exit"); 32 | // adding blocks 33 | z_basic_block_t &entry = cfg->insert("entry"); 34 | z_basic_block_t &exit = cfg->insert("exit"); 35 | z_basic_block_t &bb1 = cfg->insert("bb1"); 36 | z_basic_block_t &bb2 = cfg->insert("bb2"); 37 | // adding control flow 38 | entry >> bb1; 39 | entry >> bb2; 40 | bb1 >> exit; 41 | bb2 >> exit; 42 | 43 | z_var b1(vfac["b1"], crab::BOOL_TYPE, 1); 44 | z_var b2(vfac["b2"], crab::BOOL_TYPE, 1); 45 | z_var b3(vfac["b3"], crab::BOOL_TYPE, 1); 46 | z_var bTrue(vfac["bTrue"], crab::BOOL_TYPE, 1); 47 | z_var bFalse(vfac["bFalse"], crab::BOOL_TYPE, 1); 48 | z_var x(vfac["x"], crab::INT_TYPE, 32); 49 | z_var y(vfac["y"], crab::INT_TYPE, 32); 50 | 51 | // adding statements 52 | entry.havoc(x); 53 | entry.havoc(y); 54 | entry.bool_assign(b1, z_lin_exp_t(x) <= z_lin_exp_t(y)); 55 | entry.bool_assume(b1); 56 | entry.assume(z_lin_exp_t(y) >= 0); 57 | entry.bool_assign(b3, z_lin_exp_t(y) <= -1); 58 | entry.bool_assign(bTrue, z_lin_cst_t::get_true()); 59 | entry.bool_assign(bFalse, z_lin_cst_t::get_false()); 60 | bb1.assume(z_lin_exp_t(x) >= 0); 61 | bb1.bool_select(b2, b3, bTrue, b1); 62 | bb2.assume(z_lin_exp_t(x) <= -1); 63 | bb2.bool_select(b2, b3, b1, bFalse); 64 | // The assertion is NOT provable 65 | exit.bool_assert(b2); 66 | 67 | return cfg; 68 | } 69 | 70 | 71 | int main(int argc, char **argv) { 72 | bool stats_enabled = false; 73 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 74 | return 0; 75 | } 76 | 77 | variable_factory_t vfac; 78 | { 79 | z_cfg_t *cfg = prog1(vfac); 80 | //crab::outs() << *cfg << "\n"; 81 | z_bool_num_domain_t init; 82 | run_and_check(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 83 | delete cfg; 84 | } 85 | 86 | return 0; 87 | 88 | } 89 | -------------------------------------------------------------------------------- /tests/domains/gen_abs_dom.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace crab::cfg; 5 | using namespace crab::cfg_impl; 6 | using namespace crab::domain_impl; 7 | using namespace ikos; 8 | 9 | int main(int argc, char **argv) { 10 | bool stats_enabled = false; 11 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 12 | return 0; 13 | } 14 | variable_factory_t vfac; 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var z(vfac["z"], crab::INT_TYPE, 32); 18 | z_var w(vfac["w"], crab::INT_TYPE, 32); 19 | 20 | z_sdbm_domain_t sdbm_top; 21 | z_abs_domain_t dom1(sdbm_top); 22 | dom1 += (x >= y); 23 | dom1 += (z >= 10); 24 | // This also allowed because the constructor is not explicit 25 | z_abs_domain_t dom2 = sdbm_top; 26 | dom2 += (x >= y); 27 | dom2 += (z >= 5); 28 | 29 | auto dom3 = dom1 | dom2; 30 | crab::outs() << "Join(" << dom1 << "," << dom2 << ")=" << dom3 << "\n"; 31 | 32 | auto dom4 = dom1 & dom2; 33 | crab::outs() << "Meet(" << dom1 << "," << dom2 << ")=" << dom4 << "\n"; 34 | 35 | auto dom5 = dom1 || dom2; 36 | crab::outs() << "Widen(" << dom1 << "," << dom2 << ")=" << dom5 << "\n"; 37 | 38 | z_abs_domain_t dom6(dom1); 39 | dom6.apply(OP_ADDITION, w, x, 5); 40 | crab::outs() << w << ":=" << x << "+ 5 in " << dom1 << "=" << dom6 << "\n"; 41 | 42 | //// This should not compile: 43 | // z_abs_domain_t dom4; 44 | // crab::outs() << dom4; 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/domains/lookahead-widening.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | /* 13 | x := 0; 14 | y := 0; 15 | while (true) { 16 | if (x<=50) { 17 | y++; 18 | } else { 19 | y--; 20 | } 21 | if (y < 0) break; 22 | x++; 23 | } 24 | */ 25 | // Defining program variables 26 | z_var x(vfac["x"], crab::INT_TYPE, 32); 27 | z_var y(vfac["y"], crab::INT_TYPE, 32); 28 | // entry and exit block 29 | auto cfg = new z_cfg_t("entry", "exit"); 30 | // adding blocks 31 | z_basic_block_t &entry = cfg->insert("entry"); 32 | z_basic_block_t &bb1 = cfg->insert("bb1"); 33 | z_basic_block_t &bb2 = cfg->insert("bb2"); 34 | z_basic_block_t &bb3 = cfg->insert("bb3"); 35 | z_basic_block_t &bb4 = cfg->insert("bb4"); 36 | z_basic_block_t &bb5 = cfg->insert("bb5"); 37 | z_basic_block_t &bb6 = cfg->insert("bb6"); 38 | z_basic_block_t &bb7 = cfg->insert("bb7"); 39 | z_basic_block_t &exit = cfg->insert("exit"); 40 | // adding control flow 41 | entry >> bb1; 42 | bb1 >> bb2; 43 | bb1 >> bb3; 44 | bb2 >> bb4; 45 | bb3 >> bb4; 46 | bb4 >> bb5; 47 | bb4 >> bb7; 48 | bb5 >> bb6; 49 | bb6 >> bb1; 50 | bb7 >> exit; 51 | // adding statements 52 | entry.assign(x, 0); 53 | entry.assign(y, 0); 54 | bb2.assume(x <= 50); 55 | bb2.add(y, y, 1); 56 | bb3.assume(x >= 51); 57 | bb3.sub(y, y, 1); 58 | bb5.assume(y >= 0); 59 | bb6.add(x, x, 1); 60 | //bb6.assertion(x+y <= 102); 61 | bb7.assume(y <= -1); 62 | 63 | return cfg; 64 | } 65 | 66 | /* Example of how to infer invariants from the above CFG */ 67 | int main(int argc, char **argv) { 68 | bool stats_enabled = false; 69 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 70 | return 0; 71 | } 72 | 73 | variable_factory_t vfac; 74 | z_cfg_t *cfg = prog(vfac); 75 | crab::outs() << *cfg << "\n"; 76 | 77 | { 78 | z_soct_domain_t init; 79 | run(cfg, cfg->entry(), init, false, 2, 1, 0, stats_enabled); 80 | } 81 | 82 | { 83 | z_soct_domain_lw_t init; 84 | run(cfg, cfg->entry(), init, false, 2, 1, 0, stats_enabled); 85 | } 86 | 87 | // free the CFG 88 | delete cfg; 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /tests/domains/nested-1.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog(variable_factory_t &vfac) { 10 | 11 | /* 12 | i := 0; 13 | 14 | while (true) { 15 | i := i + 1; 16 | j := 0; 17 | 18 | while (j <= 9) { 19 | assert(i >= 0); 20 | assert(i <= 10); 21 | j := j + 1; 22 | } 23 | if (i >= 10) { 24 | i := 0; 25 | } 26 | } 27 | */ 28 | z_cfg_t *cfg = new z_cfg_t("entry"); 29 | z_basic_block_t &entry = cfg->insert("entry"); 30 | z_basic_block_t &l1 = cfg->insert("l1"); 31 | z_basic_block_t &l1_entry = cfg->insert("l1_entry"); 32 | z_basic_block_t &l1_reset = cfg->insert("l1_reset"); 33 | z_basic_block_t &l1_dont_reset = cfg->insert("l1_dont_reset"); 34 | z_basic_block_t &l2 = cfg->insert("l2"); 35 | z_basic_block_t &l2_body = cfg->insert("l2_body"); 36 | z_basic_block_t &l2_exit = cfg->insert("l2_exit"); 37 | 38 | entry >> l1; 39 | // outer loop 40 | l1 >> l1_entry; 41 | l1_entry >> l2; 42 | // inner loop 43 | l2 >> l2_body; 44 | l2_body >> l2; 45 | l2 >> l2_exit; 46 | // outer loop again 47 | l2_exit >> l1_reset; 48 | l2_exit >> l1_dont_reset; 49 | l1_reset >> l1; 50 | l1_dont_reset >> l1; 51 | 52 | z_var i(vfac["i"], crab::INT_TYPE, 32); 53 | z_var j(vfac["j"], crab::INT_TYPE, 32); 54 | 55 | entry.assign(i, 0); 56 | l1_entry.add(i, i, 1); 57 | l1_entry.assign(j, 0); 58 | 59 | l2_body.assume(j <= 9); 60 | l2_body.assertion(i >= 0); 61 | l2_body.assertion(i <= 10); 62 | l2_body.add(j, j, 1); 63 | 64 | l2_exit.assume(j >= 10); 65 | 66 | l1_reset.assume(i >= 10); 67 | l1_reset.assign(i, 0); 68 | l1_dont_reset.assume(i <= 9); 69 | 70 | return cfg; 71 | } 72 | 73 | int main(int argc, char **argv) { 74 | 75 | bool stats_enabled = false; 76 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 77 | return 0; 78 | } 79 | 80 | variable_factory_t vfac; 81 | z_cfg_t *cfg = prog(vfac); 82 | cfg->simplify(); 83 | crab::outs() << *cfg << "\n"; 84 | z_interval_domain_t init; 85 | run_and_check(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 86 | 87 | delete cfg; 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/domains/nested-2.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog(variable_factory_t &vfac) { 10 | 11 | /* 12 | i := 0; 13 | while (i<=3) { 14 | j:=0; 15 | while (j <= 3) { 16 | assert (i <= j + 3); 17 | i++; 18 | j++; 19 | } 20 | i := i - j + 1; 21 | } 22 | */ 23 | z_cfg_t *cfg = new z_cfg_t("entry"); 24 | z_basic_block_t &entry = cfg->insert("entry"); 25 | z_basic_block_t &l1 = cfg->insert("l1"); 26 | z_basic_block_t &l1_entry = cfg->insert("l1_entry"); 27 | z_basic_block_t &l1_cont = cfg->insert("l1_cont"); 28 | z_basic_block_t &l2 = cfg->insert("l2"); 29 | z_basic_block_t &l2_body = cfg->insert("l2_body"); 30 | z_basic_block_t &l2_exit = cfg->insert("l2_exit"); 31 | 32 | entry >> l1; 33 | // outer loop 34 | l1 >> l1_entry; 35 | l1_entry >> l2; 36 | // inner loop 37 | l2 >> l2_body; 38 | l2_body >> l2; 39 | l2 >> l2_exit; 40 | // outer loop again 41 | l2_exit >> l1_cont; 42 | l1_cont >> l1; 43 | 44 | z_var i(vfac["i"], crab::INT_TYPE, 32); 45 | z_var j(vfac["j"], crab::INT_TYPE, 32); 46 | 47 | entry.assign(i, 0); 48 | l1.assume(i <= 3); 49 | l1_entry.assign(j, 0); 50 | 51 | l2_body.assume(j <= 3); 52 | l2_body.assertion(i <= j + 3); 53 | l2_body.add(i, i, 1); 54 | l2_body.add(j, j, 1); 55 | 56 | l2_exit.assume(j >= 4); 57 | l1_cont.assign(i, i - j + 1); 58 | 59 | return cfg; 60 | } 61 | 62 | int main(int argc, char **argv) { 63 | 64 | bool stats_enabled = false; 65 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 66 | return 0; 67 | } 68 | 69 | variable_factory_t vfac; 70 | z_cfg_t *cfg = prog(vfac); 71 | cfg->simplify(); 72 | crab::outs() << *cfg << "\n"; 73 | 74 | { 75 | z_interval_domain_t init; 76 | run_and_check(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 77 | } 78 | { 79 | z_sdbm_domain_t init; 80 | run_and_check(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 81 | } 82 | 83 | delete cfg; 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /tests/domains/nested-3.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog(variable_factory_t &vfac) { 10 | /* 11 | i := 0; 12 | while (true) { 13 | assert (i >= 0); 14 | j := 0; 15 | while (j <= 9) { 16 | j++; 17 | } 18 | i:= i + 11 -j 19 | } 20 | */ 21 | z_cfg_t *cfg = new z_cfg_t("entry"); 22 | z_basic_block_t &entry = cfg->insert("entry"); 23 | z_basic_block_t &l1 = cfg->insert("l1"); 24 | z_basic_block_t &l1_entry = cfg->insert("l1_entry"); 25 | z_basic_block_t &l1_cont = cfg->insert("l1_cont"); 26 | z_basic_block_t &l2 = cfg->insert("l2"); 27 | z_basic_block_t &l2_body = cfg->insert("l2_body"); 28 | z_basic_block_t &l2_exit = cfg->insert("l2_exit"); 29 | 30 | entry >> l1; 31 | // outer loop 32 | l1 >> l1_entry; 33 | l1_entry >> l2; 34 | // inner loop 35 | l2 >> l2_body; 36 | l2_body >> l2; 37 | l2 >> l2_exit; 38 | // outer loop again 39 | l2_exit >> l1_cont; 40 | l1_cont >> l1; 41 | 42 | z_var i(vfac["i"], crab::INT_TYPE, 32); 43 | z_var j(vfac["j"], crab::INT_TYPE, 32); 44 | 45 | entry.assign(i, 0); 46 | l1_entry.assertion(i >= 0); 47 | l1_entry.assign(j, 0); 48 | 49 | l2_body.assume(j <= 9); 50 | l2_body.add(j, j, 1); 51 | 52 | l2_exit.assume(j >= 10); 53 | 54 | l1_cont.assign(i, i + 11 - j); 55 | 56 | return cfg; 57 | } 58 | 59 | int main(int argc, char **argv) { 60 | bool stats_enabled = false; 61 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 62 | return 0; 63 | } 64 | 65 | variable_factory_t vfac; 66 | z_cfg_t *cfg = prog(vfac); 67 | cfg->simplify(); 68 | crab::outs() << *cfg << "\n"; 69 | 70 | z_interval_domain_t init; 71 | run_and_check(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 72 | 73 | delete cfg; 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /tests/domains/terms-1.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog(variable_factory_t &vfac) { 10 | //// 11 | // Building the CFG 12 | //// 13 | 14 | // Definining program variables 15 | z_var i(vfac["i"], crab::INT_TYPE, 32); 16 | z_var k(vfac["k"], crab::INT_TYPE, 32); 17 | // entry and exit block 18 | z_cfg_t *cfg = new z_cfg_t("x0", "ret"); 19 | // adding blocks 20 | z_basic_block_t &x0 = cfg->insert("x0"); 21 | z_basic_block_t &x1 = cfg->insert("x1"); 22 | z_basic_block_t &x2 = cfg->insert("x2"); 23 | z_basic_block_t &x3 = cfg->insert("x3"); 24 | z_basic_block_t &entry = cfg->insert("entry"); 25 | z_basic_block_t &bb1 = cfg->insert("bb1"); 26 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 27 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 28 | z_basic_block_t &bb2 = cfg->insert("bb2"); 29 | z_basic_block_t &ret = cfg->insert("ret"); 30 | // adding control flow 31 | x0 >> x1; 32 | x1 >> x2; 33 | x2 >> x3; 34 | x3 >> entry; 35 | entry >> bb1; 36 | bb1 >> bb1_t; 37 | bb1 >> bb1_f; 38 | bb1_t >> bb2; 39 | bb2 >> bb1; 40 | bb1_f >> ret; 41 | // adding statements 42 | x0.assign(k, 50); 43 | entry.assign(i, 0); 44 | bb1_t.assume(i <= 99); 45 | bb1_f.assume(i >= 100); 46 | bb2.add(i, i, 1); 47 | 48 | return cfg; 49 | } 50 | 51 | int main(int argc, char **argv) { 52 | bool stats_enabled = false; 53 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 54 | return 0; 55 | } 56 | 57 | variable_factory_t vfac; 58 | z_cfg_t *cfg = prog(vfac); 59 | cfg->simplify(); 60 | crab::outs() << *cfg << "\n"; 61 | 62 | { 63 | z_interval_domain_t init; 64 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 65 | } 66 | { 67 | z_term_domain_t init; 68 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 69 | } 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tests/domains/terms-2.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *prog(variable_factory_t &vfac) { 10 | //// 11 | // Building the CFG 12 | //// 13 | 14 | // Definining program variables 15 | z_var x(vfac["x"], crab::INT_TYPE, 32); 16 | z_var y(vfac["y"], crab::INT_TYPE, 32); 17 | z_var z(vfac["z"], crab::INT_TYPE, 32); 18 | z_var z0(vfac["z0"], crab::INT_TYPE, 32); 19 | z_var y0(vfac["y0"], crab::INT_TYPE, 32); 20 | // entry and exit block 21 | z_cfg_t *cfg = new z_cfg_t("p0", "ret"); 22 | // adding blocks 23 | z_basic_block_t &p0 = cfg->insert("p0"); 24 | z_basic_block_t &p_neg = cfg->insert("p_neg"); 25 | z_basic_block_t &p_pos = cfg->insert("p_pos"); 26 | z_basic_block_t &exit = cfg->insert("exit"); 27 | z_basic_block_t &ret = cfg->insert("ret"); 28 | // adding control flow 29 | p0 >> p_pos; 30 | p0 >> p_neg; 31 | p_neg >> exit; 32 | p_pos >> exit; 33 | exit >> ret; 34 | 35 | // adding statements 36 | p0.assign(x, 50); 37 | p0.havoc(y); 38 | p0.assume(y >= -1); 39 | p0.assume(y <= 1); 40 | p0.mul(z, x, y); 41 | 42 | p_neg.assume(y <= -1); 43 | p_neg.mul(z, z, -1); 44 | 45 | p_pos.assume(y >= 0); 46 | 47 | exit.assign(z0, z); 48 | exit.assign(y0, y); 49 | 50 | return cfg; 51 | } 52 | 53 | int main(int argc, char **argv) { 54 | bool stats_enabled = false; 55 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 56 | return 0; 57 | } 58 | variable_factory_t vfac; 59 | z_cfg_t *cfg = prog(vfac); 60 | cfg->simplify(); 61 | crab::outs() << *cfg << "\n"; 62 | 63 | { 64 | z_interval_domain_t init; 65 | run(cfg, cfg->entry(), init, true, 1, 2, 20, stats_enabled); 66 | } 67 | { 68 | z_term_domain_t init; 69 | run(cfg, cfg->entry(), init, true, 1, 2, 20, stats_enabled); 70 | } 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /tests/domains/terms-3.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to build a CFG */ 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | 12 | // Definining program variables 13 | z_var i(vfac["i"], crab::INT_TYPE, 32); 14 | z_var x(vfac["x"], crab::INT_TYPE, 32); 15 | z_var y(vfac["y"], crab::INT_TYPE, 32); 16 | z_var z(vfac["z"], crab::INT_TYPE, 32); 17 | z_var w(vfac["w"], crab::INT_TYPE, 32); 18 | z_var s(vfac["s"], crab::INT_TYPE, 32); 19 | z_var t(vfac["t"], crab::INT_TYPE, 32); 20 | z_var nd1(vfac["nd1"], crab::INT_TYPE, 32); 21 | z_var nd2(vfac["nd2"], crab::INT_TYPE, 32); 22 | // entry and exit block 23 | z_cfg_t *cfg = new z_cfg_t("entry", "ret"); 24 | // adding blocks 25 | z_basic_block_t &entry = cfg->insert("entry"); 26 | z_basic_block_t &bb1 = cfg->insert("bb1"); 27 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 28 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 29 | z_basic_block_t &bb2 = cfg->insert("bb2"); 30 | z_basic_block_t &ret = cfg->insert("ret"); 31 | // adding control flow 32 | entry >> bb1; 33 | bb1 >> bb1_t; 34 | bb1 >> bb1_f; 35 | bb1_t >> bb2; 36 | bb2 >> bb1; 37 | bb1_f >> ret; 38 | // adding statements 39 | entry.assign(i, 0); 40 | entry.assign(x, 5); 41 | entry.assign(y, 5); 42 | entry.assign(z, 3); 43 | entry.assign(w, 3); 44 | entry.assign(s, 0); 45 | entry.assign(t, 0); 46 | bb1_t.assume(i <= 99); 47 | bb1_f.assume(i >= 100); 48 | bb2.havoc(nd1); 49 | bb2.havoc(nd2); 50 | bb2.bitwise_and(x, x, nd1); 51 | bb2.bitwise_and(y, y, nd1); 52 | bb2.bitwise_or(z, z, nd1); 53 | bb2.bitwise_or(w, w, nd1); 54 | bb2.bitwise_xor(s, nd1, nd2); 55 | bb2.bitwise_xor(t, nd1, nd2); 56 | bb2.add(i, i, 1); 57 | 58 | return cfg; 59 | } 60 | 61 | /* Example of how to infer invariants from the above CFG */ 62 | int main(int argc, char **argv) { 63 | bool stats_enabled = false; 64 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 65 | return 0; 66 | } 67 | variable_factory_t vfac; 68 | z_cfg_t *cfg = prog(vfac); 69 | cfg->simplify(); // this is optional 70 | crab::outs() << *cfg << "\n"; 71 | 72 | { 73 | z_interval_domain_t init; 74 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 75 | } 76 | { 77 | z_dbm_domain_t init; 78 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 79 | } 80 | { 81 | z_term_domain_t init; 82 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 83 | } 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /tests/domains/test1-real-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace crab::cfg; 5 | using namespace crab::cfg_impl; 6 | using namespace crab::domain_impl; 7 | 8 | /* Example of how to build a CFG */ 9 | q_cfg_t *prog(variable_factory_t &vfac) { 10 | 11 | // Definining program variables 12 | q_var i(vfac["i"], crab::REAL_TYPE); 13 | // entry and exit block 14 | q_cfg_t *cfg = new q_cfg_t("entry", "ret"); 15 | // adding blocks 16 | q_basic_block_t &entry = cfg->insert("entry"); 17 | q_basic_block_t &bb1 = cfg->insert("bb1"); 18 | q_basic_block_t &bb1_t = cfg->insert("bb1_t"); 19 | q_basic_block_t &bb1_f = cfg->insert("bb1_f"); 20 | q_basic_block_t &bb2 = cfg->insert("bb2"); 21 | q_basic_block_t &ret = cfg->insert("ret"); 22 | // adding control flow 23 | entry >> bb1; 24 | bb1 >> bb1_t; 25 | bb1 >> bb1_f; 26 | bb1_t >> bb2; 27 | bb2 >> bb1; 28 | bb1_f >> ret; 29 | // adding statements 30 | entry.assign(i, q_number(0.0)); 31 | bb1_t.assume(i <= q_number(9.9)); 32 | bb1_f.assume(i >= q_number(10)); 33 | bb2.add(i, i, q_number(1)); 34 | 35 | return cfg; 36 | } 37 | 38 | /* Example of how to infer invariants from the above CFG */ 39 | int main(int argc, char **argv) { 40 | #ifdef HAVE_APRON 41 | bool stats_enabled = false; 42 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 43 | return 0; 44 | } 45 | variable_factory_t vfac; 46 | q_cfg_t *cfg = prog(vfac); 47 | cfg->simplify(); // this is optional 48 | crab::outs() << *cfg << "\n"; 49 | 50 | q_pk_apron_domain_t init; 51 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 52 | #endif 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/domains/test1-real.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace crab::cfg; 5 | using namespace crab::cfg_impl; 6 | using namespace crab::domain_impl; 7 | 8 | /* Example of how to build a CFG */ 9 | q_cfg_t *prog(variable_factory_t &vfac) { 10 | 11 | // Definining program variables 12 | q_var i(vfac["i"], crab::REAL_TYPE); 13 | // entry and exit block 14 | q_cfg_t *cfg = new q_cfg_t("entry", "ret"); 15 | // adding blocks 16 | q_basic_block_t &entry = cfg->insert("entry"); 17 | q_basic_block_t &bb1 = cfg->insert("bb1"); 18 | q_basic_block_t &bb1_t = cfg->insert("bb1_t"); 19 | q_basic_block_t &bb1_f = cfg->insert("bb1_f"); 20 | q_basic_block_t &bb2 = cfg->insert("bb2"); 21 | q_basic_block_t &ret = cfg->insert("ret"); 22 | // adding control flow 23 | entry >> bb1; 24 | bb1 >> bb1_t; 25 | bb1 >> bb1_f; 26 | bb1_t >> bb2; 27 | bb2 >> bb1; 28 | bb1_f >> ret; 29 | // adding statements 30 | entry.assign(i, q_number(0.0)); 31 | bb1_t.assume(i <= q_number(9.9)); 32 | bb1_f.assume(i >= q_number(10)); 33 | bb2.add(i, i, q_number(1)); 34 | 35 | return cfg; 36 | } 37 | 38 | /* Example of how to infer invariants from the above CFG */ 39 | int main(int argc, char **argv) { 40 | bool stats_enabled = false; 41 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 42 | return 0; 43 | } 44 | variable_factory_t vfac; 45 | q_cfg_t *cfg = prog(vfac); 46 | cfg->simplify(); // this is optional 47 | crab::outs() << *cfg << "\n"; 48 | 49 | q_interval_domain_t init; 50 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/domains/test2-real-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // To run abstract domains defined over reals 5 | 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | /* Example of how to build a CFG */ 11 | q_cfg_t *prog(variable_factory_t &vfac) { 12 | 13 | // Definining program variables 14 | q_var x(vfac["x"], crab::REAL_TYPE); 15 | q_var y(vfac["y"], crab::REAL_TYPE); 16 | // entry and exit block 17 | q_cfg_t *cfg = new q_cfg_t("entry", "bb1"); 18 | // adding blocks 19 | q_basic_block_t &entry = cfg->insert("entry"); 20 | q_basic_block_t &bb1 = cfg->insert("bb1"); 21 | // adding control flow 22 | entry >> bb1; 23 | bb1 >> bb1; 24 | // adding statements 25 | entry.assign(x, q_number(0.0)); 26 | entry.assign(y, q_number(0.5)); 27 | bb1.add(x, x, y); 28 | bb1.div(y, y, q_number(2)); 29 | 30 | return cfg; 31 | } 32 | 33 | /* Example of how to infer invariants from the above CFG */ 34 | int main(int argc, char **argv) { 35 | #ifdef HAVE_APRON 36 | bool stats_enabled = false; 37 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 38 | return 0; 39 | } 40 | variable_factory_t vfac; 41 | q_cfg_t *cfg = prog(vfac); 42 | crab::outs() << *cfg << "\n"; 43 | q_pk_apron_domain_t init; 44 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 45 | #endif 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/domains/test2-real-boxes.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // To run abstract domains defined over reals 5 | 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | /* Example of how to build a CFG */ 11 | q_cfg_t *prog(variable_factory_t &vfac) { 12 | 13 | // Definining program variables 14 | q_var x(vfac["x"], crab::REAL_TYPE); 15 | q_var y(vfac["y"], crab::REAL_TYPE); 16 | // entry and exit block 17 | q_cfg_t *cfg = new q_cfg_t("entry", "bb1"); 18 | // adding blocks 19 | q_basic_block_t &entry = cfg->insert("entry"); 20 | q_basic_block_t &bb1 = cfg->insert("bb1"); 21 | // adding control flow 22 | entry >> bb1; 23 | bb1 >> bb1; 24 | // adding statements 25 | entry.assign(x, q_number(0.0)); 26 | entry.assign(y, q_number(0.5)); 27 | bb1.add(x, x, y); 28 | bb1.div(y, y, q_number(2)); 29 | 30 | return cfg; 31 | } 32 | 33 | /* Example of how to infer invariants from the above CFG */ 34 | int main(int argc, char **argv) { 35 | #ifdef HAVE_LDD 36 | bool stats_enabled = false; 37 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 38 | return 0; 39 | } 40 | variable_factory_t vfac; 41 | q_cfg_t *cfg = prog(vfac); 42 | crab::outs() << *cfg << "\n"; 43 | q_boxes_domain_t init; 44 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 45 | #endif 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/domains/test2-real.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // To run abstract domains defined over reals 5 | 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | /* Example of how to build a CFG */ 11 | q_cfg_t *prog(variable_factory_t &vfac) { 12 | 13 | // Definining program variables 14 | q_var x(vfac["x"], crab::REAL_TYPE); 15 | q_var y(vfac["y"], crab::REAL_TYPE); 16 | // entry and exit block 17 | q_cfg_t *cfg = new q_cfg_t("entry", "bb1"); 18 | // adding blocks 19 | q_basic_block_t &entry = cfg->insert("entry"); 20 | q_basic_block_t &bb1 = cfg->insert("bb1"); 21 | // adding control flow 22 | entry >> bb1; 23 | bb1 >> bb1; 24 | // adding statements 25 | entry.assign(x, q_number(0.0)); 26 | entry.assign(y, q_number(0.5)); 27 | bb1.add(x, x, y); 28 | bb1.div(y, y, q_number(2)); 29 | 30 | return cfg; 31 | } 32 | 33 | /* Example of how to infer invariants from the above CFG */ 34 | int main(int argc, char **argv) { 35 | bool stats_enabled = false; 36 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 37 | return 0; 38 | } 39 | variable_factory_t vfac; 40 | q_cfg_t *cfg = prog(vfac); 41 | crab::outs() << *cfg << "\n"; 42 | { 43 | q_interval_domain_t init; 44 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/domains/test3-real-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // To run abstract domains defined over reals 5 | 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | /* Example of how to build a CFG */ 11 | q_cfg_t *prog(variable_factory_t &vfac) { 12 | 13 | // Definining program variables 14 | q_var x(vfac["x"], crab::REAL_TYPE); 15 | q_var y(vfac["y"], crab::REAL_TYPE); 16 | // entry and exit block 17 | q_cfg_t *cfg = new q_cfg_t("entry", "exit"); 18 | // adding blocks 19 | q_basic_block_t &entry = cfg->insert("entry"); 20 | q_basic_block_t &header = cfg->insert("header"); 21 | q_basic_block_t &body = cfg->insert("body"); 22 | q_basic_block_t &exit = cfg->insert("exit"); 23 | 24 | // adding control flow 25 | entry >> header; 26 | header >> body; 27 | body >> header; 28 | header >> exit; 29 | 30 | // adding statements 31 | entry.assign(x, q_number(1)); 32 | entry.assign(y, q_number(0)); 33 | 34 | body.add(x, x, y); 35 | body.add(y, y, q_number(1)); 36 | 37 | exit.assertion(x >= y); 38 | return cfg; 39 | } 40 | 41 | /* Example of how to infer invariants from the above CFG */ 42 | int main(int argc, char **argv) { 43 | #ifdef HAVE_APRON 44 | bool stats_enabled = false; 45 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 46 | return 0; 47 | } 48 | variable_factory_t vfac; 49 | q_cfg_t *cfg = prog(vfac); 50 | crab::outs() << *cfg << "\n"; 51 | 52 | q_pk_apron_domain_t init; 53 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 54 | #endif 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tests/domains/test3-real-boxes.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // To run abstract domains defined over reals 5 | 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | /* Example of how to build a CFG */ 11 | q_cfg_t *prog(variable_factory_t &vfac) { 12 | 13 | // Definining program variables 14 | q_var x(vfac["x"], crab::REAL_TYPE); 15 | q_var y(vfac["y"], crab::REAL_TYPE); 16 | // entry and exit block 17 | q_cfg_t *cfg = new q_cfg_t("entry", "exit"); 18 | // adding blocks 19 | q_basic_block_t &entry = cfg->insert("entry"); 20 | q_basic_block_t &header = cfg->insert("header"); 21 | q_basic_block_t &body = cfg->insert("body"); 22 | q_basic_block_t &exit = cfg->insert("exit"); 23 | 24 | // adding control flow 25 | entry >> header; 26 | header >> body; 27 | body >> header; 28 | header >> exit; 29 | 30 | // adding statements 31 | entry.assign(x, q_number(1)); 32 | entry.assign(y, q_number(0)); 33 | 34 | body.add(x, x, y); 35 | body.add(y, y, q_number(1)); 36 | 37 | exit.assertion(x >= y); 38 | return cfg; 39 | } 40 | 41 | /* Example of how to infer invariants from the above CFG */ 42 | int main(int argc, char **argv) { 43 | #ifdef HAVE_LDD 44 | bool stats_enabled = false; 45 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 46 | return 0; 47 | } 48 | variable_factory_t vfac; 49 | q_cfg_t *cfg = prog(vfac); 50 | crab::outs() << *cfg << "\n"; 51 | 52 | q_boxes_domain_t init; 53 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 54 | #endif 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /tests/domains/test3-real.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | // To run abstract domains defined over reals 5 | 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | /* Example of how to build a CFG */ 11 | q_cfg_t *prog(variable_factory_t &vfac) { 12 | 13 | // Definining program variables 14 | q_var x(vfac["x"], crab::REAL_TYPE); 15 | q_var y(vfac["y"], crab::REAL_TYPE); 16 | // entry and exit block 17 | q_cfg_t *cfg = new q_cfg_t("entry", "exit"); 18 | // adding blocks 19 | q_basic_block_t &entry = cfg->insert("entry"); 20 | q_basic_block_t &header = cfg->insert("header"); 21 | q_basic_block_t &body = cfg->insert("body"); 22 | q_basic_block_t &exit = cfg->insert("exit"); 23 | 24 | // adding control flow 25 | entry >> header; 26 | header >> body; 27 | body >> header; 28 | header >> exit; 29 | 30 | // adding statements 31 | entry.assign(x, q_number(1)); 32 | entry.assign(y, q_number(0)); 33 | 34 | body.add(x, x, y); 35 | body.add(y, y, q_number(1)); 36 | 37 | exit.assertion(x >= y); 38 | return cfg; 39 | } 40 | 41 | /* Example of how to infer invariants from the above CFG */ 42 | int main(int argc, char **argv) { 43 | bool stats_enabled = false; 44 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 45 | return 0; 46 | } 47 | variable_factory_t vfac; 48 | q_cfg_t *cfg = prog(vfac); 49 | crab::outs() << *cfg << "\n"; 50 | 51 | q_interval_domain_t init; 52 | run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/domains/test4-real-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to infer invariants from the above CFG */ 10 | int main(int argc, char **argv) { 11 | #ifdef HAVE_APRON 12 | bool stats_enabled = false; 13 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 14 | return 0; 15 | } 16 | 17 | crab::outs() << "Running APRON\n\n"; 18 | variable_factory_t vfac; 19 | { 20 | q_pk_apron_domain_t inv; 21 | q_lin_cst_sys_t csts; 22 | csts += (q_var(vfac["x"], crab::REAL_TYPE) >= q_number(1)); 23 | csts += (q_var(vfac["x"], crab::REAL_TYPE) <= q_number(1)); 24 | crab::outs() << "INITIALLY=" << inv << "\n"; 25 | crab::outs() << "ADDING CONSTRAINTS=" << csts << "\n"; 26 | inv += csts; 27 | crab::outs() << "EXPECTED={x = 1}\n"; 28 | crab::outs() << "RESULT=" << inv << "\n"; 29 | } 30 | crab::outs() << "------------------------------------\n"; 31 | { 32 | q_pk_apron_domain_t inv; 33 | q_lin_cst_sys_t csts; 34 | csts += (q_var(vfac["x"], crab::REAL_TYPE) >= q_number(0.5)); 35 | csts += (q_var(vfac["x"], crab::REAL_TYPE) <= q_number(0.5)); 36 | crab::outs() << "INITIALLY=" << inv << "\n"; 37 | crab::outs() << "ADDING CONSTRAINTS=" << csts << "\n"; 38 | inv += csts; 39 | crab::outs() << "EXPECTED={x = 1/2}\n"; 40 | crab::outs() << "RESULT=" << inv << "\n"; 41 | } 42 | crab::outs() << "------------------------------------\n"; 43 | { 44 | q_oct_apron_domain_t inv; 45 | q_lin_cst_sys_t csts; 46 | csts += (q_var(vfac["x"], crab::REAL_TYPE) >= q_number(0.5)); 47 | csts += (q_var(vfac["x"], crab::REAL_TYPE) <= q_number(0.5)); 48 | crab::outs() << "INITIALLY=" << inv << "\n"; 49 | crab::outs() << "ADDING CONSTRAINTS=" << csts << "\n"; 50 | inv += csts; 51 | crab::outs() << "EXPECTED={x = 1/2}\n"; 52 | crab::outs() << "RESULT=" << inv << "\n"; 53 | } 54 | crab::outs() << "------------------------------------\n"; 55 | 56 | #endif 57 | 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/domains/test4-real-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | /* Example of how to infer invariants from the above CFG */ 10 | int main(int argc, char **argv) { 11 | #ifdef HAVE_ELINA 12 | 13 | bool stats_enabled = false; 14 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 15 | return 0; 16 | } 17 | 18 | crab::outs() << "Running ELINA\n\n"; 19 | variable_factory_t vfac; 20 | { 21 | q_oct_elina_domain_t inv; 22 | q_lin_cst_sys_t csts; 23 | csts += (q_var(vfac["x"], crab::REAL_TYPE) >= q_number(1)); 24 | csts += (q_var(vfac["x"], crab::REAL_TYPE) <= q_number(1)); 25 | crab::outs() << "INITIALLY=" << inv << "\n"; 26 | crab::outs() << "ADDING CONSTRAINTS=" << csts << "\n"; 27 | inv += csts; 28 | crab::outs() << "EXPECTED={x = 1}\n"; 29 | crab::outs() << "RESULT=" << inv << "\n"; 30 | } 31 | crab::outs() << "------------------------------------\n"; 32 | { 33 | q_oct_elina_domain_t inv; 34 | q_lin_cst_sys_t csts; 35 | csts += (q_var(vfac["x"], crab::REAL_TYPE) >= q_number(0.5)); 36 | csts += (q_var(vfac["x"], crab::REAL_TYPE) <= q_number(0.5)); 37 | crab::outs() << "INITIALLY=" << inv << "\n"; 38 | crab::outs() << "ADDING CONSTRAINTS=" << csts << "\n"; 39 | inv += csts; 40 | crab::outs() << "EXPECTED={x = 1/2}\n"; 41 | crab::outs() << "RESULT=" << inv << "\n"; 42 | } 43 | 44 | crab::outs() << "------------------------------------\n"; 45 | { 46 | q_oct_elina_domain_t inv; 47 | q_lin_cst_sys_t csts; 48 | csts += (q_var(vfac["x"], crab::REAL_TYPE) >= q_number(0.5)); 49 | csts += (q_var(vfac["x"], crab::REAL_TYPE) <= q_number(0.5)); 50 | crab::outs() << "INITIALLY=" << inv << "\n"; 51 | crab::outs() << "ADDING CONSTRAINTS=" << csts << "\n"; 52 | inv += csts; 53 | crab::outs() << "EXPECTED={x = 1/2}\n"; 54 | crab::outs() << "RESULT=" << inv << "\n"; 55 | } 56 | crab::outs() << "------------------------------------\n"; 57 | #endif 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/domains/test8.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | /******************************************************************* 5 | * We test the feature of starting the analysis at some arbitrary 6 | * block. 7 | *******************************************************************/ 8 | 9 | using namespace std; 10 | using namespace crab::cfg; 11 | using namespace crab::cfg_impl; 12 | using namespace crab::domain_impl; 13 | 14 | int main(int argc, char **argv) { 15 | bool stats_enabled = false; 16 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 17 | return 0; 18 | } 19 | variable_factory_t vfac; 20 | 21 | z_cfg_t cfg("loop1_entry", "ret"); 22 | z_basic_block_t &loop1_entry = cfg.insert("loop1_entry"); 23 | z_basic_block_t &loop1_bb1 = cfg.insert("loop1_bb1"); 24 | z_basic_block_t &loop1_bb1_t = cfg.insert("loop1_bb1_t"); 25 | z_basic_block_t &loop1_bb1_f = cfg.insert("loop1_bb1_f"); 26 | z_basic_block_t &loop1_bb2 = cfg.insert("loop1_bb2"); 27 | z_basic_block_t &loop2_entry = cfg.insert("loop2_entry"); 28 | z_basic_block_t &loop2_bb1 = cfg.insert("loop2_bb1"); 29 | z_basic_block_t &loop2_bb1_t = cfg.insert("loop2_bb1_t"); 30 | z_basic_block_t &loop2_bb1_f = cfg.insert("loop2_bb1_f"); 31 | z_basic_block_t &loop2_bb2 = cfg.insert("loop2_bb2"); 32 | z_basic_block_t &ret = cfg.insert("ret"); 33 | 34 | loop1_entry >> loop1_bb1; 35 | loop1_bb1 >> loop1_bb1_t; 36 | loop1_bb1 >> loop1_bb1_f; 37 | loop1_bb1_t >> loop1_bb2; 38 | loop1_bb2 >> loop1_bb1; 39 | loop1_bb1_f >> loop2_entry; 40 | 41 | loop2_entry >> loop2_bb1; 42 | loop2_bb1 >> loop2_bb1_t; 43 | loop2_bb1 >> loop2_bb1_f; 44 | loop2_bb1_t >> loop2_bb2; 45 | loop2_bb2 >> loop2_bb1; 46 | loop2_bb1_f >> ret; 47 | 48 | z_var i(vfac["i"], crab::INT_TYPE, 32); 49 | z_var j(vfac["j"], crab::INT_TYPE, 32); 50 | z_var k(vfac["k"], crab::INT_TYPE, 32); 51 | 52 | loop1_entry.assign(i, 0); 53 | loop1_entry.assign(k, 30); 54 | loop1_bb1_t.assume(i <= 9); 55 | loop1_bb1_f.assume(i >= 10); 56 | loop1_bb2.add(i, i, 1); 57 | 58 | loop2_entry.assign(j, 0); 59 | loop2_bb1_t.assume(j <= 9); 60 | loop2_bb1_f.assume(j >= 10); 61 | loop2_bb2.add(j, j, 1); 62 | 63 | crab::outs() << cfg << "\n"; 64 | 65 | crab::outs() << "Starting at the entry of CFG:\n"; 66 | z_interval_domain_t init; 67 | run(&cfg, cfg.entry(), init, false, 1, 2, 20, stats_enabled); 68 | crab::outs() << "Starting at the entry of the second loop:\n"; 69 | run(&cfg, loop2_entry.label(), init, false, 1, 2, 20, stats_enabled); 70 | crab::outs() << "Starting at the middle of the second loop:\n"; 71 | run(&cfg, loop2_bb2.label(), init, false, 1, 2, 20, stats_enabled); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/domains/test9.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace std; 5 | using namespace crab::cfg; 6 | using namespace crab::cfg_impl; 7 | using namespace crab::domain_impl; 8 | 9 | z_cfg_t *cfg1(variable_factory_t &vfac) { 10 | 11 | /* 12 | i := 0; 13 | x := 1; 14 | y := 0; 15 | 16 | while(i <= 99) { 17 | x = x + y; 18 | y = y + 1; 19 | i = i + 1; 20 | } 21 | z := x; 22 | w := y; 23 | assert(z>= w); 24 | */ 25 | 26 | // === Define program variables 27 | z_var i(vfac["i"], crab::INT_TYPE, 32); 28 | z_var x(vfac["x"], crab::INT_TYPE, 32); 29 | z_var y(vfac["y"], crab::INT_TYPE, 32); 30 | z_var z(vfac["z"], crab::INT_TYPE, 32); 31 | z_var w(vfac["w"], crab::INT_TYPE, 32); 32 | // === Create empty CFG 33 | z_cfg_t *cfg = new z_cfg_t("entry", "ret"); 34 | // === Adding CFG blocks 35 | z_basic_block_t &entry = cfg->insert("entry"); 36 | z_basic_block_t &bb1 = cfg->insert("bb1"); 37 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 38 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 39 | z_basic_block_t &bb2 = cfg->insert("bb2"); 40 | z_basic_block_t &bb3 = cfg->insert("bb3"); 41 | z_basic_block_t &ret = cfg->insert("ret"); 42 | // === Adding CFG edges 43 | entry.add_succ(bb1); 44 | bb1.add_succ(bb1_t); 45 | bb1.add_succ(bb1_f); 46 | bb1_t.add_succ(bb2); 47 | bb2.add_succ(bb1); 48 | bb1_f.add_succ(bb3); 49 | bb3.add_succ(ret); 50 | // === Adding statements 51 | entry.assign(i, 0); 52 | entry.assign(x, 1); 53 | entry.assign(y, 0); 54 | bb1_t.assume(i <= 99); 55 | bb1_f.assume(i >= 100); 56 | bb2.add(x, x, y); 57 | bb2.add(y, y, 1); 58 | bb2.add(i, i, 1); 59 | ret.assign(z, x); 60 | ret.assign(w, y); 61 | ret.assertion(z >= w); 62 | return cfg; 63 | } 64 | 65 | int main(int argc, char **argv) { 66 | 67 | bool stats_enabled = false; 68 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 69 | return 0; 70 | } 71 | 72 | variable_factory_t vfac; 73 | 74 | z_cfg_t *p1 = cfg1(vfac); 75 | crab::outs() << *p1 << "\n"; 76 | z_sdbm_domain_t init; 77 | run_and_check(p1, p1->entry(), init, false, 2, 2, 20, stats_enabled); 78 | delete p1; 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /tests/domains/unittests-array-adaptive.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace crab::cfg; 5 | using namespace crab::cfg_impl; 6 | using namespace crab::domain_impl; 7 | using namespace ikos; 8 | 9 | int main(int argc, char **argv) { 10 | array_adaptive_domain_params p(true/*is_smashable*/, 11 | false/*smash_at_nonzero_offset*/, 12 | 64/*max_smashable_cells*/, 13 | 512/*max_array_size*/); 14 | crab_domain_params_man::get().update_params(p); 15 | 16 | bool stats_enabled = false; 17 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 18 | return 0; 19 | } 20 | 21 | crab::outs() << "Unit tests for array adaptive domain\n\n"; 22 | 23 | { // join 24 | variable_factory_t vfac; 25 | unsigned elem_sz = 4; 26 | z_var a(vfac["A"], crab::ARR_INT_TYPE); 27 | z_var b(vfac["B"], crab::ARR_INT_TYPE); 28 | z_var c(vfac["C"], crab::ARR_INT_TYPE); 29 | z_aa_bool_int_t inv1, inv2, inv3; 30 | inv1.array_store(a, elem_sz, 4, 5, true); 31 | inv1.array_store(b, elem_sz, 0, 66, true); 32 | inv2.array_store(a, elem_sz, 4, 10, true); 33 | inv2.array_store(c, elem_sz, 8, 32, true); 34 | inv3 = inv1 | inv2; 35 | crab::outs() << inv1 << " | " << inv2 << "=" << inv3 << "\n"; 36 | crab::outs() << inv1 << " |= " << inv2 << "="; 37 | inv1 |= inv2; 38 | crab::outs() << inv1 << "\n"; 39 | } 40 | 41 | { // meet 42 | variable_factory_t vfac; 43 | unsigned elem_sz = 4; 44 | z_var a(vfac["A"], crab::ARR_INT_TYPE); 45 | z_var b(vfac["B"], crab::ARR_INT_TYPE); 46 | z_var c(vfac["C"], crab::ARR_INT_TYPE); 47 | z_aa_bool_int_t inv1, inv2, inv3; 48 | inv1.array_store(a, elem_sz, 4, 5, true); 49 | inv1.array_store(b, elem_sz, 0, 66, true); 50 | inv2.array_store(a, elem_sz, 4, 10, true); 51 | inv2.array_store(c, elem_sz, 8, 32, true); 52 | inv3 = inv1 & inv2; 53 | crab::outs() << inv1 << " & " << inv2 << "=" << inv3 << "\n"; 54 | } 55 | 56 | { // meet 57 | variable_factory_t vfac; 58 | unsigned elem_sz = 4; 59 | z_var a(vfac["A"], crab::ARR_INT_TYPE); 60 | z_var b(vfac["B"], crab::ARR_INT_TYPE); 61 | z_var c(vfac["C"], crab::ARR_INT_TYPE); 62 | z_aa_bool_int_t inv1, inv2, inv3; 63 | inv1.array_store(a, elem_sz, 4, 5, true); 64 | inv1.array_store(b, elem_sz, 0, 66, true); 65 | inv2.array_store(a, elem_sz, 4, 5, true); 66 | inv2.array_store(c, elem_sz, 8, 32, true); 67 | inv3 = inv1 & inv2; 68 | crab::outs() << inv1 << " & " << inv2 << "=" << inv3 << "\n"; 69 | } 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tests/domains/unittests-num-packing.cc: -------------------------------------------------------------------------------- 1 | #include "../program_options.hpp" 2 | #include "../common.hpp" 3 | #include 4 | 5 | using namespace std; 6 | using namespace crab::analyzer; 7 | using namespace crab::cfg; 8 | using namespace crab::cfg_impl; 9 | using namespace crab::domain_impl; 10 | 11 | namespace { 12 | 13 | using z_packing_domain_t = numerical_packing_domain; 14 | } 15 | 16 | int main(int argc, char** argv) { 17 | bool stats_enabled = false; 18 | if (!crab_tests::parse_user_options(argc,argv,stats_enabled)) { 19 | return 0; 20 | } 21 | variable_factory_t vfac; 22 | 23 | z_var x(vfac["x"], crab::INT_TYPE, 32); 24 | z_var y(vfac["y"], crab::INT_TYPE, 32); 25 | z_var w(vfac["w"], crab::INT_TYPE, 32); 26 | z_var z(vfac["z"], crab::INT_TYPE, 32); 27 | 28 | { 29 | z_packing_domain_t dom; 30 | dom += (z_lin_exp_t(x) == z_lin_exp_t(y)); 31 | crab::outs() << "EXPECTED={({x,y},{x=y})} ACTUAL=" << dom << "\n"; 32 | } 33 | 34 | { 35 | z_packing_domain_t dom; 36 | dom.assign(x, z_number(5)); 37 | dom.assign(y, z_number(10)); 38 | //crab::outs() << dom << "\n"; 39 | dom += (z_lin_exp_t(x) == z_lin_exp_t(y)); 40 | crab::outs() << "EXPECTED=_|_ ACTUAL=" << dom << "\n"; 41 | } 42 | 43 | { 44 | z_packing_domain_t dom1,dom2; 45 | crab::outs() << "EXPECTED=top ACTUAL=" << dom1 << "\n"; 46 | dom1.assign(x, z_number(5)); 47 | dom2.assign(x, z_number(10)); 48 | dom1 |= dom2; 49 | dom1.assign(y, z_number(10)); 50 | dom1.assign(z, z_number(0)); 51 | crab::outs() << "EXPECTED={({x},{x->[5,10]}),({y},{y->10}),({z},{z->0})} ACTUAL=" << dom1 << "\n"; 52 | dom1 += (z_lin_exp_t(x) == z_lin_exp_t(y)); 53 | crab::outs() << "EXPECTED={({x,y},{x->10, y->10}), ({z},{z->0})} ACTUAL=" << dom1 << "\n"; 54 | dom1 -= y; 55 | crab::outs() << "EXPECTED={({x},{x->10}), ({z},{z->0})} ACTUAL=" << dom1 << "\n"; 56 | } 57 | 58 | { 59 | z_packing_domain_t dom; 60 | dom.assign(w, z_number(5)); 61 | dom.assign(z, z_number(10)); 62 | crab::outs() << "EXPECTED={({w},{w->5}),({z},{z->10})} ACTUAL=" << dom << "\n"; 63 | dom += (z_lin_exp_t(x) == z_lin_exp_t(y)); 64 | crab::outs() << "EXPECTED={({w},{w->5}),({z},{z->10}), ({x,y},{x=y})} ACTUAL=" << dom << "\n"; 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /tests/domains/unittests-rename-apron.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace crab::cfg; 5 | using namespace crab::cfg_impl; 6 | using namespace crab::domain_impl; 7 | using namespace ikos; 8 | 9 | int main(int argc, char **argv) { 10 | #ifdef HAVE_APRON 11 | 12 | bool stats_enabled = false; 13 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 14 | return 0; 15 | } 16 | 17 | variable_factory_t vfac; 18 | z_var x(vfac["x"], crab::INT_TYPE, 32); 19 | z_var y(vfac["y"], crab::INT_TYPE, 32); 20 | z_var z(vfac["z"], crab::INT_TYPE, 32); 21 | z_var w(vfac["w"], crab::INT_TYPE, 32); 22 | z_var v(vfac["v"], crab::INT_TYPE, 32); 23 | 24 | z_pk_apron_domain_t inv; 25 | crab::outs() << " ===== " << inv.domain_name() << " ====\n"; 26 | inv += z_lin_cst_t(x <= 0); 27 | inv += z_lin_cst_t(y == 5); 28 | crab::outs() << "Before renaming " << inv << "\n"; 29 | 30 | { 31 | z_pk_apron_domain_t tmp(inv); 32 | tmp.rename({x, y}, {w, z}); 33 | crab::outs() << "After rename x with w and y with z=" << tmp << "\n"; 34 | } 35 | { 36 | z_pk_apron_domain_t tmp(inv); 37 | tmp.rename({x}, {w}); 38 | crab::outs() << "After rename x with w=" << tmp << "\n"; 39 | } 40 | // { 41 | // z_pk_apron_domain_t tmp(inv); 42 | // tmp.rename({x}, {y}); 43 | // crab::outs() << "After rename x with y=" << tmp << "\n"; 44 | // // This should raise an error: 45 | // // CRAB ERROR: rename expects y to be unconstrained 46 | // } 47 | #endif 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/domains/unittests-rename-elina.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | using namespace crab::cfg; 5 | using namespace crab::cfg_impl; 6 | using namespace crab::domain_impl; 7 | using namespace ikos; 8 | 9 | int main(int argc, char **argv) { 10 | #ifdef HAVE_ELINA 11 | 12 | bool stats_enabled = false; 13 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 14 | return 0; 15 | } 16 | 17 | variable_factory_t vfac; 18 | z_var x(vfac["x"], crab::INT_TYPE, 32); 19 | z_var y(vfac["y"], crab::INT_TYPE, 32); 20 | z_var z(vfac["z"], crab::INT_TYPE, 32); 21 | z_var w(vfac["w"], crab::INT_TYPE, 32); 22 | z_var v(vfac["v"], crab::INT_TYPE, 32); 23 | 24 | z_pk_elina_domain_t inv; 25 | crab::outs() << " ===== " << inv.domain_name() << " ====\n"; 26 | inv += z_lin_cst_t(x <= 0); 27 | inv += z_lin_cst_t(y == 5); 28 | crab::outs() << "Before renaming " << inv << "\n"; 29 | 30 | { 31 | z_pk_elina_domain_t tmp(inv); 32 | tmp.rename({x, y}, {w, z}); 33 | crab::outs() << "After rename x with w and y with z=" << tmp << "\n"; 34 | } 35 | { 36 | z_pk_elina_domain_t tmp(inv); 37 | tmp.rename({x}, {w}); 38 | crab::outs() << "After rename x with w=" << tmp << "\n"; 39 | } 40 | // { 41 | // z_pk_elina_domain_t tmp(inv); 42 | // tmp.rename({x}, {y}); 43 | // crab::outs() << "After rename x with y=" << tmp << "\n"; 44 | // // This should raise an error: 45 | // // CRAB ERROR: rename expects y to be unconstrained 46 | // } 47 | #endif 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /tests/icrab.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "./crab_lang.hpp" 3 | 4 | #include 5 | 6 | using params_t = crab::analyzer::inter_analyzer_parameters; 7 | 8 | // To run abstract domains defined over integers 9 | template 10 | extern void z_bu_inter_run_and_check(crab::cg_impl::z_cg_t &cg, BUDom bu_top, 11 | TDDom td_top, bool run_liveness, 12 | const params_t ¶ms, bool enable_stats); 13 | 14 | // To run abstract domains defined over integers 15 | 16 | template 17 | extern void z_td_inter_run_and_check(crab::cg_impl::z_cg_t &cg, Dom init, 18 | const params_t ¶ms, 19 | bool print_checks, bool print_invariants, 20 | bool enable_stats); 21 | 22 | // To run abstract domains defined over integers 23 | template 24 | void bu_inter_run(crab::cg_impl::z_cg_t &cg, BUDom bu_top, TDDom td_top, 25 | bool run_liveness, const params_t ¶ms, bool enable_stats) { 26 | #ifdef USE_GENERIC_WRAPPER 27 | using namespace crab::domain_impl; 28 | z_abs_domain_t bu_top_wrapper(bu_top); 29 | z_abs_domain_t td_top_wrapper(td_top); 30 | z_bu_inter_run_and_check(cg, bu_top_wrapper, td_top_wrapper, run_liveness, params, enable_stats); 31 | #else 32 | z_bu_inter_run_and_check(cg, bu_top, td_top, run_liveness, params, enable_stats); 33 | #endif 34 | } 35 | 36 | template 37 | void td_inter_run(crab::cg_impl::z_cg_t &cg, Dom init, const params_t ¶ms, 38 | bool print_checks, bool print_invariants, bool enable_stats) { 39 | #ifdef USE_GENERIC_WRAPPER 40 | using namespace crab::domain_impl; 41 | z_abs_domain_t init_wrapper(init); 42 | z_td_inter_run_and_check(cg, init_wrapper, params, print_checks, 43 | print_invariants, enable_stats); 44 | #else 45 | z_td_inter_run_and_check(cg, init, params, print_checks, print_invariants, 46 | enable_stats); 47 | #endif 48 | } 49 | -------------------------------------------------------------------------------- /tests/icrab_inst.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "./icrab.hpp" 4 | 5 | // Here all explicit instantiations 6 | 7 | #define Z_BU_RUNNER(BUDOM, TDDOM) \ 8 | template void z_bu_inter_run_and_check( \ 9 | crab::cg_impl::z_cg_t &, BUDOM, TDDOM, bool, const params_t&, bool); 10 | 11 | #define Z_TD_RUNNER(DOM) \ 12 | template void z_td_inter_run_and_check( \ 13 | crab::cg_impl::z_cg_t &, DOM, const params_t&, bool, bool, bool); 14 | 15 | #ifdef USE_GENERIC_WRAPPER 16 | Z_BU_RUNNER(crab::domain_impl::z_abs_domain_t, 17 | crab::domain_impl::z_abs_domain_t) 18 | Z_TD_RUNNER(crab::domain_impl::z_abs_domain_t) 19 | /////////////////// 20 | #else 21 | /////////////////// 22 | Z_BU_RUNNER(crab::domain_impl::z_dbm_domain_t, 23 | crab::domain_impl::z_interval_domain_t) 24 | #ifdef HAVE_APRON 25 | Z_BU_RUNNER(crab::domain_impl::z_oct_apron_domain_t, 26 | crab::domain_impl::z_interval_domain_t) 27 | #endif 28 | Z_BU_RUNNER(crab::domain_impl::z_term_domain_t, 29 | crab::domain_impl::z_interval_domain_t) 30 | Z_BU_RUNNER(crab::domain_impl::z_num_domain_t, 31 | crab::domain_impl::z_num_domain_t) 32 | Z_TD_RUNNER(crab::domain_impl::z_dbm_domain_t) 33 | Z_TD_RUNNER(crab::domain_impl::z_sdbm_domain_t) 34 | Z_TD_RUNNER(crab::domain_impl::z_rgn_sdbm_t) 35 | #ifdef HAVE_APRON 36 | Z_TD_RUNNER(crab::domain_impl::z_oct_apron_domain_t) 37 | #endif 38 | #ifdef HAVE_ELINA 39 | Z_TD_RUNNER(crab::domain_impl::z_oct_elina_domain_t) 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /tests/inter/td_inter_3.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | Example where the callsite and the declaration of the callee share 10 | variables. 11 | 12 | All the assertions should be proven. 13 | 14 | int foo(int x, int y) { 15 | int z = x; 16 | return z; 17 | } 18 | 19 | void main() { 20 | int x = 5; 21 | int y = 10; 22 | int z = 8; 23 | z = call foo(x, y); 24 | assert(x = 5); 25 | assert(y = 10); 26 | assert(z = 5); 27 | } 28 | */ 29 | using namespace std; 30 | using namespace crab::analyzer; 31 | using namespace crab::cfg; 32 | using namespace crab::cfg_impl; 33 | using namespace crab::domain_impl; 34 | using namespace crab::cg; 35 | using namespace crab::cg_impl; 36 | 37 | z_cfg_t *foo(z_var x, z_var y, z_var z) { 38 | function_decl decl("foo", {x, y}, {z}); 39 | z_cfg_t *cfg = new z_cfg_t("entry", "exit", decl); 40 | z_basic_block_t &entry = cfg->insert("entry"); 41 | z_basic_block_t &exit = cfg->insert("exit"); 42 | entry >> exit; 43 | exit.assign(z, x); 44 | return cfg; 45 | } 46 | 47 | z_cfg_t *m(z_var x, z_var y, z_var z) { 48 | function_decl decl("main", {}, {}); 49 | z_cfg_t *cfg = new z_cfg_t("entry", "exit", decl); 50 | z_basic_block_t &entry = cfg->insert("entry"); 51 | z_basic_block_t &exit = cfg->insert("exit"); 52 | entry >> exit; 53 | entry.assign(x, 5); 54 | entry.assign(y, 10); 55 | entry.assign(z, 8); 56 | exit.callsite("foo", {z}, {x, y}); 57 | exit.assertion(x == 5); 58 | exit.assertion(y == 10); 59 | exit.assertion(z == 5); 60 | return cfg; 61 | } 62 | 63 | int main(int argc, char **argv) { 64 | bool stats_enabled = false; 65 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 66 | return 0; 67 | } 68 | 69 | using inter_params_t = inter_analyzer_parameters; 70 | variable_factory_t vfac; 71 | // Defining program variables 72 | z_var x(vfac["x"], crab::INT_TYPE, 32); 73 | z_var y(vfac["y"], crab::INT_TYPE, 32); 74 | z_var z(vfac["z"], crab::INT_TYPE, 32); 75 | 76 | z_cfg_t *t1 = foo(x, y, z); 77 | z_cfg_t *t2 = m(x, y, z); 78 | 79 | crab::outs() << *t1 << "\n" << *t2 << "\n"; 80 | 81 | vector cfgs({*t1, *t2}); 82 | z_sdbm_domain_t init; 83 | crab::outs() << "Running top-down inter-procedural analysis with " 84 | << init.domain_name() << "\n"; 85 | z_cg_t cg(cfgs); 86 | inter_params_t params; 87 | td_inter_run(cg, init, params, true, false, false); 88 | 89 | delete t1; 90 | delete t2; 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /tests/inter/td_inter_6.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | using namespace std; 10 | using namespace crab::analyzer; 11 | using namespace crab::cfg; 12 | using namespace crab::cfg_impl; 13 | using namespace crab::domain_impl; 14 | using namespace crab::cg; 15 | /* 16 | int foo(n) { 17 | if (n <= 0) return n; 18 | else return 1 + foo(n-1); 19 | } 20 | */ 21 | z_cfg_t *foo(variable_factory_t &vfac) { 22 | // Defining program variables 23 | z_var n(vfac["n"], crab::INT_TYPE, 32); 24 | z_var n1(vfac["n1"], crab::INT_TYPE, 32); 25 | z_var ret_val(vfac["res"], crab::INT_TYPE, 32); 26 | z_var foo_ret(vfac["foo_ret"], crab::INT_TYPE, 32); 27 | 28 | function_decl decl("foo", {n}, {ret_val}); 29 | // entry and exit block 30 | z_cfg_t *cfg = new z_cfg_t("entry", "exit", decl); 31 | // adding blocks 32 | z_basic_block_t &entry = cfg->insert("entry"); 33 | z_basic_block_t &base = cfg->insert("base"); 34 | z_basic_block_t &rec = cfg->insert("rec"); 35 | z_basic_block_t &exit = cfg->insert("exit"); 36 | // adding control flow 37 | entry >> base; 38 | entry >> rec; 39 | base >> exit; 40 | rec >> exit; 41 | // adding statements 42 | base.assume(n <= 0); 43 | base.assign(ret_val, n); 44 | rec.assume(n >= 1); 45 | rec.sub(n1, n, 1); 46 | rec.callsite("foo", {foo_ret}, {n1}); 47 | rec.add(ret_val, foo_ret, 1); 48 | return cfg; 49 | } 50 | 51 | using callgraph_t = call_graph; 52 | using inter_params_t = inter_analyzer_parameters; 53 | 54 | int main(int argc, char **argv) { 55 | bool stats_enabled = false; 56 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 57 | return 0; 58 | } 59 | 60 | variable_factory_t vfac; 61 | z_cfg_t *t1 = foo(vfac); 62 | crab::outs() << *t1 << "\n"; 63 | vector cfgs({*t1}); 64 | callgraph_t cg(cfgs); 65 | crab::outs() << "CallGraph=" << cg << "\n"; 66 | { 67 | z_sdbm_domain_t init; 68 | crab::outs() << "Running top-down inter-procedural analysis with " 69 | << init.domain_name() << "\n"; 70 | inter_params_t params; 71 | params.analyze_recursive_functions = true; 72 | td_inter_run(cg, init, params, true, true, false); 73 | } 74 | 75 | 76 | delete t1; 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /tests/liveness/live-1.cc: -------------------------------------------------------------------------------- 1 | #include "../common.hpp" 2 | #include "../program_options.hpp" 3 | #include 4 | 5 | using namespace std; 6 | using namespace crab::cfg; 7 | using namespace crab::cfg_impl; 8 | using namespace crab::domain_impl; 9 | 10 | z_cfg_t *prog(variable_factory_t &vfac) { 11 | /* 12 | i := 0; 13 | x := 1; 14 | y := 0; 15 | z := 3; 16 | w := 3; 17 | while (i < 100) { 18 | x := x + y; 19 | y := y + 1; 20 | nd := *; 21 | z := z xor nd; 22 | w := w xor nd; 23 | i := i + 1; 24 | } 25 | */ 26 | // Definining program variables 27 | z_var i(vfac["i"], crab::INT_TYPE, 32); 28 | z_var x(vfac["x"], crab::INT_TYPE, 32); 29 | z_var y(vfac["y"], crab::INT_TYPE, 32); 30 | z_var z(vfac["z"], crab::INT_TYPE, 32); 31 | z_var w(vfac["w"], crab::INT_TYPE, 32); 32 | z_var nd1(vfac["nd1"], crab::INT_TYPE, 32); 33 | z_var nd2(vfac["nd2"], crab::INT_TYPE, 32); 34 | // entry and exit block 35 | z_cfg_t *cfg = new z_cfg_t("entry", "ret"); 36 | // adding blocks 37 | z_basic_block_t &entry = cfg->insert("entry"); 38 | z_basic_block_t &bb1 = cfg->insert("bb1"); 39 | z_basic_block_t &bb1_t = cfg->insert("bb1_t"); 40 | z_basic_block_t &bb1_f = cfg->insert("bb1_f"); 41 | z_basic_block_t &bb2 = cfg->insert("bb2"); 42 | z_basic_block_t &exit = cfg->insert("exit"); 43 | z_basic_block_t &ret = cfg->insert("ret"); 44 | // adding control flow 45 | entry >> bb1; 46 | bb1 >> bb1_t; 47 | bb1 >> bb1_f; 48 | bb1_t >> bb2; 49 | bb2 >> bb1; 50 | bb1_f >> exit; 51 | exit >> ret; 52 | // adding statements 53 | entry.assign(i, 0); 54 | entry.assign(x, 1); 55 | entry.assign(y, 0); 56 | entry.assign(z, 3); 57 | entry.assign(w, 3); 58 | bb1_t.assume(i <= 99); 59 | bb1_f.assume(i >= 100); 60 | bb2.havoc(nd1); 61 | bb2.havoc(nd2); 62 | bb2.add(x, x, y); 63 | bb2.add(y, y, 1); 64 | bb2.bitwise_xor(z, z, nd1); 65 | bb2.bitwise_xor(w, w, nd1); 66 | bb2.add(i, i, 1); 67 | exit.assume(x <= y); 68 | 69 | return cfg; 70 | } 71 | 72 | int main(int argc, char **argv) { 73 | bool stats_enabled = false; 74 | if (!crab_tests::parse_user_options(argc, argv, stats_enabled)) { 75 | return 0; 76 | } 77 | variable_factory_t vfac; 78 | z_cfg_t *cfg = prog(vfac); 79 | crab::outs() << *cfg << "\n"; 80 | 81 | using liveness_t = crab::analyzer::live_and_dead_analysis; 82 | liveness_t live(*cfg); 83 | live.exec(); 84 | 85 | // use --log=Liveness --log=liveness 86 | 87 | delete cfg; 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/run_coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 2 ]; then 4 | echo "Usage: $0 BUILD_DIR CRAB_ROOT" 5 | echo "BUILD_DIR is the build directory (e.g., build) where tests are located" 6 | exit 1 7 | fi 8 | 9 | BUILD_DIR=$1 10 | CRAB_ROOT=$2 11 | 12 | if [ ! -d "$BUILD_DIR/test-bin" ]; then 13 | echo "$BUILD_DIR/test-bin does not exist" 14 | exit 1 15 | fi 16 | 17 | OUTFILE=all.info 18 | REPORT=lcov_report 19 | 20 | LCOV=lcov 21 | GENHTML=genhtml 22 | 23 | ## Run all the tests 24 | echo 'Running tests ...' 25 | for test in $BUILD_DIR/test-bin/* 26 | do 27 | $test >& /dev/null 28 | done 29 | echo 'done!' 30 | 31 | # Generate coverage information 32 | if [ ! -d $BUILD_DIR/lcov_files ]; then 33 | mkdir $BUILD_DIR/lcov_files 34 | fi 35 | echo 'Generating coverage information ...' 36 | PATTERNS= 37 | for test in $BUILD_DIR/test-bin/* 38 | do 39 | test=${test##*/} 40 | $LCOV -c -d $BUILD_DIR/tests/CMakeFiles/$test.dir/ -b $BUILD_DIR \ 41 | -o $BUILD_DIR/lcov_files/coverage.$test.info 42 | $LCOV -e $BUILD_DIR/lcov_files/coverage.$test.info \ 43 | "${CRAB_ROOT}/include/crab/*" \ 44 | "${CRAB_ROOT}/lib/*" \ 45 | -o $BUILD_DIR/lcov_files/$test.info 46 | cat $BUILD_DIR/lcov_files/coverage.$test.info >> $BUILD_DIR/${OUTFILE} 47 | done 48 | echo 'done!' 49 | 50 | echo 'Generating report ...' 51 | $GENHTML $BUILD_DIR/${OUTFILE} --output-directory $BUILD_DIR/$REPORT 52 | -------------------------------------------------------------------------------- /tests/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | usage() { 4 | echo "Usage: $0 EXPECTED_OUTPUT BUILD_DIR" 5 | echo "where" 6 | echo " EXPECTED_OUTPUT = expected_results.[apron|pplite|elina|boxes].out" 7 | echo " BUILD_DIR is the build directory (e.g., build) where tests are located" 8 | } 9 | 10 | if [ $# -ne 2 ]; then 11 | echo "ERROR: $0 expects 2 parameters but given $#" 12 | usage 13 | exit 1 14 | fi 15 | 16 | OLDLOG=$1 17 | DIR=$2 18 | 19 | if [ ! -d "$DIR/test-bin" ]; then 20 | echo "$DIR/test-bin does not exist" 21 | exit 1 22 | fi 23 | 24 | if [ ! -f "$OLDLOG" ]; then 25 | echo "$OLDLOG does not exist" 26 | exit 1 27 | fi 28 | 29 | ## From OLDLOG we can extract which external library tests (if any) 30 | ## should be included 31 | lib=$(basename -- "$OLDLOG") 32 | lib="${lib##expected_results.}" 33 | lib="${lib%.out}" 34 | 35 | if [[ $lib != "apron" ]] && [[ $lib != "pplite" ]] && [[ $lib != "boxes" ]] && [[ $lib != "elina" ]] && [[ $lib != "out" ]]; then 36 | echo "First parameter should be expected_results.[apron|pplite|elina|boxes].out but it is $OLDLOG" 37 | exit 1 38 | fi 39 | 40 | 41 | #DIFF=/Applications/DiffMerge.app/Contents/MacOS/DiffMerge 42 | DIFF=diff 43 | 44 | timestamp=$(date +"%m_%d_%y.%H_%M") 45 | NEWLOG=results_${timestamp}.out 46 | 47 | 48 | ## Run all the tests 49 | for test in $DIR/test-bin/* 50 | do 51 | if [[ $lib == "out" ]]; then 52 | if [[ $test != *"apron"* ]] && [[ $test != *"pplite"* ]] && [[ $test != *"boxes"* ]] && [[ $test != *"elina"* ]]; then 53 | echo "Running $test" 54 | echo "=== Begin $test ===" >> $NEWLOG 55 | $test >> $NEWLOG 2>/dev/null 56 | echo "=== End $test ===" >> $NEWLOG 57 | fi 58 | else 59 | # lib should be apron, pplite, boxes, or elina 60 | if [[ $test == *"$lib"* ]]; then 61 | echo "Running $test" 62 | echo "=== Begin $test ===" >> $NEWLOG 63 | $test >> $NEWLOG 2>/dev/null 64 | echo "=== End $test ===" >> $NEWLOG 65 | fi 66 | fi 67 | done 68 | 69 | LOGDIR=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX") 70 | LOG="$LOGDIR/log.txt" 71 | 72 | ## Diff the output of the tests with the expected output 73 | $DIFF --suppress-common-lines \ 74 | --ignore-matching-lines="CRAB WARNING:*" \ 75 | --ignore-matching-lines="=== *" \ 76 | $OLDLOG $NEWLOG >& $LOG 77 | STATUS=$? 78 | 79 | ################################################################### 80 | ## Comment this line if we want to keep the generated output 81 | ################################################################### 82 | rm -f $NEWLOG 83 | 84 | if [ $STATUS -eq 0 ]; then 85 | echo "All tests passed successfully!" 86 | exit 0 87 | else 88 | echo "Some tests produced unexpected output:" 89 | cat $LOG 90 | exit 1 91 | fi 92 | --------------------------------------------------------------------------------