├── .clang-format ├── .github └── workflows │ ├── nightly-clam-docker.yaml │ ├── test-clam-dev14-docker.yaml │ └── test-clam-docker.yml ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── clam_arch.jpg ├── cmake ├── TargetArch.cmake ├── cotire.cmake ├── crab-git.cmake ├── llvm-seahorn-git.cmake └── seadsa-git.cmake ├── demo ├── test.c └── test.c.dot.png ├── docker ├── clam.Dockerfile └── readme.md ├── emacs-mode └── crab-mode.el ├── include └── clam │ ├── CfgBuilder.hh │ ├── CfgBuilderParams.hh │ ├── Clam.hh │ ├── ClamAnalysisParams.hh │ ├── ClamQueryAPI.hh │ ├── CrabDomain.hh │ ├── CrabDomainParser.hh │ ├── CrabIREmitter.hh │ ├── DummyHeapAbstraction.hh │ ├── HeapAbstraction.hh │ ├── Passes.hh │ ├── RegisterAnalysis.hh │ ├── SeaDsaHeapAbstraction.hh │ ├── Support │ ├── Boost.hh │ ├── CFG.hh │ ├── Debug.hh │ └── NameValues.hh │ ├── Transforms │ ├── DevirtFunctions.hh │ └── Optimizer.hh │ ├── clam.h │ ├── config.h.cmake │ └── crab │ ├── crab_lang.hh │ └── read_json.hh ├── lib ├── CMakeLists.txt ├── Clam │ ├── CMakeLists.txt │ ├── CfgBuilder.cc │ ├── CfgBuilderEmitters.cc │ ├── CfgBuilderEmitters.hh │ ├── CfgBuilderLit.cc │ ├── CfgBuilderLit.hh │ ├── CfgBuilderMemRegions.cc │ ├── CfgBuilderMemRegions.hh │ ├── CfgBuilderUtils.cc │ ├── CfgBuilderUtils.hh │ ├── Clam.cc │ ├── ClamOptions.def │ ├── ClamQueryCache.cc │ ├── ClamQueryCache.hh │ ├── CrabDomainParser.cc │ ├── NameValues.cc │ ├── Optimizer │ │ └── Optimizer.cc │ ├── Properties │ │ ├── BndCheck.cc │ │ ├── BndCheck.hh │ │ ├── MemoryCheckUtils.cc │ │ ├── MemoryCheckUtils.hh │ │ ├── NullCheck.cc │ │ ├── NullCheck.hh │ │ ├── UafCheck.cc │ │ └── UafCheck.hh │ ├── RegisterAnalysis.cc │ ├── SeaDsaHeapAbstraction.cc │ ├── SeaDsaHeapAbstractionUtils.cc │ ├── SeaDsaHeapAbstractionUtils.hh │ ├── SeaDsaToRegion.cc │ ├── SeaDsaToRegion.hh │ ├── Support │ │ ├── BoostException.cc │ │ └── CFGPrinter.cc │ └── crab │ │ ├── domains │ │ ├── boxes.cc │ │ ├── boxes.hh │ │ ├── crab_defs.hh │ │ ├── crab_domains.hh │ │ ├── dis_intervals.cc │ │ ├── dis_intervals.hh │ │ ├── intervals.cc │ │ ├── intervals.hh │ │ ├── oct.cc │ │ ├── oct.hh │ │ ├── pk.cc │ │ ├── pk.hh │ │ ├── pk_pplite.cc │ │ ├── pk_pplite.hh │ │ ├── register_domains.hh │ │ ├── ric.cc │ │ ├── ric.hh │ │ ├── sign_constant.cc │ │ ├── sign_constant.hh │ │ ├── split_dbm.cc │ │ ├── split_dbm.hh │ │ ├── split_oct.cc │ │ ├── split_oct.hh │ │ ├── terms_dis_intervals.cc │ │ ├── terms_dis_intervals.hh │ │ ├── terms_intervals.cc │ │ ├── terms_intervals.hh │ │ ├── terms_zones.cc │ │ ├── terms_zones.hh │ │ ├── wrapped_intervals.cc │ │ └── wrapped_intervals.hh │ │ ├── output │ │ ├── crabir │ │ │ ├── cfg_printer.cc │ │ │ └── cfg_printer.hpp │ │ └── json │ │ │ ├── linear_constraints_parser_impl.hpp │ │ │ ├── read_json.cc │ │ │ ├── write_json.cc │ │ │ └── write_json.hh │ │ └── path_analysis │ │ ├── path_analyzer.cc │ │ └── path_analyzer.hpp └── Transforms │ ├── CMakeLists.txt │ ├── DevirtFunctions.cc │ ├── DevirtFunctionsPass.cc │ ├── ExternalizeAddressTakenFunctions.cc │ ├── ExternalizeFunctions.cc │ ├── InsertEntryPoint.cc │ ├── LoopPeeler.cc │ ├── LowerCstExpr.cc │ ├── LowerSelect.cc │ ├── LowerUnsignedICmp.cc │ ├── MarkInternalInline.cc │ ├── NondetInit.cc │ ├── PromoteAssume.cc │ ├── PromoteMalloc.cc │ ├── PropertyInstrumentation │ ├── MemoryCheck.cc │ ├── MemoryCheck.hh │ ├── NullCheck.cc │ └── UseAfterFreeCheck.cc │ └── RemoveUnreachableBlocksPass.cc ├── py ├── CMakeLists.txt ├── clam-yaml.py ├── clam.py └── stats.py ├── scripts ├── CMakeLists.txt ├── debug_assertion.py ├── output_check.py └── read_results.py ├── tests ├── CMakeLists.txt ├── array-adapt │ ├── test-array-adaptive-1.c │ ├── test-array-adaptive-10.c │ ├── test-array-adaptive-10.unsafe.c │ ├── test-array-adaptive-11.c │ ├── test-array-adaptive-11.unsafe.c │ ├── test-array-adaptive-12.c │ ├── test-array-adaptive-12.unsafe.c │ ├── test-array-adaptive-13.c │ ├── test-array-adaptive-13.unsafe.1.c │ ├── test-array-adaptive-13.unsafe.2.c │ ├── test-array-adaptive-2.c │ ├── test-array-adaptive-3.c │ ├── test-array-adaptive-4.c │ ├── test-array-adaptive-5.c │ ├── test-array-adaptive-6.c │ ├── test-array-adaptive-7.c │ ├── test-array-adaptive-8.c │ ├── test-array-adaptive-8.m64.c │ ├── test-array-adaptive-8.unsafe.c │ ├── test-array-adaptive-9.c │ ├── test-array-adaptive-9.warning.c │ ├── test-ptr-8.c │ ├── test_lower_gv.1.c │ ├── test_lower_gv.1.packed.c │ ├── test_lower_gv.2.c │ └── test_lower_gv.2.packed.c ├── clam_config.py.cmake ├── demo │ ├── demo1.c │ ├── demo2 │ ├── demo2.c │ └── lit.local.cfg ├── inter │ ├── test-inter1.c │ ├── test-inter2.c │ ├── test-inter3.c │ ├── test-inter4.c │ ├── test-inter5.c │ └── test-inter6.c ├── lit.cfg ├── mem │ ├── lit.local.cfg │ ├── test-mem-1-unsafe.c │ ├── test-mem-1.c │ ├── test-mem-10.c │ ├── test-mem-10.no_sing_alias.c │ ├── test-mem-10.warning.c │ ├── test-mem-11.c │ ├── test-mem-12.c │ ├── test-mem-13-unsafe.c │ ├── test-mem-13.c │ ├── test-mem-14.c │ ├── test-mem-15.c │ ├── test-mem-16.c │ ├── test-mem-2-unsafe.c │ ├── test-mem-2.c │ ├── test-mem-3-unsafe.c │ ├── test-mem-3.c │ ├── test-mem-4.c │ ├── test-mem-4b.c │ ├── test-mem-5.c │ ├── test-mem-6-unsafe.c │ ├── test-mem-6.c │ ├── test-mem-7.c │ ├── test-mem-8.c │ ├── test-mem-8_inlined.c │ ├── test-mem-9.c │ ├── test-mem-array-1.c │ ├── test-mem-array-10.c │ ├── test-mem-array-10.unsafe.c │ ├── test-mem-array-11.c │ ├── test-mem-array-11.unsafe.c │ ├── test-mem-array-12.c │ ├── test-mem-array-12.unsafe.c │ ├── test-mem-array-13.c │ ├── test-mem-array-13.unsafe.1.c │ ├── test-mem-array-2.c │ ├── test-mem-array-3.c │ ├── test-mem-array-4.c │ ├── test-mem-array-5.c │ ├── test-mem-array-6.c │ ├── test-mem-array-7.c │ ├── test-mem-array-8.c │ ├── test-mem-array-8.m64.c │ ├── test-mem-array-8.unsafe.c │ ├── test-mem-array-9.c │ ├── test-mem-array-9.warning.c │ ├── test-mem-array-local-1.c │ ├── test-mem-is-deref.c │ ├── test-mem-ptr-not-equal.c │ └── transfer-lamports.c ├── ntdrivers-simplified │ ├── cdaudio_simpl1_false-unreach-call_true-termination.cil.c │ ├── cdaudio_simpl1_true-unreach-call_true-termination.cil.c │ ├── diskperf_simpl1_true-unreach-call_true-termination.cil.c │ ├── floppy_simpl3_false-unreach-call_true-termination.cil.c │ ├── floppy_simpl3_true-unreach-call_true-termination.cil.c │ ├── floppy_simpl4_false-unreach-call_true-termination.cil.c │ ├── floppy_simpl4_true-unreach-call_true-termination.cil.c │ ├── kbfiltr_simpl1_true-unreach-call_true-termination.cil.c │ ├── kbfiltr_simpl2_false-unreach-call_true-termination.cil.c │ ├── kbfiltr_simpl2_true-unreach-call_true-termination.cil.c │ └── lit.local.cfg ├── opt │ ├── lit.local.cfg │ ├── test-opt-1 │ ├── test-opt-1.c │ ├── test-opt-2 │ └── test-opt-2.c ├── simple │ ├── fntest-1.c │ ├── fntest-1.unsafe.c │ ├── fntest-2.c │ ├── fntest-3.c │ ├── fntest-4.c │ ├── fntest-5.c │ ├── fntest-6.c │ ├── fntest-7.c │ ├── lit.local.cfg │ ├── test-arr-1-local.c │ ├── test-arr-1.c │ ├── test-arr-1.unsafe.c │ ├── test-arr-10.c │ ├── test-arr-11.c │ ├── test-arr-2.c │ ├── test-arr-3.c │ ├── test-arr-4.c │ ├── test-arr-4.unsafe.c │ ├── test-arr-4.warning.c │ ├── test-arr-5.c │ ├── test-arr-6.c │ ├── test-arr-7.c │ ├── test-arr-8.c │ ├── test-arr-9.c │ ├── test-bool-1.c │ ├── test-bool-2.c │ ├── test-bool-3.c │ ├── test-bool-4.c │ ├── test-bool-5.c │ ├── test-cond-1.c │ ├── test-count-by-one.c │ ├── test-count-by-one.fail.c │ ├── test-global-1.c │ ├── test-global-1.unsafe.c │ ├── test-global-2.c │ ├── test-heap-translation-1.c │ ├── test-heap-translation-1.non_singleton.crab │ ├── test-heap-translation-1.singleton.crab │ ├── test-intrinsic-1.c │ ├── test-intrinsic-2.c │ ├── test-list-1.c │ ├── test-loop-1.c │ ├── test-loop-1.unsafe.c │ ├── test-loop-2.c │ ├── test-loop-3.c │ ├── test-loop-4.c │ ├── test-loop-4.warning.c │ ├── test-memset.c │ ├── test-nested-1.c │ ├── test-nested-2.c │ ├── test-nested-3.c │ ├── test-nested-4.c │ ├── test-octagons.c │ ├── test-pagai.c │ ├── test-ptr-1.c │ ├── test-ptr-2.c │ ├── test-ptr-3.c │ ├── test-ptr-4.c │ ├── test-ptr-5.c │ ├── test-ptr-6.c │ ├── test-ptr-7.c │ ├── test-switch-1.c │ ├── test-term-1.c │ ├── test-term-2.c │ ├── test-term-3.c │ ├── test-term-4.c │ ├── test-term-5.c │ ├── test-unsigned-cmp-1.c │ ├── test-wrapped.c │ ├── test-zones-2.c │ ├── test-zones.c │ ├── test-zones.unsafe.c │ └── test_identity.c ├── ssh-simplified │ ├── lit.local.cfg │ ├── s3_clnt_1_false-unreach-call.cil.c │ ├── s3_clnt_1_true-unreach-call.cil.c │ ├── s3_clnt_2_false-unreach-call_true-termination.cil.c │ ├── s3_clnt_2_true-unreach-call_true-termination.cil.c │ ├── s3_clnt_3.cil_true-unreach-call_true-termination.c │ ├── s3_clnt_3_false-unreach-call.cil.c │ ├── s3_clnt_3_true-unreach-call.cil.c │ ├── s3_clnt_4_false-unreach-call.cil.c │ ├── s3_clnt_4_true-unreach-call.cil.c │ ├── s3_srvr_10_false-unreach-call.cil.c │ ├── s3_srvr_11_false-unreach-call.cil.c │ ├── s3_srvr_12_false-unreach-call.cil.c │ ├── s3_srvr_13_false-unreach-call.cil.c │ ├── s3_srvr_14_false-unreach-call.cil.c │ ├── s3_srvr_1_false-unreach-call.cil.c │ ├── s3_srvr_1_true-unreach-call.cil.c │ ├── s3_srvr_1a_true-unreach-call.cil.c │ ├── s3_srvr_1b_true-unreach-call_false-termination.cil.c │ ├── s3_srvr_2_false-unreach-call.cil.c │ ├── s3_srvr_2_true-unreach-call.cil.c │ ├── s3_srvr_3_true-unreach-call.cil.c │ ├── s3_srvr_4_true-unreach-call.cil.c │ ├── s3_srvr_6_false-unreach-call.cil.c │ ├── s3_srvr_6_true-unreach-call.cil.c │ ├── s3_srvr_7_true-unreach-call.cil.c │ └── s3_srvr_8_true-unreach-call.cil.c ├── ssh │ ├── lit.local.cfg │ ├── s3_clnt.blast.01_true-unreach-call.i.cil.c │ ├── s3_clnt.blast.02_true-unreach-call.i.cil.c │ ├── s3_clnt.blast.03_true-unreach-call.i.cil.c │ ├── s3_clnt.blast.04_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.01_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.02_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.06_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.07_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.08_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.09_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.10_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.11_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.12_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.13_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.14_true-unreach-call.i.cil.c │ ├── s3_srvr.blast.15_true-unreach-call.i.cil.c │ └── s3_srvr.blast.16_true-unreach-call.i.cil.c ├── tag-analysis │ ├── test1.c │ └── test2.c └── uaf │ ├── test1-ok.c │ ├── test1a-fail.c │ ├── test1b-fail.c │ ├── test2-ok.c │ ├── test2a-fail.c │ └── test2b-fail.c ├── tools ├── CMakeLists.txt ├── clam-diff │ ├── CMakeLists.txt │ └── clam-diff.cc ├── clam-pp │ ├── CMakeLists.txt │ └── clam-pp.cc └── clam │ ├── CMakeLists.txt │ └── clam.cc └── yaml-configurations ├── clam.inter.mem.yaml ├── clam.intra.mem.yaml └── clam.svcomp19.yaml /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | AllowShortFunctionsOnASingleLine: All 4 | IndentWidth: '2' 5 | 6 | ... 7 | -------------------------------------------------------------------------------- /.github/workflows/test-clam-dev14-docker.yaml: -------------------------------------------------------------------------------- 1 | # Workflow to build and test clam after each push or pull request 2 | 3 | name: CI-dev14 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the dev14 branch 8 | push: 9 | branches: dev14 10 | pull_request: 11 | branches: dev14 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: dev14 27 | - name: Build clam and run tests 28 | run: docker build -t seahorn/clam-llvm14:nightly -f docker/clam.Dockerfile . 29 | -------------------------------------------------------------------------------- /.github/workflows/test-clam-docker.yml: -------------------------------------------------------------------------------- 1 | # Workflow to build and test clam after each push or pull request 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 clam and run tests 28 | run: docker build -t seahorn/clam-llvm14:nightly -f docker/clam.Dockerfile . 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /debug/ 3 | /ext/ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: trusty 3 | os: linux 4 | cache: apt 5 | script: 6 | - docker build --build-arg BRANCH=$TRAVIS_BRANCH -t seahorn/clam-llvm10:latest -f docker/clam.Dockerfile . 7 | 8 | - 'if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then 9 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin && 10 | docker push seahorn/clam-llvm10:latest; 11 | fi ' 12 | 13 | services: 14 | - docker 15 | install: true 16 | notifications: 17 | slack: seahornteam:NAUqZmZHFFviPH4ktQbJXgKu 18 | email: 19 | recipients: 20 | - seahorn-build@googlegroups.com 21 | on_success: always 22 | on_failure: always 23 | -------------------------------------------------------------------------------- /clam_arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seahorn/clam/9ce8172cb1658a62687d0420121e038f793ae4fc/clam_arch.jpg -------------------------------------------------------------------------------- /cmake/crab-git.cmake: -------------------------------------------------------------------------------- 1 | if(TopLevel) 2 | set(CRAB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/crab" CACHE STRING "crab source directory") 3 | else() 4 | set(CRAB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/clam/crab" CACHE STRING "crab source directory" FORCE) 5 | endif() 6 | set(CRAB_REPO "https://github.com/seahorn/crab.git" CACHE STRING "crab repo") 7 | add_custom_target(crab-git 8 | ${GIT_EXECUTABLE} clone ${CRAB_REPO} ${CRAB_SOURCE_DIR}) 9 | -------------------------------------------------------------------------------- /cmake/llvm-seahorn-git.cmake: -------------------------------------------------------------------------------- 1 | set(SEAHORN_LLVM_SOURCE_DIR "${CMAKE_SOURCE_DIR}/llvm-seahorn" CACHE STRING "seahorn-llvm source directory") 2 | if (TopLevel) 3 | set(SEAHORN_LLVM_REPO "https://github.com/seahorn/llvm-seahorn" CACHE STRING "seahorn-llvm repo") 4 | add_custom_target(seahorn-llvm-git 5 | ${GIT_EXECUTABLE} clone -b dev14 ${SEAHORN_LLVM_REPO} ${SEAHORN_LLVM_SOURCE_DIR}) 6 | endif() 7 | -------------------------------------------------------------------------------- /cmake/seadsa-git.cmake: -------------------------------------------------------------------------------- 1 | set(SEADSA_SOURCE_DIR "${CMAKE_SOURCE_DIR}/sea-dsa" CACHE STRING "seadsa source directory") 2 | if (TopLevel) 3 | set(SEA_DSA_REPO "https://github.com/seahorn/sea-dsa" CACHE STRING "sea-dsa repo") 4 | add_custom_target(sea-dsa-git 5 | ${GIT_EXECUTABLE} clone -b dev14 ${SEA_DSA_REPO} ${SEADSA_SOURCE_DIR}) 6 | endif() 7 | -------------------------------------------------------------------------------- /demo/test.c: -------------------------------------------------------------------------------- 1 | extern void __CRAB_assume (int); 2 | extern void __CRAB_assert(int); 3 | extern int __CRAB_nd(); 4 | 5 | int main() { 6 | int k = __CRAB_nd(); 7 | int n = __CRAB_nd(); 8 | __CRAB_assume (k > 0); 9 | __CRAB_assume (n > 0); 10 | 11 | int x = k; 12 | int y = k; 13 | while (x < n) { 14 | x++; 15 | y++; 16 | } 17 | __CRAB_assert (x >= y); 18 | __CRAB_assert (x <= y); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /demo/test.c.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seahorn/clam/9ce8172cb1658a62687d0420121e038f793ae4fc/demo/test.c.dot.png -------------------------------------------------------------------------------- /docker/readme.md: -------------------------------------------------------------------------------- 1 | # Building Clam in Docker and running tests 2 | 3 | This container builds Clam and runs some tests: 4 | 5 | ```shell 6 | docker build -t seahorn/clam-llvm14 -f docker/clam.Dockerfile . 7 | docker run -v `pwd`:/host -it seahorn/clam-llvm14 8 | ``` 9 | -------------------------------------------------------------------------------- /include/clam/ClamQueryAPI.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/ADT/Optional.h" 4 | #include "llvm/Analysis/AliasAnalysis.h" 5 | #include "llvm/IR/ConstantRange.h" 6 | #include 7 | #include 8 | 9 | namespace llvm { 10 | class BasicBlock; 11 | class Instruction; 12 | class Value; 13 | } 14 | 15 | namespace clam { 16 | 17 | class ClamQueryAPI { 18 | public: 19 | /* a tag is just an unsigned integer */ 20 | using TagVector = std::vector; 21 | 22 | virtual ~ClamQueryAPI() {} 23 | 24 | virtual llvm::AliasResult alias(const llvm::MemoryLocation &Loc1, 25 | const llvm::MemoryLocation &Loc2, 26 | llvm::AAQueryInfo &AAQI) = 0; 27 | 28 | 29 | // Return the range for the left-hand side of I before the execution 30 | // of I. The type of I should be either integer or pointer, 31 | // otherwise an error will be raised. If the returned range is the 32 | // empty constant range then the instruction is unreachable. 33 | virtual llvm::ConstantRange range(const llvm::Instruction &I) = 0; 34 | 35 | // Return the range for V that holds at the entry of B. The type of 36 | // V should be either integer or pointer, otherwise an error will be 37 | // raised. If the returned range is the empty constant range then 38 | // the basic block is unreachable. 39 | virtual llvm::ConstantRange range(const llvm::BasicBlock &B, const llvm::Value &V) = 0; 40 | 41 | // Return the tags associated to the left-hand side of I before the 42 | // execution of I. If the type of I is not a pointer then it 43 | // returns None. 44 | virtual llvm::Optional tags(const llvm::Instruction &I) = 0; 45 | 46 | // Return the tags associated to V that hold at the entry of B. If 47 | // the type of V is not a pointer than it returns None. 48 | virtual llvm::Optional tags(const llvm::BasicBlock &B, 49 | const llvm::Value &V) = 0; 50 | 51 | }; 52 | } // end namespace clam 53 | -------------------------------------------------------------------------------- /include/clam/CrabDomainParser.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "clam/CrabDomain.hh" 4 | 5 | #include "llvm/ADT/StringRef.h" 6 | #include "llvm/Support/CommandLine.h" 7 | 8 | #include 9 | 10 | namespace clam { 11 | struct CrabDomainParser : public llvm::cl::parser { 12 | CrabDomainParser(llvm::cl::Option &O); 13 | 14 | void addLiteralOption(llvm::StringRef Name, const unsigned &V, 15 | llvm::StringRef HelpStr); 16 | // parse - Return true on error. 17 | bool parse(llvm::cl::Option &O, llvm::StringRef ArgName, 18 | llvm::StringRef ArgValue, CrabDomain::Type &Val); 19 | }; 20 | } // end namespace clam 21 | -------------------------------------------------------------------------------- /include/clam/RegisterAnalysis.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace clam { 7 | class DomainRegistry { 8 | public: 9 | using FactoryMap = std::map; 10 | static FactoryMap &getFactoryMap(); 11 | 12 | static void registerAllDomains(); 13 | static bool count(CrabDomain::Type dom_ty); 14 | static clam_abstract_domain at(CrabDomain::Type dom_ty); 15 | }; 16 | 17 | } // end namespace clam 18 | -------------------------------------------------------------------------------- /include/clam/Support/Boost.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef BOOST_NO_EXCEPTIONS 4 | #include "llvm/Support/ErrorHandling.h" 5 | namespace boost { 6 | template void throw_exception(E const &e) { 7 | llvm::report_fatal_error("boost threw an exception", false); 8 | } 9 | } // namespace boost 10 | #endif 11 | -------------------------------------------------------------------------------- /include/clam/Support/CFG.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// Extra support for llvm CFG 4 | 5 | #include "llvm/ADT/iterator_range.h" 6 | #include "llvm/IR/CFG.h" 7 | 8 | namespace clam { 9 | inline llvm::iterator_range succs(llvm::BasicBlock &bb) { 10 | return llvm::make_range(succ_begin(&bb), succ_end(&bb)); 11 | } 12 | 13 | inline llvm::iterator_range 14 | succs(const llvm::BasicBlock &bb) { 15 | return llvm::make_range(succ_begin(&bb), succ_end(&bb)); 16 | } 17 | 18 | inline llvm::iterator_range preds(llvm::BasicBlock &bb) { 19 | return llvm::make_range(pred_begin(&bb), pred_end(&bb)); 20 | } 21 | 22 | inline llvm::iterator_range 23 | preds(const llvm::BasicBlock &bb) { 24 | return llvm::make_range(pred_begin(&bb), pred_end(&bb)); 25 | } 26 | } // namespace clam 27 | -------------------------------------------------------------------------------- /include/clam/Support/Debug.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/Support/raw_ostream.h" 4 | #include // to access to CrabWarningFlag 5 | 6 | namespace clam { 7 | 8 | #define CLAM_ERROR(...) \ 9 | do { \ 10 | llvm::errs() << "CLAM ERROR: "; \ 11 | llvm::errs() << __VA_ARGS__; \ 12 | llvm::errs() << " at " << __FILE__ << ":" << __LINE__ << "\n"; \ 13 | std::exit(EXIT_FAILURE); \ 14 | } while (0) 15 | 16 | #define CLAM_WARNING(...) \ 17 | do { \ 18 | if (::crab::CrabWarningFlag) { \ 19 | llvm::errs() << "CLAM WARNING: "; \ 20 | llvm::errs() << __VA_ARGS__; \ 21 | llvm::errs() << "\n"; \ 22 | } \ 23 | } while (0) 24 | 25 | } // end namespace clam 26 | -------------------------------------------------------------------------------- /include/clam/Support/NameValues.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/IR/Function.h" 4 | #include "llvm/IR/Module.h" 5 | #include "llvm/Pass.h" 6 | 7 | namespace clam { 8 | 9 | class NameValues : public llvm::ModulePass { 10 | public: 11 | static char ID; 12 | 13 | NameValues() : llvm::ModulePass(ID) {} 14 | 15 | virtual bool runOnModule(llvm::Module &M) override; 16 | 17 | bool runOnFunction(llvm::Function &F); 18 | 19 | virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override; 20 | 21 | virtual llvm::StringRef getPassName() const override { return "Clam: Name values"; } 22 | }; 23 | } // namespace clam 24 | -------------------------------------------------------------------------------- /include/clam/config.h.cmake: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** Define whether llvm-seahorn is available */ 4 | #cmakedefine HAVE_LLVM_SEAHORN ${HAVE_LLVM_SEAHORN} 5 | 6 | /** Whether to use big numbers for representing weights in DBM-based domains **/ 7 | #cmakedefine USE_DBM_BIGNUM ${USE_DBM_BIGNUM} 8 | 9 | /** Whether to use safe or unsafe for representing weights 10 | ** in DBM-based domains. Only if USE_DBM_BIGNUM is disabled. **/ 11 | #cmakedefine USE_DBM_SAFEINT ${USE_DBM_SAFEINT} 12 | 13 | /** Include all default abstract domains.**/ 14 | #cmakedefine INCLUDE_ALL_DOMAINS ${INCLUDE_ALL_DOMAINS} 15 | 16 | /** whether Clam is compiled as a standalone application **/ 17 | #cmakedefine CLAM_IS_TOPLEVEL ${CLAM_IS_TOPLEVEL} 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Clam) 2 | if (CLAM_INCLUDE_TRANSFORMS) 3 | add_subdirectory(Transforms) 4 | endif() 5 | -------------------------------------------------------------------------------- /lib/Clam/CfgBuilderMemRegions.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "clam/HeapAbstraction.hh" 4 | #include "clam/CfgBuilderParams.hh" 5 | #include 6 | 7 | namespace llvm { 8 | class Instruction; 9 | class Value; 10 | } // end namespace llvm 11 | 12 | /** 13 | * Convenient utilities to extract memory regions from LLVM 14 | * instructions. 15 | **/ 16 | namespace clam { 17 | 18 | using RegionVec = typename HeapAbstraction::RegionVec; 19 | using RegionSet = std::set; 20 | 21 | // Return the region associated to ptr 22 | Region getRegion(HeapAbstraction &mem, RegionSet &Regions, 23 | const CrabBuilderParams ¶ms, 24 | const llvm::Function &fun, const llvm::Value &ptr); 25 | 26 | Region getRegion(HeapAbstraction &mem, RegionSet &Regions, 27 | const CrabBuilderParams ¶ms, 28 | const llvm::Instruction &I, const llvm::Value &ptr); 29 | 30 | // Return whether the region contains a singleton alias class. 31 | const llvm::Value *getSingletonValue(Region r, bool enable_unique_scalars); 32 | 33 | // v is either a llvm::Function or llvm::CallInst. 34 | template 35 | RegionVec getInputRegions(HeapAbstraction &mem, 36 | const CrabBuilderParams ¶ms, V &v); 37 | 38 | // v is either a llvm::Function or llvm::CallInst. 39 | template 40 | RegionVec getInputOutputRegions(HeapAbstraction &mem, 41 | const CrabBuilderParams ¶ms, V &v); 42 | 43 | // v is either a llvm::Function or llvm::CallInst. 44 | template 45 | RegionVec getOutputRegions(HeapAbstraction &mem, 46 | const CrabBuilderParams ¶ms, V &v); 47 | 48 | } // end namespace clam 49 | -------------------------------------------------------------------------------- /lib/Clam/CrabDomainParser.cc: -------------------------------------------------------------------------------- 1 | #include "clam/CrabDomainParser.hh" 2 | 3 | namespace clam { 4 | CrabDomainParser::CrabDomainParser(llvm::cl::Option &O) 5 | : llvm::cl::parser(O) {} 6 | 7 | void CrabDomainParser::addLiteralOption(llvm::StringRef Name, const unsigned &V, 8 | llvm::StringRef HelpStr) { 9 | CrabDomain::Type TV; 10 | bool found = false; 11 | for (auto t : CrabDomain::List) { 12 | if (t.value() == V) { 13 | TV = t; 14 | found = true; 15 | break; 16 | } 17 | } 18 | if (found) { 19 | OptionInfo X(Name, TV, HelpStr); 20 | Values.push_back(X); 21 | AddLiteralOption(Owner, Name); 22 | } else { 23 | // TODO: ERROR 24 | } 25 | } 26 | 27 | // parse - Return true on error. 28 | bool CrabDomainParser::parse(llvm::cl::Option &O, llvm::StringRef ArgName, 29 | llvm::StringRef ArgValue, 30 | CrabDomain::Type &Val) { 31 | bool found = false; 32 | for (auto t : CrabDomain::List) { 33 | if (t.name() == ArgValue) { 34 | Val = t; 35 | found = true; 36 | break; 37 | } 38 | } 39 | return !found; 40 | } 41 | } // end namespace clam 42 | -------------------------------------------------------------------------------- /lib/Clam/Properties/MemoryCheckUtils.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Utilities for memory-based property checkers. 5 | **/ 6 | 7 | #include "llvm/ADT/PointerIntPair.h" 8 | 9 | namespace llvm { 10 | class Value; 11 | } // end namespace llvm 12 | 13 | namespace clam { 14 | namespace memory_check_utils { 15 | // The Pointer is the base (global, alloca or function parameter) or 16 | // null if it cannot identified. The Integer is either 0 or 1, 17 | // indicating if the base is dereferenceable. 18 | using DerefPointer = llvm::PointerIntPair; 19 | DerefPointer getBasePtr(llvm::Value *V); 20 | } // end namespace memory_check_utils 21 | } // end namespace clam 22 | -------------------------------------------------------------------------------- /lib/Clam/RegisterAnalysis.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "crab/domains/register_domains.hh" 5 | 6 | namespace clam { 7 | 8 | void DomainRegistry::registerAllDomains() { 9 | register_interval_domain(); 10 | register_ric_domain(); 11 | register_wrapped_interval_domain(); 12 | register_dis_interval_domain(); 13 | register_boxes_domain(); 14 | register_split_dbm_domain(); 15 | register_split_oct_domain(); 16 | register_term_int_domain(); 17 | register_term_dis_int_domain(); 18 | register_num_domain(); 19 | register_oct_domain(); 20 | register_pk_domain(); 21 | register_pk_pplite_domain(); 22 | register_sign_constant_domain(); 23 | } 24 | 25 | bool DomainRegistry::count(CrabDomain::Type dom_ty) { 26 | auto &map = getFactoryMap(); 27 | return map.find(dom_ty) != map.end(); 28 | } 29 | 30 | clam_abstract_domain DomainRegistry::at(CrabDomain::Type dom_ty) { 31 | auto &map = getFactoryMap(); 32 | return map.at(dom_ty); 33 | } 34 | 35 | DomainRegistry::FactoryMap &DomainRegistry::getFactoryMap() { 36 | static FactoryMap map; 37 | return map; 38 | } 39 | } // end namespace clam 40 | -------------------------------------------------------------------------------- /lib/Clam/SeaDsaHeapAbstractionUtils.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "clam/config.h" 3 | 4 | #include 5 | 6 | namespace llvm { 7 | class Type; 8 | class Function; 9 | } // namespace llvm 10 | 11 | namespace seadsa { 12 | class Graph; 13 | class Node; 14 | } // namespace seadsa 15 | 16 | namespace clam { 17 | namespace seadsa_heap_abs_impl { 18 | 19 | struct NodeOrdering { 20 | bool operator()(const seadsa::Node *n1, const seadsa::Node *n2) const; 21 | }; 22 | 23 | using NodeSet = std::set; 24 | 25 | void set_difference(NodeSet &s1, NodeSet &s2); 26 | 27 | void set_union(NodeSet &s1, NodeSet &s2); 28 | 29 | void markReachableNodes(const seadsa::Node *n, NodeSet &set); 30 | 31 | void reachableNodes(const llvm::Function &fn, seadsa::Graph &g, 32 | NodeSet &inputReach, NodeSet &retReach); 33 | 34 | /// Computes Node reachable from the call arguments in the graph. 35 | /// reach - all reachable nodes 36 | /// outReach - subset of reach that is only reachable from the return node 37 | void argReachableNodes(const llvm::Function &fn, seadsa::Graph &G, 38 | NodeSet &reach, NodeSet &outReach); 39 | 40 | struct isInteger { 41 | unsigned m_bitwidth; // bits 42 | isInteger() : m_bitwidth(0) {} 43 | bool operator()(const llvm::Type *t); 44 | }; 45 | 46 | struct isBool { 47 | bool operator()(const llvm::Type *t) const; 48 | }; 49 | 50 | struct isIntegerOrBool { 51 | bool operator()(const llvm::Type *t) const; 52 | }; 53 | 54 | struct isPointer { 55 | bool operator()(const llvm::Type *t) const; 56 | }; 57 | 58 | } // end namespace seadsa_heap_abs_impl 59 | } // end namespace clam 60 | -------------------------------------------------------------------------------- /lib/Clam/SeaDsaToRegion.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "clam/HeapAbstraction.hh" 3 | 4 | namespace llvm { 5 | class DataLayout; 6 | class Value; 7 | } // namespace llvm 8 | 9 | namespace seadsa { 10 | class Cell; 11 | class Node; 12 | } // namespace seadsa 13 | 14 | namespace clam { 15 | 16 | // Translate a sea-dsa **cell** to a Clam memory region. 17 | RegionInfo SeaDsaToRegion(const seadsa::Cell &c, const llvm::DataLayout &dl, 18 | // flags to allow unsound disambiguation 19 | bool disambiguate_unknown, bool disambiguate_ptr_cast, 20 | bool disambiguate_external); 21 | 22 | } // end namespace clam 23 | -------------------------------------------------------------------------------- /lib/Clam/Support/BoostException.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if BOOST_VERSION / 100 % 100 >= 73 6 | #include 7 | #endif 8 | #ifdef BOOST_NO_EXCEPTIONS 9 | namespace boost { 10 | void throw_exception(std::exception const &e) { 11 | // TBD: print error message 12 | std::exit(1); 13 | } 14 | #if BOOST_VERSION / 100 % 100 >= 73 15 | // Starting with boost 1.73 16 | void throw_exception(std::exception const &e, 17 | boost::source_location const &loc) { 18 | // TBD: print error message 19 | std::exit(1); 20 | } 21 | #endif 22 | } // namespace boost 23 | #endif 24 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/boxes.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "boxes.hh" 6 | 7 | namespace clam { 8 | #ifdef INCLUDE_ALL_DOMAINS 9 | #ifdef HAVE_LDD 10 | REGISTER_DOMAIN(clam::CrabDomain::BOXES, boxes_domain) 11 | #else 12 | UNREGISTER_DOMAIN(boxes_domain) 13 | #endif 14 | #else 15 | UNREGISTER_DOMAIN(boxes_domain) 16 | #endif 17 | } // end namespace clam 18 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/boxes.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "crab_defs.hh" 6 | 7 | namespace clam { 8 | using BASE(boxes_domain_t) = crab::domains::boxes_domain; 9 | // Boxes can reason natively about booleans so that's why we don't 10 | // combine it with a boolean domain. 11 | // 12 | // TODO: Boxes does not implement rename operation so we cannot wrap 13 | // it in REF_FUN or ARRAY_FUN. 14 | using boxes_domain_t = crab::domains::array_smashing; 15 | } // end namespace clam 16 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/crab_domains.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "boxes.hh" 4 | #include "dis_intervals.hh" 5 | #include "intervals.hh" 6 | #include "oct.hh" 7 | #include "pk.hh" 8 | #include "pk_pplite.hh" 9 | #include "ric.hh" 10 | #include "split_dbm.hh" 11 | #include "split_oct.hh" 12 | #include "sign_constant.hh" 13 | #include "terms_dis_intervals.hh" 14 | #include "terms_intervals.hh" 15 | #include "terms_zones.hh" 16 | #include "wrapped_intervals.hh" 17 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/dis_intervals.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "dis_intervals.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::DIS_INTERVALS, dis_interval_domain) 9 | #else 10 | UNREGISTER_DOMAIN(dis_interval_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/dis_intervals.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using BASE(dis_interval_domain_t) = 8 | crab::domains::dis_interval_domain; 9 | using dis_interval_domain_t = 10 | RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(dis_interval_domain_t)))); 11 | } // end namespace clam 12 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/intervals.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "intervals.hh" 5 | 6 | 7 | namespace clam { 8 | #ifdef INCLUDE_ALL_DOMAINS 9 | REGISTER_DOMAIN(clam::CrabDomain::INTERVALS, interval_domain) 10 | #else 11 | UNREGISTER_DOMAIN(interval_domain) 12 | #endif 13 | } // end namespace clam 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/intervals.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using BASE(interval_domain_t) = ikos::interval_domain; 8 | using interval_domain_t = RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(interval_domain_t)))); 9 | } // end namespace clam 10 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/oct.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "oct.hh" 6 | 7 | namespace clam { 8 | #ifdef INCLUDE_ALL_DOMAINS 9 | #if defined(HAVE_APRON) || defined(HAVE_ELINA) 10 | REGISTER_DOMAIN(clam::CrabDomain::OCT, oct_domain) 11 | #else 12 | UNREGISTER_DOMAIN(oct_domain) 13 | #endif 14 | #else 15 | UNREGISTER_DOMAIN(oct_domain) 16 | #endif 17 | } // end namespace clam 18 | 19 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/oct.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "crab_defs.hh" 6 | 7 | namespace clam { 8 | #ifdef HAVE_APRON 9 | using BASE(oct_domain_t) = 10 | crab::domains::apron_domain; 12 | #else 13 | using BASE(oct_domain_t) = 14 | crab::domains::elina_domain; 16 | #endif 17 | using oct_domain_t = RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(oct_domain_t)))); 18 | } // end namespace clam 19 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/pk.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pk.hh" 6 | 7 | namespace clam { 8 | #ifdef INCLUDE_ALL_DOMAINS 9 | #if defined(HAVE_APRON) || defined(HAVE_ELINA) 10 | REGISTER_DOMAIN(clam::CrabDomain::PK, pk_domain) 11 | #else 12 | UNREGISTER_DOMAIN(pk_domain) 13 | #endif 14 | #else 15 | UNREGISTER_DOMAIN(pk_domain) 16 | #endif 17 | } // end namespace clam 18 | 19 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/pk.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "crab_defs.hh" 6 | 7 | namespace clam { 8 | #ifdef HAVE_APRON 9 | using BASE(pk_domain_t) = 10 | crab::domains::apron_domain; 12 | #else 13 | using BASE(pk_domain_t) = 14 | crab::domains::elina_domain; 16 | #endif 17 | using pk_domain_t = RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(pk_domain_t)))); 18 | } // end namespace clam 19 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/pk_pplite.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pk_pplite.hh" 6 | 7 | namespace clam { 8 | #ifdef INCLUDE_ALL_DOMAINS 9 | #ifdef HAVE_PPLITE 10 | REGISTER_DOMAIN(clam::CrabDomain::PK_PPLITE, pk_pplite_domain) 11 | #else 12 | UNREGISTER_DOMAIN(pk_pplite_domain) 13 | #endif 14 | #else 15 | UNREGISTER_DOMAIN(pk_pplite_domain) 16 | #endif 17 | } // end namespace clam 18 | 19 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/pk_pplite.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using BASE(pk_pplite_domain_t) = 8 | crab::domains::apron_domain; 10 | using pk_pplite_domain_t = RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(pk_pplite_domain_t)))); 11 | } // end namespace clam 12 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/register_domains.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace clam { 4 | extern bool register_boxes_domain(); 5 | extern bool register_dis_interval_domain(); 6 | extern bool register_interval_domain(); 7 | extern bool register_oct_domain(); 8 | extern bool register_pk_domain(); 9 | extern bool register_pk_pplite_domain(); 10 | extern bool register_ric_domain(); 11 | extern bool register_sign_constant_domain(); 12 | extern bool register_split_dbm_domain(); 13 | extern bool register_split_oct_domain(); 14 | extern bool register_term_dis_int_domain(); 15 | extern bool register_term_int_domain(); 16 | extern bool register_num_domain(); 17 | extern bool register_wrapped_interval_domain(); 18 | } // end namespace clam 19 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/ric.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ric.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::INTERVALS_CONGRUENCES, ric_domain) 9 | #else 10 | UNREGISTER_DOMAIN(ric_domain) 11 | #endif 12 | } // end namespace clam 13 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/ric.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "intervals.hh" 5 | 6 | namespace clam { 7 | using BASE(ric_domain_t) = 8 | crab::domains::numerical_congruence_domain; 9 | using ric_domain_t = RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(ric_domain_t)))); 10 | } // end namespace clam 11 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/sign_constant.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "sign_constant.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::SIGN_CONSTANTS, sign_constant_domain) 9 | #else 10 | UNREGISTER_DOMAIN(sign_constant_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/sign_constant.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using BASE(sign_constant_domain_t) = 8 | crab::domains::sign_constant_domain; 9 | using sign_constant_domain_t = 10 | RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(sign_constant_domain_t)))); 11 | } // end namespace clam 12 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/split_dbm.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "split_dbm.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::ZONES_SPLIT_DBM, split_dbm_domain) 9 | #else 10 | UNREGISTER_DOMAIN(split_dbm_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/split_dbm.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | /// To choose DBM parameters 8 | struct BigNumDBMParams { 9 | /* This version uses unlimited integers so no overflow */ 10 | enum { chrome_dijkstra = 1 }; 11 | enum { widen_restabilize = 1 }; 12 | enum { special_assign = 1 }; 13 | enum { close_bounds_inline = 0 }; 14 | using Wt = ikos::z_number; 15 | using graph_t = crab::SparseWtGraph; 16 | }; 17 | struct SafeFastDBMParams { 18 | /* This version checks for overflow and raise error if detected*/ 19 | enum { chrome_dijkstra = 1 }; 20 | enum { widen_restabilize = 1 }; 21 | enum { special_assign = 1 }; 22 | enum { close_bounds_inline = 0 }; 23 | using Wt = crab::safe_i64; 24 | using graph_t = crab::AdaptGraph; 25 | }; 26 | struct FastDBMParams { 27 | /* This version does not check for overflow */ 28 | enum { chrome_dijkstra = 1 }; 29 | enum { widen_restabilize = 1 }; 30 | enum { special_assign = 1 }; 31 | enum { close_bounds_inline = 0 }; 32 | using Wt = int64_t; 33 | using graph_t = crab::AdaptGraph; 34 | }; 35 | 36 | #ifdef USE_DBM_BIGNUM 37 | using DBMParams = BigNumDBMParams; 38 | #else 39 | #ifdef USE_DBM_SAFEINT 40 | using DBMParams = SafeFastDBMParams; 41 | #else 42 | using DBMParams = FastDBMParams; 43 | #endif 44 | #endif 45 | 46 | using BASE(split_dbm_domain_t) = 47 | crab::domains::split_dbm_domain; 48 | using split_dbm_domain_t = 49 | RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(split_dbm_domain_t)))); 50 | } // end namespace clam 51 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/split_oct.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "split_oct.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::OCT_SPLIT_DBM, split_oct_domain) 9 | #else 10 | UNREGISTER_DOMAIN(split_oct_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/split_oct.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | /// To choose DBM parameters 8 | struct BigNumDBMParams { 9 | /* This version uses unlimited integers so no overflow */ 10 | enum { chrome_dijkstra = 1 }; 11 | enum { widen_restabilize = 1 }; 12 | enum { special_assign = 1 }; 13 | enum { close_bounds_inline = 0 }; 14 | using Wt = ikos::z_number; 15 | using graph_t = crab::SparseWtGraph; 16 | }; 17 | struct SafeFastDBMParams { 18 | /* This version checks for overflow and raise error if detected*/ 19 | enum { chrome_dijkstra = 1 }; 20 | enum { widen_restabilize = 1 }; 21 | enum { special_assign = 1 }; 22 | enum { close_bounds_inline = 0 }; 23 | using Wt = crab::safe_i64; 24 | using graph_t = crab::AdaptGraph; 25 | }; 26 | struct FastDBMParams { 27 | /* This version does not check for overflow */ 28 | enum { chrome_dijkstra = 1 }; 29 | enum { widen_restabilize = 1 }; 30 | enum { special_assign = 1 }; 31 | enum { close_bounds_inline = 0 }; 32 | using Wt = int64_t; 33 | using graph_t = crab::AdaptGraph; 34 | }; 35 | 36 | #ifdef USE_DBM_BIGNUM 37 | using DBMParams = BigNumDBMParams; 38 | #else 39 | #ifdef USE_DBM_SAFEINT 40 | using DBMParams = SafeFastDBMParams; 41 | #else 42 | using DBMParams = FastDBMParams; 43 | #endif 44 | #endif 45 | 46 | using BASE(split_oct_domain_t) = 47 | crab::domains::split_oct_domain; 48 | using split_oct_domain_t = 49 | RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(split_oct_domain_t)))); 50 | } // end namespace clam 51 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/terms_dis_intervals.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "terms_dis_intervals.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::TERMS_DIS_INTERVALS, term_dis_int_domain) 9 | #else 10 | UNREGISTER_DOMAIN(term_dis_int_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/terms_dis_intervals.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using str_dis_interval_domain_t = 8 | crab::domains::dis_interval_domain; 9 | using term_dis_int_domain_t = 10 | RGN_FUN(ARRAY_FUN(BOOL_NUM(TERM_FUN(str_dis_interval_domain_t)))); 11 | } // end namespace clam 12 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/terms_intervals.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "terms_intervals.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::TERMS_INTERVALS, term_int_domain) 9 | #else 10 | UNREGISTER_DOMAIN(term_int_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/terms_intervals.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using str_interval_domain_t = interval_domain; 8 | using term_int_domain_t = 9 | RGN_FUN(ARRAY_FUN(BOOL_NUM(TERM_FUN(str_interval_domain_t)))); 10 | } // end namespace clam 11 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/terms_zones.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "terms_zones.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::TERMS_ZONES, num_domain) 9 | #else 10 | UNREGISTER_DOMAIN(num_domain) 11 | #endif 12 | } // end namespace clam 13 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/terms_zones.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "split_dbm.hh" 5 | 6 | namespace clam { 7 | /// -- Reduced product of term(dis_intervals) and zones 8 | using str_dis_interval_domain_t = crab::domains::dis_interval_domain; 9 | using BASE(num_domain_t) = reduced_numerical_domain_product2< 10 | TERM_FUN(str_dis_interval_domain_t), 11 | BASE(split_dbm_domain_t), 12 | reduced_product_impl::term_dbm_params>; 13 | using num_domain_t = RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(num_domain_t)))); 14 | } // end namespace clam 15 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/wrapped_intervals.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "wrapped_intervals.hh" 5 | 6 | namespace clam { 7 | #ifdef INCLUDE_ALL_DOMAINS 8 | REGISTER_DOMAIN(clam::CrabDomain::WRAPPED_INTERVALS, wrapped_interval_domain) 9 | #else 10 | UNREGISTER_DOMAIN(wrapped_interval_domain) 11 | #endif 12 | } // end namespace clam 13 | 14 | -------------------------------------------------------------------------------- /lib/Clam/crab/domains/wrapped_intervals.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "crab_defs.hh" 5 | 6 | namespace clam { 7 | using BASE(wrapped_interval_domain_t) = 8 | crab::domains::wrapped_interval_domain; 9 | using wrapped_interval_domain_t = 10 | RGN_FUN(ARRAY_FUN(BOOL_NUM(BASE(wrapped_interval_domain_t)))); 11 | } // end namespace clam 12 | -------------------------------------------------------------------------------- /lib/Clam/crab/output/json/write_json.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "clam/Clam.hh" 4 | #include 5 | 6 | namespace clam { 7 | namespace json { 8 | 9 | using abs_dom_map_t = typename IntraClam::abs_dom_map_t; 10 | using checks_db_t = typename IntraClam::checks_db_t; 11 | 12 | class json_report_impl; 13 | 14 | class json_report { 15 | std::unique_ptr m_pimpl; 16 | 17 | public: 18 | json_report(); 19 | 20 | ~json_report(); 21 | 22 | void write(/* the cfg under analysis */ 23 | cfg_ref_t m_cfg, 24 | /* parameters used for the analysis*/ 25 | const AnalysisParams ¶ms, 26 | /* invariants that hold at the beginning of each basic block*/ 27 | const abs_dom_map_t &invariants, 28 | /* database with number of proven/disproven assertions */ 29 | const checks_db_t &m_checksdb); 30 | 31 | std::string generate(); 32 | }; 33 | 34 | } // end namespace json 35 | } // end namespace clam 36 | -------------------------------------------------------------------------------- /lib/Transforms/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_library(LlvmPasses ${CLAM_LIBS_TYPE} DISABLE_LLVM_LINK_LLVM_DYLIB 2 | InsertEntryPoint.cc 3 | LowerCstExpr.cc 4 | LowerSelect.cc 5 | LowerUnsignedICmp.cc 6 | RemoveUnreachableBlocksPass.cc 7 | MarkInternalInline.cc 8 | DevirtFunctions.cc 9 | DevirtFunctionsPass.cc 10 | ExternalizeFunctions.cc 11 | ExternalizeAddressTakenFunctions.cc 12 | PromoteAssume.cc 13 | PromoteMalloc.cc 14 | NondetInit.cc 15 | LoopPeeler.cc 16 | PropertyInstrumentation/MemoryCheck.cc 17 | PropertyInstrumentation/NullCheck.cc 18 | PropertyInstrumentation/UseAfterFreeCheck.cc 19 | ) 20 | 21 | llvm_map_components_to_libnames(LLVM_LIBS 22 | support core irreader bitwriter instrumentation ipo scalaropts codegen objcarcopts) 23 | 24 | target_link_libraries(LlvmPasses 25 | ${SEA_DSA_LIBS} 26 | ## Needed if dynamic linking 27 | ${LLVM_LIBS}) 28 | 29 | install(TARGETS LlvmPasses 30 | ARCHIVE DESTINATION lib 31 | LIBRARY DESTINATION lib) 32 | -------------------------------------------------------------------------------- /lib/Transforms/MarkInternalInline.cc: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/Module.h" 2 | #include "llvm/Pass.h" 3 | 4 | using namespace llvm; 5 | 6 | namespace clam { 7 | 8 | /// marks all internal functions with AlwaysInline attribute 9 | struct MarkInternalInline : public ModulePass { 10 | static char ID; 11 | MarkInternalInline() : ModulePass(ID) {} 12 | 13 | virtual void getAnalysisUsage(AnalysisUsage &AU) const override { 14 | AU.setPreservesAll(); 15 | } 16 | 17 | virtual bool runOnModule(Module &M) override { 18 | for (Function &F : M) 19 | if (!F.isDeclaration() && F.hasLocalLinkage()) { 20 | F.setLinkage(GlobalValue::PrivateLinkage); 21 | F.removeFnAttr(Attribute::NoInline); 22 | F.removeFnAttr(Attribute::OptimizeNone); 23 | F.addFnAttr(Attribute::AlwaysInline); 24 | } 25 | return true; 26 | } 27 | 28 | virtual StringRef getPassName() const override { 29 | return "Clam: Mark internal functions with AlwaysInline attribute"; 30 | } 31 | }; 32 | 33 | char MarkInternalInline::ID = 0; 34 | Pass *createMarkInternalInlinePass() { return new MarkInternalInline(); } 35 | } // namespace clam 36 | -------------------------------------------------------------------------------- /lib/Transforms/PropertyInstrumentation/MemoryCheck.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* Common code in property checkers */ 4 | 5 | #include "llvm/ADT/PointerIntPair.h" 6 | 7 | namespace llvm { 8 | class Value; 9 | } // end namespace llvm 10 | 11 | namespace clam { 12 | namespace property_instrumentation { 13 | // The Pointer is the base (global, alloca or function parameter) or 14 | // null if it cannot identified. The Integer is either 0 or 1, 15 | // indicating if the base is dereferenceable. 16 | using DerefPointer = llvm::PointerIntPair; 17 | DerefPointer getBasePtr(llvm::Value *V); 18 | } // end namespace property_instrumentation 19 | } // end namespace clam 20 | -------------------------------------------------------------------------------- /lib/Transforms/RemoveUnreachableBlocksPass.cc: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/Function.h" 2 | #include "llvm/Pass.h" 3 | #include "llvm/Transforms/Utils/Local.h" 4 | 5 | #include "clam/config.h" 6 | 7 | #include "seadsa/DsaAnalysis.hh" 8 | #include "seadsa/ShadowMem.hh" 9 | 10 | using namespace llvm; 11 | 12 | namespace clam { 13 | struct RemoveUnreachableBlocksPass : public FunctionPass { 14 | static char ID; 15 | RemoveUnreachableBlocksPass() : FunctionPass(ID) {} 16 | 17 | virtual bool runOnFunction(Function &F) override { 18 | return removeUnreachableBlocks(F); 19 | } 20 | 21 | virtual void getAnalysisUsage(AnalysisUsage &AU) const override { 22 | // Preserve Sea-DSA passes 23 | AU.addPreservedID(seadsa::DsaAnalysis::ID); 24 | AU.addPreservedID(seadsa::ShadowMemPass::ID); 25 | } 26 | 27 | virtual StringRef getPassName() const override { 28 | return "Clam: Remove unreachable blocks"; 29 | } 30 | }; 31 | 32 | char RemoveUnreachableBlocksPass::ID = 0; 33 | Pass *createRemoveUnreachableBlocksPass() { 34 | return new RemoveUnreachableBlocksPass(); 35 | } 36 | } // namespace clam 37 | -------------------------------------------------------------------------------- /py/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_program(PYTHON python3 REQUIRED) 2 | 3 | if (PYTHON) 4 | install(PROGRAMS clam.py DESTINATION bin) 5 | install(PROGRAMS clam-yaml.py DESTINATION bin) 6 | install(FILES stats.py DESTINATION bin) 7 | endif() 8 | -------------------------------------------------------------------------------- /scripts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_program(PYTHON python3 REQUIRED) 2 | 3 | if (PYTHON) 4 | install(PROGRAMS read_results.py DESTINATION bin) 5 | install(PROGRAMS debug_assertion.py DESTINATION bin) 6 | endif() 7 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | return t[2] + t[4] + t[6] + t[15]; 22 | } 23 | 24 | int32_t compute2(uint32_t t[6][2]) { 25 | int i2 = nd_int(); 26 | return t[0][1] + t[1][1] + t[5][1]; 27 | } 28 | 29 | int main () { 30 | int i; 31 | for (i=0;i<10;i++) { 32 | a[i] = (nd_int() ? 3: 5); 33 | } 34 | 35 | int y = nd_int(); 36 | __CRAB_assume(y >= 0); 37 | __CRAB_assume(y < 10); 38 | int res = a[y]; 39 | __CRAB_assert(res >= 0); 40 | __CRAB_assert(res <= 5); 41 | 42 | int z = compute1(table1); 43 | __CRAB_assert(z == 31); 44 | 45 | int w = compute2(table2); 46 | __CRAB_assert(w == 90); 47 | 48 | 49 | return res+z+w; 50 | } 51 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-10.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | #define sassert(X) __CRAB_assert(X) 8 | 9 | void check(int* s, int flag) { 10 | if (flag > 0) { 11 | sassert(s[4] >= 0); 12 | sassert(s[4] <= 1); 13 | } else { 14 | sassert(s[8] >= 0); 15 | sassert(s[8] <= 1); 16 | } 17 | } 18 | 19 | 20 | int main(){ 21 | 22 | int a[10]; 23 | 24 | if (nd_int()) 25 | a[0] = 1; 26 | if (nd_int()) 27 | a[1] = 1; 28 | if (nd_int()) 29 | a[2] = 1; 30 | if (nd_int()) 31 | a[3] = 1; 32 | if (nd_int()) 33 | a[4] = 1; 34 | if (nd_int()) 35 | a[5] = 1; 36 | if (nd_int()) 37 | a[6] = 1; 38 | if (nd_int()) 39 | a[7] = 1; 40 | if (nd_int()) 41 | a[8] = 1; 42 | if (nd_int()) 43 | a[9] = 1; 44 | 45 | check(&a[0], nd_int()); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-10.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | int a[10]; 7 | 8 | void check(int* s, int flag) { 9 | if (flag > 0) { 10 | __CRAB_assert(s[4] >= 0); 11 | __CRAB_assert(s[4] <= 1); 12 | } else { 13 | __CRAB_assert(s[8] >= 0); 14 | __CRAB_assert(s[8] <= 1); 15 | } 16 | } 17 | 18 | int main(){ 19 | 20 | if (nd_int()) 21 | a[0] = 1; 22 | if (nd_int()) 23 | a[1] = 1; 24 | if (nd_int()) 25 | a[2] = 1; 26 | if (nd_int()) 27 | a[3] = 1; 28 | if (nd_int()) 29 | a[4] = 1; 30 | if (nd_int()) 31 | a[5] = 1; 32 | if (nd_int()) 33 | a[6] = 1; 34 | if (nd_int()) 35 | a[7] = 1; 36 | if (nd_int()) 37 | a[8] = 1; 38 | if (nd_int()) 39 | a[9] = 1; 40 | if (nd_int()) 41 | a[8] = 2; 42 | 43 | check(&a[0], nd_int()); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-11.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^8 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | typedef struct { 7 | int x; 8 | int y; 9 | } S1; 10 | 11 | #define N 20 12 | S1 a[N]; 13 | int b[10]; 14 | 15 | void check(S1* s1, int *s2, int flag) { 16 | if (flag > 0) { 17 | __CRAB_assert(s1[4].x >= 0); 18 | __CRAB_assert(s1[4].x <= 1); 19 | __CRAB_assert(s2[5] >= 0); 20 | __CRAB_assert(s2[5] <= 1); 21 | 22 | } else { 23 | __CRAB_assert(s1[8].y >= 0); 24 | __CRAB_assert(s1[8].y <= 1); 25 | __CRAB_assert(s2[9] >= 0); 26 | __CRAB_assert(s2[9] <= 1); 27 | 28 | } 29 | } 30 | 31 | int main(){ 32 | 33 | int i; 34 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^8 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | typedef struct { 7 | int x; 8 | int y; 9 | int z[10]; 10 | } S1; 11 | 12 | #define N 20 13 | S1 a[N]; 14 | 15 | void check(S1* s1, int flag) { 16 | if (flag > 0) { 17 | __CRAB_assert(s1[4].z[4] >= 0); 18 | __CRAB_assert(s1[4].z[4] <= 1); 19 | __CRAB_assert(s1[5].x >= 0); 20 | __CRAB_assert(s1[5].x <= 1); 21 | 22 | } else { 23 | __CRAB_assert(s1[8].z[7] >= 0); 24 | __CRAB_assert(s1[8].z[7] <= 1); 25 | __CRAB_assert(s1[6].x >= 0); 26 | __CRAB_assert(s1[6].x <= 1); 27 | 28 | } 29 | } 30 | 31 | int main(){ 32 | int i,j; 33 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | typedef struct { 7 | int x; 8 | int y; 9 | int z[10]; 10 | } S1; 11 | 12 | #define N 20 13 | S1 a[N]; 14 | 15 | void check(S1* s1, int flag) { 16 | if (flag > 0) { 17 | __CRAB_assert(s1[4].z[4] >= 0); 18 | __CRAB_assert(s1[4].z[4] <= 1); 19 | __CRAB_assert(s1[5].x >= 0); 20 | __CRAB_assert(s1[5].x <= 1); 21 | 22 | } else { 23 | __CRAB_assert(s1[8].z[7] >= 0); 24 | __CRAB_assert(s1[8].z[7] <= 1); 25 | __CRAB_assert(s1[6].x >= 0); 26 | __CRAB_assert(s1[6].x <= 1); 27 | 28 | } 29 | } 30 | 31 | int main(){ 32 | int i,j; 33 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^8 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | #define N 20 7 | 8 | typedef struct { 9 | int x; 10 | int y; 11 | int z[10]; 12 | } S1; 13 | 14 | S1 a[N]; 15 | 16 | void foo(S1* s1, int flag) { 17 | if (flag > 0) { 18 | s1[4].z[4] = 2; 19 | s1[5].x = 2; 20 | } else { 21 | s1[8].z[7] = 2; 22 | s1[6].x = 2; 23 | } 24 | } 25 | 26 | void check(S1* s1, int flag) { 27 | if (flag > 0) { 28 | __CRAB_assert(s1[4].z[4] >= 0); 29 | __CRAB_assert(s1[4].z[4] <= 2); 30 | __CRAB_assert(s1[5].x >= 0); 31 | __CRAB_assert(s1[5].x <= 2); 32 | 33 | } else { 34 | __CRAB_assert(s1[8].z[7] >= 0); 35 | __CRAB_assert(s1[8].z[7] <= 2); 36 | __CRAB_assert(s1[6].x >= 0); 37 | __CRAB_assert(s1[6].x <= 2); 38 | 39 | } 40 | } 41 | 42 | int main(){ 43 | int i,j; 44 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | #define N 20 7 | 8 | typedef struct { 9 | int x; 10 | int y; 11 | int z[10]; 12 | } S1; 13 | 14 | S1 a[N]; 15 | 16 | void foo(S1* s1, int flag) { 17 | if (flag > 0) { 18 | s1[4].z[4] = 2; 19 | s1[5].x = 2; 20 | } else { 21 | s1[8].z[7] = 3; 22 | s1[6].x = 2; 23 | } 24 | } 25 | 26 | void check(S1* s1, int flag) { 27 | if (flag > 0) { 28 | __CRAB_assert(s1[4].z[4] >= 0); 29 | __CRAB_assert(s1[4].z[4] <= 2); 30 | __CRAB_assert(s1[5].x >= 0); 31 | __CRAB_assert(s1[5].x <= 2); 32 | 33 | } else { 34 | __CRAB_assert(s1[8].z[7] >= 0); 35 | __CRAB_assert(s1[8].z[7] <= 2); 36 | __CRAB_assert(s1[6].x >= 0); 37 | __CRAB_assert(s1[6].x <= 2); 38 | 39 | } 40 | } 41 | 42 | int main(){ 43 | int i,j; 44 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total safe checks$ 3 | // CHECK: ^8 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | #define N 20 7 | 8 | typedef struct { 9 | int x; 10 | char y; // <-- make everything collapses 11 | int z[10]; 12 | } S1; 13 | 14 | S1 a[N]; 15 | 16 | void foo(S1* s1, int flag) { 17 | if (flag > 0) { 18 | s1[4].z[4] = 2; 19 | s1[5].x = 2; 20 | } else { 21 | s1[8].z[7] = 2; 22 | s1[6].x = 2; 23 | } 24 | } 25 | 26 | void check(S1* s1, int flag) { 27 | if (flag > 0) { 28 | __CRAB_assert(s1[4].z[4] >= 0); 29 | __CRAB_assert(s1[4].z[4] <= 2); 30 | __CRAB_assert(s1[5].x >= 0); 31 | __CRAB_assert(s1[5].x <= 2); 32 | 33 | } else { 34 | __CRAB_assert(s1[8].z[7] >= 0); 35 | __CRAB_assert(s1[8].z[7] <= 2); 36 | __CRAB_assert(s1[6].x >= 0); 37 | __CRAB_assert(s1[6].x <= 2); 38 | 39 | } 40 | } 41 | 42 | int main(){ 43 | int i,j; 44 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^2 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | __CRAB_assume(i1 >= 0 && i1 < 16); 22 | __CRAB_assert(t[i1] >= 0); 23 | // The pointer analysis cannot tell that the accesses are wrt to the 24 | // base address of the memory region because the memory region is 25 | // marked as "sequence" by sea-dsa. Thus, the indexes are not 26 | // translated precisely to Crab. 27 | 28 | // The return value is [4,64] 29 | return t[2] + t[4] + t[6] + t[15]; 30 | } 31 | 32 | int32_t compute2(uint32_t t[6][2]) { 33 | int i2 = nd_int(); 34 | __CRAB_assume(i2 >= 0 && i2 < 6); 35 | __CRAB_assert(t[i2][1] <= 100); 36 | // Same than above. 37 | 38 | // The return value is [30, 180] 39 | return t[0][1] + t[1][1] + t[5][1]; 40 | } 41 | 42 | int main () { 43 | int i; 44 | for (i=0;i<10;i++) { 45 | a[i] = (nd_int() ? 0: 5); 46 | } 47 | 48 | int y = nd_int(); 49 | __CRAB_assume(y >= 0); 50 | __CRAB_assume(y < 10); 51 | int res = a[y]; 52 | __CRAB_assert(res >= 0); 53 | __CRAB_assert(res <= 5); 54 | 55 | int z = compute1(table1); 56 | __CRAB_assert(z == 31); // cannot be proven 57 | 58 | int w = compute2(table2); 59 | __CRAB_assert(w == 90); // cannot be proven 60 | return res+z+w; 61 | } 62 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-4.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | int y; 22 | switch (nd_int()) { 23 | case 1: 24 | y = 2; 25 | break; 26 | case 2: 27 | y = 4; 28 | break; 29 | case 3: 30 | y = 6; 31 | break; 32 | default: 33 | y = 15; 34 | break; 35 | } 36 | t[y] = 100; 37 | return t[2] + t[4] + t[6] + t[15]; 38 | } 39 | 40 | int32_t compute2(const uint32_t t[6][2]) { 41 | int i2 = nd_int(); 42 | return t[0][1] + t[1][1] + t[5][1]; 43 | } 44 | 45 | int main () { 46 | int i; 47 | for (i=0;i<10;i++) { 48 | a[i] = (nd_int() ? 3: 5); 49 | } 50 | 51 | int y = nd_int(); 52 | __CRAB_assume(y >= 0); 53 | __CRAB_assume(y < 10); 54 | int res = a[y]; 55 | __CRAB_assert(res >= 0); 56 | __CRAB_assert(res <= 5); 57 | 58 | table2[5][1] = nd_int(); // * 59 | 60 | int z = compute1(table1); 61 | __CRAB_assert(z <= 400); 62 | 63 | int w = compute2(table2); 64 | __CRAB_assert(w == 90); // it's not true because of * 65 | 66 | 67 | return res+z+w; 68 | } 69 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-5.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^3 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | int y; 22 | switch (nd_int()) { 23 | case 1: 24 | y = 2; 25 | break; 26 | case 2: 27 | y = 4; 28 | break; 29 | case 3: 30 | y = 6; 31 | break; 32 | default: 33 | y = 15; 34 | break; 35 | } 36 | t[y] = 100; 37 | return t[2] + t[4] + t[6] + t[15]; 38 | } 39 | 40 | int32_t compute2(const uint32_t t[6][2]) { 41 | int i2 = nd_int(); 42 | return t[0][1] + t[1][1] + t[5][1]; 43 | } 44 | 45 | int main () { 46 | int i; 47 | for (i=0;i<10;i++) { 48 | a[i] = (nd_int() ? 3: 5); 49 | } 50 | 51 | int y = nd_int(); 52 | __CRAB_assume(y >= 0); 53 | __CRAB_assume(y < 10); 54 | a[y] = nd_int(); // (1) 55 | 56 | int res = a[y]; 57 | __CRAB_assert(res >= 0); // it's not true because (1) 58 | __CRAB_assert(res <= 5); 59 | 60 | table1[15] = nd_int(); // (2) 61 | int z = compute1(table1); 62 | __CRAB_assert(z <= 400); // it's not true because of (2) 63 | 64 | int w = compute2(table2); 65 | __CRAB_assert(w == 90); 66 | 67 | 68 | return res+z+w; 69 | } 70 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-6.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int x; 9 | int a[10]; 10 | 11 | int32_t compute1(int32_t *t) { 12 | int idx = nd_int(); 13 | __CRAB_assume(idx >= 0); 14 | __CRAB_assume(idx <= 3); 15 | // res = 6 but if idx == 3 then there is undefined behavior. 16 | return t[idx]; 17 | } 18 | 19 | int32_t compute2(const uint32_t t[6][2]) { 20 | // res = 30 21 | return t[0][1] + t[2][1]; 22 | } 23 | 24 | int main () { 25 | 26 | int32_t table1[4]; 27 | table1[0] = 1; 28 | table1[1] = 2; 29 | table1[2] = 3; 30 | 31 | uint32_t table2[3][2]; 32 | table2[0][1] = 10; 33 | table2[2][1] = 20; 34 | 35 | int i; 36 | for (i=0;i<10;i++) { 37 | a[i] = (nd_int() ? 3: 5); 38 | } 39 | 40 | int y = nd_int(); 41 | __CRAB_assume(y >= 0); 42 | __CRAB_assume(y < 10); 43 | int res = a[y]; 44 | __CRAB_assert(res >= 0); 45 | __CRAB_assert(res <= 5); 46 | 47 | //table1[3] = 5; 48 | int z = compute1(table1); 49 | __CRAB_assert(z <= 3); 50 | 51 | int w = compute2(table2); 52 | __CRAB_assert(w == 30); 53 | 54 | 55 | return res+z+w; 56 | } 57 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-7.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^5 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int x; 9 | int a[10]; 10 | 11 | int32_t compute1(int32_t *t) { 12 | int64_t res = t[0] + t[2]; // exact res = 4 but we get res =[2,40] 13 | int idx = nd_int(); 14 | __CRAB_assume(idx >= 0); 15 | __CRAB_assume(idx <= 3); 16 | // A symbolic index makes the pointer analysis to classify t as a 17 | // "sequence" node and therefore the translation of GEP is 18 | // imprecise. 19 | t[idx] = 30; 20 | return res; 21 | } 22 | 23 | int32_t compute2(const uint32_t t[6][2]) { 24 | // res = 30 25 | return t[0][1] + t[2][1]; 26 | } 27 | 28 | int main () { 29 | 30 | int32_t table1[4]; 31 | table1[0] = 1; 32 | table1[1] = 20; 33 | table1[2] = 3; 34 | 35 | uint32_t table2[3][2]; 36 | table2[0][1] = 10; 37 | table2[2][1] = 20; 38 | 39 | int i; 40 | for (i=0;i<10;i++) { 41 | a[i] = (nd_int() ? 3: 5); 42 | } 43 | 44 | int y = nd_int(); 45 | __CRAB_assume(y >= 0); 46 | __CRAB_assume(y < 10); 47 | int res = a[y]; 48 | __CRAB_assert(res >= 0); // ok 49 | __CRAB_assert(res <= 5); // ok 50 | 51 | int z = compute1(table1); 52 | __CRAB_assert(z <= 40); // ok 53 | 54 | z = table1[1]; 55 | __CRAB_assert(z <= 30); // ok 56 | 57 | 58 | int w = compute2(table2); 59 | __CRAB_assert(w == 30); // ok 60 | 61 | 62 | return res+z+w; 63 | } 64 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-8.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp --crab-widening-jump-set=20 --llvm-pp-loops "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | // XFAIL: * 5 | 6 | #include "clam/clam.h" 7 | 8 | extern char* nd_string(void); 9 | 10 | typedef struct { 11 | char *name; 12 | char id; 13 | } S1; 14 | 15 | 16 | void foo(S1 *devices, int len) { 17 | int i = nd_int(); 18 | __CRAB_assume(i >= 0); 19 | __CRAB_assume(i < len); 20 | devices[i].id = 0; 21 | devices[i].name = nd_string(); 22 | } 23 | 24 | S1 devices[4]; 25 | extern void avoid_opt(S1 *); 26 | 27 | int main(){ 28 | avoid_opt(&devices[0]); 29 | 30 | for (unsigned i=0; i<4; ++i) { 31 | devices[i].id = i; 32 | devices[i].name = nd_string(); 33 | } 34 | 35 | foo(&devices[0], 4); 36 | 37 | 38 | int x = nd_int(); 39 | __CRAB_assume(x >= 0); 40 | __CRAB_assume(x < 4); 41 | __CRAB_assert(devices[x].id >= 0); 42 | __CRAB_assert(devices[x].id <= 4); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-8.m64.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m64 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp --crab-widening-jump-set=20 --llvm-pp-loops "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | // XFAIL: * 5 | 6 | // With a relational domain we should be able to prove the property. 7 | // The problem is that after some LLVM optimizations we lose precision 8 | // after widening the variable "i" in the for loop in main. 9 | 10 | #include "clam/clam.h" 11 | 12 | extern char* nd_string(void); 13 | 14 | typedef struct { 15 | char *name; 16 | char id; 17 | } S1; 18 | 19 | 20 | void foo(S1 *devices, int len) { 21 | int i = nd_int(); 22 | __CRAB_assume(i >= 0); 23 | __CRAB_assume(i < len); 24 | devices[i].id = 0; 25 | devices[i].name = nd_string(); 26 | } 27 | 28 | S1 devices[4]; 29 | extern void avoid_opt(S1 *); 30 | 31 | int main(){ 32 | avoid_opt(&devices[0]); 33 | 34 | for (unsigned i=0; i<4; ++i) { 35 | devices[i].id = i; 36 | devices[i].name = nd_string(); 37 | } 38 | 39 | foo(&devices[0], 4); 40 | 41 | 42 | int x = nd_int(); 43 | __CRAB_assume(x >= 0); 44 | __CRAB_assume(x < 4); 45 | __CRAB_assert(devices[x].id >= 0); 46 | __CRAB_assert(devices[x].id <= 4); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-8.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" --crab-widening-jump-set=20 --llvm-pp-loops 2>&1 | OutputCheck %s 2 | // RUN: %clam -m64 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" --crab-widening-jump-set=20 --llvm-pp-loops 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total safe checks$ 4 | // CHECK: ^1 Number of total warning checks$ 5 | 6 | //#include 7 | #include "clam/clam.h" 8 | 9 | extern char* nd_string(void); 10 | 11 | typedef struct { 12 | char *name; 13 | char id; 14 | } S1; 15 | 16 | 17 | void foo(S1 *devices, int len) { 18 | int i = nd_int(); 19 | __CRAB_assume(i >= 0); 20 | __CRAB_assume(i < len); 21 | devices[i].id = 8; // unsafe 22 | } 23 | 24 | S1 devices[4]; 25 | extern void avoid_opt(S1 *); 26 | 27 | int main(){ 28 | avoid_opt(&devices[0]); 29 | 30 | for (unsigned i=0; i<4; ++i) { 31 | devices[i].id = i; 32 | devices[i].name = nd_string(); 33 | } 34 | foo(&devices[0], 4); 35 | 36 | 37 | int x = nd_int(); 38 | __CRAB_assume(x >= 0); 39 | __CRAB_assume(x < 4); 40 | __CRAB_assert(devices[x].id >= 0); 41 | __CRAB_assert(devices[x].id <= 4); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-9.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | int a[10]; 7 | 8 | void check(int* s, int n) { 9 | __CRAB_assert(s[n] >= 0); 10 | __CRAB_assert(s[n] <= 1); 11 | } 12 | 13 | int main(){ 14 | 15 | if (nd_int()) 16 | a[0] = 1; 17 | if (nd_int()) 18 | a[1] = 1; 19 | if (nd_int()) 20 | a[2] = 1; 21 | if (nd_int()) 22 | a[3] = 1; 23 | if (nd_int()) 24 | a[4] = 1; 25 | if (nd_int()) 26 | a[5] = 1; 27 | if (nd_int()) 28 | a[6] = 1; 29 | if (nd_int()) 30 | a[7] = 1; 31 | if (nd_int()) 32 | a[8] = 1; 33 | if (nd_int()) 34 | a[9] = 1; 35 | 36 | check(&a[0], 4); 37 | check(&a[0], 6); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/array-adapt/test-array-adaptive-9.warning.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | int a[10]; 8 | 9 | void check(int* s, int n) { 10 | __CRAB_assert(s[n] >= 0); 11 | __CRAB_assert(s[n] <= 1); 12 | } 13 | 14 | int main(){ 15 | 16 | if (nd_int()) 17 | a[0] = 1; 18 | if (nd_int()) 19 | a[1] = 1; 20 | if (nd_int()) 21 | a[2] = 1; 22 | if (nd_int()) 23 | a[3] = 1; 24 | if (nd_int()) 25 | a[4] = 1; 26 | if (nd_int()) 27 | a[5] = 1; 28 | if (nd_int()) 29 | a[6] = 1; 30 | if (nd_int()) 31 | a[7] = 1; 32 | if (nd_int()) 33 | a[8] = 1; 34 | if (nd_int()) 35 | a[9] = 1; 36 | 37 | check(&a[2], 4); // <- we lose precision if we take the address of a 38 | // non-zero index. 39 | check(&a[2], 6); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /tests/array-adapt/test-ptr-8.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam --crab-track=sing-mem --crab-dom=int --crab-inter --crab-check=assert --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | #include "clam/clam.h" 4 | 5 | void g(int x, int* p) { 6 | *p = x; 7 | } 8 | 9 | int f() { 10 | int x = 0; 11 | int* p = &x; 12 | g(1, p); 13 | return x; 14 | } 15 | 16 | int main(void) { 17 | int y = f(); 18 | // __CRAB_assert(y == 1); 19 | __CRAB_assert(y >= 0 && y <= 1); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/array-adapt/test_lower_gv.1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -m64 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^2 Number of total safe checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include 7 | #include "clam/clam.h" 8 | 9 | typedef struct { 10 | char *name; 11 | char id; 12 | } S1; 13 | 14 | 15 | S1 devices[4]; 16 | extern void avoid_opt(S1 *); 17 | 18 | int main(){ 19 | avoid_opt(&devices[0]); 20 | 21 | for (unsigned i=0; i<4; ++i) { 22 | printf("id=%d\n", devices[i].id); 23 | } 24 | 25 | int x = nd_int(); 26 | __CRAB_assume(x >= 0); 27 | __CRAB_assume(x < 4); 28 | __CRAB_assert(devices[x].id >= 0); 29 | __CRAB_assert(devices[x].id <= 4); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/array-adapt/test_lower_gv.1.packed.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -m64 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^2 Number of total safe checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include 7 | #include "clam/clam.h" 8 | 9 | typedef struct __attribute__((packed)) { 10 | char *name; 11 | char id; 12 | } S1; 13 | 14 | 15 | S1 devices[4]; 16 | extern void avoid_opt(S1 *); 17 | 18 | int main(){ 19 | avoid_opt(&devices[0]); 20 | 21 | for (unsigned i=0; i<4; ++i) { 22 | printf("id=%d\n", devices[i].id); 23 | } 24 | 25 | int x = nd_int(); 26 | __CRAB_assume(x >= 0); 27 | __CRAB_assume(x < 4); 28 | __CRAB_assert(devices[x].id >= 0); 29 | __CRAB_assert(devices[x].id <= 4); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/array-adapt/test_lower_gv.2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -m64 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^2 Number of total safe checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include 7 | #include "clam/clam.h" 8 | 9 | typedef struct { 10 | char *name; 11 | int id; 12 | } S1; 13 | 14 | 15 | S1 devices[4] = { {"name1", 0}, {"name2", 1}, {"name3", 2}, {"name4", 4} }; 16 | extern void avoid_opt(S1 *); 17 | 18 | int main(){ 19 | 20 | avoid_opt(&devices[0]); 21 | for (unsigned i=0; i<4; ++i) { 22 | printf("id=%d\n", devices[i].id); 23 | } 24 | 25 | int x = nd_int(); 26 | __CRAB_assume(x >= 0); 27 | __CRAB_assume(x < 4); 28 | 29 | __CRAB_assert(devices[x].id >= 0); 30 | __CRAB_assert(devices[x].id <= 4); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/array-adapt/test_lower_gv.2.packed.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -m64 --crab-inter --crab-track=sing-mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^2 Number of total safe checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include 7 | #include "clam/clam.h" 8 | 9 | typedef struct __attribute__((packed)) { 10 | char *name; 11 | int id; 12 | } S1; 13 | 14 | 15 | S1 devices[4] = { {"name1", 0}, {"name2", 1}, {"name3", 2}, {"name4", 4} }; 16 | extern void avoid_opt(S1 *); 17 | 18 | int main(){ 19 | 20 | avoid_opt(&devices[0]); 21 | for (unsigned i=0; i<4; ++i) { 22 | printf("id=%d\n", devices[i].id); 23 | } 24 | 25 | int x = nd_int(); 26 | __CRAB_assume(x >= 0); 27 | __CRAB_assume(x < 4); 28 | 29 | __CRAB_assert(devices[x].id >= 0); 30 | __CRAB_assert(devices[x].id <= 4); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/clam_config.py.cmake: -------------------------------------------------------------------------------- 1 | ## --- CMake options --- ## 2 | 3 | # whether Apron library is included 4 | use_apron = "${CRAB_USE_APRON}" 5 | # whether Elina library is included 6 | use_elina = "${CRAB_USE_ELINA}" 7 | # whether ldd-based boxes is included 8 | use_ldd_boxes = "${CRAB_USE_LDD}" 9 | -------------------------------------------------------------------------------- /tests/demo/demo1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include "clam/clam.h" 7 | 8 | int main() { 9 | int k = nd_int(); 10 | int n = nd_int(); 11 | __CRAB_assume(k > 0); 12 | __CRAB_assume(n > 0); 13 | 14 | int x = k; 15 | int y = k; 16 | while (x < n) { 17 | x++; 18 | y++; 19 | } 20 | __CRAB_assert(x >= y); 21 | __CRAB_assert(x <= y); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/demo/demo2.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[10]; 4 | int main (){ 5 | int i; 6 | for (i=0;i<10;i++) { 7 | if (nd_int ()) 8 | a[i]=0; 9 | else 10 | a[i]=5; 11 | } 12 | int res = a[i-1]; 13 | return res; 14 | } 15 | -------------------------------------------------------------------------------- /tests/demo/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | config.suffixes = ['.c',''] 4 | config.excludes = ['demo2.c'] 5 | 6 | -------------------------------------------------------------------------------- /tests/inter/test-inter1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-inter-recursive-functions --crab-dom=zones --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | 4 | #include "clam/clam.h" 5 | 6 | // Example of simple recursive function 7 | 8 | int foo(int x) { 9 | if (x > 0) { 10 | return 1 + foo(x-1); 11 | } else { 12 | return x; 13 | } 14 | } 15 | 16 | int main () { 17 | 18 | int x1 = nd_int(); 19 | int y1 = foo(x1); 20 | __CRAB_assert(y1 == x1); 21 | 22 | int x2 = 1000; 23 | int y2 = foo(x2); 24 | __CRAB_assert(y2 == 1000); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/inter/test-inter2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-inter-recursive-functions --crab-dom=zones --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | 4 | #include "clam/clam.h" 5 | 6 | int foo(int); 7 | int bar(int); 8 | 9 | // Example of mutually recursive functions 10 | 11 | int foo(int x) { 12 | if (x > 0) { 13 | return 1 + bar(x-1); 14 | } else { 15 | return x; 16 | } 17 | } 18 | 19 | int bar(int x) { 20 | int y = foo(x); 21 | __CRAB_assert(y == x); 22 | return y; 23 | } 24 | 25 | int main () { 26 | 27 | int x1 = nd_int(); 28 | int y1 = foo(x1); 29 | __CRAB_assert(y1 == x1); 30 | 31 | int x2 = 1000; 32 | int y2 = foo(x2); 33 | __CRAB_assert(y2 == 1000); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /tests/inter/test-inter3.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-inter-recursive-functions --crab-dom=zones --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // XFAIL: * 4 | 5 | #include "clam/clam.h" 6 | 7 | // Example of simple recursive function 8 | int foo(int i, int n) { 9 | if (i < n) { 10 | return 1 + foo(i+1,n); 11 | } 12 | return 0; 13 | } 14 | 15 | int main () { 16 | 17 | int n1 = nd_int(); 18 | __CRAB_assume(n1 > 0); 19 | int y1 = foo(0, n1); 20 | __CRAB_assert(y1 <= n1); 21 | __CRAB_assert(y1 >= n1); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/inter/test-inter6.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=zones --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | 4 | #include "clam/clam.h" 5 | #include "seadsa/sea_dsa.h" 6 | #include 7 | 8 | struct object { 9 | int x; 10 | int y; 11 | }; 12 | 13 | struct object *mult_obj(struct object *obj, int k) { 14 | obj->x = k; 15 | obj->y = k; 16 | struct object *ret = (struct object *)malloc(sizeof(struct object)); 17 | ret->x = k; 18 | ret->y = k; 19 | return ret; 20 | } 21 | 22 | int main() { 23 | int a = nd_int(); 24 | __CRAB_assume(a == 3); 25 | struct object* obj = (struct object *)malloc(sizeof(struct object)); 26 | obj->x = 4; 27 | obj->y = 5; 28 | struct object * ret = mult_obj(obj, a); 29 | sea_dsa_alias(ret, obj); 30 | __CRAB_assert(ret->x == 3); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/mem/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | import clam_config 4 | 5 | config.excludes = [] 6 | 7 | if clam_config.use_apron == "OFF" and clam_config.use_elina == "OFF": 8 | config.excludes += ['test-mem-15.c'] 9 | -------------------------------------------------------------------------------- /tests/mem/test-mem-1-unsafe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^0 Number of total safe checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | 7 | int main() { 8 | volatile int *a = (int*) malloc(sizeof(int)); 9 | volatile int *p,*q; 10 | 11 | if (nd_int()) { 12 | p = a; 13 | } else { 14 | q = a; 15 | } 16 | 17 | if (nd_int()) { 18 | *p = 5; 19 | } else { 20 | *q = 10; 21 | } 22 | 23 | __CRAB_assert(*a < 5); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /tests/mem/test-mem-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^2 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | int main() { 9 | volatile int *a = (int*) malloc(sizeof(int)); 10 | volatile int *p,*q; 11 | 12 | if (nd_int()) { 13 | p = a; 14 | } else { 15 | q = a; 16 | } 17 | 18 | if (nd_int()) { 19 | *p = 5; 20 | } else { 21 | *q = 10; 22 | } 23 | 24 | __CRAB_assert(*a >= 5); 25 | __CRAB_assert(*a <= 10); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/mem/test-mem-10.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=mem --crab-singleton-aliases --crab-heap-analysis=cs-sea-dsa --llvm-peel-loops=1 --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | 4 | #include "clam/clam.h" 5 | 6 | /** Same as test-arr-4.c but with --crab-track=mem **/ 7 | 8 | int x = 5; 9 | int y = 3; 10 | 11 | void foo () 12 | { 13 | x++; 14 | } 15 | 16 | void bar () 17 | { 18 | y++; 19 | } 20 | 21 | int a[10]; 22 | 23 | int main () 24 | { 25 | int i; 26 | foo (); 27 | for (i=0;i<10;i++) 28 | { 29 | if (nd_int()) 30 | a[i] =y; 31 | else 32 | a[i] =x; 33 | } 34 | bar (); 35 | int res = a[i-1]; 36 | __CRAB_assert(res >= 0 && res <= 6); 37 | return res; 38 | } 39 | -------------------------------------------------------------------------------- /tests/mem/test-mem-10.no_sing_alias.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | 4 | #include "clam/clam.h" 5 | 6 | /** Same as test-arr-4.c but with --crab-track=mem **/ 7 | 8 | int x = 5; 9 | int y = 3; 10 | 11 | void foo () 12 | { 13 | x++; 14 | } 15 | 16 | void bar () 17 | { 18 | y++; 19 | } 20 | 21 | int a[10]; 22 | 23 | int main () 24 | { 25 | int i; 26 | foo (); 27 | for (i=0;i<10;i++) 28 | { 29 | if (nd_int()) 30 | a[i] =y; 31 | else 32 | a[i] =x; 33 | } 34 | bar (); 35 | int res = a[i-1]; 36 | __CRAB_assert(res >= 0 && res <= 6); 37 | return res; 38 | } 39 | -------------------------------------------------------------------------------- /tests/mem/test-mem-10.warning.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-singleton-aliases --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total error checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | /** Same as test-arr-4.warning.c but with --crab-track=mem **/ 8 | 9 | int x = 5; 10 | int y = 3; 11 | 12 | void foo () 13 | { 14 | x++; 15 | } 16 | 17 | void bar () 18 | { 19 | y++; 20 | } 21 | 22 | int a[10]; 23 | 24 | int main () 25 | { 26 | int i; 27 | foo (); 28 | for (i=0;i<10;i++) 29 | { 30 | if (nd_int()) 31 | a[i] =y; 32 | else 33 | a[i] =x; 34 | } 35 | bar (); 36 | int res = a[i-1]; 37 | __CRAB_assert(res >= 6); 38 | return res; 39 | } 40 | -------------------------------------------------------------------------------- /tests/mem/test-mem-11.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-inter-recursive-functions --crab-dom=int --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // XFAIL: * 4 | 5 | #include "clam/clam.h" 6 | 7 | // We need to statically or dynamically peel the recursive function 8 | // one iteration to keep the invariant that forall i :: a[i] == 5. 9 | 10 | /* Initialize an array */ 11 | void rec_init(int* a, int n) { 12 | if (n == 0) { 13 | a[0] = 5; 14 | return; 15 | } 16 | else { 17 | __CRAB_assert(n > 0); 18 | a[n] = 5; 19 | rec_init(a, n-1); 20 | } 21 | } 22 | 23 | int main () { 24 | int a[10]; 25 | rec_init(&a[0], 9); 26 | 27 | int i = nd_int(); 28 | __CRAB_assume(i >=0); 29 | __CRAB_assume(i < 10); 30 | int res = a[i-1]; 31 | __CRAB_assert(res == 5); 32 | return res; 33 | } 34 | -------------------------------------------------------------------------------- /tests/mem/test-mem-12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=sign-const --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^1 Number of total safe checks$ 6 | // CHECK: ^1 Number of total warning checks$ 7 | 8 | typedef struct node{ 9 | int f; 10 | int* s; 11 | struct node *n; 12 | } *List; 13 | 14 | #define N 10000 15 | 16 | List mk_list(int n, int*p, int*q) { 17 | List l = 0; 18 | 19 | /* first loop unrolling */ 20 | List tmp = (List) malloc(sizeof(struct node)); 21 | __CRAB_assume(tmp > 0); 22 | 23 | tmp->f = 0; 24 | if (nd_int()) { 25 | tmp->s = p; 26 | } else { 27 | tmp->s = q; 28 | } 29 | tmp->n = l ; 30 | l = tmp; 31 | 32 | /* n-1 loop iterations */ 33 | int i; 34 | for (i=1; i 0); 37 | 38 | tmp->f = i; 39 | if (nd_int()) { 40 | tmp->s = p; 41 | } else { 42 | tmp->s = q; 43 | } 44 | tmp->n = l ; 45 | l = tmp; 46 | } 47 | return l; 48 | } 49 | 50 | int main() { 51 | 52 | int x; 53 | int y; 54 | 55 | /* read the list */ 56 | List aux = mk_list(N, &x, &y); 57 | int acc = 0; 58 | while (aux) { 59 | __CRAB_assert(aux->f <= N-1); // SAFE but sign-const cannot prove it 60 | __CRAB_assert(aux->s > 0); // SAFE 61 | acc += aux->f; 62 | aux = aux->n; 63 | } 64 | 65 | return acc; 66 | } 67 | -------------------------------------------------------------------------------- /tests/mem/test-mem-13-unsafe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-inter-recursive-functions --crab-dom=int --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^0 Number of total safe checks$ 6 | // CHECK: ^1 Number of total warning checks$ 7 | 8 | typedef void (*funcPtr)(int); 9 | extern funcPtr int_func_ptr(void); 10 | 11 | void fun1(int a) { 12 | printf("Value of a is %d\n", a); 13 | } 14 | void fun2(int a) { 15 | printf("Value of a is %d\n", a+1); 16 | } 17 | void fun3(int a) { 18 | printf("Value of a is %d\n", a+2); 19 | } 20 | 21 | void (*fun_ptr)(int) = fun3; 22 | 23 | int main() { 24 | 25 | int x = nd_int(); 26 | __CRAB_assume (x >= 0); 27 | if (x > 0) 28 | fun_ptr = fun1; 29 | else 30 | fun_ptr = int_func_ptr(); 31 | 32 | if (x < 0) fun_ptr = fun3; 33 | 34 | __CRAB_assert(fun_ptr != fun3); 35 | 36 | (*fun_ptr)(x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/mem/test-mem-13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-inter-recursive-functions --crab-dom=int --crab-track=mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^1 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | void fun1(int a) { 9 | printf("Value of a is %d\n", a); 10 | } 11 | void fun2(int a) { 12 | printf("Value of a is %d\n", a+1); 13 | } 14 | void fun3(int a) { 15 | printf("Value of a is %d\n", a+2); 16 | } 17 | 18 | void (*fun_ptr)(int) = fun3; 19 | 20 | int main() { 21 | 22 | int x = nd_int(); 23 | __CRAB_assume(x >= 0); 24 | if (x > 0) 25 | fun_ptr = fun1; 26 | else 27 | fun_ptr = fun2; 28 | 29 | if (x < 0) fun_ptr = fun3; 30 | 31 | __CRAB_assert(fun_ptr != fun3); 32 | 33 | (*fun_ptr)(x); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/mem/test-mem-14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "clam/clam.h" 7 | 8 | // RUN: %clam -O0 --crab-inter --crab-dom=soct --promote-malloc=false --crab-track=mem --crab-check=bounds "%s" 2>&1 | OutputCheck %s 9 | // CHECK: ^2 Number of total safe checks$ 10 | // CHECK: ^0 Number of total warning checks$ 11 | 12 | bool uninterpreted_predicate_fn(uint8_t value) { 13 | return nd_bool(); 14 | } 15 | 16 | int main() { 17 | int len = nd_int(); 18 | __CRAB_assume(len > 0); 19 | int max_len = 1024; 20 | __CRAB_assume(len < max_len); 21 | int data_type = 1; 22 | uint8_t *ptr = malloc(len * data_type); 23 | while (len > 0) { 24 | uint8_t *p2 = ptr + (len - 1); 25 | uint8_t tmp = *p2; 26 | if (uninterpreted_predicate_fn(tmp)) break; 27 | -- len; 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tests/mem/test-mem-15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "clam/clam.h" 7 | 8 | // RUN: %clam -O0 --crab-inter --crab-dom=pk --promote-malloc=false --crab-track=mem --crab-check=bounds "%s" 2>&1 | OutputCheck %s 9 | // CHECK: ^4 Number of total safe checks$ 10 | // CHECK: ^1 Number of total warning checks$ 11 | 12 | // Domain: polka 13 | int main(void) { 14 | int cap = nd_int(); 15 | int max = 10; 16 | __CRAB_assume(cap > 0); 17 | __CRAB_assume(cap <= max); 18 | 19 | int *out = malloc(sizeof(int) * cap); 20 | for (int i = 0; i < cap; ++i) { 21 | out[i] = i; 22 | } 23 | for (int i = 0; i < cap; ++i) { 24 | // load reference is safe 25 | __CRAB_assert(out[i] >= 0); // no element determined 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /tests/mem/test-mem-16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "clam/clam.h" 7 | 8 | // RUN: %clam -O0 --crab-inter --crab-dom=soct --promote-malloc=false --crab-track=mem --crab-check=is-deref "%s" 2>&1 | OutputCheck %s 9 | // CHECK: ^1 Number of total safe checks$ 10 | // CHECK: ^0 Number of total warning checks$ 11 | 12 | extern bool sea_is_dereferenceable(const void *ptr, intptr_t offset); 13 | 14 | int main(void) { 15 | int cap = nd_int(); 16 | int min = 3; 17 | int max = 10; 18 | __CRAB_assume(cap > min); 19 | __CRAB_assume(cap <= max); 20 | 21 | int *out = malloc(sizeof(int) * cap); 22 | // clam adds an assertion so no need to add __CRAB_assert. 23 | sea_is_dereferenceable(out, min); 24 | //__CRAB_assert(sea_is_dereferenceable(out, min)); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tests/mem/test-mem-2-unsafe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^0 Number of total safe checks$ 6 | // CHECK: ^1 Number of total warning checks$ 7 | 8 | int* foo(int *p) { 9 | if (nd_int()) { 10 | *p = 5; 11 | } else { 12 | *p = 10; 13 | } 14 | return p; 15 | } 16 | 17 | int main() { 18 | int *p = (int*) malloc(sizeof(int)); 19 | int *q = foo(p); 20 | __CRAB_assert(*q >= 6); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/mem/test-mem-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^1 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | int* foo(int *p) { 9 | if (nd_int()) { 10 | *p = 5; 11 | } else { 12 | *p = 10; 13 | } 14 | return p; 15 | } 16 | 17 | /* The malloc is converted to an alloca the LLVM frontend. 18 | * 19 | * With -crab-track=sing-mem, Clam infers that *q is between 0 and 20 | * 10. The lower bound is not 5 because Clam assumes that all allocas 21 | * are initialized to 0. Then, the first store in foo is already a 22 | * weak update. 23 | * 24 | * With --crab-track=mem Clam can infer that *q is between 5 and 10. 25 | */ 26 | int main() { 27 | int *p = (int*) malloc(sizeof(int)); 28 | int *q = foo(p); 29 | __CRAB_assert(*q >= 5); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /tests/mem/test-mem-3-unsafe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^0 Number of total safe checks$ 6 | // CHECK: ^1 Number of total warning checks$ 7 | 8 | int* foo() { 9 | int *p = (int*) malloc(sizeof(int)); 10 | if (nd_int()) { 11 | *p = 4; 12 | } else { 13 | *p = 10; 14 | } 15 | return p; 16 | } 17 | 18 | int main() { 19 | int *q = foo(); 20 | __CRAB_assert(*q >= 5); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/mem/test-mem-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^1 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | /* 9 | * The malloc cannot be converted to an alloca by the frontend. 10 | * 11 | * With --crab-track=sing-mem, Clam ignores dynamically allocated memory. 12 | * 13 | * With --crab-track=mem, Clam can prove the property. 14 | * 15 | */ 16 | int* foo() { 17 | int *p = (int*) malloc(sizeof(int)); 18 | if (nd_int()) { 19 | *p = 5; 20 | } else { 21 | *p = 10; 22 | } 23 | return p; 24 | } 25 | 26 | int main() { 27 | int *q = foo(); 28 | __CRAB_assert(*q >= 5); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tests/mem/test-mem-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --llvm-peel-loops=1 --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^6 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | typedef struct node{ 9 | int f; 10 | int s; 11 | struct node *n; 12 | } *List; 13 | 14 | #define N 10000 15 | 16 | int main() { 17 | 18 | /* The malloc is converted to an alloca by the LLVM frontend */ 19 | 20 | /* create the list from the end to the start*/ 21 | List l = 0; 22 | int i; 23 | for (i=0; if = i; 26 | if (nd_int()) { 27 | tmp->s = N*2; 28 | } else { 29 | tmp->s = N*3; 30 | } 31 | tmp->n = l ; 32 | l = tmp; 33 | } 34 | 35 | /* read the list */ 36 | List aux = l; 37 | int acc = 0; 38 | while (aux) { 39 | __CRAB_assert(aux->f <= N-1); // SAFE 40 | __CRAB_assert(aux->s >= N*2); // SAFE 41 | __CRAB_assert(aux->s <= N*3); // SAFE 42 | acc += aux->f; 43 | aux = aux->n; 44 | } 45 | 46 | return acc; 47 | } 48 | -------------------------------------------------------------------------------- /tests/mem/test-mem-4b.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-inter --crab-dom=zones --crab-track=mem --llvm-peel-loops=1 --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^6 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | typedef struct node{ 9 | int f; 10 | int s; 11 | struct node *n; 12 | } *List; 13 | 14 | #define N 10000 15 | 16 | int main() { 17 | 18 | /* The malloc is converted to an alloca by the LLVM frontend */ 19 | 20 | /* create the list from the end to the start*/ 21 | List l = 0; 22 | int i; 23 | for (i=0; if = i; 26 | if (nd_int()) { 27 | tmp->s = N*2; 28 | } else { 29 | tmp->s = N*3; 30 | } 31 | tmp->n = l ; 32 | l = tmp; 33 | } 34 | 35 | /* read the list */ 36 | List aux = l; 37 | int acc = 0; 38 | while (aux) { 39 | __CRAB_assert(aux->f <= N-1); // SAFE 40 | __CRAB_assert(aux->s >= N*2); // SAFE 41 | __CRAB_assert(aux->s <= N*3); // SAFE 42 | acc += aux->f; 43 | aux = aux->n; 44 | } 45 | 46 | return acc; 47 | } 48 | -------------------------------------------------------------------------------- /tests/mem/test-mem-5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^3 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | typedef struct node{ 9 | int f; 10 | int s; 11 | struct node *n; 12 | } *List; 13 | 14 | #define N 10000 15 | 16 | List mk_list(int n) { 17 | List l = 0; 18 | 19 | /* first loop unrolling */ 20 | List tmp = (List) malloc(sizeof(struct node)); 21 | tmp->f = 0; 22 | if (nd_int()) { 23 | tmp->s = n*2; 24 | } else { 25 | tmp->s = n*3; 26 | } 27 | tmp->n = l ; 28 | l = tmp; 29 | 30 | /* n-1 loop iterations */ 31 | int i; 32 | for (i=1; if = i; 35 | if (nd_int()) { 36 | tmp->s = n*2; 37 | } else { 38 | tmp->s = n*3; 39 | } 40 | tmp->n = l ; 41 | l = tmp; 42 | } 43 | return l; 44 | } 45 | 46 | int main() { 47 | 48 | /* read the list */ 49 | List aux = mk_list(N); 50 | int acc = 0; 51 | while (aux) { 52 | __CRAB_assert(aux->f <= N-1); // SAFE 53 | __CRAB_assert(aux->s >= N*2); // SAFE 54 | __CRAB_assert(aux->s <= N*3); // SAFE 55 | acc += aux->f; 56 | aux = aux->n; 57 | } 58 | 59 | return acc; 60 | } 61 | -------------------------------------------------------------------------------- /tests/mem/test-mem-6-unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | // The first store in f is a strong update and the second is a weak 8 | // update. 9 | 10 | // if p and q alias then *p=2 and *q=2 11 | // else *p=1 and *q=2 12 | void f(int* p, int* q) { 13 | if (nd_int()) { 14 | p = q; 15 | } 16 | *p = 1; 17 | *q = 2; 18 | } 19 | 20 | int main() { 21 | volatile int x; 22 | volatile int y; 23 | f(&x, &y); 24 | 25 | __CRAB_assert(x >= 1); 26 | __CRAB_assert(x <= 2); 27 | __CRAB_assert(y == 2); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/mem/test-mem-6.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | void f(int* p, int* q) { 8 | *p = 1; 9 | *q = 2; 10 | } 11 | 12 | int main() { 13 | volatile int x; 14 | volatile int y; 15 | f(&x, &y); 16 | 17 | __CRAB_assert(x == 1); 18 | __CRAB_assert(y == 2); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /tests/mem/test-mem-7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | // RUN: %clam -O0 --lower-select --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 5 | // CHECK: ^2 Number of total safe checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | typedef struct node{ 9 | int f; 10 | int* s; 11 | struct node *n; 12 | } *List; 13 | 14 | #define N 10000 15 | 16 | List mk_list(int n, int*p, int*q) { 17 | List l = 0; 18 | 19 | /* first loop unrolling */ 20 | List tmp = (List) malloc(sizeof(struct node)); 21 | __CRAB_assume(tmp > 0); 22 | 23 | tmp->f = 0; 24 | if (nd_int()) { 25 | tmp->s = p; 26 | } else { 27 | tmp->s = q; 28 | } 29 | tmp->n = l ; 30 | l = tmp; 31 | 32 | /* n-1 loop iterations */ 33 | int i; 34 | for (i=1; i 0); 37 | 38 | tmp->f = i; 39 | if (nd_int()) { 40 | tmp->s = p; 41 | } else { 42 | tmp->s = q; 43 | } 44 | tmp->n = l ; 45 | l = tmp; 46 | } 47 | return l; 48 | } 49 | 50 | int main() { 51 | 52 | int x; 53 | int y; 54 | 55 | /* read the list */ 56 | List aux = mk_list(N, &x, &y); 57 | int acc = 0; 58 | while (aux) { 59 | __CRAB_assert(aux->f <= N-1); // SAFE 60 | __CRAB_assert(aux->s > 0); // SAFE 61 | acc += aux->f; 62 | aux = aux->n; 63 | } 64 | 65 | return acc; 66 | } 67 | -------------------------------------------------------------------------------- /tests/mem/test-mem-8.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | /* c/loops/veris.c_NetBSD-libc__loop_true-unreach-call_true-termination.i */ 4 | 5 | // RUN: %clam -O0 --lower-select --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 6 | // CHECK: ^1 Number of total safe checks$ 7 | // CHECK: ^0 Number of total warning checks$ 8 | 9 | void __VERIFIER_assert(int cond) { 10 | if (!(cond)) { 11 | ERROR: __VERIFIER_error(); 12 | } 13 | return; 14 | } 15 | typedef int Char; 16 | 17 | 18 | Char *tmp; 19 | 20 | int glob2 (Char *pathbuf, Char *pathlim) 21 | { 22 | Char *p; 23 | 24 | for (p = pathbuf; p <= pathlim; p++) { 25 | 26 | __VERIFIER_assert(p<=tmp); 27 | *p = 1; 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | int main () 34 | { 35 | Char pathbuf[1 +1]; 36 | 37 | Char *bound = pathbuf + sizeof(pathbuf)/sizeof(*pathbuf) - 1; 38 | 39 | tmp = pathbuf + sizeof(pathbuf)/sizeof(*pathbuf) - 1; 40 | 41 | glob2 (pathbuf, bound); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/mem/test-mem-8_inlined.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | /* c/loops/veris.c_NetBSD-libc__loop_true-unreach-call_true-termination.i */ 4 | 5 | // RUN: %clam -O0 --lower-select --crab-inter --crab-dom=zones --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks --inline "%s" 2>&1 | OutputCheck %s 6 | // CHECK: ^1 Number of total safe checks$ 7 | // CHECK: ^0 Number of total warning checks$ 8 | 9 | void __VERIFIER_assert(int cond) { 10 | if (!(cond)) { 11 | ERROR: __VERIFIER_error(); 12 | } 13 | return; 14 | } 15 | typedef int Char; 16 | 17 | 18 | Char *tmp; 19 | 20 | int glob2 (Char *pathbuf, Char *pathlim) 21 | { 22 | Char *p; 23 | 24 | for (p = pathbuf; p <= pathlim; p++) { 25 | 26 | __VERIFIER_assert(p<=tmp); 27 | *p = 1; 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | int main () 34 | { 35 | Char pathbuf[1 +1]; 36 | 37 | Char *bound = pathbuf + sizeof(pathbuf)/sizeof(*pathbuf) - 1; 38 | 39 | tmp = pathbuf + sizeof(pathbuf)/sizeof(*pathbuf) - 1; 40 | 41 | glob2 (pathbuf, bound); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | return t[2] + t[4] + t[6] + t[15]; 22 | } 23 | 24 | int32_t compute2(uint32_t t[6][2]) { 25 | int i2 = nd_int(); 26 | return t[0][1] + t[1][1] + t[5][1]; 27 | } 28 | 29 | int main () { 30 | int i; 31 | for (i=0;i<10;i++) { 32 | a[i] = (nd_int() ? 3: 5); 33 | } 34 | 35 | int y = nd_int(); 36 | __CRAB_assume(y >= 0); 37 | __CRAB_assume(y < 10); 38 | int res = a[y]; 39 | __CRAB_assert(res >= 0); 40 | __CRAB_assert(res <= 5); 41 | 42 | int z = compute1(table1); 43 | __CRAB_assert(z == 31); 44 | 45 | int w = compute2(table2); 46 | __CRAB_assert(w == 90); 47 | 48 | 49 | return res+z+w; 50 | } 51 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-10.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | #define sassert(X) __CRAB_assert(X) 8 | 9 | void check(int* s, int flag) { 10 | if (flag > 0) { 11 | sassert(s[4] >= 0); 12 | sassert(s[4] <= 1); 13 | } else { 14 | sassert(s[8] >= 0); 15 | sassert(s[8] <= 1); 16 | } 17 | } 18 | 19 | 20 | int main(){ 21 | 22 | int a[10]; 23 | 24 | if (nd_int()) 25 | a[0] = 1; 26 | if (nd_int()) 27 | a[1] = 1; 28 | if (nd_int()) 29 | a[2] = 1; 30 | if (nd_int()) 31 | a[3] = 1; 32 | if (nd_int()) 33 | a[4] = 1; 34 | if (nd_int()) 35 | a[5] = 1; 36 | if (nd_int()) 37 | a[6] = 1; 38 | if (nd_int()) 39 | a[7] = 1; 40 | if (nd_int()) 41 | a[8] = 1; 42 | if (nd_int()) 43 | a[9] = 1; 44 | 45 | check(&a[0], nd_int()); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-10.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | int a[10]; 8 | 9 | void check(int* s, int flag) { 10 | if (flag > 0) { 11 | __CRAB_assert(s[4] >= 0); 12 | __CRAB_assert(s[4] <= 1); 13 | } else { 14 | __CRAB_assert(s[8] >= 0); 15 | __CRAB_assert(s[8] <= 1); 16 | } 17 | } 18 | 19 | int main(){ 20 | 21 | if (nd_int()) 22 | a[0] = 1; 23 | if (nd_int()) 24 | a[1] = 1; 25 | if (nd_int()) 26 | a[2] = 1; 27 | if (nd_int()) 28 | a[3] = 1; 29 | if (nd_int()) 30 | a[4] = 1; 31 | if (nd_int()) 32 | a[5] = 1; 33 | if (nd_int()) 34 | a[6] = 1; 35 | if (nd_int()) 36 | a[7] = 1; 37 | if (nd_int()) 38 | a[8] = 1; 39 | if (nd_int()) 40 | a[9] = 1; 41 | if (nd_int()) 42 | a[8] = 2; 43 | 44 | check(&a[0], nd_int()); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-11.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^8 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | typedef struct { 8 | int x; 9 | int y; 10 | } S1; 11 | 12 | #define N 20 13 | S1 a[N]; 14 | int b[10]; 15 | 16 | void check(S1* s1, int *s2, int flag) { 17 | if (flag > 0) { 18 | __CRAB_assert(s1[4].x >= 0); 19 | __CRAB_assert(s1[4].x <= 1); 20 | __CRAB_assert(s2[5] >= 0); 21 | __CRAB_assert(s2[5] <= 1); 22 | 23 | } else { 24 | __CRAB_assert(s1[8].y >= 0); 25 | __CRAB_assert(s1[8].y <= 1); 26 | __CRAB_assert(s2[9] >= 0); 27 | __CRAB_assert(s2[9] <= 1); 28 | 29 | } 30 | } 31 | 32 | int main(){ 33 | 34 | int i; 35 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^8 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | typedef struct { 8 | int x; 9 | int y; 10 | int z[10]; 11 | } S1; 12 | 13 | #define N 20 14 | S1 a[N]; 15 | 16 | void check(S1* s1, int flag) { 17 | if (flag > 0) { 18 | __CRAB_assert(s1[4].z[4] >= 0); 19 | __CRAB_assert(s1[4].z[4] <= 1); 20 | __CRAB_assert(s1[5].x >= 0); 21 | __CRAB_assert(s1[5].x <= 1); 22 | 23 | } else { 24 | __CRAB_assert(s1[8].z[7] >= 0); 25 | __CRAB_assert(s1[8].z[7] <= 1); 26 | __CRAB_assert(s1[6].x >= 0); 27 | __CRAB_assert(s1[6].x <= 1); 28 | 29 | } 30 | } 31 | 32 | int main(){ 33 | int i,j; 34 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | typedef struct { 8 | int x; 9 | int y; 10 | int z[10]; 11 | } S1; 12 | 13 | #define N 20 14 | S1 a[N]; 15 | 16 | void check(S1* s1, int flag) { 17 | if (flag > 0) { 18 | __CRAB_assert(s1[4].z[4] >= 0); 19 | __CRAB_assert(s1[4].z[4] <= 1); 20 | __CRAB_assert(s1[5].x >= 0); 21 | __CRAB_assert(s1[5].x <= 1); 22 | 23 | } else { 24 | __CRAB_assert(s1[8].z[7] >= 0); 25 | __CRAB_assert(s1[8].z[7] <= 1); 26 | __CRAB_assert(s1[6].x >= 0); 27 | __CRAB_assert(s1[6].x <= 1); 28 | 29 | } 30 | } 31 | 32 | int main(){ 33 | int i,j; 34 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^8 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | #define N 20 8 | 9 | typedef struct { 10 | int x; 11 | int y; 12 | int z[10]; 13 | } S1; 14 | 15 | S1 a[N]; 16 | 17 | void foo(S1* s1, int flag) { 18 | if (flag > 0) { 19 | s1[4].z[4] = 2; 20 | s1[5].x = 2; 21 | } else { 22 | s1[8].z[7] = 2; 23 | s1[6].x = 2; 24 | } 25 | } 26 | 27 | void check(S1* s1, int flag) { 28 | if (flag > 0) { 29 | __CRAB_assert(s1[4].z[4] >= 0); 30 | __CRAB_assert(s1[4].z[4] <= 2); 31 | __CRAB_assert(s1[5].x >= 0); 32 | __CRAB_assert(s1[5].x <= 2); 33 | 34 | } else { 35 | __CRAB_assert(s1[8].z[7] >= 0); 36 | __CRAB_assert(s1[8].z[7] <= 2); 37 | __CRAB_assert(s1[6].x >= 0); 38 | __CRAB_assert(s1[6].x <= 2); 39 | 40 | } 41 | } 42 | 43 | int main(){ 44 | int i,j; 45 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | #define N 20 8 | 9 | typedef struct { 10 | int x; 11 | int y; 12 | int z[10]; 13 | } S1; 14 | 15 | S1 a[N]; 16 | 17 | void foo(S1* s1, int flag) { 18 | if (flag > 0) { 19 | s1[4].z[4] = 2; 20 | s1[5].x = 2; 21 | } else { 22 | s1[8].z[7] = 3; 23 | s1[6].x = 2; 24 | } 25 | } 26 | 27 | void check(S1* s1, int flag) { 28 | if (flag > 0) { 29 | __CRAB_assert(s1[4].z[4] >= 0); 30 | __CRAB_assert(s1[4].z[4] <= 2); 31 | __CRAB_assert(s1[5].x >= 0); 32 | __CRAB_assert(s1[5].x <= 2); 33 | 34 | } else { 35 | __CRAB_assert(s1[8].z[7] >= 0); 36 | __CRAB_assert(s1[8].z[7] <= 2); 37 | __CRAB_assert(s1[6].x >= 0); 38 | __CRAB_assert(s1[6].x <= 2); 39 | 40 | } 41 | } 42 | 43 | int main(){ 44 | int i,j; 45 | for(i=0;i&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^2 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | __CRAB_assume(i1 >= 0 && i1 < 16); 22 | __CRAB_assert(t[i1] >= 0); 23 | // The pointer analysis cannot tell that the accesses are wrt to the 24 | // base address of the memory region because the memory region is 25 | // marked as "sequence" by sea-dsa. Thus, the indexes are not 26 | // translated precisely to Crab. 27 | 28 | // The return value is [4,64] 29 | return t[2] + t[4] + t[6] + t[15]; 30 | } 31 | 32 | int32_t compute2(uint32_t t[6][2]) { 33 | int i2 = nd_int(); 34 | __CRAB_assume(i2 >= 0 && i2 < 6); 35 | __CRAB_assert(t[i2][1] <= 100); 36 | // Same than above. 37 | 38 | // The return value is [30, 180] 39 | return t[0][1] + t[1][1] + t[5][1]; 40 | } 41 | 42 | int main () { 43 | int i; 44 | for (i=0;i<10;i++) { 45 | a[i] = (nd_int() ? 0: 5); 46 | } 47 | 48 | int y = nd_int(); 49 | __CRAB_assume(y >= 0); 50 | __CRAB_assume(y < 10); 51 | int res = a[y]; 52 | __CRAB_assert(res >= 0); 53 | __CRAB_assert(res <= 5); 54 | 55 | int z = compute1(table1); 56 | __CRAB_assert(z == 31); // cannot be proven 57 | 58 | int w = compute2(table2); 59 | __CRAB_assert(w == 90); // cannot be proven 60 | return res+z+w; 61 | } 62 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-4.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | int y; 22 | switch (nd_int()) { 23 | case 1: 24 | y = 2; 25 | break; 26 | case 2: 27 | y = 4; 28 | break; 29 | case 3: 30 | y = 6; 31 | break; 32 | default: 33 | y = 15; 34 | break; 35 | } 36 | t[y] = 100; 37 | return t[2] + t[4] + t[6] + t[15]; 38 | } 39 | 40 | int32_t compute2(const uint32_t t[6][2]) { 41 | int i2 = nd_int(); 42 | return t[0][1] + t[1][1] + t[5][1]; 43 | } 44 | 45 | int main () { 46 | int i; 47 | for (i=0;i<10;i++) { 48 | a[i] = (nd_int() ? 3: 5); 49 | } 50 | 51 | int y = nd_int(); 52 | __CRAB_assume(y >= 0); 53 | __CRAB_assume(y < 10); 54 | int res = a[y]; 55 | __CRAB_assert(res >= 0); 56 | __CRAB_assert(res <= 5); 57 | 58 | table2[5][1] = nd_int(); // * 59 | 60 | int z = compute1(table1); 61 | __CRAB_assert(z <= 400); 62 | 63 | int w = compute2(table2); 64 | __CRAB_assert(w == 90); // it's not true because of * 65 | 66 | 67 | return res+z+w; 68 | } 69 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-5.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^3 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int32_t table1[16] = { 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 10 | }; 11 | 12 | uint32_t table2[6][2] = { 13 | { 1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {6, 60} 14 | }; 15 | 16 | int x; 17 | int a[10]; 18 | 19 | int32_t compute1(int32_t *t) { 20 | int i1 = nd_int(); 21 | int y; 22 | switch (nd_int()) { 23 | case 1: 24 | y = 2; 25 | break; 26 | case 2: 27 | y = 4; 28 | break; 29 | case 3: 30 | y = 6; 31 | break; 32 | default: 33 | y = 15; 34 | break; 35 | } 36 | t[y] = 100; 37 | return t[2] + t[4] + t[6] + t[15]; 38 | } 39 | 40 | int32_t compute2(const uint32_t t[6][2]) { 41 | int i2 = nd_int(); 42 | return t[0][1] + t[1][1] + t[5][1]; 43 | } 44 | 45 | int main () { 46 | int i; 47 | for (i=0;i<10;i++) { 48 | a[i] = (nd_int() ? 3: 5); 49 | } 50 | 51 | int y = nd_int(); 52 | __CRAB_assume(y >= 0); 53 | __CRAB_assume(y < 10); 54 | a[y] = nd_int(); // (1) 55 | 56 | int res = a[y]; 57 | __CRAB_assert(res >= 0); // it's not true because (1) 58 | __CRAB_assert(res <= 5); 59 | 60 | table1[15] = nd_int(); // (2) 61 | int z = compute1(table1); 62 | __CRAB_assert(z <= 400); // it's not true because of (2) 63 | 64 | int w = compute2(table2); 65 | __CRAB_assert(w == 90); 66 | 67 | 68 | return res+z+w; 69 | } 70 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-6.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int x; 9 | int a[10]; 10 | 11 | int32_t compute1(int32_t *t) { 12 | int idx = nd_int(); 13 | __CRAB_assume(idx >= 0); 14 | __CRAB_assume(idx <= 3); 15 | // res = 6 but if idx == 3 then there is undefined behavior. 16 | return t[idx]; 17 | } 18 | 19 | int32_t compute2(const uint32_t t[6][2]) { 20 | // res = 30 21 | return t[0][1] + t[2][1]; 22 | } 23 | 24 | int main () { 25 | 26 | int32_t table1[4]; 27 | table1[0] = 1; 28 | table1[1] = 2; 29 | table1[2] = 3; 30 | 31 | uint32_t table2[3][2]; 32 | table2[0][1] = 10; 33 | table2[2][1] = 20; 34 | 35 | int i; 36 | for (i=0;i<10;i++) { 37 | a[i] = (nd_int() ? 3: 5); 38 | } 39 | 40 | int y = nd_int(); 41 | __CRAB_assume(y >= 0); 42 | __CRAB_assume(y < 10); 43 | int res = a[y]; 44 | __CRAB_assert(res >= 0); 45 | __CRAB_assert(res <= 5); 46 | 47 | //table1[3] = 5; 48 | int z = compute1(table1); 49 | __CRAB_assert(z <= 3); 50 | 51 | int w = compute2(table2); 52 | __CRAB_assert(w == 30); 53 | 54 | 55 | return res+z+w; 56 | } 57 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-7.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^5 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | int x; 9 | int a[10]; 10 | 11 | int32_t compute1(int32_t *t) { 12 | int64_t res = t[0] + t[2]; // exact res = 4 but we get res =[2,40] 13 | int idx = nd_int(); 14 | __CRAB_assume(idx >= 0); 15 | __CRAB_assume(idx <= 3); 16 | // A symbolic index makes the pointer analysis to classify t as a 17 | // "sequence" node and therefore the translation of GEP is 18 | // imprecise. 19 | t[idx] = 30; 20 | return res; 21 | } 22 | 23 | int32_t compute2(const uint32_t t[6][2]) { 24 | // res = 30 25 | return t[0][1] + t[2][1]; 26 | } 27 | 28 | int main () { 29 | 30 | int32_t table1[4]; 31 | table1[0] = 1; 32 | table1[1] = 20; 33 | table1[2] = 3; 34 | 35 | uint32_t table2[3][2]; 36 | table2[0][1] = 10; 37 | table2[2][1] = 20; 38 | 39 | int i; 40 | for (i=0;i<10;i++) { 41 | a[i] = (nd_int() ? 3: 5); 42 | } 43 | 44 | int y = nd_int(); 45 | __CRAB_assume(y >= 0); 46 | __CRAB_assume(y < 10); 47 | int res = a[y]; 48 | __CRAB_assert(res >= 0); // ok 49 | __CRAB_assert(res <= 5); // ok 50 | 51 | int z = compute1(table1); 52 | __CRAB_assert(z <= 40); // ok 53 | 54 | z = table1[1]; 55 | __CRAB_assert(z <= 30); // ok 56 | 57 | 58 | int w = compute2(table2); 59 | __CRAB_assert(w == 30); // ok 60 | 61 | 62 | return res+z+w; 63 | } 64 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-8.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp --crab-widening-jump-set=20 --llvm-pp-loops "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | // XFAIL: * 5 | 6 | #include "clam/clam.h" 7 | 8 | extern char* name_nd(void); 9 | 10 | typedef struct { 11 | char *name; 12 | char id; 13 | } S1; 14 | 15 | 16 | void foo(S1 *devices, int len) { 17 | int i = nd_int(); 18 | __CRAB_assume(i >= 0); 19 | __CRAB_assume(i < len); 20 | devices[i].id = 0; 21 | devices[i].name = name_nd(); 22 | } 23 | 24 | S1 devices[4]; 25 | extern void avoid_opt(S1 *); 26 | 27 | int main(){ 28 | avoid_opt(&devices[0]); 29 | 30 | for (unsigned i=0; i<4; ++i) { 31 | devices[i].id = i; 32 | devices[i].name = name_nd(); 33 | } 34 | 35 | foo(&devices[0], 4); 36 | 37 | 38 | int x = nd_int(); 39 | __CRAB_assume(x >= 0); 40 | __CRAB_assume(x < 4); 41 | __CRAB_assert(devices[x].id >= 0); 42 | __CRAB_assert(devices[x].id <= 4); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-8.m64.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m64 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp --crab-widening-jump-set=20 --llvm-pp-loops "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | // XFAIL: * 5 | 6 | #include "clam/clam.h" 7 | 8 | // With a relational domain we should be able to prove the property. 9 | // The problem is that after some LLVM optimizations we lose precision 10 | // after widening the variable "i" in the for loop in main. 11 | 12 | extern char* name_nd(void); 13 | 14 | typedef struct { 15 | char *name; 16 | char id; 17 | } S1; 18 | 19 | 20 | void foo(S1 *devices, int len) { 21 | int i = nd_int(); 22 | __CRAB_assume(i >= 0); 23 | __CRAB_assume(i < len); 24 | devices[i].id = 0; 25 | devices[i].name = name_nd(); 26 | } 27 | 28 | S1 devices[4]; 29 | extern void avoid_opt(S1 *); 30 | 31 | int main(){ 32 | avoid_opt(&devices[0]); 33 | 34 | for (unsigned i=0; i<4; ++i) { 35 | devices[i].id = i; 36 | devices[i].name = name_nd(); 37 | } 38 | 39 | foo(&devices[0], 4); 40 | 41 | 42 | int x = nd_int(); 43 | __CRAB_assume(x >= 0); 44 | __CRAB_assume(x < 4); 45 | __CRAB_assert(devices[x].id >= 0); 46 | __CRAB_assert(devices[x].id <= 4); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-8.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" --crab-widening-jump-set=20 --llvm-pp-loops 2>&1 | OutputCheck %s 2 | // RUN: %clam -m64 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" --crab-widening-jump-set=20 --llvm-pp-loops 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total safe checks$ 4 | // CHECK: ^1 Number of total warning checks$ 5 | 6 | //#include 7 | 8 | #include "clam/clam.h" 9 | 10 | extern char* name_nd(void); 11 | 12 | typedef struct { 13 | char *name; 14 | char id; 15 | } S1; 16 | 17 | 18 | void foo(S1 *devices, int len) { 19 | int i = nd_int(); 20 | __CRAB_assume(i >= 0); 21 | __CRAB_assume(i < len); 22 | devices[i].id = 8; // unsafe 23 | } 24 | 25 | S1 devices[4]; 26 | extern void avoid_opt(S1 *); 27 | 28 | int main(){ 29 | avoid_opt(&devices[0]); 30 | 31 | for (unsigned i=0; i<4; ++i) { 32 | devices[i].id = i; 33 | devices[i].name = name_nd(); 34 | } 35 | foo(&devices[0], 4); 36 | 37 | 38 | int x = nd_int(); 39 | __CRAB_assume(x >= 0); 40 | __CRAB_assume(x < 4); 41 | __CRAB_assert(devices[x].id >= 0); 42 | __CRAB_assert(devices[x].id <= 4); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-9.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks --crab-heap-analysis=cs-sea-dsa-types "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^4 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | int a[10]; 8 | 9 | void check(int* s, int n) { 10 | __CRAB_assert(s[n] >= 0); 11 | __CRAB_assert(s[n] <= 1); 12 | } 13 | 14 | int main(){ 15 | 16 | if (nd_int()) 17 | a[0] = 1; 18 | if (nd_int()) 19 | a[1] = 1; 20 | if (nd_int()) 21 | a[2] = 1; 22 | if (nd_int()) 23 | a[3] = 1; 24 | if (nd_int()) 25 | a[4] = 1; 26 | if (nd_int()) 27 | a[5] = 1; 28 | if (nd_int()) 29 | a[6] = 1; 30 | if (nd_int()) 31 | a[7] = 1; 32 | if (nd_int()) 33 | a[8] = 1; 34 | if (nd_int()) 35 | a[9] = 1; 36 | 37 | check(&a[0], 4); 38 | check(&a[0], 6); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-9.warning.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -m32 --crab-inter --crab-track=mem --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total safe checks$ 3 | // CHECK: ^4 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | int a[10]; 8 | 9 | void check(int* s, int n) { 10 | __CRAB_assert(s[n] >= 0); 11 | __CRAB_assert(s[n] <= 1); 12 | } 13 | 14 | int main(){ 15 | 16 | if (nd_int()) 17 | a[0] = 1; 18 | if (nd_int()) 19 | a[1] = 1; 20 | if (nd_int()) 21 | a[2] = 1; 22 | if (nd_int()) 23 | a[3] = 1; 24 | if (nd_int()) 25 | a[4] = 1; 26 | if (nd_int()) 27 | a[5] = 1; 28 | if (nd_int()) 29 | a[6] = 1; 30 | if (nd_int()) 31 | a[7] = 1; 32 | if (nd_int()) 33 | a[8] = 1; 34 | if (nd_int()) 35 | a[9] = 1; 36 | 37 | check(&a[2], 4); // <- we lose precision if we take the address of a 38 | // non-zero index. 39 | check(&a[2], 6); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /tests/mem/test-mem-array-local-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=mem --llvm-peel-loops=1 --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=mem --llvm-peel-loops=1 --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | #include "clam/clam.h" 9 | 10 | /* 11 | With option crab-track=sing-mem we cannot prove this program. The 12 | reason is that this option sing-mem uses array-adaptive while mem 13 | uses the region domain. They both smash arrays sooner or later but 14 | that makes a difference. Nevertheless, we need loop peeling=1 15 | 16 | See tests/simple/test-arr-1-local.c for more details. 17 | */ 18 | 19 | int main () { 20 | // local array 21 | int a[10]; 22 | int i; 23 | for (i=0;i<10;i++) { 24 | if (nd_int()) 25 | a[i] =0; 26 | else 27 | a[i] =5; 28 | } 29 | 30 | int res = a[i-1]; 31 | __CRAB_assert(res >= 0 && res <= 5); 32 | return res; 33 | } 34 | -------------------------------------------------------------------------------- /tests/mem/test-mem-is-deref.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-track=mem --crab-only-cfg --crab-print-cfg=true "%s" 2>&1 | OutputCheck %s 2 | // CHECK: crab_intrinsic 3 | // CHECK: crab_intrinsic 4 | 5 | #include 6 | #include 7 | #include "clam/clam.h" 8 | 9 | // Check that sea_is_dereferenceable is translated propertly as a Crab 10 | // intrinsics. 11 | 12 | extern int __CRAB_intrinsic_foo(int, int); 13 | extern bool __CRAB_intrinsic_is_dereferenceable(const void *ptr, intptr_t offset); 14 | 15 | int main (){ 16 | 17 | int x,y, i; 18 | x=0; 19 | y=0; 20 | for (i=0;i< 10;i++) { 21 | x++; 22 | y++; 23 | __CRAB_assert(sea_is_dereferenceable(&x, sizeof(int))); 24 | __CRAB_assert(__CRAB_intrinsic_is_dereferenceable(&y, sizeof(int))); 25 | } 26 | 27 | __CRAB_assert(x>=y); 28 | __CRAB_assert(y>=x); 29 | return x+y; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /tests/mem/test-mem-ptr-not-equal.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-track=mem --crab-dom=zones --crab-check=assert --crab-sanity-checks --crab-dom-params="region.is_dereferenceable=true" --crab-widening-delay=2 "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total warning checks$ 4 | // XFAIL: * 5 | 6 | 7 | // Note that we need to delay widening two iterations to prove the 8 | // assertion. 9 | 10 | // After Crab commit cb2d8c57: we cannot prove the assertion because 11 | // the transfer function for p != q is not precise enough. 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "clam/clam.h" 20 | 21 | int main() { 22 | int sz = nd_int(); 23 | __CRAB_assume(sz > 0); 24 | __CRAB_assume(sz < 10); 25 | uint8_t *start = malloc(sizeof(uint8_t) * sz); 26 | uint8_t *end = start + sz; 27 | uint8_t *i = start; 28 | while (i != end) { 29 | __CRAB_assert(sea_is_dereferenceable(i, 1)); 30 | i++; 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/ntdrivers-simplified/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | config.excludes = ['cdaudio_simpl1_false-unreach-call_true-termination.cil.c', 4 | #'cdaudio_simpl1_true-unreach-call_true-termination.cil.c', 5 | 'diskperf_simpl1_true-unreach-call_true-termination.cil.c', 6 | 'floppy_simpl3_false-unreach-call_true-termination.cil.c', 7 | #'floppy_simpl3_true-unreach-call_true-termination.cil.c', 8 | 'floppy_simpl4_false-unreach-call_true-termination.cil.c', 9 | #'floppy_simpl4_true-unreach-call_true-termination.cil.c' 10 | ] 11 | 12 | -------------------------------------------------------------------------------- /tests/opt/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | config.suffixes = ['.c',''] 4 | config.excludes = ['test-opt-1.c', 'test-opt-2.c'] 5 | 6 | -------------------------------------------------------------------------------- /tests/opt/test-opt-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | void fun1(int a) { 5 | printf("Value of a is %d\n", a); 6 | } 7 | void fun2(int a) { 8 | printf("Value of a is %d\n", a+1); 9 | } 10 | void fun3(int a) { 11 | printf("You shoud not see this.\n"); 12 | } 13 | 14 | void (*fun_ptr)(int) = fun3; 15 | 16 | int main() { 17 | 18 | int x = nd_int(); 19 | __CRAB_assume (x >= 0); 20 | if (x > 0) 21 | fun_ptr = fun1; 22 | else 23 | fun_ptr = fun2; 24 | 25 | if (x < 0) fun_ptr = fun3; 26 | 27 | (*fun_ptr)(x); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/opt/test-opt-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | int x = 0; 5 | 6 | void incr_x() { 7 | x++; 8 | } 9 | 10 | void decr_x() { 11 | x--; 12 | } 13 | 14 | int bar(int y) { 15 | printf("fool llvm\n"); 16 | return y; 17 | } 18 | 19 | void foo() { 20 | printf("this function should not be called\n"); 21 | } 22 | 23 | int a[10]; 24 | 25 | int main(int argc, char**argv) { 26 | incr_x(); 27 | decr_x(); 28 | 29 | int i; 30 | int n = nd_int(); 31 | __CRAB_assume(n == 10); 32 | 33 | for (i=0;i= 0); 38 | __CRAB_assume(j < 10); 39 | int k = bar(a[j]); 40 | if (k != 0) { 41 | foo(); 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/simple/fntest-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=sing-mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int rec1 (int x); 8 | int rec2 (int y); 9 | 10 | int foo (int x) { 11 | int y = x +1; 12 | return y + 2; 13 | } 14 | 15 | int bar (int a) { 16 | int x = a; 17 | int w = 5; 18 | return foo (x); 19 | } 20 | 21 | 22 | int rec1 (int x) { 23 | if (x == 0) return 0; 24 | else return rec2 (x-1); 25 | } 26 | 27 | int rec2 (int x) { 28 | return rec1 (x); 29 | } 30 | 31 | int main (){ 32 | int x = 3; 33 | int y = bar (x); 34 | int z = rec1 (y); 35 | int w= foo (y); 36 | __CRAB_assert (w == 9); 37 | return z + w; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/fntest-1.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=sing-mem --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^1 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int rec1 (int x); 8 | int rec2 (int y); 9 | 10 | int foo (int x) { 11 | int y = x +1; 12 | return y + 2; 13 | } 14 | 15 | int bar (int a) { 16 | int x = a; 17 | int w = 5; 18 | return foo (x); 19 | } 20 | 21 | 22 | int rec1 (int x) { 23 | if (x == 0) return 0; 24 | else return rec2 (x-1); 25 | } 26 | 27 | int rec2 (int x) { 28 | return rec1 (x); 29 | } 30 | 31 | int main (){ 32 | int x = 3; 33 | int y = bar (x); 34 | int z = rec1 (y); 35 | int w= foo (y); 36 | __CRAB_assert (w == 10); 37 | return z + w; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/fntest-2.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int addOne(int x) { 4 | return x + 1; 5 | } 6 | 7 | int addTwo(int x) { 8 | return x + 2; 9 | } 10 | 11 | int addThree(int x) { 12 | return x + 3; 13 | } 14 | 15 | int main() { 16 | //int (*fPtr_array[2])(int); 17 | int (*f) (int); 18 | int x = 8; 19 | if (nd_int()) { 20 | //fPtr_array[0] = &addOne; 21 | f = &addOne; 22 | } else if (nd_int()) { 23 | //fPtr_array[1] = &addTwo; 24 | f = &addTwo; 25 | } else { 26 | f = &addThree; 27 | //fPtr_array[1] = &addThree; 28 | } 29 | 30 | //int res1 = fPtr_array[0](x); 31 | //int res2 = fPtr_array[1](x); 32 | // assert(res1 == 9); 33 | // assert(res2 >= 10 && res2 <= 11); 34 | return f (x); 35 | } 36 | -------------------------------------------------------------------------------- /tests/simple/fntest-3.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int addOne(int x, int y) { 4 | return x + 1; 5 | } 6 | 7 | int addTwo(int x, int y) { 8 | return x + 2; 9 | } 10 | 11 | int addThree(int x, int y) { 12 | return x + 3; 13 | } 14 | 15 | int main() { 16 | //int (*fPtr_array[2])(int); 17 | int (*f) (int, int); 18 | int x = 8; 19 | if (nd_int()) { 20 | //fPtr_array[0] = &addOne; 21 | f = &addOne; 22 | } else if (nd_int()) { 23 | //fPtr_array[1] = &addTwo; 24 | f = &addTwo; 25 | } else { 26 | f = &addThree; 27 | //fPtr_array[1] = &addThree; 28 | } 29 | 30 | //int res1 = fPtr_array[0](x); 31 | //int res2 = fPtr_array[1](x); 32 | // assert(res1 == 9); 33 | // assert(res2 >= 10 && res2 <= 11); 34 | return f (x, 8); 35 | } 36 | -------------------------------------------------------------------------------- /tests/simple/fntest-4.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int x =2; 4 | int y =5; 5 | 6 | int addTwo(int a) { 7 | x+=2; 8 | y++; 9 | return a+1; 10 | } 11 | 12 | int addOne(int a) { 13 | x++; 14 | int b=0; 15 | if (nd_int()) 16 | b = addTwo (a); 17 | return a+b+1; // return value is lost from the summary 18 | } 19 | 20 | 21 | int addThree(int a) { 22 | x+=3; 23 | return a+1; 24 | } 25 | 26 | int main() { 27 | 28 | int a = 2; 29 | int b = addOne (a); 30 | int c = addTwo (b); 31 | int d = addThree (c); 32 | 33 | return x+y+d; 34 | } 35 | -------------------------------------------------------------------------------- /tests/simple/fntest-5.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --devirt-functions=types --crab-inter --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int a (void); 8 | int b (void); 9 | 10 | int main(int argc, char** argv) { 11 | int (*p) (void); 12 | if (argc == 1) 13 | p = a; 14 | else 15 | p = b; 16 | int x = p(); 17 | __CRAB_assert(x>=5 && x <=10); 18 | return 0; 19 | } 20 | 21 | int a() {return 10;} 22 | int b() {return 5;} 23 | -------------------------------------------------------------------------------- /tests/simple/fntest-6.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --devirt-functions=types --crab-inter --crab-check=assert --crab-sanity-checks --lower-unsigned-icmp "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | // If devirt-functions=types uses bounce functions then we cannot 7 | // prove the two checks. 8 | 9 | #include "clam/clam.h" 10 | 11 | int a (void); 12 | int b (void); 13 | int c (void); 14 | int d (void); 15 | 16 | int main(int argc, char** argv) { 17 | int (*p) (void); 18 | int (*q) (void); 19 | 20 | if (argc == 1) { 21 | p = a; 22 | q = c; 23 | } else { 24 | p = b; 25 | q = d; 26 | } 27 | 28 | int x = p(); 29 | int y = q(); 30 | 31 | __CRAB_assert(x>= 5); 32 | __CRAB_assert(y>= 15); 33 | return 0; 34 | } 35 | 36 | int a() {return 10;} 37 | int b() {return 5;} 38 | int c() {return 15;} 39 | int d() {return 20;} 40 | -------------------------------------------------------------------------------- /tests/simple/fntest-7.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --devirt-functions=sea-dsa --crab-inter --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include "clam/clam.h" 7 | 8 | int a (void); 9 | int b (void); 10 | int c (void); 11 | int d (void); 12 | 13 | int main(int argc, char** argv) { 14 | int (*p) (void); 15 | int (*q) (void); 16 | 17 | if (argc == 1) { 18 | p = a; 19 | q = c; 20 | } else { 21 | p = b; 22 | q = d; 23 | } 24 | 25 | int x = p(); 26 | int y = q(); 27 | 28 | __CRAB_assert(x>= 5); 29 | __CRAB_assert(y>= 15); 30 | return 0; 31 | } 32 | 33 | int a() {return 10;} 34 | int b() {return 5;} 35 | int c() {return 15;} 36 | int d() {return 20;} 37 | -------------------------------------------------------------------------------- /tests/simple/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | import clam_config 4 | 5 | config.excludes = [ 6 | ## Tests for indirect call resolution 7 | 'fntest-2.c' 8 | ,'fntest-3.c' 9 | ,'fntest-4.c' 10 | ## Miscelaneous 11 | ,'test-cond-1.c' 12 | ## Term domain 13 | ,'test-term-2.c' 14 | ,'test-term-3.c' 15 | ,'test-term-4.c' 16 | ,'test-term-5.c' 17 | ## Hard loop examples 18 | ,'test-loop-3.c' 19 | ## Tests for dsa translation 20 | ,'test-ptr-1.c' 21 | ,'test-ptr-2.c' 22 | ,'test-ptr-3.c' 23 | ,'test-ptr-4.c' 24 | ,'test-ptr-5.c' 25 | ,'test-ptr-6.c' 26 | ,'test-ptr-7.c' 27 | ,'test-list-1.c' 28 | ## More tests for dsa translation/ array reasoning 29 | ,'test-arr-6.c' 30 | ,'test-arr-7.c' 31 | ,'test-arr-8.c' 32 | ,'test-arr-10.c' 33 | ,'test-memset.c' 34 | ## C translation tests should be skipped 35 | ,'test-heap-translation-1.c' 36 | ] 37 | 38 | if clam_config.use_apron == "OFF" and clam_config.use_elina == "OFF": 39 | config.excludes += ['test-loop-4.c'] 40 | if clam_config.use_ldd_boxes == "OFF": 41 | config.excludes += ['test-pagai.c'] 42 | -------------------------------------------------------------------------------- /tests/simple/test-arr-1-local.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | // XFAIL: * 8 | 9 | #include "clam/clam.h" 10 | 11 | /* 12 | Even with loop peeling the array_adaptive domain (used by option 13 | sing-mem) cannot be precise here. Let's assume that we have peeled 14 | one iteration the loop. Before we start the loop we have 0<= a[0..3] 15 | <= 5. After one loop iteration, we have 0<= a[0..3] <= 5 and 0<= 16 | a[4..7] <= 5. After we join, we have 0<=a[0..3]<= 5. In the second 17 | iteration 1<=i<=2 so we smash the array because the array index i is 18 | not a constant. The problem arises now. The information we have 19 | about the array is only 0<=a[0..3]<= 5. However, the domain 20 | remembers that the cell a[4..7] was created. Since there is no 21 | information about it, after we smash we lose everything. 22 | */ 23 | 24 | int main () { 25 | // local array 26 | int a[10]; 27 | int i; 28 | for (i=0;i<10;i++) { 29 | if (nd_int()) 30 | a[i] =0; 31 | else 32 | a[i] =5; 33 | } 34 | 35 | int res = a[i-1]; 36 | __CRAB_assert(res >= 0 && res <= 5); 37 | return res; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/test-arr-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | 5 | // CHECK: ^1 Number of total safe checks$ 6 | // CHECK: ^0 Number of total error checks$ 7 | // CHECK: ^0 Number of total warning checks$ 8 | 9 | #include "clam/clam.h" 10 | 11 | int a[10]; 12 | 13 | int main (){ 14 | int i; 15 | for (i=0;i<10;i++) 16 | { 17 | if (nd_int()) 18 | a[i] =0; 19 | else 20 | a[i] =5; 21 | } 22 | 23 | int res = a[i-1]; 24 | __CRAB_assert(res >= 0 && res <= 5); 25 | return res; 26 | } 27 | -------------------------------------------------------------------------------- /tests/simple/test-arr-1.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=term-dis-int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=term-dis-int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=term-dis-int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | int a[10]; 9 | 10 | int main () { 11 | int i; 12 | for (i=0;i<10;i++) 13 | { 14 | if (nd_int()) 15 | a[i] =0; 16 | else 17 | a[i] =5; 18 | } 19 | 20 | int res = a[i-1]; 21 | __CRAB_assert(res == 4); 22 | return res; 23 | } 24 | -------------------------------------------------------------------------------- /tests/simple/test-arr-10.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[10]; 4 | 5 | int main (){ 6 | int *p = &a[0]; 7 | while (1) { 8 | *p = 5; 9 | p++; 10 | if (p >= 10) 11 | break; 12 | } 13 | int *q = &a[0]; 14 | return *(q+4); 15 | } 16 | -------------------------------------------------------------------------------- /tests/simple/test-arr-11.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | #include "clam/clam.h" 8 | 9 | typedef struct { 10 | int x; 11 | int y; 12 | } gstate; 13 | 14 | gstate g; 15 | int a[10]; 16 | const char* str = "hello world"; 17 | 18 | int main () 19 | { 20 | g.x = 5; 21 | g.y = 3; 22 | int i; 23 | int *p =&g.x; 24 | *p= *p + 1; 25 | for (i=0;i<10;i++) 26 | { 27 | if (nd_int()) 28 | a[i] =g.y; 29 | else 30 | a[i] =g.x; 31 | } 32 | g.y++; 33 | int res = a[i-1]; 34 | __CRAB_assert(res >= 0 && res <= 6); 35 | return res + str[0]; 36 | } 37 | -------------------------------------------------------------------------------- /tests/simple/test-arr-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | 8 | #include "clam/clam.h" 9 | 10 | int x = 5; 11 | int y = 3; 12 | 13 | int a[10]; 14 | 15 | int main () 16 | { 17 | int i; 18 | int *p =&x; 19 | *p= *p + 1; 20 | for (i=0;i<10;i++) 21 | { 22 | if (nd_int()) 23 | a[i] =y; 24 | else 25 | a[i] =x; 26 | } 27 | y++; 28 | int res = a[i-1]; 29 | 30 | __CRAB_assert(res >= 0 && res <= 6); 31 | return res; 32 | } 33 | -------------------------------------------------------------------------------- /tests/simple/test-arr-3.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | #include "clam/clam.h" 8 | 9 | int x = 5; 10 | 11 | int a[10]; 12 | int main () 13 | { 14 | int i; 15 | x++; 16 | for (i=0;i<10;i++) 17 | { 18 | a[i] =x; 19 | } 20 | int res = a[i-1]; 21 | __CRAB_assert(res >= 0 && res <= 9); 22 | return res; 23 | } 24 | -------------------------------------------------------------------------------- /tests/simple/test-arr-4.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^1 Number of total safe checks$ 5 | #include "clam/clam.h" 6 | 7 | int x = 5; 8 | int y = 3; 9 | 10 | void foo () 11 | { 12 | x++; 13 | } 14 | 15 | void bar () 16 | { 17 | y++; 18 | } 19 | 20 | int a[10]; 21 | 22 | int main () 23 | { 24 | int i; 25 | foo (); 26 | for (i=0;i<10;i++) 27 | { 28 | if (nd_int()) 29 | a[i] =y; 30 | else 31 | a[i] =x; 32 | } 33 | bar (); 34 | int res = a[i-1]; 35 | __CRAB_assert(res >= 0 && res <= 6); 36 | return res; 37 | } 38 | -------------------------------------------------------------------------------- /tests/simple/test-arr-4.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | int x = 5; 9 | int y = 3; 10 | 11 | void foo () 12 | { 13 | x++; 14 | } 15 | 16 | void bar () 17 | { 18 | y++; 19 | } 20 | 21 | int a[10]; 22 | 23 | int main () 24 | { 25 | int i; 26 | foo (); 27 | for (i=0;i<10;i++) 28 | { 29 | if (nd_int()) 30 | a[i] =y; 31 | else 32 | a[i] =x; 33 | } 34 | bar (); 35 | int res = a[i-1]; 36 | __CRAB_assert(res >= 7); 37 | return res; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/test-arr-4.warning.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-inter --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | int x = 5; 9 | int y = 3; 10 | 11 | void foo () 12 | { 13 | x++; 14 | } 15 | 16 | void bar () 17 | { 18 | y++; 19 | } 20 | 21 | int a[10]; 22 | 23 | int main () 24 | { 25 | int i; 26 | foo (); 27 | for (i=0;i<10;i++) 28 | { 29 | if (nd_int()) 30 | a[i] =y; 31 | else 32 | a[i] =x; 33 | } 34 | bar (); 35 | int res = a[i-1]; 36 | __CRAB_assert(res >= 6); 37 | return res; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/test-arr-5.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | #include "clam/clam.h" 8 | 9 | int a[10]; 10 | int b[10]; 11 | 12 | int main () 13 | { 14 | int i; 15 | for (i=0;i<10;i++) 16 | { 17 | if (nd_int()) 18 | a[i] =0; 19 | else 20 | a[i] =5; 21 | } 22 | 23 | for (i=0;i<10;i++) 24 | { 25 | if (nd_int()) 26 | b[i] =20; 27 | else 28 | b[i] =25; 29 | } 30 | 31 | int x = a[i-1] + b[i-1]; 32 | __CRAB_assert (x >= 0 && x<=30); 33 | 34 | if (x >= 0 && x<=30) 35 | return 42; 36 | else 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/test-arr-6.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "clam/clam.h" 4 | 5 | int* foo (int *x) 6 | { 7 | int * m = (int*) malloc (sizeof (int) * 10); 8 | int i; 9 | for (i=0;i<10;i++) 10 | { 11 | m[i] = x[i]; 12 | x[i] = 0; 13 | } 14 | return m; 15 | } 16 | 17 | int a[10]; 18 | int b[10]; 19 | 20 | int main () 21 | { 22 | int i; 23 | for (i=0;i<10;i++) 24 | b[i] = 5; 25 | int * c = foo (a); 26 | int res = c[9]; 27 | return res; 28 | } 29 | -------------------------------------------------------------------------------- /tests/simple/test-arr-7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | #define N 10 5 | // To test loops that decrements a counter 6 | int main(int argc, char** argv) { 7 | int i; 8 | int a[N]; 9 | for (i = N - 1; i >= 0; i--) { 10 | a[i] = i; 11 | } 12 | 13 | printf("%d\n", a[i + 1]); 14 | printf("%d\n", a[N - 1]); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /tests/simple/test-arr-8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | int* mymalloc (int *a) { 5 | //return (int*) calloc (10, sizeof(int)); 6 | return a; 7 | } 8 | 9 | int main () 10 | { 11 | int *_a = (int*) calloc (10, sizeof(int)); 12 | int *a = mymalloc (_a); 13 | int b[10]; 14 | int i; 15 | for (i=0;i<10;i++) 16 | b[i] = a[i]; 17 | 18 | int x = a[i-1] + b[i-1]; 19 | if (x == 0) 20 | return 42; 21 | else 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/simple/test-arr-9.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=zones --crab-track=sing-mem --crab-heap-analysis=ci-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-inter --crab-dom=zones --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-inter --crab-dom=zones --crab-track=sing-mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^0 Number of total safe checks 5 | // CHECK: ^1 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | /** 9 | Current array domain cannot handle this case but we at least check 10 | that all sanity checks pass. 11 | **/ 12 | 13 | 14 | int* foo(int sz, int val) { 15 | int* res = (int*) malloc (sz* sizeof(int)); 16 | int i; 17 | for (i=0;i= 0 && j < N); 36 | int x = b[j]; 37 | 38 | __CRAB_assert(x == 5); 39 | 40 | /* if (x != 5) { */ 41 | /* __VERIFIER_error (); */ 42 | /* } */ 43 | 44 | return 42; 45 | /* if (x == 0) */ 46 | /* return 42; */ 47 | /* else */ 48 | /* return 0; */ 49 | } 50 | -------------------------------------------------------------------------------- /tests/simple/test-bool-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^2 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^0 Number of total warning checks$ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "clam/clam.h" 13 | 14 | int main(void) { 15 | uint8_t x = nd_uint8_t(); 16 | __CRAB_assume(x > 5); 17 | uint8_t mmax = 10; 18 | __CRAB_assume(x < mmax); 19 | 20 | 21 | __CRAB_assert(x >= 3); 22 | __CRAB_assert(x <= 9); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /tests/simple/test-bool-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --lower-unsigned-icmp --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-lower-unsigned-icmp --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "clam/clam.h" 13 | 14 | uint8_t uint8_t_nd(void) { 15 | int8_t res = nd_int8_t(); 16 | __CRAB_assume(res >= 0); 17 | return (uint8_t)res; 18 | } 19 | 20 | int main(void) { 21 | uint8_t x = uint8_t_nd(); 22 | __CRAB_assume(x > 5); 23 | uint8_t mmax = 10; 24 | __CRAB_assume(x < mmax); 25 | 26 | 27 | __CRAB_assert(x >= 3); // CAN BE PROVEN 28 | __CRAB_assert(x <= 8); // EXPECTED OK BUT CANNOT BE PROVEN 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tests/simple/test-bool-5.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam --crab-dom=zones --crab-track=mem --inline --crab-heap-analysis=cs-sea-dsa --lower-unsigned-icmp --crab-lower-with-overflow-intrinsics=true --crab-check=assert "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "clam/clam.h" 12 | 13 | size_t size_t_nd(void) { 14 | int res = nd_int(); 15 | __CRAB_assume(res >= 0); 16 | return res; 17 | } 18 | 19 | int main() { 20 | 21 | bool a = nd_bool(); 22 | bool b = nd_bool(); 23 | bool c = nd_bool(); 24 | 25 | __CRAB_assume(a && b); // translate into single assume 26 | 27 | bool d = a && c; // should not translate 28 | 29 | if (d) { 30 | __CRAB_assert(b); 31 | } else { 32 | __CRAB_assume(d); 33 | } 34 | 35 | __CRAB_assert(d); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/simple/test-cond-1.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int foo (int x, int flag) { 4 | 5 | if (flag > 0) 6 | return x + flag; 7 | else 8 | return x + 2; 9 | } 10 | 11 | int main (){ 12 | 13 | int x = 5; 14 | int res = foo (x, nd_int()); 15 | return res; 16 | } 17 | -------------------------------------------------------------------------------- /tests/simple/test-count-by-one.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=int --crab-check=assert --inline --crab-widening-jump-set=20 --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | extern void __VERIFIER_error(void); 7 | void __VERIFIER_assert(int cond) { 8 | if (!(cond)) { 9 | ERROR: __VERIFIER_error(); 10 | } 11 | return; 12 | } 13 | 14 | int main() { 15 | int i; 16 | for (i = 0; i != 1000000; i++) { 17 | __VERIFIER_assert(i <= 1000000); 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /tests/simple/test-count-by-one.fail.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --inline --crab-widening-jump-set=20 --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-dom=oct --crab-check=assert --inline --crab-widening-jump-set=20 --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // RUN: %clam -O0 --crab-dom=pk --crab-check=assert --inline --crab-widening-jump-set=20 --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^1 Number of total safe checks$ 5 | // CHECK: ^0 Number of total error checks$ 6 | // CHECK: ^0 Number of total warning checks$ 7 | // XFAIL: * 8 | #include "clam/clam.h" 9 | 10 | /* It requires widening with thresholds */ 11 | 12 | void __VERIFIER_assert(int cond) { 13 | if (!(cond)) { 14 | ERROR: __VERIFIER_error(); 15 | } 16 | return; 17 | } 18 | int main() { 19 | int i; 20 | for (i = 0; i != 1000000; i++) { 21 | __VERIFIER_assert(i <= 1000000); 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /tests/simple/test-global-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-track=sing-mem --lower-unsigned-icmp --crab-dom=int --crab-widening-delay=3 --crab-check=assert "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-track=sing-mem --crab-lower-unsigned-icmp --crab-dom=int --crab-widening-delay=3 --crab-check=assert "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^3 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^0 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | int e=0; 9 | int s=2; 10 | 11 | // we should get e=[0,2] and s=[2,5] with thresholds or widening delay > 2 12 | // we should get e=[0,+oo] and s=[2,5] otherwise 13 | 14 | int main () { 15 | 16 | while (nd_int()) { 17 | if (s == 2){ 18 | if (e ==0) e=1; 19 | s = 3; 20 | } 21 | else if (s == 3){ 22 | if (e ==1) e=2; 23 | s=4; 24 | } 25 | else if (s == 4){ 26 | if (e == 3) { 27 | __VERIFIER_error(); 28 | } 29 | s=5; 30 | } 31 | } 32 | __CRAB_assert (e >= 0 && e <=2); 33 | __CRAB_assert (s >= 2 && s <=5); 34 | 35 | return 42; 36 | } 37 | -------------------------------------------------------------------------------- /tests/simple/test-global-1.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-widening-delay=1 --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-widening-delay=1 --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^3 Number of total warning checks$ 4 | #include "clam/clam.h" 5 | 6 | 7 | int e=0; 8 | int s=2; 9 | 10 | // we should get e=[0,2] and s=[2,5] with thresholds or --crab-widening-delay > 2 11 | // we should get e=[0,+oo] and s=[2,5] otherwise 12 | 13 | int main () { 14 | 15 | while (nd_int()) { 16 | if (s == 2){ 17 | if (e ==0) e=1; 18 | s = 3; 19 | } 20 | else if (s == 3){ 21 | if (e ==1) e=2; 22 | s=4; 23 | } 24 | else if (s == 4){ 25 | if (e == 3) { 26 | __VERIFIER_error(); 27 | } 28 | s=5; 29 | } 30 | } 31 | __CRAB_assert (e >= 0 && e <=2); 32 | __CRAB_assert (s >= 2 && s <=5); 33 | 34 | return 42; 35 | } 36 | -------------------------------------------------------------------------------- /tests/simple/test-global-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=int --crab-widening-delay=3 --crab-check=assert --inline --crab-sanity-checks --crab-track=sing-mem --crab-singleton-aliases "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=int --crab-widening-delay=3 --crab-check=assert --inline --crab-sanity-checks --crab-track=sing-mem --crab-singleton-aliases "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int e=0; 8 | int s=2; 9 | 10 | // we should get e=[0,2] and s=[2,5] without applying widening 11 | 12 | void foo() { 13 | 14 | while (nd_int()) { 15 | if (s == 2){ 16 | if (e ==0) e=1; 17 | s = 3; 18 | } 19 | else if (s == 3){ 20 | if (e ==1) e=2; 21 | s=4; 22 | } 23 | else if (s == 4){ 24 | if (e == 3) { 25 | __VERIFIER_error(); 26 | } 27 | s=5; 28 | } 29 | } 30 | 31 | __CRAB_assert (e >= 0 && e <=2); 32 | __CRAB_assert (s >= 2 && s <=5); 33 | } 34 | 35 | 36 | int main(){ 37 | foo(); 38 | return 42; 39 | } 40 | -------------------------------------------------------------------------------- /tests/simple/test-heap-translation-1.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int x = 5; 4 | int y = 3; 5 | 6 | void foo () 7 | { 8 | x++; 9 | } 10 | 11 | void bar () 12 | { 13 | y++; 14 | } 15 | 16 | int a[10]; 17 | 18 | int main () 19 | { 20 | int i; 21 | foo (); 22 | for (i=0;i<10;i++) 23 | { 24 | if (nd_int()) 25 | a[i] =y; 26 | else 27 | a[i] =x; 28 | } 29 | bar (); 30 | int res = a[i-1]; 31 | __CRAB_assert(res >= 0 && res <= 6); 32 | return res; 33 | } 34 | -------------------------------------------------------------------------------- /tests/simple/test-intrinsic-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-only-cfg --crab-print-cfg=true "%s" 2>&1 | OutputCheck %s 2 | // CHECK: crab_intrinsic 3 | #include "clam/clam.h" 4 | 5 | extern int __CRAB_intrinsic_foo(int, int); 6 | int main (){ 7 | 8 | int x,y,z, i; 9 | x=0; 10 | y=0; 11 | z=0; 12 | for (i=0;i< 10;i++) { 13 | x++; 14 | y++; 15 | z = __CRAB_intrinsic_foo(x, y); 16 | } 17 | 18 | __CRAB_assert(x>=y); 19 | __CRAB_assert(y>=x); 20 | __CRAB_assert(z>=x); 21 | 22 | return x+y; 23 | } 24 | 25 | 26 | /* _ret:int declare main() */ 27 | /* _br: */ 28 | /* .03 = 0; */ 29 | /* .02 = 0; */ 30 | /* .01 = 0; */ 31 | /* .0 = 0; */ 32 | /* goto _.03; */ 33 | /* _.03: */ 34 | /* goto __@bb_5,__@bb_6; */ 35 | /* __@bb_5: */ 36 | /* assume(.0 <= 9); */ 37 | /* goto _4; */ 38 | /* _4: */ 39 | /* _5 = .01+1; */ 40 | /* _6 = .02+1; */ 41 | /* _7 = crab_intrinsic(foo,_5:int,_6:int); */ 42 | /* _br2 = .0+1; */ 43 | /* .03 = _7; */ 44 | /* .02 = _6; */ 45 | /* .01 = _5; */ 46 | /* .0 = _br2; */ 47 | /* goto _.03; */ 48 | /* __@bb_6: */ 49 | /* assume(-.0 <= -10); */ 50 | /* goto _9; */ 51 | /* _9: */ 52 | /* _10 = (.02-.01 <= 0); */ 53 | /* assert(_10); */ 54 | /* _12 = (-.02+.01 <= 0); */ 55 | /* assert(_12); */ 56 | /* _14 = (-.03+.01 <= 0); */ 57 | /* assert(_14); */ 58 | /* _ret = .01+.02; */ 59 | /* return _ret; */ 60 | 61 | -------------------------------------------------------------------------------- /tests/simple/test-intrinsic-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-track=mem --crab-inter --crab-print-invariants=false --crab-disable-warnings "%s" 2>&1 | OutputCheck %s 2 | // XFAIL: * 3 | #include "clam/clam.h" 4 | 5 | 6 | int* mk_int_ptr_and_init(int val) { 7 | int* res= (int*)malloc(sizeof(int)); 8 | *res = val; 9 | return res; 10 | } 11 | 12 | int main (){ 13 | 14 | int x,y,z, i; 15 | x=0; 16 | y=0; 17 | int* w = mk_int_ptr_and_init(0); 18 | for (i=0;i< 10;i++) { 19 | x++; 20 | y++; 21 | *w = *w+1; 22 | } 23 | CRAB_PRINT_INVARIANTS(x); 24 | /* it should print something like 25 | crab_intrinsic(print_invariants,.01:int32) // loc(file=none line=-1 col=-1) id=1 26 | ({}, {.01 -> [10, 10]}) 27 | */ 28 | 29 | CRAB_PRINT_INVARIANTS(y,*w); 30 | 31 | /* it should print something like 32 | crab_intrinsic(print_invariants,.02:int32,_call3:int32) // loc(file=none line=-1 col=-1) id=2 33 | ({}, {.02 -> [10, 10], _call3 -> [10, 10]}) 34 | */ 35 | 36 | return 0; 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /tests/simple/test-list-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clam/clam.h" 3 | 4 | typedef struct node{ 5 | int f; 6 | int s; 7 | struct node *n; 8 | } *List; 9 | 10 | int main() { 11 | 12 | /* create the list */ 13 | List l = 0; 14 | int i; 15 | for (i=-17; i<42;i++) { 16 | List tmp = (List) malloc(sizeof(struct node)); 17 | tmp->f = i; 18 | tmp->s = 500; 19 | tmp->n = l ; 20 | l = tmp; 21 | } 22 | 23 | /* read the list */ 24 | List aux = l; 25 | int acc = 0; 26 | while (aux) { 27 | acc += aux->f; 28 | aux = aux->n; 29 | } 30 | 31 | return acc; 32 | } 33 | -------------------------------------------------------------------------------- /tests/simple/test-loop-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --inline --lower-unsigned-icmp --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck -l debug %s 2 | // RUN: %clam -O0 --inline --crab-lower-unsigned-icmp --crab-dom=int --crab-check=assert "%s" 2>&1 | OutputCheck -l debug %s 3 | // CHECK: ^0 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^0 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | 9 | void __VERIFIER_assert(int cond) { 10 | if (!(cond)) { 11 | ERROR: __VERIFIER_error(); 12 | } 13 | return; 14 | } 15 | 16 | /** 17 | The fact x is unsigned makes this program hard to verify because it 18 | requires non-trivial boolean reasoning due to the lowering of 19 | unsigned < operator and >= to signed operators. 20 | 21 | LLVM 5.0: llvm_seahorn::createInstructionCombiningPass or GVN 22 | passes can remove the assertion. 23 | **/ 24 | 25 | int main(void) { 26 | unsigned int x = 0; 27 | while (x < 0x0fffffff) { 28 | x++; 29 | } 30 | __VERIFIER_assert(x >= 0x0fffffff); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/simple/test-loop-1.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --inline --lower-unsigned-icmp --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // RUN: %clam -O0 --inline --crab-lower-unsigned-icmp --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 3 | // CHECK: ^0 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | void __VERIFIER_assert(int cond) { 9 | if (!(cond)) { 10 | ERROR: __VERIFIER_error(); 11 | } 12 | return; 13 | } 14 | 15 | /** 16 | The fact x is unsigned makes this program hard to verify because it 17 | requires non-trivial boolean reasoning due to the lowering of 18 | unsigned < operator and >= to signed operators. 19 | **/ 20 | 21 | int main(void) { 22 | unsigned int x = 0; 23 | while (x < 0x0fffffff) { 24 | x++; 25 | } 26 | __VERIFIER_assert(x > 0x0fffffff); 27 | } 28 | -------------------------------------------------------------------------------- /tests/simple/test-loop-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | #define assert(X) if(!(X)){__VERIFIER_error();} 8 | 9 | int main(){ 10 | int x = 0; 11 | int y = 1; 12 | 13 | while (nd_int()) { 14 | int nx = x; 15 | int ny = y; 16 | if (nd_int()) { 17 | if (nx < 32) { 18 | nx += 2; 19 | ny += 2; 20 | } else { 21 | nx++; 22 | break; 23 | } 24 | } 25 | x = nx; 26 | y = ny; 27 | } 28 | assert(x <= y); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tests/simple/test-loop-3.c: -------------------------------------------------------------------------------- 1 | /* Challenging example: 2 | To keep the relationship x = y - 1 while x <= 31 is easy. 3 | The tricky part is when x = 32: 4 | - We add one to x so the relationship between x and y is x = y so 5 | the assertion still holds. 6 | - Set err to 1. 7 | Once err is one we don't update x or y anymore. 8 | 9 | After the switch we lose whether err is 0 or 1 so we will 10 | keep incrementing x and y. 11 | */ 12 | #include "clam/clam.h" 13 | 14 | #define assert(X) if(!(X)){__VERIFIER_error();} 15 | 16 | int main(){ 17 | // Constructor 18 | int x = 0; 19 | int y = 1; 20 | 21 | while (nd_int()) { 22 | int fid = nd_int(); 23 | // We create snapshots for all state variables. 24 | int nx = x; 25 | int ny = y; 26 | int err = 0; 27 | switch (fid) { 28 | case 0: 29 | if (nx < 32) { 30 | nx += 2; 31 | ny += 2; 32 | } else { 33 | nx++; 34 | err = 1; 35 | } 36 | break; 37 | default:;; 38 | } 39 | if (err == 0) { 40 | // Commit state changes. 41 | x = nx; 42 | y = ny; 43 | } 44 | } 45 | assert(x <= y); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/simple/test-loop-4.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=pk --crab-inter --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | /** Example where polyhedra is more precise than octagons or zones **/ 8 | 9 | void __VERIFIER_assert(int cond) { 10 | if (!(cond)) { 11 | ERROR: __VERIFIER_error(); 12 | } 13 | return; 14 | } 15 | int main() { 16 | int i,j; 17 | i = 1; 18 | j = 10; 19 | while (j >= i) { 20 | i = i + 2; 21 | j = -1 + j; 22 | } 23 | __VERIFIER_assert(j == 6); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /tests/simple/test-loop-4.warning.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-inter --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-dom=soct --crab-inter --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^0 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^1 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | void __VERIFIER_assert(int cond) { 9 | if (!(cond)) { 10 | ERROR: __VERIFIER_error(); 11 | } 12 | return; 13 | } 14 | int main() { 15 | int i,j; 16 | i = 1; 17 | j = 10; 18 | while (j >= i) { 19 | i = i + 2; 20 | j = -1 + j; 21 | } 22 | __VERIFIER_assert(j == 6); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /tests/simple/test-memset.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "clam/clam.h" 4 | 5 | int main () 6 | { 7 | int a[5],b[5]; 8 | int i; 9 | memset(a, 5, sizeof(int)*5); 10 | 11 | for (i=0;i<5;i++) 12 | { 13 | if (nd_int()) 14 | b[i] =a[i]; 15 | else 16 | b[i] =a[i]+1; 17 | } 18 | 19 | int res = b[i-1]; 20 | return res; 21 | } 22 | -------------------------------------------------------------------------------- /tests/simple/test-nested-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | // simple program with nested loops from Scozzari SAS'13 8 | int main(void) { 9 | int i,j; 10 | 11 | i=0; 12 | while (i < 10) { 13 | j=0; 14 | while (j < 10) { 15 | j++; 16 | } 17 | i++; 18 | } 19 | __CRAB_assert(i == 10); 20 | return 0; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/simple/test-nested-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | // program hybrid from Scozzari SAS'13 8 | int main(void) { 9 | int i,j; 10 | 11 | i=0; 12 | while (1) { 13 | i++; 14 | j=0; 15 | while (j < 10) { 16 | __CRAB_assert(i >= 0); 17 | __CRAB_assert(i <= 10); 18 | j++; 19 | } 20 | if (i>9) i=0; 21 | } 22 | 23 | return 0; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /tests/simple/test-nested-3.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | // program hh from Scozzari SAS'13 8 | int main(void) { 9 | int i,j; 10 | 11 | i=0; 12 | while (i<4) { 13 | j=0; 14 | while (j < 4) { 15 | __CRAB_assert(i <= j+3); 16 | i++; 17 | j++; 18 | } 19 | i = i-j+1; 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/simple/test-nested-4.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | // program nested2 from Scozzari SAS'13 8 | int main(void) { 9 | int i,j; 10 | 11 | i=0; 12 | while (1) { 13 | __CRAB_assert(i>=0); 14 | j=0; 15 | while (j < 10) { 16 | j++; 17 | } 18 | i = i+11-j; 19 | } 20 | 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/simple/test-octagons.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=soct --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int main (){ 8 | 9 | int k = 200; 10 | int n = 100; 11 | int x = 0, y = k; 12 | 13 | while (x < n) { 14 | x++; 15 | y = k - 2*x; 16 | } 17 | __CRAB_assert(x+y <= k); 18 | 19 | return x+y; 20 | } 21 | -------------------------------------------------------------------------------- /tests/simple/test-pagai.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=boxes --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck -l debug %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | // XFAIL: * 6 | #include "clam/clam.h" 7 | 8 | int main () { 9 | int x = 0 ; 10 | int t = 0 ; 11 | int phase = 0 ; 12 | while ( t < 100) { 13 | if (phase == 0) 14 | x = x +2; 15 | if (phase == 1) 16 | x = x - 1; 17 | 18 | phase = 1 - phase ; 19 | t++; 20 | } 21 | __CRAB_assert ( x <= 100); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-1.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[10]; 4 | 5 | /* 6 | Pointer arithmetic example. sea-dsa is fine because the array is 7 | never accessed. 8 | */ 9 | int main() { 10 | int* p; 11 | 12 | if (nd_int()) { 13 | p = &a[0] + 2; 14 | } 15 | else { 16 | p = &a[0] + 3; 17 | } 18 | 19 | int res; 20 | if ( p == &a[0]+1) { 21 | res = 0; 22 | } else { 23 | res = 1; 24 | } 25 | return res; 26 | } 27 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-2.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[10]; 4 | 5 | /* Example of overlapping cells. 6 | The final dsa node looks like this: 7 | flags=[MR] size=8 types={0:i32,2:i16,4:i32} links=[] 8 | 9 | EXPECTED: we won't produce an array for offsets a[0] or p but we 10 | should for a[1]. 11 | */ 12 | int main() { 13 | int n=10; 14 | 15 | if (nd_int()) 16 | a[0] = 5; 17 | if (nd_int()) 18 | a[1] = 10; 19 | 20 | short* p = (short*) &a[0]; 21 | short x = 1; 22 | return p[x]; 23 | } 24 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-3.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[10]; 4 | 5 | /* 6 | Example of converting non-array dsa node to an array node. 7 | The final dsa node gets collapsed (see explanation below) 8 | */ 9 | int main() { 10 | int n=10; 11 | 12 | /* The node is initially marked as non-array by sea-dsa */ 13 | if (nd_int()) 14 | a[0] = 5; 15 | if (nd_int()) 16 | a[1] = 10; 17 | 18 | /* After this loop, the node is marked as array because of symbolic 19 | accesses. Moreover, sea-dsa will collapse the node because the 20 | size when it was a non-array size (4) does not fit into the size 21 | of the node as an array (2). 22 | */ 23 | short* p = (short*) &a[0]; 24 | int i; 25 | for(i=0;i<10;++i) { 26 | p[i] = 7; 27 | } 28 | return p[1]; 29 | } 30 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-4.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | short a[10]; 4 | 5 | /* Example of converting non-array dsa node to an array node. 6 | 7 | The final dsa node looks like this: 8 | types={0:i16|i32,2:i16} flags=[AMR], size=4, links=[] 9 | 10 | EXPECTED: no crab arrays extracted from dsa node due to overlapping 11 | cells. 12 | */ 13 | int main() { 14 | int n=10; 15 | 16 | /* The node is initially marked as non-array by sea-dsa */ 17 | if (nd_int()) 18 | a[0] = 5; 19 | if (nd_int()) 20 | a[1] = 10; 21 | if (nd_int()) 22 | a[2] = 20; 23 | 24 | /* After this loop, the node is marked as array because of symbolic 25 | accesses. However, sea-dsa will NOT collapse the node because 26 | the size when it was a non-array size (2) fits into the size of 27 | the node as an array (4). 28 | */ 29 | int* p = (int*) &a[0]; 30 | int i; 31 | for(i=0;i<5;++i) { 32 | p[i] = 7; 33 | } 34 | return p[1]; 35 | } 36 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-5.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | char a[40]; 4 | 5 | /* 6 | Similar to test-ptr-2.c and test-ptr-4.c 7 | The DSA node looks like this: 8 | flags=[AMR] size=4 types={0:i32,3:i8} links=[]. 9 | 10 | EXPECTED: we do not produce an array because we might have 11 | overlapping cells. Even if we would replace a[3] with a[4] we would 12 | not generate an array. 13 | */ 14 | int main() { 15 | int n=10; 16 | 17 | if (nd_int()) 18 | a[3] = 10; 19 | 20 | int* p = (int*) &a[0]; 21 | int i; 22 | for(i=1;i<10;++i) { 23 | p[i] = 7; 24 | } 25 | return p[1]; 26 | } 27 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-6.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | short a[40]; 4 | 5 | /* 6 | Smaller array unified with larger array. 7 | The a and p are unified and collapsed. 8 | */ 9 | int main() { 10 | int i; 11 | 12 | for(i=0;i<20;++i) { 13 | a[i] = 7; 14 | } 15 | 16 | int* p = (int*) &a[0]; 17 | for(i=0;i<10;++i) { 18 | p[i] = 7; 19 | } 20 | 21 | return p[1] + a[3]; 22 | } 23 | -------------------------------------------------------------------------------- /tests/simple/test-ptr-7.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[40]; 4 | 5 | /* 6 | Larger array unified with smaller array. 7 | The a and p are unified and collapsed. 8 | */ 9 | 10 | int main() { 11 | int i; 12 | 13 | for(i=0;i<10;++i) { 14 | a[i] = 7; 15 | } 16 | 17 | short* p = (short*) &a[0]; 18 | for(i=0;i<20;++i) { 19 | p[i] = 8; 20 | } 21 | 22 | return p[1]; 23 | } 24 | -------------------------------------------------------------------------------- /tests/simple/test-switch-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int main () { 8 | int x = 7; 9 | int y = 8; 10 | int v = nd_int(); 11 | switch (v) { 12 | case 1: 13 | x = 0; 14 | y = 1; 15 | break; 16 | case 2: 17 | x = 1; 18 | y = 2; 19 | break; 20 | case 3: 21 | x = 2; 22 | y = 3; 23 | break; 24 | default: 25 | x = 5; 26 | y = 6; 27 | } 28 | 29 | __CRAB_assert(x >= 0 && x <= 7); // proved by preprocessor 30 | __CRAB_assert(y >= 1 && y <= 8); // proved by preprocessor 31 | __CRAB_assert(y >= x+1); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/simple/test-term-1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --lower-unsigned-icmp --crab-dom=term-dis-int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-lower-unsigned-icmp --crab-dom=term-dis-int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total safe checks$ 4 | // CHECK: ^0 Number of total error checks$ 5 | // CHECK: ^0 Number of total warning checks$ 6 | #include "clam/clam.h" 7 | 8 | int main() 9 | { 10 | int u,y,z,x; 11 | 12 | if (nd_int ()) 13 | u = 0; 14 | else 15 | u = 10; 16 | 17 | if (nd_int ()) 18 | y = 0; 19 | else 20 | y = 10; 21 | 22 | if (nd_int ()) 23 | z = 0; 24 | else 25 | z = 10; 26 | 27 | if (nd_int ()) 28 | x = u+y; 29 | else 30 | x = u+z; 31 | 32 | if (x < 3) 33 | u = u + 3; 34 | else 35 | u = 3; 36 | 37 | //__CRAB_assert(u >= 3 && u <= 13); 38 | 39 | __CRAB_assert(u >= 3 && u <= 5); 40 | if (nd_int ()) 41 | return 42; 42 | else 43 | return u; 44 | } 45 | -------------------------------------------------------------------------------- /tests/simple/test-term-2.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int main() 4 | { 5 | int x,y,z; 6 | x=0; 7 | y=0; 8 | z=0; 9 | while (nd_int ()) 10 | { 11 | x ++; 12 | y++; 13 | z = z -2; 14 | } 15 | while (nd_int ()) 16 | { 17 | x = x - 1; 18 | y = y - 3; 19 | z = z + 2; 20 | } 21 | 22 | if (nd_int ()) 23 | return x+y+z; 24 | else 25 | return 42; 26 | } 27 | -------------------------------------------------------------------------------- /tests/simple/test-term-3.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int main () { 4 | int i,x,y,offset_x,offset_y; 5 | x=0; 6 | y=0; 7 | for (i=0; i < nd_int (); i++){ 8 | offset_x = nd_int (); 9 | offset_x += i+4; 10 | 11 | offset_y = nd_int (); 12 | offset_y += i+4; 13 | 14 | x+=offset_x; 15 | y+=offset_y; 16 | } 17 | return 42; 18 | } 19 | -------------------------------------------------------------------------------- /tests/simple/test-term-4.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int a[10]; 4 | int b[10]; 5 | 6 | int main () { 7 | 8 | int i; 9 | for (i=0; i < 10; i++){ 10 | a[i] = b[i]; 11 | } 12 | 13 | int j = nd_int (); 14 | if (j >= 0 && j < 10) 15 | return a[j]; 16 | } 17 | -------------------------------------------------------------------------------- /tests/simple/test-term-5.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | int foo(int* p, const int* A, const int* B, int n) { 4 | int numNonZero = n - 1; 5 | while (numNonZero--) { 6 | *p *= (*A++) * (*B++); 7 | } 8 | return *p; 9 | } 10 | int main(int argc, char** argv) { 11 | int p; 12 | int A[10]; 13 | int B[10]; 14 | return (int)foo(&p, &A, &B, 10); 15 | } 16 | -------------------------------------------------------------------------------- /tests/simple/test-unsigned-cmp-1.c: -------------------------------------------------------------------------------- 1 | #include "clam/clam.h" 2 | 3 | // RUN: %clam -O0 --inline --crab-lower-unsigned-icmp --crab-check=assert "%s" 2>&1 | OutputCheck %s 4 | // CHECK: ^2 Number of total safe checks$ 5 | // CHECK: ^0 Number of total warning checks$ 6 | 7 | extern int8_t nd_int8_t(void); 8 | 9 | uint8_t uint8_t_nd(void) { 10 | int8_t res = nd_int8_t(); 11 | __CRAB_assume(res > 0); 12 | return res; 13 | } 14 | 15 | uint8_t call_f(uint8_t max_len) { 16 | uint8_t len = uint8_t_nd(); 17 | __CRAB_assume(len <= max_len); 18 | return len; 19 | } 20 | 21 | int main(void) { 22 | int8_t max_len = 0b10000000; // unsigned: 128, signed: -128 23 | uint8_t res_f = call_f(max_len); 24 | __CRAB_assert(res_f <= 128); 25 | __CRAB_assert(res_f > 0); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/simple/test-wrapped.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=w-int --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int main() { 8 | char x,y; 9 | 10 | y=-10; 11 | if(nd_int()) x=0; 12 | else x=100; 13 | while (x >= y){ 14 | x = x-y; 15 | } 16 | __CRAB_assert(x >= -128 && x <= -119); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /tests/simple/test-zones-2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | #include "clam/clam.h" 6 | 7 | int main (){ 8 | 9 | int x,y,i; 10 | x=0; 11 | y=0; 12 | for (i=0;i< 10;i++) { 13 | x++; 14 | y++; 15 | } 16 | 17 | __CRAB_assert(x==y); 18 | return x+y; 19 | } 20 | -------------------------------------------------------------------------------- /tests/simple/test-zones.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^2 Number of total safe checks$ 3 | // CHECK: ^0 Number of total error checks$ 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include "clam/clam.h" 7 | 8 | int main (){ 9 | int x,y,i; 10 | x=0; 11 | y=0; 12 | for (i=0;i< 10;i++) { 13 | x++; 14 | y++; 15 | } 16 | 17 | __CRAB_assert(x>=y); 18 | __CRAB_assert(y>=x); 19 | 20 | return x+y; 21 | } 22 | -------------------------------------------------------------------------------- /tests/simple/test-zones.unsafe.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=zones --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^0 Number of total error checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include "clam/clam.h" 6 | 7 | int main (){ 8 | 9 | int x,y,i; 10 | x=0; 11 | y=0; 12 | for (i=0;i< 10;i++) { 13 | x++; 14 | y++; 15 | } 16 | 17 | __CRAB_assert(x> y); //error 18 | 19 | return x+y; 20 | } 21 | -------------------------------------------------------------------------------- /tests/simple/test_identity.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam --crab-dom=int --crab-inter --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^1 Number of total safe checks$ 3 | 4 | #include "clam/clam.h" 5 | 6 | int f(int x) { 7 | return x; 8 | } 9 | 10 | int main(void) { 11 | int y = f(0); 12 | __CRAB_assert(y == 0); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /tests/ssh-simplified/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | config.excludes = [ 4 | # 's3_clnt_1_false-unreach-call.cil.c' 5 | # ,'s3_clnt_2_false-unreach-call_true-termination.cil.c' 6 | # ,'s3_clnt_3_false-unreach-call.cil.c' 7 | # ,'s3_clnt_4_false-unreach-call.cil.c' 8 | 's3_srvr_10_false-unreach-call.cil.c' 9 | ,'s3_srvr_11_false-unreach-call.cil.c' 10 | ,'s3_srvr_12_false-unreach-call.cil.c' 11 | ,'s3_srvr_13_false-unreach-call.cil.c' 12 | ,'s3_srvr_14_false-unreach-call.cil.c' 13 | ,'s3_srvr_2_false-unreach-call.cil.c' 14 | ,'s3_srvr_6_false-unreach-call.cil.c' 15 | ] 16 | 17 | 18 | 19 | config.substitutions.append(('%opts', '--crab-widening-delay=15 --crab-narrowing-iterations=2')) 20 | -------------------------------------------------------------------------------- /tests/ssh/lit.local.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | config.excludes = [] 4 | config.substitutions.append(('%opts', '--crab-widening-delay=15 --crab-narrowing-iterations=2')) 5 | 6 | -------------------------------------------------------------------------------- /tests/tag-analysis/test1.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | /* seadsa */ 9 | extern void sea_dsa_set_read(const void *p); 10 | extern void sea_dsa_set_modified(const void *p); 11 | 12 | /* Tag analysis */ 13 | typedef uint64_t tag_t; 14 | extern void __CRAB_intrinsic_add_tag(void *, tag_t); 15 | extern void __CRAB_intrinsic_check_does_not_have_tag(void *, tag_t); 16 | #define ADD_TAG(PTR, TAG) \ 17 | __CRAB_intrinsic_add_tag(PTR, TAG); \ 18 | sea_dsa_set_modified(PTR); 19 | 20 | #define CHECK_NOT_TAG(PTR, TAG) \ 21 | __CRAB_intrinsic_check_does_not_have_tag(PTR ,TAG); \ 22 | sea_dsa_set_read(PTR); 23 | 24 | /* Program starts here */ 25 | 26 | int main(int argc, char**argv) { 27 | int x = 0; 28 | int y = 1; 29 | int i = 0; 30 | 31 | ADD_TAG(&i, 1); 32 | ADD_TAG(&x, 2); 33 | ADD_TAG(&y, 3); 34 | 35 | 36 | int n = nd_int(); 37 | __CRAB_assume(n > 0); 38 | 39 | while (i < n) { 40 | x = x + y; 41 | y = y + 1; 42 | i = i + 1; 43 | } 44 | 45 | CHECK_NOT_TAG(&i, 2); 46 | CHECK_NOT_TAG(&i, 3); 47 | CHECK_NOT_TAG(&y, 1); 48 | CHECK_NOT_TAG(&x, 3); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /tests/tag-analysis/test2.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --crab-heap-analysis=cs-sea-dsa --crab-check=assert --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // CHECK: ^3 Number of total safe checks$ 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | /* seadsa */ 9 | extern void sea_dsa_set_read(const void *p); 10 | extern void sea_dsa_set_modified(const void *p); 11 | 12 | /* Tag analysis */ 13 | typedef uint64_t tag_t; 14 | extern void __CRAB_intrinsic_add_tag(void *, tag_t); 15 | extern void __CRAB_intrinsic_check_does_not_have_tag(void *, tag_t); 16 | #define ADD_TAG(PTR, TAG) \ 17 | __CRAB_intrinsic_add_tag(PTR, TAG); \ 18 | sea_dsa_set_modified(PTR); 19 | 20 | #define CHECK_NOT_TAG(PTR, TAG) \ 21 | __CRAB_intrinsic_check_does_not_have_tag(PTR ,TAG); \ 22 | sea_dsa_set_read(PTR); 23 | 24 | 25 | /* Program starts here */ 26 | 27 | void init(int*x, int*y, int*i) { 28 | ADD_TAG(i, 1); 29 | ADD_TAG(x, 2); 30 | ADD_TAG(y, 3); 31 | } 32 | 33 | void loop_body(int* x, int*y, int*i){ 34 | *x = *x + *y; 35 | *y = *y + 1; 36 | *i = *i + 1; 37 | 38 | } 39 | int main(int argc, char**argv) { 40 | int x = 0; 41 | int y = 1; 42 | int i = 0; 43 | init(&x,&y,&i); 44 | int n = nd_int(); 45 | __CRAB_assume(n > 0); 46 | while (i < n) { 47 | loop_body(&x, &y, &i); 48 | } 49 | 50 | CHECK_NOT_TAG(&i, 2); // OK 51 | CHECK_NOT_TAG(&i, 3); // OK 52 | CHECK_NOT_TAG(&y, 1); // OK 53 | CHECK_NOT_TAG(&x, 3); // FAIL 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /tests/uaf/test1-ok.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf-legacy --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | 4 | // CHECK: ^0 Number of total warning checks$ 5 | 6 | #include 7 | #include "clam/clam.h" 8 | 9 | struct s { 10 | int f1; 11 | int f2; 12 | int f3; 13 | }; 14 | 15 | void * malloc_x(int sz) { 16 | void *p = malloc(sz); 17 | __CRAB_assume(p > 0); 18 | return p; 19 | } 20 | 21 | void free_x(void*p) { 22 | free(p); 23 | } 24 | 25 | void init(struct s* p) { 26 | p->f1 = nd_int(); 27 | p->f2 = nd_int(); 28 | p->f3 = 5; 29 | } 30 | 31 | int main () { 32 | struct s *p = (struct s*) malloc_x(sizeof(struct s)); 33 | init(p); 34 | p->f3 = 5; 35 | free_x(p); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/uaf/test1a-fail.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf-legacy --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | struct s { 9 | int f1; 10 | int f2; 11 | int f3; 12 | }; 13 | 14 | void * malloc_x(int sz) { 15 | void *p = malloc(sz); 16 | __CRAB_assume(p > 0); 17 | return p; 18 | } 19 | 20 | void free_x(void*p) { 21 | free(p); 22 | } 23 | 24 | void init(struct s* p) { 25 | p->f1 = nd_int(); 26 | p->f2 = nd_int(); 27 | p->f3 = nd_int(); 28 | } 29 | 30 | int main () { 31 | struct s *p = (struct s*) malloc_x(sizeof(struct s)); 32 | init(p); 33 | free_x(p); // bug 34 | p->f3 = 5; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /tests/uaf/test1b-fail.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf-legacy --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | struct s { 9 | int f1; 10 | int f2; 11 | int f3; 12 | }; 13 | 14 | void * malloc_x(int sz) { 15 | void *p = malloc(sz); 16 | __CRAB_assume(p > 0); 17 | return p; 18 | } 19 | 20 | void free_x(void*p) { 21 | free(p); 22 | } 23 | 24 | void init(struct s* p) { 25 | p->f1 = nd_int(); 26 | p->f2 = nd_int(); 27 | p->f3 = nd_int(); 28 | } 29 | 30 | int main () { 31 | struct s *p = (struct s*) malloc_x(sizeof(struct s)); 32 | init(p); 33 | free_x(&(p->f2)); // bug 34 | p->f3 = 5; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /tests/uaf/test2-ok.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf-legacy --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^0 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | struct s { 9 | int f1; 10 | int f2; 11 | int f3; 12 | }; 13 | 14 | 15 | void init(struct s* p) { 16 | // x is allocated here but it doesn't escape 17 | int *x = (int*) malloc(sizeof(int)); 18 | if (nd_int()) { 19 | *x = 5; 20 | } else { 21 | *x = 7; 22 | } 23 | p->f1 = *x; 24 | p->f2 = nd_int(); 25 | p->f3 = *x; 26 | free(x); 27 | } 28 | 29 | int main () { 30 | // a memory block is allocated and passed to callee 31 | struct s *p = (struct s*) malloc(sizeof(struct s)); 32 | __CRAB_assume(p > 0); 33 | init(p); 34 | p->f3 = 5; 35 | free(p); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/uaf/test2a-fail.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf-legacy --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | struct s { 9 | int f1; 10 | int f2; 11 | int f3; 12 | }; 13 | 14 | 15 | void init(struct s* p) { 16 | // x is allocated here but it doesn't escape 17 | int *x = (int*) malloc(sizeof(int)); 18 | if (nd_int()) { 19 | *x = 5; 20 | } else { 21 | *x = 7; 22 | } 23 | p->f1 = *x; 24 | p->f2 = nd_int(); 25 | p->f3 = *x; 26 | free(x); 27 | // inject bug 28 | free(&(p->f3)); 29 | } 30 | 31 | int main () { 32 | // a memory block is allocated and passed to callee 33 | struct s *p = (struct s*) malloc(sizeof(struct s)); 34 | __CRAB_assume(p > 0); 35 | init(p); 36 | int x = p->f3; 37 | __CRAB_assert(x >= 5); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /tests/uaf/test2b-fail.c: -------------------------------------------------------------------------------- 1 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf-legacy --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 2 | // RUN: %clam -O0 --crab-inter --crab-dom=int --crab-track=mem --promote-malloc=false --crab-check=uaf --crab-sanity-checks "%s" 2>&1 | OutputCheck %s 3 | // CHECK: ^1 Number of total warning checks$ 4 | 5 | #include 6 | #include "clam/clam.h" 7 | 8 | struct s { 9 | int f1; 10 | int f2; 11 | int f3; 12 | }; 13 | 14 | 15 | void foo(void *p, int x) { 16 | if (x > 0) { 17 | free(p); 18 | } 19 | } 20 | void bar(void *p, int x) { 21 | foo (p, x+1); 22 | } 23 | 24 | void init(struct s* p) { 25 | // x is allocated here but it doesn't escape 26 | int *x = (int*) malloc(sizeof(int)); 27 | if (nd_int()) { 28 | *x = 5; 29 | } else { 30 | *x = 7; 31 | } 32 | p->f1 = *x; 33 | p->f2 = nd_int(); 34 | p->f3 = *x; 35 | free(x); 36 | } 37 | 38 | int main () { 39 | // a memory block is allocated and passed to callee 40 | struct s *p = (struct s*) malloc(sizeof(struct s)); 41 | __CRAB_assume(p > 0); 42 | init(p); 43 | // inject bug 44 | foo(&(p->f2), 1); 45 | int x = p->f3; 46 | __CRAB_assert(x >= 5); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(clam) 2 | add_subdirectory(clam-diff) 3 | add_subdirectory(clam-pp) 4 | -------------------------------------------------------------------------------- /tools/clam-diff/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D__STDC_CONSTANT_MACROS) 2 | add_definitions(-D__STDC_LIMIT_MACROS) 3 | 4 | set(LLVM_LINK_COMPONENTS 5 | irreader 6 | bitwriter 7 | ipo 8 | scalaropts 9 | instrumentation 10 | transformutils 11 | core 12 | codegen 13 | objcarcopts) 14 | 15 | 16 | add_llvm_executable(clam-diff DISABLE_LLVM_LINK_LLVM_DYLIB clam-diff.cc) 17 | target_link_libraries(clam-diff PRIVATE 18 | ClamAnalysis 19 | ) 20 | 21 | llvm_config(clam-diff ${LLVM_LINK_COMPONENTS}) 22 | install(TARGETS clam-diff RUNTIME DESTINATION bin) 23 | 24 | if (CLAM_STATIC_EXE) 25 | set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") 26 | set_target_properties(clam-diff PROPERTIES LINK_SEARCH_START_STATIC ON) 27 | set_target_properties(clam-diff PROPERTIES LINK_SEARCH_END_STATIC ON) 28 | endif() 29 | -------------------------------------------------------------------------------- /tools/clam-pp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D__STDC_CONSTANT_MACROS) 2 | add_definitions(-D__STDC_LIMIT_MACROS) 3 | 4 | set(LLVM_LINK_COMPONENTS 5 | irreader 6 | bitwriter 7 | ipo 8 | scalaropts 9 | instrumentation 10 | transformutils 11 | core 12 | codegen 13 | objcarcopts) 14 | 15 | add_llvm_executable(clam-pp DISABLE_LLVM_LINK_LLVM_DYLIB clam-pp.cc) 16 | target_link_libraries(clam-pp PRIVATE 17 | LlvmPasses 18 | ${LLVM_SEAHORN_LIBS} 19 | ) 20 | llvm_config(clam-pp ${LLVM_LINK_COMPONENTS}) 21 | install(TARGETS clam-pp RUNTIME DESTINATION bin) 22 | 23 | if (CLAM_STATIC_EXE) 24 | set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") 25 | set_target_properties(clam-pp PROPERTIES LINK_SEARCH_START_STATIC ON) 26 | set_target_properties(clam-pp PROPERTIES LINK_SEARCH_END_STATIC ON) 27 | endif() 28 | -------------------------------------------------------------------------------- /tools/clam/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_definitions(-D__STDC_CONSTANT_MACROS) 2 | add_definitions(-D__STDC_LIMIT_MACROS) 3 | 4 | set(LLVM_LINK_COMPONENTS 5 | irreader 6 | bitwriter 7 | ipo 8 | scalaropts 9 | instrumentation 10 | transformutils 11 | core 12 | codegen 13 | objcarcopts) 14 | 15 | add_llvm_executable(clam DISABLE_LLVM_LINK_LLVM_DYLIB clam.cc) 16 | target_link_libraries(clam PRIVATE 17 | ClamAnalysis 18 | ClamOptimizer 19 | LlvmPasses 20 | ${LLVM_SEAHORN_LIBS} 21 | ${SEA_DSA_LIBS} 22 | ) 23 | llvm_config(clam ${LLVM_LINK_COMPONENTS}) 24 | install(TARGETS clam RUNTIME DESTINATION bin) 25 | 26 | if (CLAM_STATIC_EXE) 27 | set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") 28 | set_target_properties(clam PROPERTIES LINK_SEARCH_START_STATIC ON) 29 | set_target_properties(clam PROPERTIES LINK_SEARCH_END_STATIC ON) 30 | endif() 31 | -------------------------------------------------------------------------------- /yaml-configurations/clam.inter.mem.yaml: -------------------------------------------------------------------------------- 1 | clam_options: 2 | # 3 | # Optimization level 4 | # 5 | # '-O3': '' 6 | # 7 | # Debug symbols 8 | # 9 | '-g' : '' 10 | # 11 | # PREPROCESSING 12 | # 13 | # convert unsigned icmp instructions into signed icmp instructions 14 | lower-unsigned-icmp : '' 15 | # peel loops to improve precision of the region and array domains 16 | llvm-peel-loops: '0' 17 | # weak support for function pointers. sea-dsa is better but less stable 18 | devirt-functions: 'types' 19 | # disable lowering of vector operations into scalar ones 20 | disable-scalarize: '' 21 | # 22 | # ANALYSIS 23 | # 24 | # enable inter-procedural analysis 25 | crab-inter : '' 26 | # highest precision level for the translation from LLVM to Crab 27 | crab-track : 'mem' 28 | crab-singleton-aliases : '' 29 | # pointer analysis to disambiguate memory: context-sensitive with types 30 | crab-heap-analysis : 'cs-sea-dsa-types' 31 | # enable sanity checks 32 | crab-sanity-checks : '' 33 | # do not print invariants 34 | # crab-do-not-print-invariants: '' 35 | # disable warnings 36 | crab-disable-warnings: '' 37 | # keep intermediate results for debugging 38 | # save-temps: '' 39 | # temp-dir: /tmp/clam 40 | # time and result stats 41 | crab-stats: '' 42 | # 43 | # CHECKER 44 | # 45 | # Check for user-defined assertions 46 | crab-check: 'assert' -------------------------------------------------------------------------------- /yaml-configurations/clam.intra.mem.yaml: -------------------------------------------------------------------------------- 1 | clam_options: 2 | # 3 | # Optimization level 4 | # 5 | # '-O3': '' 6 | # 7 | # Debug symbols 8 | # 9 | '-g' : '' 10 | # 11 | # PREPROCESSING 12 | # 13 | # convert unsigned icmp instructions into signed icmp instructions 14 | crab-lower-unsigned-icmp : '' 15 | # peel loops to improve precision of the region and array domains 16 | llvm-peel-loops: '0' 17 | # weak support for function pointers. sea-dsa is better but less stable 18 | devirt-functions: 'types' 19 | # disable lowering of vector operations into scalar ones 20 | disable-scalarize: '' 21 | # Inline aggressively 22 | inline: '' 23 | # 24 | # ANALYSIS 25 | # 26 | # highest precision level for the translation from LLVM to Crab 27 | crab-track : 'mem' 28 | crab-singleton-aliases : '' 29 | # pointer analysis to disambiguate memory: context-sensitive with types 30 | crab-heap-analysis : 'cs-sea-dsa-types' 31 | # enable sanity checks 32 | crab-sanity-checks : '' 33 | # do not print invariants 34 | # crab-do-not-print-invariants: '' 35 | # disable warnings 36 | crab-disable-warnings: '' 37 | # keep intermediate results for debugging 38 | # save-temps: '' 39 | # temp-dir: /tmp/clam 40 | # time and result stats 41 | crab-stats: '' 42 | # 43 | # CHECKER 44 | # 45 | # Check for user-defined assertions 46 | crab-check: 'assert' -------------------------------------------------------------------------------- /yaml-configurations/clam.svcomp19.yaml: -------------------------------------------------------------------------------- 1 | clam_options: 2 | # CLANG 3 | # 4 | '-g' : '' 5 | '-m64': '' 6 | # Optimization level for seaopt 7 | '-O3': '' 8 | # 9 | # PREPROCESSING 10 | # 11 | # SVCOMP19 has a weird memory model different from standard C memory 12 | # model. Programs can have uninitialized variables and reading from 13 | # them it is okay and treated as reading from a non-deterministic value. 14 | turn-undef-nondet : '' 15 | # convert unsigned icmp instructions into signed icmp instructions 16 | crab-lower-unsigned-icmp : '' 17 | # weak support for function pointers. sea-dsa is better but less stable 18 | devirt-functions: 'types' 19 | # Inline aggressively 20 | inline: '' 21 | externalize-addr-taken-functions: '' 22 | crab-name-values: false 23 | # 24 | # ANALYSIS 25 | # 26 | # Reason about all memory contents 27 | crab-track : 'mem' 28 | # Optimization to convert treat memory contents as scalars 29 | crab-singleton-aliases : '' 30 | # Pointer analysis to disambiguate memory: context-sensitive with types 31 | crab-heap-analysis : 'cs-sea-dsa-types' 32 | # Perform two iterations of narrowing 33 | crab-narrowing-iterations: '2' 34 | # Delay widening three fixpoint iterations 35 | crab-widening-delay: '3' 36 | # Do not use widening jump set 37 | crab-widening-jump-set: '0' 38 | # Option to free invariants as soon as possible 39 | crab-preserve-invariants: false 40 | # 41 | # CHECKER 42 | # 43 | crab-check: 'assert' 44 | # 45 | # OUTPUT 46 | # 47 | # crab-sanity-checks : '' 48 | crab-disable-warnings: '' 49 | crab-print-invariants: false 50 | # 51 | # RESOURCE LIMITS 52 | # 53 | # Timeout of 3 minutes 54 | cpu: '180' 55 | # Limit memory to 4GB 56 | # mem: '4096' 57 | --------------------------------------------------------------------------------