diff --git a/.cirrus.yml b/.cirrus.yml index 828f667364..c0c113987c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,16 +1,16 @@ task: freebsd_instance: matrix: - - image_family: freebsd-12-3-snap - - image_family: freebsd-13-1-snap + - image_family: freebsd-13-2-snap + - image_family: freebsd-14-0-snap deps_script: - sed -i.bak -e 's/quarterly/latest/' /etc/pkg/FreeBSD.conf - env ASSUME_ALWAYS_YES=yes pkg update -f - - env ASSUME_ALWAYS_YES=yes pkg install -y llvm11 gmake z3 cmake pkgconf google-perftools python3 py39-sqlite3 py39-tabulate + - env ASSUME_ALWAYS_YES=yes pkg install -y llvm11 gmake z3 cmake pkgconf google-perftools python3 py39-sqlite3 py39-tabulate nlohmann-json bash coreutils build_script: - mkdir build - cd build - - cmake -DLLVM_DIR=/usr/local/llvm11 -DMAKE_BINARY=/usr/local/bin/gmake -DENABLE_TCMALLOC:BOOL=true -DENABLE_POSIX_RUNTIME:BOOL=ON -DENABLE_SOLVER_Z3:BOOL=true -DENABLE_SYSTEM_TESTS:BOOL=ON .. + - cmake -DLLVM_DIR=/usr/local/llvm11 -DMAKE_BINARY=/usr/local/bin/gmake -DJSON_SRC_DIR=/usr/local -DENABLE_TCMALLOC:BOOL=true -DENABLE_POSIX_RUNTIME:BOOL=ON -DENABLE_SOLVER_Z3:BOOL=true -DENABLE_SYSTEM_TESTS:BOOL=ON .. - gmake test_script: - sed -i.bak -e 's/lit\./lit11\./' test/lit.cfg diff --git a/.github/workflows/build-in-base-env.yml b/.github/workflows/build-in-base-env.yml index daf22bff94..04b7da3633 100644 --- a/.github/workflows/build-in-base-env.yml +++ b/.github/workflows/build-in-base-env.yml @@ -1,14 +1,15 @@ name: Build in UTBot base_env on: - pull_request: - branches: [utbot-main] - push: - branches: [utbot-main] + workflow_run: + workflows: ["Clang Format"] + types: + - completed jobs: build: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} container: image: ghcr.io/unittestbot/utbotcpp/base_env:02-02-2022 credentials: diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dc2c95350c..192af2535f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -2,10 +2,10 @@ name: CI on: - pull_request: - branches: [main, utbot-main] - push: - branches: [main, utbot-main] + workflow_run: + workflows: ["Clang Format"] + types: + - completed # Defaults for building KLEE env: @@ -21,7 +21,7 @@ env: LLVM_VERSION: 11 MINISAT_VERSION: "master" REQUIRES_RTTI: 0 - SOLVERS: Z3:STP + SOLVERS: BITWUZLA:Z3:STP STP_VERSION: 2.3.3 TCMALLOC_VERSION: 2.9.1 UCLIBC_VERSION: klee_uclibc_v1.3 @@ -29,10 +29,13 @@ env: USE_LIBCXX: 1 Z3_VERSION: 4.8.15 SQLITE_VERSION: 3400100 + BITWUZLA_VERSION: 0.3.1 + JSON_VERSION: v3.11.3 jobs: Linux: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} strategy: matrix: name: [ @@ -48,6 +51,7 @@ jobs: "Z3 only", "metaSMT", "STP master", + "Bitwuzla only", "Latest klee-uclibc", "Asserts disabled", "No TCMalloc, optimised runtime", @@ -109,6 +113,10 @@ jobs: env: SOLVERS: STP STP_VERSION: master + # Test just using Bitwuzla only + - name: "Bitwuzla only" + env: + SOLVERS: BITWUZLA # Check we can build latest klee-uclibc branch - name: "Latest klee-uclibc" env: @@ -137,6 +145,7 @@ jobs: macOS: runs-on: macos-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} env: BASE: /tmp SOLVERS: STP @@ -157,6 +166,7 @@ jobs: Docker: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout KLEE Code uses: actions/checkout@v3 @@ -167,11 +177,13 @@ jobs: Coverage: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} strategy: matrix: name: [ "STP", "Z3", + "Bitwuzla", ] include: - name: "STP" @@ -180,6 +192,9 @@ jobs: - name: "Z3" env: SOLVERS: Z3:STP + - name: "Bitwuzla" + env: + SOLVERS: BITWUZLA:Z3 env: ENABLE_OPTIMIZED: 0 COVERAGE: 1 @@ -198,14 +213,3 @@ jobs: - name: Run tests env: ${{ matrix.env }} run: scripts/build/run-tests.sh --coverage --upload-coverage --run-docker --debug - - clang-format: - runs-on: ubuntu-latest - steps: - - name: Checkout KLEE Code - uses: actions/checkout@v2 - - name: Run clang-format on KLEE Code - uses: jidicula/clang-format-action@v4.10.2 - with: - clang-format-version: '13' - include-regex: '(^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|((ino|pde|proto|cu))$)|^(include|lib)\/.*\.inc)$' diff --git a/.github/workflows/clang-format.yaml b/.github/workflows/clang-format.yaml new file mode 100644 index 0000000000..12d8135906 --- /dev/null +++ b/.github/workflows/clang-format.yaml @@ -0,0 +1,20 @@ +--- +name: Clang Format + +on: + pull_request: + branches: [main, utbot-main] + push: + branches: [main, utbot-main] + +jobs: + clang-format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: pre-commit/action@v3.0.1 + - uses: pre-commit-ci/lite-action@v1.0.2 + if: always() diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml index 55bba98245..8595473f42 100644 --- a/.github/workflows/differential-shellcheck.yml +++ b/.github/workflows/differential-shellcheck.yml @@ -4,9 +4,9 @@ name: Differential ShellCheck on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] permissions: contents: read diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d21b6002fc..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "json"] - path = json - url = https://github.com/nlohmann/json.git -[submodule "optional"] - path = optional - url = https://github.com/martinmoene/optional-lite.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..be6def773b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +files: '(^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|((ino|pde|proto|cu))$)|^(include|lib)\/.*\.inc)$' + +repos: +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v13.0.1 + hooks: + - id: clang-format diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d853e189..72ef2d30fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,16 +17,16 @@ project(KLEE CXX C) # Project version ############################################################################### set(KLEE_VERSION_MAJOR 3) -set(KLEE_VERSION_MINOR 0-utbot) +set(KLEE_VERSION_MINOR 0) set(KLEE_VERSION "${KLEE_VERSION_MAJOR}.${KLEE_VERSION_MINOR}") # If a patch is needed, we can add KLEE_VERSION_PATCH # set(KLEE_VERSION_PATCH 0) # set(KLEE_VERSION "${KLEE_VERSION_MAJOR}.${KLEE_VERSION_MINOR}.${KLEE_VERSION_PATCH}") -message(STATUS "KLEE version ${KLEE_VERSION}") -set(PACKAGE_STRING "\"KLEE ${KLEE_VERSION}\"") -set(PACKAGE_URL "\"https://klee.github.io\"") +message(STATUS "KLEEF version ${KLEE_VERSION}") +set(PACKAGE_STRING "\"KLEEF ${KLEE_VERSION}\"") +set(PACKAGE_URL "\"https://toolchain-labs.com/projects/kleef.html\"") ################################################################################ # Sanity check - Disallow building in source. @@ -204,14 +204,19 @@ include(${CMAKE_SOURCE_DIR}/cmake/find_stp.cmake) include(${CMAKE_SOURCE_DIR}/cmake/find_z3.cmake) # metaSMT include(${CMAKE_SOURCE_DIR}/cmake/find_metasmt.cmake) +# bitwuzla +include(${CMAKE_SOURCE_DIR}/cmake/find_bitwuzla.cmake) -if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_STP}) AND (NOT ${ENABLE_METASMT})) + +if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_STP}) AND (NOT ${ENABLE_METASMT}) AND (NOT ${ENABLE_BITWUZLA})) message(FATAL_ERROR "No solver was specified. At least one solver is required." "You should enable a solver by passing one of more the following options" " to cmake:\n" "\"-DENABLE_SOLVER_STP=ON\"\n" "\"-DENABLE_SOLVER_Z3=ON\"\n" - "\"-DENABLE_SOLVER_METASMT=ON\"") + "\"-DENABLE_SOLVER_BITWUZLA=ON\"\n" + "\"-DENABLE_SOLVER_METASMT=ON\" + ") endif() ############################################################################### @@ -473,10 +478,10 @@ endif() ################################################################################ option(ENABLE_FLOATING_POINT "Enable KLEE's floating point extension" OFF) if (ENABLE_FLOATING_POINT) - if (NOT ${ENABLE_Z3}) + if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_BITWUZLA})) message (FATAL_ERROR "Floating point extension is availible only when using Z3 backend." - "You should enable Z3 by passing the following option to cmake:\n" - "\"-DENABLE_SOLVER_Z3=ON\"\n") + "You should enable either Z3 or Bitwuzla by passing the following options to cmake, respectively:\n" + "\"-DENABLE_SOLVER_Z3=ON\" or \"-DENABLE_SOLVER_BITWUZLA=ON\"\n") else() set(ENABLE_FP 1) # For config.h message(STATUS "Floating point extension enabled") @@ -643,6 +648,12 @@ unset(_flags) configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/config.h.cmin ${CMAKE_BINARY_DIR}/include/klee/Config/config.h) +################################################################################ +# Generate `klee/klee.h` and `klee-test-comp.c` +################################################################################ +configure_file(${CMAKE_SOURCE_DIR}/include/klee/klee.h ${CMAKE_BINARY_DIR}/include/klee/klee.h COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/include/klee-test-comp.c ${CMAKE_BINARY_DIR}/include/klee-test-comp.c COPYONLY) + ################################################################################ # Generate `CompileTimeInfo.h` ################################################################################ @@ -667,8 +678,7 @@ configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/CompileTimeInfo.h.cmin ################################################################################ include_directories("${CMAKE_BINARY_DIR}/include") include_directories("${CMAKE_SOURCE_DIR}/include") -include_directories("${CMAKE_SOURCE_DIR}/json/include") -include_directories("${CMAKE_SOURCE_DIR}/optional/include") +include_directories("${JSON_SRC_DIR}/include") # set(KLEE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include) ################################################################################ diff --git a/Dockerfile b/Dockerfile index d345ff5c63..52fc4fc719 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ ENV Z3_VERSION=4.8.15 ENV USE_LIBCXX=1 ENV KLEE_RUNTIME_BUILD="Debug+Asserts" ENV SQLITE_VERSION=3400100 +ENV JSON_VERSION=v3.11.3 LABEL maintainer="KLEE Developers" # TODO remove adding sudo package diff --git a/README.md b/README.md index 9aefd2c9bf..b1577b18b3 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,9 @@ -KLEE Symbolic Virtual Machine +KLEEF Symbolic Virtual Machine ============================= -[![Build Status](https://github.com/klee/klee/workflows/CI/badge.svg)](https://github.com/klee/klee/actions?query=workflow%3ACI) -[![Build Status](https://api.cirrus-ci.com/github/klee/klee.svg)](https://cirrus-ci.com/github/klee/klee) -[![Coverage](https://codecov.io/gh/klee/klee/branch/master/graph/badge.svg)](https://codecov.io/gh/klee/klee) +[![Build Status](https://github.com/UnitTestBot/klee/workflows/CI/badge.svg)](https://github.com/UnitTestBot/klee/actions?query=workflow%3ACI) +[![Coverage](https://codecov.io/gh/UnitTestBot/klee/branch/main/graph/badge.svg)](https://codecov.io/gh/UnitTestBot/klee) -`KLEE` is a symbolic virtual machine built on top of the LLVM compiler -infrastructure. Currently, there are two primary components: +`KLEEF` is a complete overhaul of the KLEE symbolic execution engine for LLVM, fine-tuned for a robust analysis of industrial C/C++ code. - 1. The core symbolic virtual machine engine; this is responsible for - executing LLVM bitcode modules with support for symbolic - values. This is comprised of the code in lib/. - - 2. A POSIX/Linux emulation layer oriented towards supporting uClibc, - with additional support for making parts of the operating system - environment symbolic. - -Additionally, there is a simple library for replaying computed inputs -on native code (for closed programs). There is also a more complicated -infrastructure for replaying the inputs generated for the POSIX/Linux -emulation layer, which handles running native programs in an -environment that matches a computed test input, including setting up -files, pipes, environment variables, and passing command line -arguments. - -For further information, see the [webpage](http://klee.github.io/). +For further information, see the [webpage](https://toolchain-labs.com/projects/kleef.html). diff --git a/build.sh b/build.sh index 7d575dad08..6878b06a10 100755 --- a/build.sh +++ b/build.sh @@ -29,24 +29,30 @@ SQLITE_VERSION="3400100" ## LLVM Required options LLVM_VERSION=14 ENABLE_OPTIMIZED=1 -ENABLE_DEBUG=1 +ENABLE_DEBUG=0 DISABLE_ASSERTIONS=1 REQUIRES_RTTI=1 ## Solvers Required options # SOLVERS=STP -SOLVERS=STP:Z3 +SOLVERS=BITWUZLA:Z3:STP ## Google Test Required options GTEST_VERSION=1.11.0 +## json options +JSON_VERSION=v3.11.3 + ## UClibC Required options UCLIBC_VERSION=klee_uclibc_v1.3 # LLVM_VERSION is also required for UClibC ## Z3 Required options Z3_VERSION=4.8.15 + STP_VERSION=2.3.3 MINISAT_VERSION=master -BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION SQLITE_VERSION=$SQLITE_VERSION ./scripts/build/build.sh klee --install-system-deps +BITWUZLA_VERSION=0.3.1 + +BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION SQLITE_VERSION=$SQLITE_VERSION JSON_VERSION=$JSON_VERSION ./scripts/build/build.sh klee --install-system-deps diff --git a/cmake/find_bitwuzla.cmake b/cmake/find_bitwuzla.cmake new file mode 100644 index 0000000000..82e9866dcc --- /dev/null +++ b/cmake/find_bitwuzla.cmake @@ -0,0 +1,46 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +find_package (PkgConfig REQUIRED) +pkg_check_modules(BITWUZLA IMPORTED_TARGET bitwuzla) + +# Set the default so that if the following is true: +# * Bitwuzla was found +# * ENABLE_SOLVER_BITWUZLA is not already set as a cache variable +# +# then the default is set to `ON`. Otherwise set the default to `OFF`. +# A consequence of this is if we fail to detect Bitwuzla the first time +# subsequent calls to CMake will not change the default. + +if(BITWUZLA_FOUND) + set(ENABLE_SOLVER_BITWUZLA_DEFAULT ON) +else() + set(ENABLE_SOLVER_BITWUZLA_DEFAULT OFF) +endif() + +option(ENABLE_SOLVER_BITWUZLA "Enable Bitwuzla solver support" ${ENABLE_SOLVER_BITWUZLA_DEFAULT}) + +if (ENABLE_SOLVER_BITWUZLA) + message(STATUS "Bitwuzla solver support enabled") + if (BITWUZLA_FOUND) + message(STATUS "Found Bitwuzla") + set(ENABLE_BITWUZLA 1) # For config.h + + list(APPEND KLEE_COMPONENT_EXTRA_INCLUDE_DIRS ${BITWUZLA_INCLUDE_DIRS}) + list(APPEND KLEE_SOLVER_LIBRARIES ${BITWUZLA_LINK_LIBRARIES}) + list(APPEND KLEE_SOLVER_INCLUDE_DIRS ${BITWUZLA_INCLUDE_DIRS}) + list(APPEND KLEE_SOLVER_LIBRARY_DIRS ${BITWUZLA_LINK_LIBRARIES}) + + else() + message(FATAL_ERROR "Bitwuzla not found.") + endif() +else() + message(STATUS "Bitwuzla solver support disabled") + set(ENABLE_BITWUZLA 0) # For config.h +endif() diff --git a/configs/annotations.json b/configs/annotations.json new file mode 100644 index 0000000000..685f60c2a6 --- /dev/null +++ b/configs/annotations.json @@ -0,0 +1,2027 @@ +{ + "atof": { + "name": "atof", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "atoi": { + "name": "atoi", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "atol": { + "name": "atol", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "atoll": { + "name": "atoll", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "bcmp": { + "name": "bcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "calloc": { + "name": "calloc", + "annotation": [ + [ + "AllocSource::1", + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "fclose": { + "name": "fclose", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fcvt": { + "name": "fcvt", + "annotation": [ + [], + [], + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "feof": { + "name": "feof", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "ferror": { + "name": "ferror", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetc": { + "name": "fgetc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetpos": { + "name": "fgetpos", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetpos64": { + "name": "fgetpos64", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgets": { + "name": "fgets", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetwc": { + "name": "fgetwc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetws": { + "name": "fgetws", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fileno": { + "name": "fileno", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fopen": { + "name": "fopen", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "fopen64": { + "name": "fopen64", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "fopen_s": { + "name": "fopen_s", + "annotation": [ + [], + [ + "InitNull:*:!=0" + ], + [], + [ + "FreeSink::4" + ] + ], + "properties": [] + }, + "fprintf": { + "name": "fprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fputc": { + "name": "fputc", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fputs": { + "name": "fputs", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fputwc": { + "name": "fputwc", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fputws": { + "name": "fputws", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fread": { + "name": "fread", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "free": { + "name": "free", + "annotation": [ + [], + [ + "FreeSink::1" + ] + ], + "properties": [] + }, + "freopen": { + "name": "freopen", + "annotation": [ + [ + "InitNull" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "freopen64": { + "name": "freopen64", + "annotation": [ + [ + "InitNull" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "freopen_s": { + "name": "freopen_s", + "annotation": [ + [], + [ + "InitNull:*:!=0" + ], + [], + [], + [ + "FreeSink::4" + ] + ], + "properties": [] + }, + "fscanf": { + "name": "fscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fscanf_s": { + "name": "fscanf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fseek": { + "name": "fseek", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fsetpos": { + "name": "fsetpos", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fsetpos64": { + "name": "fsetpos64", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "ftell": { + "name": "ftell", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fwide": { + "name": "fwide", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "fwprintf": { + "name": "fwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fwrite": { + "name": "fwrite", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fwscanf": { + "name": "fwscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "getc": { + "name": "getc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "getenv": { + "name": "getenv", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "getenv_s": { + "name": "getenv_s", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "gets": { + "name": "gets", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "gets_s": { + "name": "gets_s", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "getw": { + "name": "getw", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "getwc": { + "name": "getwc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "itoa": { + "name": "itoa", + "annotation": [ + [], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "localtime": { + "name": "localtime", + "annotation": [ + [ + "InitNull::Must" + ], + [] + ], + "properties": [] + }, + "malloc": { + "name": "malloc", + "annotation": [ + [ + "AllocSource::1", + "InitNull" + ], + [] + ], + "properties": [] + }, + "memccpy": { + "name": "memccpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memchr": { + "name": "memchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memcmp": { + "name": "memcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memcpy": { + "name": "memcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memcpy_s": { + "name": "memcpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memicmp": { + "name": "memicmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memmem": { + "name": "memmem", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memmove": { + "name": "memmove", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memmove_s": { + "name": "memmove_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "mempcpy": { + "name": "mempcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memset": { + "name": "memset", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memset_s": { + "name": "memset_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "pthread_mutex_lock": { + "name": "pthread_mutex_lock", + "annotation": [ + [], + [ + "InitNull::!=0" + ] + ], + "properties": [] + }, + "pthread_mutex_trylock": { + "name": "pthread_mutex_trylock", + "annotation": [ + [], + [ + "InitNull::!=0" + ] + ], + "properties": [] + }, + "putc": { + "name": "putc", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "puts": { + "name": "puts", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "qsort": { + "name": "qsort", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "rawmemchr": { + "name": "rawmemchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "realloc": { + "name": "realloc", + "annotation": [ + [ + "AllocSource::1", + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "setbuf": { + "name": "setbuf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "setlocale": { + "name": "setlocale", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "snprintf": { + "name": "snprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "snprintf_s": { + "name": "snprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "snwprintf": { + "name": "snwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "sprintf": { + "name": "sprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "sprintf_s": { + "name": "sprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "sscanf": { + "name": "sscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "sscanf_s": { + "name": "sscanf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "std::from_chars": { + "name": "std::from_chars", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "std::to_chars": { + "name": "std::to_chars", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "stpcpy": { + "name": "stpcpy", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strcat": { + "name": "strcat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strcat_s": { + "name": "strcat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strchr": { + "name": "strchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strchrnul": { + "name": "strchrnul", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strcmp": { + "name": "strcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strcpy": { + "name": "strcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strcpy_s": { + "name": "strcpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strdup": { + "name": "strdup", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strlen": { + "name": "strlen", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strncasecmp": { + "name": "strncasecmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncat": { + "name": "strncat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncat_s": { + "name": "strncat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncmp": { + "name": "strncmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncpy": { + "name": "strncpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncpy_s": { + "name": "strncpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strndup": { + "name": "strndup", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strnlen": { + "name": "strnlen", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strnset": { + "name": "strnset", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strpbrk": { + "name": "strpbrk", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strrchr": { + "name": "strrchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strset": { + "name": "strset", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strspn": { + "name": "strspn", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strstr": { + "name": "strstr", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "strtod": { + "name": "strtod", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strtol": { + "name": "strtol", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strtold": { + "name": "strtold", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strtoll": { + "name": "strtoll", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strtoul": { + "name": "strtoul", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strtoull": { + "name": "strtoull", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strxfrm": { + "name": "strxfrm", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "swprintf": { + "name": "swprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "swprintf_s": { + "name": "swprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "swscanf": { + "name": "swscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "swscanf_s": { + "name": "swscanf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "tmpnam": { + "name": "tmpnam", + "annotation": [ + [ + "InitNull" + ], + [] + ], + "properties": [] + }, + "vfprintf_s": { + "name": "vfprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vfscanf": { + "name": "vfscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vfwprintf": { + "name": "vfwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "vfwprintf_s": { + "name": "vfwprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vfwscanf": { + "name": "vfwscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vsnprintf_s": { + "name": "vsnprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "vsnwprintf": { + "name": "vsnwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vsprintf": { + "name": "vsprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "vsprintf_s": { + "name": "vsprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vsscanf": { + "name": "vsscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "vswscanf": { + "name": "vswscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscat": { + "name": "wcscat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscat_s": { + "name": "wcscat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcschr": { + "name": "wcschr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcschrnul": { + "name": "wcschrnul", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcscmp": { + "name": "wcscmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscoll": { + "name": "wcscoll", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscpy": { + "name": "wcscpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscpy_s": { + "name": "wcscpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscspn": { + "name": "wcscspn", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsftime": { + "name": "wcsftime", + "annotation": [ + [], + [], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsncasecmp": { + "name": "wcsncasecmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncat": { + "name": "wcsncat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncat_s": { + "name": "wcsncat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncmp": { + "name": "wcsncmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncpy": { + "name": "wcsncpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncpy_s": { + "name": "wcsncpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcspbrk": { + "name": "wcspbrk", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsrchr": { + "name": "wcsrchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsspn": { + "name": "wcsspn", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsstr": { + "name": "wcsstr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcstol": { + "name": "wcstol", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcstold": { + "name": "wcstold", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcstoll": { + "name": "wcstoll", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcstoul": { + "name": "wcstoul", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcstoull": { + "name": "wcstoull", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcsxfrm": { + "name": "wcsxfrm", + "annotation": [ + [], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wctrans": { + "name": "wctrans", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wctype": { + "name": "wctype", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wmemchr": { + "name": "wmemchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wmemcmp": { + "name": "wmemcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemcpy": { + "name": "wmemcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemcpy_s": { + "name": "wmemcpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemmove": { + "name": "wmemmove", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemmove_s": { + "name": "wmemmove_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmempcpy": { + "name": "wmempcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + } +} diff --git a/configs/options.json b/configs/options.json index 32f20ebbf7..e89988448a 100644 --- a/configs/options.json +++ b/configs/options.json @@ -18,13 +18,13 @@ "program": "${buildPath}/bin/klee", "args": [ "--use-guided-search=error", - "--mock-external-calls", "--posix-runtime", "--check-out-of-memory", "--suppress-external-warnings", "--libc=klee", "--skip-not-lazy-initialized", "--external-calls=all", + "--mock-policy=all", "--output-source=false", "--output-istats=false", "--output-stats=false", @@ -32,7 +32,6 @@ "--max-sym-alloc=${maxSymAlloc}", "--max-forks=${maxForks}", "--max-solver-time=${maxSolverTime}s", - "--mock-all-externals", "--smart-resolve-entry-function", "--extern-calls-can-return-null", "--align-symbolic-pointers=false", @@ -49,4 +48,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index ecda66ba02..3013b7d669 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// +#include #ifdef EXTERNAL #include "klee.h" #include #include -#include #include #else void klee_make_symbolic(void *addr, unsigned int nbytes, const char *name); @@ -19,20 +19,43 @@ void klee_assume(_Bool condition); __attribute__((noreturn)) void klee_silent_exit(int status); void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function); +void klee_prefer_cex(void *, uintptr_t); +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) +#include + +extern void abort(void); +void __assert_fail(const char *failedexpr, const char *file, unsigned int line, + const char *fn) { + warnx("assertion \"%s\" failed: file \"%s\", line %u%s%s%s", failedexpr, file, + line, fn ? ", function: \"" : "", fn ? fn : "", fn ? "\"" : ""); + abort(); +} #endif int __VERIFIER_nondet_int(void) { int x; klee_make_symbolic(&x, sizeof(x), "int"); + klee_prefer_cex(&x, x < 1024); return x; } unsigned int __VERIFIER_nondet_uint(void) { unsigned int x; klee_make_symbolic(&x, sizeof(x), "unsigned int"); + klee_prefer_cex(&x, x < 1024); return x; } +#ifdef __x86_64__ +unsigned __int128 __VERIFIER_nondet_uint128(void) { + unsigned __int128 x; + klee_make_symbolic(&x, sizeof(x), "unsigned __int128"); + return x; +} +#endif + unsigned __VERIFIER_nondet_unsigned(void) { unsigned x; klee_make_symbolic(&x, sizeof(x), "unsigned"); @@ -87,6 +110,7 @@ double __VERIFIER_nondet_double(void) { return x; } +/* void *__VERIFIER_nondet_pointer(void) { int size = 1024; char *obj = (char *)calloc(1, size); @@ -94,6 +118,7 @@ void *__VERIFIER_nondet_pointer(void) { return obj; } +*/ float __VERIFIER_nondet_float(void) { float x; diff --git a/include/klee/ADT/DisjointSetUnion.h b/include/klee/ADT/DisjointSetUnion.h index b479ca0765..9a3673af64 100644 --- a/include/klee/ADT/DisjointSetUnion.h +++ b/include/klee/ADT/DisjointSetUnion.h @@ -21,24 +21,32 @@ DISABLE_WARNING_POP #include namespace klee { -using ExprEitherSymcrete = either; +using ExprOrSymcrete = either; template , + typename PRED = std::equal_to, typename CMP = std::less> class DisjointSetUnion { +public: + using internal_storage_ty = std::unordered_set; + using disjoint_sets_ty = + std::unordered_map, HASH, PRED>; + using iterator = typename internal_storage_ty::iterator; + protected: - PersistentMap parent; - PersistentSet roots; - PersistentMap rank; + std::unordered_map parent; + std::set roots; + std::unordered_map rank; - PersistentSet internalStorage; - PersistentMap, CMP> disjointSets; + std::unordered_set internalStorage; + std::unordered_map, HASH, PRED> disjointSets; ValueType find(const ValueType &v) { // findparent assert(parent.find(v) != parent.end()); if (v == parent.at(v)) return v; - parent.replace({v, find(parent.at(v))}); + parent.insert_or_assign(v, find(parent.at(v))); return parent.at(v); } @@ -60,15 +68,15 @@ class DisjointSetUnion { if (rank.at(a) < rank.at(b)) { std::swap(a, b); } - parent.replace({b, a}); + parent.insert_or_assign(b, a); if (rank.at(a) == rank.at(b)) { - rank.replace({a, rank.at(a) + 1}); + rank.insert_or_assign(a, rank.at(a) + 1); } - roots.remove(b); - disjointSets.replace( - {a, SetType::merge(disjointSets.at(a), disjointSets.at(b))}); - disjointSets.remove(b); + roots.erase(b); + disjointSets.insert_or_assign( + a, SetType::merge(disjointSets.at(a), disjointSets.at(b))); + disjointSets.erase(b); } bool areJoined(const ValueType &i, const ValueType &j) const { @@ -76,10 +84,6 @@ class DisjointSetUnion { } public: - using internalStorage_ty = PersistentSet; - using disjointSets_ty = ImmutableMap, CMP>; - using iterator = typename internalStorage_ty::iterator; - iterator begin() const { return internalStorage.begin(); } iterator end() const { return internalStorage.end(); } @@ -107,7 +111,7 @@ class DisjointSetUnion { disjointSets.insert({value, new SetType(value)}); internalStorage.insert(value); - internalStorage_ty oldRoots = roots; + std::set oldRoots = roots; for (ValueType v : oldRoots) { if (!areJoined(v, value) && SetType::intersects(disjointSets.at(find(v)), @@ -122,8 +126,8 @@ class DisjointSetUnion { } void add(const DisjointSetUnion &b) { - internalStorage_ty oldRoots = roots; - internalStorage_ty newRoots = b.roots; + std::set oldRoots = roots; + std::set newRoots = b.roots; for (auto it : b.parent) { parent.insert(it); } @@ -152,16 +156,16 @@ class DisjointSetUnion { DisjointSetUnion() {} - DisjointSetUnion(const internalStorage_ty &is) { + DisjointSetUnion(const internal_storage_ty &is) { for (ValueType v : is) { addValue(v); } } public: - internalStorage_ty is() const { return internalStorage; } + internal_storage_ty is() const { return internalStorage; } - disjointSets_ty ds() const { return disjointSets; } + disjoint_sets_ty ds() const { return disjointSets; } }; } // namespace klee diff --git a/include/klee/ADT/Either.h b/include/klee/ADT/Either.h index cc01bf761e..c941d33103 100644 --- a/include/klee/ADT/Either.h +++ b/include/klee/ADT/Either.h @@ -32,6 +32,9 @@ template class either { /// @brief Required by klee::ref-managed objects class ReferenceCounter _refCount; + unsigned hashValue; + + static const unsigned MAGIC_HASH_CONSTANT = 39; public: using left = either_left; @@ -43,9 +46,10 @@ template class either { virtual EitherKind getKind() const = 0; static bool classof(const either *) { return true; } - // virtual unsigned hash() = 0; virtual int compare(const either &b) = 0; virtual bool equals(const either &b) = 0; + + unsigned hash() const { return hashValue; } }; template class either_left : public either { @@ -56,8 +60,15 @@ template class either_left : public either { private: ref value_; + unsigned computeHash() { + unsigned res = (unsigned)getKind(); + res = (res * either::MAGIC_HASH_CONSTANT) + value_->hash(); + either::hashValue = res; + return either::hashValue; + } + public: - either_left(ref leftValue) : value_(leftValue){}; + either_left(ref leftValue) : value_(leftValue) { computeHash(); }; ref value() const { return value_; } operator ref const() { return value_; } @@ -71,7 +82,6 @@ template class either_left : public either { } static bool classof(const either_left *) { return true; } - // virtual unsigned hash() override { return value_->hash(); }; virtual int compare(const either &b) override { if (b.getKind() != getKind()) { return b.getKind() < getKind() ? -1 : 1; @@ -100,8 +110,15 @@ template class either_right : public either { private: ref value_; + unsigned computeHash() { + unsigned res = (unsigned)getKind(); + res = (res * either::MAGIC_HASH_CONSTANT) + value_->hash(); + either::hashValue = res; + return either::hashValue; + } + public: - either_right(ref rightValue) : value_(rightValue){}; + either_right(ref rightValue) : value_(rightValue) { computeHash(); }; ref value() const { return value_; } operator ref const() { return value_; } @@ -115,7 +132,6 @@ template class either_right : public either { } static bool classof(const either_right *) { return true; } - // virtual unsigned hash() override { return value_->hash(); }; virtual int compare(const either &b) override { if (b.getKind() != getKind()) { return b.getKind() < getKind() ? -1 : 1; diff --git a/include/klee/ADT/ImmutableList.h b/include/klee/ADT/ImmutableList.h new file mode 100644 index 0000000000..73ce89f448 --- /dev/null +++ b/include/klee/ADT/ImmutableList.h @@ -0,0 +1,116 @@ +//===---- ImmutableList.h ---------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_IMMUTABLELIST_H +#define KLEE_IMMUTABLELIST_H + +#include +#include +#include + +namespace klee { + +template class ImmutableList { + struct ImmutableListNode { + std::shared_ptr prev; + const size_t prev_len; + std::vector values; + + [[nodiscard]] size_t size() const { return prev_len + values.size(); } + + ImmutableListNode() : prev(nullptr), prev_len(0), values() {} + + explicit ImmutableListNode(const ImmutableList &il) + : prev_len(il.size()), values() { + std::shared_ptr pr = il.node; + while (pr && pr->values.empty()) { + pr = pr->prev; + } + if (pr && pr->size()) { + prev = pr; + } else { + prev = nullptr; + } + } + }; + + std::shared_ptr node; + +public: + [[nodiscard]] size_t size() const { return node ? node->size() : 0; } + + struct iterator { + const ImmutableListNode *rootNode; + size_t get; + + public: + explicit iterator(const ImmutableListNode *p) : rootNode(p), get(0) {} + + bool operator==(const iterator &b) const { + return rootNode == b.rootNode && get == b.get; + } + + bool operator!=(const iterator &b) const { return !(*this == b); } + + iterator &operator++() { + ++get; + return *this; + } + + const T &operator*() const { + assert(get < rootNode->size() && "Out of bound"); + const ImmutableListNode *curNode = rootNode; + while (get < curNode->prev_len) { + curNode = curNode->prev.get(); + } + return curNode->values[get - curNode->prev_len]; + } + + const T &operator->() const { return **this; } + }; + + [[nodiscard]] iterator begin() const { return iterator(node.get()); } + + [[nodiscard]] iterator end() const { + auto it = iterator(node.get()); + it.get = size(); + return it; + } + + void push_back(T &&value) { + if (!node) { + node = std::make_shared(); + } + node->values.push_back(std::move(value)); + } + + void push_back(const T &value) { + if (!node) { + node = std::make_shared(); + } + node->values.push_back(value); + } + + bool empty() { return size() == 0; } + + const T &back() { + assert(node && "requiers not empty list"); + auto it = iterator(node.get()); + it.get = size() - 1; + return *it; + } + + ImmutableList() : node(){}; + ImmutableList(const ImmutableList &il) + : node(std::make_shared(il)) {} +}; + +} // namespace klee + +#endif /* KLEE_IMMUTABLELIST_H */ diff --git a/include/klee/ADT/Incremental.h b/include/klee/ADT/Incremental.h index 6f16fd0867..d5a77defa8 100644 --- a/include/klee/ADT/Incremental.h +++ b/include/klee/ADT/Incremental.h @@ -192,7 +192,7 @@ class inc_uset { } }; - using idMap = std::unordered_map<_Value, MinFrameIds, _Hash, _Pred, _Alloc>; + using idMap = std::unordered_map<_Value, MinFrameIds, _Hash, _Pred>; using citerator = typename idMap::const_iterator; idMap ids; FrameId current_frame = 0; @@ -302,7 +302,7 @@ template , class inc_umap { private: std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> map; - using idMap = std::unordered_map<_Key, FrameIds, _Hash, _Pred, _Alloc>; + using idMap = std::unordered_map<_Key, FrameIds, _Hash, _Pred>; idMap ids; FrameId current_frame = 0; diff --git a/include/klee/ADT/KTest.h b/include/klee/ADT/KTest.h index 66c68c3417..d4c08d640d 100644 --- a/include/klee/ADT/KTest.h +++ b/include/klee/ADT/KTest.h @@ -46,6 +46,7 @@ struct KTest { unsigned numObjects; KTestObject *objects; + unsigned uninitCoeff; }; /* returns the current .ktest file format version */ diff --git a/include/klee/ADT/Ref.h b/include/klee/ADT/Ref.h index 008580cc7e..eb082c2065 100644 --- a/include/klee/ADT/Ref.h +++ b/include/klee/ADT/Ref.h @@ -215,6 +215,19 @@ template class ref { bool operator!=(const ref &rhs) const { return !equals(rhs); } }; +template class OptionalRefEq { +public: + bool operator()(const ref &lhs, const ref &rhs) { + if (lhs.isNull() && rhs.isNull()) { + return true; + } + if (lhs.isNull() || rhs.isNull()) { + return false; + } + return lhs.get()->equals(*rhs.get()); + } +}; + template inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ref &e) { os << *e; diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index 84170600da..a78df85770 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -3,67 +3,56 @@ #include #include +#include #include #include +#include #include +namespace llvm { +class raw_ostream; +}; + namespace klee { -template class SparseStorage { +enum class Density { + Sparse, + Dense, +}; + +template > +class SparseStorage { private: - size_t capacity; - std::map internalStorage; + std::unordered_map internalStorage; ValueType defaultValue; + Eq eq; bool contains(size_t key) const { return internalStorage.count(key) != 0; } public: - struct Iterator { - using iterator_category = std::input_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = ValueType; - using pointer = ValueType *; - using reference = ValueType &; - - private: - size_t idx; - const SparseStorage *owner; - - public: - Iterator(size_t idx, const SparseStorage *owner) : idx(idx), owner(owner) {} - - value_type operator*() const { return owner->load(idx); } - - Iterator &operator++() { - ++idx; - return *this; - } - - Iterator operator++(int) { - Iterator snap = *this; - ++(*this); - return snap; + SparseStorage(const ValueType &defaultValue = ValueType()) + : defaultValue(defaultValue) {} + + SparseStorage(const std::unordered_map &internalStorage, + const ValueType &defaultValue) + : defaultValue(defaultValue) { + for (auto &[index, value] : internalStorage) { + store(index, value); } - - bool operator==(const Iterator &other) const { return idx == other.idx; } - - bool operator!=(const Iterator &other) const { return !(*this == other); } - }; - - SparseStorage(size_t capacity = 0, - const ValueType &defaultValue = ValueType()) - : capacity(capacity), defaultValue(defaultValue) {} + } SparseStorage(const std::vector &values, const ValueType &defaultValue = ValueType()) - : capacity(values.capacity()), defaultValue(defaultValue) { - for (size_t idx = 0; idx < values.capacity(); ++idx) { - internalStorage[idx] = values[idx]; + : defaultValue(defaultValue) { + for (size_t idx = 0; idx < values.size(); ++idx) { + store(idx, values[idx]); } } void store(size_t idx, const ValueType &value) { - if (idx < capacity) { + if (eq(value, defaultValue)) { + internalStorage.erase(idx); + } else { internalStorage[idx] = value; } } @@ -77,32 +66,20 @@ template class SparseStorage { } ValueType load(size_t idx) const { - assert(idx < capacity && idx >= 0); - return contains(idx) ? internalStorage.at(idx) : defaultValue; + auto it = internalStorage.find(idx); + return it != internalStorage.end() ? it->second : defaultValue; } - size_t size() const { return capacity; } - - void resize(size_t newCapacity) { - assert(newCapacity >= 0); - // Free to extend - if (newCapacity >= capacity) { - capacity = newCapacity; - return; - } - - // Truncate unnessecary elements - auto iterOnNewSize = internalStorage.lower_bound(newCapacity); - while (iterOnNewSize != internalStorage.end()) { - iterOnNewSize = internalStorage.erase(iterOnNewSize); + size_t sizeOfSetRange() const { + size_t sizeOfRange = 0; + for (auto i : internalStorage) { + sizeOfRange = std::max(i.first, sizeOfRange); } - - capacity = newCapacity; + return internalStorage.empty() ? 0 : sizeOfRange + 1; } bool operator==(const SparseStorage &another) const { - return size() == another.size() && defaultValue == another.defaultValue && - internalStorage == another.internalStorage; + return eq(defaultValue, another.defaultValue) && compare(another) == 0; } bool operator!=(const SparseStorage &another) const { @@ -110,22 +87,61 @@ template class SparseStorage { } bool operator<(const SparseStorage &another) const { - return internalStorage < another.internalStorage; + return compare(another) == -1; } bool operator>(const SparseStorage &another) const { - return internalStorage > another.internalStorage; + return compare(another) == 1; + } + + int compare(const SparseStorage &other) const { + auto ordered = calculateOrderedStorage(); + auto otherOrdered = other.calculateOrderedStorage(); + + if (ordered == otherOrdered) { + return 0; + } else { + return ordered < otherOrdered ? -1 : 1; + } + } + + std::map calculateOrderedStorage() const { + std::map ordered; + for (const auto &i : internalStorage) { + ordered.insert(i); + } + return ordered; + } + + std::vector getFirstNIndexes(size_t n) const { + std::vector vectorized(n); + for (size_t i = 0; i < n; i++) { + vectorized[i] = load(i); + } + return vectorized; + } + + const std::unordered_map &storage() const { + return internalStorage; + }; + + const ValueType &defaultV() const { return defaultValue; }; + + void reset() { internalStorage.clear(); } + + void reset(ValueType newDefault) { + defaultValue = newDefault; + reset(); } - Iterator begin() const { return Iterator(0, this); } - Iterator end() const { return Iterator(size(), this); } + void print(llvm::raw_ostream &os, Density) const; }; template SparseStorage sparseBytesFromValue(const U &value) { const unsigned char *valueUnsignedCharIterator = reinterpret_cast(&value); - SparseStorage result(sizeof(value)); + SparseStorage result; result.store(0, valueUnsignedCharIterator, valueUnsignedCharIterator + sizeof(value)); return result; diff --git a/include/klee/Config/config.h.cmin b/include/klee/Config/config.h.cmin index 91dbaf6868..1d3f1ac6dd 100644 --- a/include/klee/Config/config.h.cmin +++ b/include/klee/Config/config.h.cmin @@ -13,6 +13,9 @@ /* Using Z3 Solver backend */ #cmakedefine ENABLE_Z3 @ENABLE_Z3@ +/* Using Bitwuzla Solver backend */ +#cmakedefine ENABLE_BITWUZLA @ENABLE_BITWUZLA@ + /* Enable KLEE floating point extension */ #cmakedefine ENABLE_FP @ENABLE_FP@ diff --git a/include/klee/Core/Context.h b/include/klee/Core/Context.h index 64f209baaa..57a9a0f706 100644 --- a/include/klee/Core/Context.h +++ b/include/klee/Core/Context.h @@ -40,6 +40,10 @@ class Context { /// Returns width of the pointer in bits Expr::Width getPointerWidth() const { return PointerWidth; } + + Expr::ByteWidth getPointerWidthInBytes() const { + return (PointerWidth + CHAR_BIT - 1) / CHAR_BIT; + } }; } // namespace klee diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 6c7ff2f878..04eec908de 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -10,21 +10,19 @@ #define KLEE_INTERPRETER_H #include "TerminationTypes.h" +#include "klee/Module/Annotation.h" #include "klee/Module/SarifReport.h" #include #include #include +#include #include #include #include #include -#include - -using nonstd::optional; - struct KTest; namespace llvm { @@ -32,6 +30,7 @@ class BasicBlock; class Function; class LLVMContext; class Module; +class Type; class raw_ostream; class raw_fd_ostream; } // namespace llvm @@ -41,7 +40,6 @@ class ExecutionState; struct SarifReport; class Interpreter; class TreeStreamWriter; -class InstructionInfoTable; class InterpreterHandler { public: @@ -61,6 +59,29 @@ class InterpreterHandler { const char *suffix, bool isError = false) = 0; }; +/// [File][Line][Column] -> Opcode +using FLCtoOpcode = std::unordered_map< + std::string, + std::unordered_map< + unsigned, std::unordered_map>>>; + +enum class MockStrategyKind { + Naive, // For each function call new symbolic value is generated + Deterministic // Each function is treated as uninterpreted function in SMT. + // Compatible with Z3 solver only +}; + +enum class MockPolicy { + None, // No mock function generated + Failed, // Generate symbolic value for failed external calls + All // Generate IR module with all external values +}; + +enum class MockMutableGlobalsPolicy { + None, // No mock for globals + All, // Mock globals on module build stage and generate bc module for it +}; + class Interpreter { public: enum class GuidanceKind { @@ -77,21 +98,32 @@ class Interpreter { std::string LibraryDir; std::string EntryPoint; std::string OptSuffix; + std::string MainCurrentName; + std::string MainNameAfterMock; + std::string AnnotationsFile; bool Optimize; bool Simplify; bool CheckDivZero; bool CheckOvershift; + bool AnnotateOnlyExternal; bool WithFPRuntime; bool WithPOSIXRuntime; ModuleOptions(const std::string &_LibraryDir, const std::string &_EntryPoint, const std::string &_OptSuffix, - bool _Optimize, bool _Simplify, bool _CheckDivZero, - bool _CheckOvershift, bool _WithFPRuntime, + const std::string &_MainCurrentName, + const std::string &_MainNameAfterMock, + const std::string &_AnnotationsFile, bool _Optimize, + bool _Simplify, bool _CheckDivZero, bool _CheckOvershift, + bool _AnnotateOnlyExternal, bool _WithFPRuntime, bool _WithPOSIXRuntime) : LibraryDir(_LibraryDir), EntryPoint(_EntryPoint), - OptSuffix(_OptSuffix), Optimize(_Optimize), Simplify(_Simplify), - CheckDivZero(_CheckDivZero), CheckOvershift(_CheckOvershift), + OptSuffix(_OptSuffix), MainCurrentName(_MainCurrentName), + MainNameAfterMock(_MainNameAfterMock), + AnnotationsFile(_AnnotationsFile), Optimize(_Optimize), + Simplify(_Simplify), CheckDivZero(_CheckDivZero), + CheckOvershift(_CheckOvershift), + AnnotateOnlyExternal(_AnnotateOnlyExternal), WithFPRuntime(_WithFPRuntime), WithPOSIXRuntime(_WithPOSIXRuntime) {} }; @@ -109,11 +141,16 @@ class Interpreter { /// symbolic execution on concrete programs. unsigned MakeConcreteSymbolic; GuidanceKind Guidance; - nonstd::optional Paths; + std::optional Paths; + MockPolicy Mock; + MockStrategyKind MockStrategy; + MockMutableGlobalsPolicy MockMutableGlobals; - InterpreterOptions(nonstd::optional Paths) + InterpreterOptions(std::optional Paths) : MakeConcreteSymbolic(false), Guidance(GuidanceKind::NoGuidance), - Paths(std::move(Paths)) {} + Paths(std::move(Paths)), Mock(MockPolicy::None), + MockStrategy(MockStrategyKind::Naive), + MockMutableGlobals(MockMutableGlobalsPolicy::None) {} }; protected: @@ -136,13 +173,13 @@ class Interpreter { /// module /// \return The final module after it has been optimized, checks /// inserted, and modified for interpretation. - virtual llvm::Module * - setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) = 0; + virtual llvm::Module *setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals, + std::vector> redefinitions) = 0; // supply a tree stream writer which the interpreter will use // to record the concrete path (as a stream of '0' and '1' bytes). @@ -172,6 +209,8 @@ class Interpreter { virtual void setHaltExecution(HaltExecution::Reason value) = 0; + virtual HaltExecution::Reason getHaltExecution() = 0; + virtual void setInhibitForking(bool value) = 0; virtual void prepareForEarlyExit() = 0; @@ -194,7 +233,7 @@ class Interpreter { virtual void getCoveredLines(const ExecutionState &state, - std::map> &res) = 0; + std::map> &res) = 0; virtual void getBlockPath(const ExecutionState &state, std::string &blockPath) = 0; diff --git a/include/klee/Core/MockBuilder.h b/include/klee/Core/MockBuilder.h new file mode 100644 index 0000000000..da5d0ea198 --- /dev/null +++ b/include/klee/Core/MockBuilder.h @@ -0,0 +1,87 @@ +//===-- MockBuilder.h -------------------------------------------*- C++ -*-===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#ifndef KLEE_MOCKBUILDER_H +#define KLEE_MOCKBUILDER_H + +#include "klee/Core/Interpreter.h" +#include "klee/Module/Annotation.h" + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" + +#include +#include + +namespace klee { + +class MockBuilder { +private: + const llvm::Module *userModule; + llvm::LLVMContext &ctx; + std::unique_ptr mockModule; + std::unique_ptr> builder; + + const Interpreter::ModuleOptions &opts; + const Interpreter::InterpreterOptions &interpreterOptions; + + std::set ignoredExternals; + std::vector> redefinitions; + + InterpreterHandler *interpreterHandler; + + std::set &mainModuleFunctions; + std::set &mainModuleGlobals; + + AnnotationsMap annotations; + + void initMockModule(); + void buildMockMain(); + void buildExternalGlobalsDefinitions(); + void buildExternalFunctionsDefinitions(); + void + buildCallKleeMakeSymbolic(const std::string &kleeMakeSymbolicFunctionName, + llvm::Value *source, llvm::Type *type, + const std::string &symbolicName); + + void buildAnnotationForExternalFunctionArgs( + llvm::Function *func, + const std::vector> &statementsNotAllign); + void buildAnnotationForExternalFunctionReturn( + llvm::Function *func, const std::vector &statements); + void buildAnnotationForExternalFunctionProperties( + llvm::Function *func, const std::set &properties); + + std::map getExternalFunctions(); + std::map getExternalGlobals(); + + std::pair + goByOffset(llvm::Value *value, const std::vector &offset); + +public: + MockBuilder(const llvm::Module *initModule, + const Interpreter::ModuleOptions &opts, + const Interpreter::InterpreterOptions &interpreterOptions, + const std::set &ignoredExternals, + std::vector> &redefinitions, + InterpreterHandler *interpreterHandler, + std::set &mainModuleFunctions, + std::set &mainModuleGlobals); + + std::unique_ptr build(); + void buildAllocSource(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr); + void buildFree(llvm::Value *elem, const Statement::Free *freePtr); + void processingValue(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr, + bool initNullPtr); +}; + +} // namespace klee + +#endif // KLEE_MOCKBUILDER_H diff --git a/include/klee/Core/TerminationTypes.h b/include/klee/Core/TerminationTypes.h index 786cf610d6..a08b3585e7 100644 --- a/include/klee/Core/TerminationTypes.h +++ b/include/klee/Core/TerminationTypes.h @@ -97,6 +97,7 @@ enum Reason { CovCheck, NoMoreStates, ReachedTarget, + UnreachedTarget, ErrorOnWhichShouldExit, Interrupt, MaxDepth, diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h new file mode 100644 index 0000000000..cc481f8f69 --- /dev/null +++ b/include/klee/Expr/AlphaBuilder.h @@ -0,0 +1,45 @@ +//===-- AlphaBuilder.h -----------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_ALPHA_BUILDER_H +#define KLEE_ALPHA_BUILDER_H + +#include "klee/Expr/ArrayCache.h" +#include "klee/Expr/ExprHashMap.h" +#include "klee/Expr/ExprVisitor.h" + +namespace klee { + +class AlphaBuilder final : public ExprVisitor { +public: + ExprHashMap> reverseExprMap; + ArrayCache::ArrayHashMap reverseAlphaArrayMap; + ArrayCache::ArrayHashMap alphaArrayMap; + +private: + ArrayCache &arrayCache; + unsigned index = 0; + bool reverse = false; + + const Array *visitArray(const Array *arr); + UpdateList visitUpdateList(UpdateList u); + Action visitRead(const ReadExpr &re) override; + using ExprVisitor::visitExpr; + +public: + AlphaBuilder(ArrayCache &_arrayCache); + constraints_ty visitConstraints(const constraints_ty &cs); + ref build(ref v); + const Array *buildArray(const Array *arr) { return visitArray(arr); } + ref reverseBuild(ref v); +}; + +} // namespace klee + +#endif /*KLEE_ALPHA_BUILDER_H*/ diff --git a/include/klee/Expr/ArrayCache.h b/include/klee/Expr/ArrayCache.h index b46a1caab1..735b3d257b 100644 --- a/include/klee/Expr/ArrayCache.h +++ b/include/klee/Expr/ArrayCache.h @@ -61,10 +61,9 @@ class ArrayCache { klee::EquivArrayCmpFn> ArrayHashSet; ArrayHashSet cachedSymbolicArrays; - typedef std::vector ArrayPtrVec; - ArrayPtrVec concreteArrays; - unsigned getNextID() const; + // Number of arrays of each source allocated + std::unordered_map allocatedCount; }; } // namespace klee diff --git a/include/klee/Expr/Assignment.h b/include/klee/Expr/Assignment.h index 61376ff940..bb86172a60 100644 --- a/include/klee/Expr/Assignment.h +++ b/include/klee/Expr/Assignment.h @@ -25,6 +25,7 @@ class ConstraintSet; typedef std::set, SymcreteLess> SymcreteOrderedSet; using symcretes_ty = SymcreteOrderedSet; +typedef std::function)> ExprPredicate; class Assignment { public: @@ -57,11 +58,14 @@ class Assignment { ref evaluate(ref e, bool allowFreeValues = true) const; constraints_ty createConstraintsFromAssignment() const; + template + bool satisfies(InputIterator begin, InputIterator end, + ExprPredicate predicate, bool allowFreeValues = true); template bool satisfies(InputIterator begin, InputIterator end, bool allowFreeValues = true); template - bool satisfiesNonBoolean(InputIterator begin, InputIterator end, + bool satisfiesOrConstant(InputIterator begin, InputIterator end, bool allowFreeValues = true); void dump() const; @@ -95,8 +99,10 @@ class AssignmentEvaluator : public ExprEvaluator { inline ref Assignment::evaluate(const Array *array, unsigned index, bool allowFreeValues) const { assert(array); + auto sizeExpr = evaluate(array->size); bindings_ty::iterator it = bindings.find(array); - if (it != bindings.end() && index < it->second.size()) { + if (it != bindings.end() && isa(sizeExpr) && + index < cast(sizeExpr)->getZExtValue()) { return ConstantExpr::alloc(it->second.load(index), array->getRange()); } else { if (allowFreeValues) { @@ -113,28 +119,43 @@ inline ref Assignment::evaluate(ref e, bool allowFreeValues) const { return v.visit(e); } +struct isTrueBoolean { + bool operator()(ref e) const { + return e->getWidth() == Expr::Bool && e->isTrue(); + } +}; + +struct isTrueBooleanOrConstantNotBoolean { + bool operator()(ref e) const { + return (e->getWidth() == Expr::Bool && e->isTrue()) || + ((isa(e) && e->getWidth() != Expr::Bool)); + } +}; + template inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + ExprPredicate predicate, bool allowFreeValues) { AssignmentEvaluator v(*this, allowFreeValues); for (; begin != end; ++begin) { - assert((*begin)->getWidth() == Expr::Bool && "constraints must be boolean"); - if (!v.visit(*begin)->isTrue()) + if (!predicate(v.visit(*begin))) return false; } return true; } template -inline bool Assignment::satisfiesNonBoolean(InputIterator begin, +inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + bool allowFreeValues) { + return satisfies(begin, end, isTrueBoolean(), allowFreeValues); +} + +template +inline bool Assignment::satisfiesOrConstant(InputIterator begin, InputIterator end, bool allowFreeValues) { - AssignmentEvaluator v(*this, allowFreeValues); - for (; begin != end; ++begin) { - if (!isa(v.visit(*begin))) - return false; - } - return true; + return satisfies(begin, end, isTrueBooleanOrConstantNotBoolean(), + allowFreeValues); } } // namespace klee diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index d6f47e3d94..3809238a1b 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -12,11 +12,11 @@ #include "klee/ADT/Ref.h" +#include "klee/ADT/PersistentMap.h" #include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" -#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" @@ -42,13 +42,18 @@ class ConstraintSet { const std::vector> &ics); explicit ConstraintSet(constraints_ty cs); explicit ConstraintSet(); + void fork(); void addConstraint(ref e, const Assignment &delta); void addSymcrete(ref s, const Assignment &concretization); bool isSymcretized(ref expr) const; void rewriteConcretization(const Assignment &a); - ConstraintSet withExpr(ref e) const; + ConstraintSet withExpr(ref e) const { + ConstraintSet copy = ConstraintSet(*this); + copy.addConstraint(e, Assignment()); + return copy; + } std::vector gatherArrays() const; std::vector gatherSymcretizedArrays() const; @@ -85,16 +90,18 @@ class ConstraintSet { constraints_ty _constraints; symcretes_ty _symcretes; Assignment _concretization; - IndependentConstraintSetUnion _independentElements; + std::shared_ptr _independentElements; }; class PathConstraints { public: using ordered_constraints_ty = - std::map; + PersistentMap; void advancePath(KInstruction *ki); void advancePath(const Path &path); + void fork(); + ExprHashSet addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex); ExprHashSet addConstraint(ref e, const Assignment &delta); diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index ab6826e25d..c0cf039458 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -138,6 +138,10 @@ class Expr { /// The type of an expression is simply its width, in bits. typedef unsigned Width; + /// Width of an expression in bytes. + /// ByteWidth = (Width + CHAR_BIT - 1) / CHAR_BIT + typedef unsigned ByteWidth; + // NOTE: The prefix "Int" in no way implies the integer type of expression. // For example, Int64 can indicate i64, double or <2 * i32> in different // cases. @@ -260,6 +264,7 @@ class Expr { protected: unsigned hashValue; + unsigned heightValue; /// Compares `b` to `this` Expr and determines how they are ordered /// (ignoring their kid expressions - i.e. those returned by `getKid()`). @@ -291,6 +296,7 @@ class Expr { virtual Kind getKind() const = 0; virtual Width getWidth() const = 0; + ByteWidth getByteWidth() const; virtual unsigned getNumKids() const = 0; virtual ref getKid(unsigned i) const = 0; @@ -303,11 +309,13 @@ class Expr { std::string toString() const; /// Returns the pre-computed hash of the current expression - virtual unsigned hash() const { return hashValue; } + unsigned hash() const { return hashValue; } + unsigned height() const { return heightValue; } /// (Re)computes the hash of the current expression. /// Returns the hash value. virtual unsigned computeHash(); + virtual unsigned computeHeight(); /// Compares `b` to `this` Expr for structural equivalence. /// @@ -412,7 +420,7 @@ struct Expr::CreateArg { // Comparison operators inline bool operator==(const Expr &lhs, const Expr &rhs) { - return lhs.compare(rhs) == 0; + return lhs.equals(rhs); } inline bool operator<(const Expr &lhs, const Expr &rhs) { @@ -522,6 +530,7 @@ class NotOptimizedExpr : public NonConstantExpr { static ref alloc(const ref &src) { ref r(new NotOptimizedExpr(src)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -557,6 +566,7 @@ class UpdateNode { // cache instead of recalc unsigned hashValue; + unsigned heightValue; public: const ref next; @@ -578,11 +588,13 @@ class UpdateNode { int compare(const UpdateNode &b) const; bool equals(const UpdateNode &b) const; unsigned hash() const { return hashValue; } + unsigned height() const { return heightValue; } UpdateNode() = delete; ~UpdateNode() = default; unsigned computeHash(); + unsigned computeHeight(); }; class Array { @@ -629,10 +641,7 @@ class Array { public: bool isSymbolicArray() const { return !isConstantArray(); } - bool isConstantArray() const { - return isa(source) || - isa(source); - } + bool isConstantArray() const { return isa(source); } const std::string getName() const { return source->toString(); } const std::string getIdentifier() const { @@ -677,6 +686,7 @@ class UpdateList { bool operator<(const UpdateList &rhs) const { return compare(rhs) < 0; } unsigned hash() const; + unsigned height() const; }; /// Class representing a one byte read from an array. @@ -693,6 +703,7 @@ class ReadExpr : public NonConstantExpr { static ref alloc(const UpdateList &updates, const ref &index) { ref r(new ReadExpr(updates, index)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -714,6 +725,7 @@ class ReadExpr : public NonConstantExpr { } virtual unsigned computeHash(); + virtual unsigned computeHeight(); private: ReadExpr(const UpdateList &_updates, const ref &_index) @@ -740,12 +752,20 @@ class SelectExpr : public NonConstantExpr { const ref &f) { ref r(new SelectExpr(c, t, f)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(ref c, ref t, ref f); - Width getWidth() const { return trueExpr->getWidth(); } + Width getWidth() const { + if (trueExpr->height() < falseExpr->height()) { + return trueExpr->getWidth(); + } else { + return falseExpr->getWidth(); + } + } + Kind getKind() const { return Select; } unsigned getNumKids() const { return numKids; } @@ -804,6 +824,7 @@ class ConcatExpr : public NonConstantExpr { static ref alloc(const ref &l, const ref &r) { ref c(new ConcatExpr(l, r)); c->computeHash(); + c->computeHeight(); return createCachedExpr(c); } @@ -874,6 +895,7 @@ class ExtractExpr : public NonConstantExpr { static ref alloc(const ref &e, unsigned o, Width w) { ref r(new ExtractExpr(e, o, w)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -924,6 +946,7 @@ class NotExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new NotExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -997,6 +1020,7 @@ class CastExpr : public NonConstantExpr { static ref alloc(const ref &e, Width w) { \ ref r(new _class_kind##Expr(e, w)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, Width w); \ @@ -1030,6 +1054,7 @@ CAST_EXPR_CLASS(FPExt) llvm::APFloat::roundingMode rm) { \ ref r(new _class_kind##Expr(e, w, rm)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, Width w, \ @@ -1076,10 +1101,10 @@ FP_CAST_EXPR_CLASS(SIToFP) static ref alloc(const ref &l, const ref &r) { \ ref res(new _class_kind##Expr(l, r)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ - Width getWidth() const { return left->getWidth(); } \ Kind getKind() const { return _class_kind; } \ virtual ref rebuild(ref kids[]) const { \ return create(kids[0], kids[1]); \ @@ -1089,6 +1114,13 @@ FP_CAST_EXPR_CLASS(SIToFP) return E->getKind() == Expr::_class_kind; \ } \ static bool classof(const _class_kind##Expr *) { return true; } \ + Width getWidth() const { \ + if (left->height() < right->height()) { \ + return left->getWidth(); \ + } else { \ + return right->getWidth(); \ + } \ + } \ \ protected: \ virtual int compareContents(const Expr &b) const { \ @@ -1126,11 +1158,19 @@ ARITHMETIC_EXPR_CLASS(AShr) const llvm::APFloat::roundingMode rm) { \ ref res(new _class_kind##Expr(l, r, rm)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r, \ llvm::APFloat::roundingMode rm); \ - Width getWidth() const { return left->getWidth(); } \ + Width getWidth() const { \ + if (left->height() < right->height()) { \ + return left->getWidth(); \ + } else { \ + return right->getWidth(); \ + } \ + } \ + \ Kind getKind() const { return _class_kind; } \ virtual ref rebuild(ref kids[]) const { \ return create(kids[0], kids[1], roundingMode); \ @@ -1172,6 +1212,7 @@ FLOAT_ARITHMETIC_EXPR_CLASS(FMin) static ref alloc(const ref &l, const ref &r) { \ ref res(new _class_kind##Expr(l, r)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ @@ -1218,6 +1259,7 @@ COMPARISON_EXPR_CLASS(FOGe) static ref alloc(const ref &e) { \ ref r(new _class_kind##Expr(e)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e); \ @@ -1263,6 +1305,7 @@ FP_PRED_EXPR_CLASS(IsSubnormal) const llvm::APFloat::roundingMode rm) { \ ref r(new _class_kind##Expr(e, rm)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, \ @@ -1309,6 +1352,7 @@ class FAbsExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new FAbsExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(const ref &e); @@ -1341,6 +1385,7 @@ class FNegExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new FNegExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(const ref &e); @@ -1447,12 +1492,14 @@ class ConstantExpr : public Expr { static ref alloc(const llvm::APInt &v) { ref r(new ConstantExpr(v)); r->computeHash(); + r->computeHeight(); return r; } static ref alloc(const llvm::APFloat &f) { ref r(new ConstantExpr(f)); r->computeHash(); + r->computeHeight(); return r; } diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h index 4ec9e11c5a..c4ce9a4559 100644 --- a/include/klee/Expr/IndependentConstraintSetUnion.h +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -8,22 +8,26 @@ namespace klee { class IndependentConstraintSetUnion - : public DisjointSetUnion, - IndependentConstraintSet> { + : public DisjointSetUnion, IndependentConstraintSet, + ExprOrSymcreteHash, ExprOrSymcreteCmp> { public: Assignment concretization; + std::vector> constraintQueue; + Assignment updateQueue; + Assignment removeQueue; public: ExprHashMap> concretizedExprs; public: - void updateConcretization(const Assignment &c); + void updateConcretization(const Assignment &delta); void removeConcretization(const Assignment &remove); + void calculateUpdateConcretizationQueue(); + void calculateRemoveConcretizationQueue(); void reEvaluateConcretization(const Assignment &newConcretization); - IndependentConstraintSetUnion getConcretizedVersion() const; - IndependentConstraintSetUnion - getConcretizedVersion(const Assignment &c) const; + IndependentConstraintSetUnion getConcretizedVersion(); + IndependentConstraintSetUnion getConcretizedVersion(const Assignment &c); IndependentConstraintSetUnion(); IndependentConstraintSetUnion(const constraints_ty &is, @@ -35,14 +39,13 @@ class IndependentConstraintSetUnion addIndependentConstraintSetUnion(const IndependentConstraintSetUnion &icsu); void getAllDependentConstraintSets( - ref e, - std::vector> &result) const; + ref e, std::vector> &result); void getAllIndependentConstraintSets( - ref e, - std::vector> &result) const; + ref e, std::vector> &result); void addExpr(ref e); void addSymcrete(ref s); + void calculateQueue(); }; } // namespace klee diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index a0878ea6c2..af84a4dd8a 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -22,7 +22,19 @@ DISABLE_WARNING_POP #include namespace klee { -using ExprEitherSymcrete = either; +using ExprOrSymcrete = either; +class IndependentConstraintSetUnion; + +struct ExprOrSymcreteHash { + unsigned operator()(const ref &e) const { return e->hash(); } +}; + +struct ExprOrSymcreteCmp { + bool operator()(const ref &a, + const ref &b) const { + return a == b; + } +}; template class DenseSet { typedef std::set set_ty; @@ -86,8 +98,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, class IndependentConstraintSet { private: - using InnerSetUnion = - DisjointSetUnion, IndependentConstraintSet>; + using InnerSetUnion = IndependentConstraintSetUnion; void initIndependentConstraintSet(ref e); void initIndependentConstraintSet(ref s); @@ -107,7 +118,9 @@ class IndependentConstraintSet { Assignment concretization; - InnerSetUnion concretizedSets; + std::shared_ptr concretizedSets; + + std::set uninterpretedFunctions; ref addExpr(ref e) const; ref @@ -123,7 +136,7 @@ class IndependentConstraintSet { Assignment &assign) const; IndependentConstraintSet(); - explicit IndependentConstraintSet(ref v); + explicit IndependentConstraintSet(ref v); IndependentConstraintSet(const IndependentConstraintSet &ics); void print(llvm::raw_ostream &os) const; diff --git a/include/klee/Expr/Parser/Lexer.h b/include/klee/Expr/Parser/Lexer.h index 8b3fe53a30..dc4c111adc 100644 --- a/include/klee/Expr/Parser/Lexer.h +++ b/include/klee/Expr/Parser/Lexer.h @@ -32,6 +32,8 @@ struct Token { KWFalse, ///< 'false' KWQuery, ///< 'query' KWPath, ///< 'path' + KWDefault, ///< 'default' + KWNull, ///< 'null' KWReserved, ///< fp[0-9]+([.].*)?, i[0-9]+ KWSymbolic, ///< 'symbolic' KWTrue, ///< 'true' diff --git a/include/klee/Expr/Parser/Parser.h b/include/klee/Expr/Parser/Parser.h index 0f6ec291c0..5009125c85 100644 --- a/include/klee/Expr/Parser/Parser.h +++ b/include/klee/Expr/Parser/Parser.h @@ -220,6 +220,8 @@ class Parser { static Parser *Create(const std::string Name, const llvm::MemoryBuffer *MB, ExprBuilder *Builder, ArrayCache *TheArrayCache, KModule *km, bool ClearArrayAfterQuery); + + virtual ArrayCache &getArrayCache() = 0; }; } // namespace expr } // namespace klee diff --git a/include/klee/Expr/Path.h b/include/klee/Expr/Path.h index 48bb63ec47..a556a00213 100644 --- a/include/klee/Expr/Path.h +++ b/include/klee/Expr/Path.h @@ -1,6 +1,8 @@ #ifndef KLEE_PATH_H #define KLEE_PATH_H +#include "klee/ADT/ImmutableList.h" + #include #include #include @@ -16,7 +18,7 @@ using stackframe_ty = std::pair; class Path { public: - using path_ty = std::vector; + using path_ty = ImmutableList; enum class TransitionKind { StepInto, StepOut, None }; struct PathIndex { @@ -38,23 +40,6 @@ class Path { void advance(KInstruction *ki); - friend bool operator==(const Path &lhs, const Path &rhs) { - return lhs.KBlocks == rhs.KBlocks && - lhs.firstInstruction == rhs.firstInstruction && - lhs.lastInstruction == rhs.lastInstruction; - } - friend bool operator!=(const Path &lhs, const Path &rhs) { - return !(lhs == rhs); - } - - friend bool operator<(const Path &lhs, const Path &rhs) { - return lhs.KBlocks < rhs.KBlocks || - (lhs.KBlocks == rhs.KBlocks && - (lhs.firstInstruction < rhs.firstInstruction || - (lhs.firstInstruction == rhs.firstInstruction && - lhs.lastInstruction < rhs.lastInstruction))); - } - unsigned KBlockSize() const; const path_ty &getBlocks() const; unsigned getFirstIndex() const; @@ -64,7 +49,6 @@ class Path { std::vector getStack(bool reversed) const; - std::vector> asFunctionRanges() const; std::string toString() const; static Path concat(const Path &l, const Path &r); @@ -73,7 +57,7 @@ class Path { Path() = default; - Path(unsigned firstInstruction, std::vector kblocks, + Path(unsigned firstInstruction, const path_ty &kblocks, unsigned lastInstruction) : KBlocks(kblocks), firstInstruction(firstInstruction), lastInstruction(lastInstruction) {} diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 7b57e2f8c9..1a353901e0 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -1,21 +1,32 @@ #ifndef KLEE_SOURCEBUILDER_H #define KLEE_SOURCEBUILDER_H -#include "klee/ADT/Ref.h" #include "klee/Expr/SymbolicSource.h" -#include "klee/Module/KModule.h" namespace klee { +class KInstruction; +class KGlobalVariable; + +template class SparseStorage; +template class ref; + class SourceBuilder { public: SourceBuilder() = delete; static ref - constant(const std::vector> &constantValues); - static ref symbolicSizeConstant(unsigned defaultValue); - static ref symbolicSizeConstantAddress(unsigned defaultValue, - unsigned version); + constant(SparseStorage> constantValues); + + static ref uninitialized(unsigned version, + const KInstruction *allocSite); + static ref + symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite, + ref size); + static ref + symbolicSizeConstantAddress(unsigned version, + const KGlobalVariable *allocSite, ref size); + static ref makeSymbolic(const std::string &name, unsigned version); static ref lazyInitializationAddress(ref pointer); @@ -28,6 +39,13 @@ class SourceBuilder { static ref value(const llvm::Value &_allocSite, int _index, KModule *km); static ref irreproducible(const std::string &name); + static ref mockNaive(const KModule *kModule, + const llvm::Function &kFunction, + unsigned version); + static ref + mockDeterministic(const KModule *kModule, const llvm::Function &kFunction, + const std::vector> &args); + static ref alpha(int _index); }; }; // namespace klee diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index be65580f7b..7bdea46962 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -3,11 +3,14 @@ #include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Support/CompilerWarning.h" + DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Argument.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" DISABLE_WARNING_POP @@ -17,10 +20,15 @@ DISABLE_WARNING_POP namespace klee { +class Expr; class Array; class Expr; class ConstantExpr; +struct KGlobalVariable; class KModule; +struct KFunction; +struct KValue; +struct KInstruction; class SymbolicSource { protected: @@ -33,7 +41,7 @@ class SymbolicSource { enum Kind { Constant = 3, - SymbolicSizeConstant, + Uninitialied, SymbolicSizeConstantAddress, MakeSymbolic, LazyInitializationContent, @@ -41,7 +49,10 @@ class SymbolicSource { LazyInitializationSize, Instruction, Argument, - Irreproducible + Irreproducible, + MockNaive, + MockDeterministic, + Alpha }; public: @@ -63,24 +74,26 @@ class SymbolicSource { class ConstantSource : public SymbolicSource { public: - /// constantValues - The constant initial values for this array, or empty for - /// a symbolic array. If non-empty, this size of this array is equivalent to - /// the array size. - const std::vector> constantValues; + const SparseStorage> constantValues; + + ConstantSource(SparseStorage> _constantValues) + : constantValues(std::move(_constantValues)) { + assert(constantValues.defaultV() && "Constant must be constant!"); + } - ConstantSource(const std::vector> &_constantValues) - : constantValues(_constantValues){}; Kind getKind() const override { return Kind::Constant; } - virtual std::string getName() const override { return "constant"; } - uint64_t size() const { return constantValues.size(); } + + std::string getName() const override { return "constant"; } static bool classof(const SymbolicSource *S) { return S->getKind() == Kind::Constant; } + static bool classof(const ConstantSource *) { return true; } - virtual unsigned computeHash() override; - virtual int internalCompare(const SymbolicSource &b) const override { + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override { if (getKind() != b.getKind()) { return getKind() < b.getKind() ? -1 : 1; } @@ -92,43 +105,38 @@ class ConstantSource : public SymbolicSource { } }; -class SymbolicSizeConstantSource : public SymbolicSource { +class UninitializedSource : public SymbolicSource { public: - const unsigned defaultValue; - SymbolicSizeConstantSource(unsigned _defaultValue) - : defaultValue(_defaultValue) {} + const unsigned version; + const KInstruction *allocSite; - Kind getKind() const override { return Kind::SymbolicSizeConstant; } - virtual std::string getName() const override { - return "symbolicSizeConstant"; - } + UninitializedSource(unsigned version, const KInstruction *allocSite) + : version(version), allocSite(allocSite) {} + + Kind getKind() const override { return Kind::Uninitialied; } + + std::string getName() const override { return "uninitialized"; } static bool classof(const SymbolicSource *S) { - return S->getKind() == Kind::SymbolicSizeConstant; + return S->getKind() == Kind::Uninitialied; } - static bool classof(const SymbolicSizeConstantSource *) { return true; } - virtual unsigned computeHash() override; + static bool classof(const UninitializedSource *) { return true; } - virtual int internalCompare(const SymbolicSource &b) const override { - if (getKind() != b.getKind()) { - return getKind() < b.getKind() ? -1 : 1; - } - const SymbolicSizeConstantSource &ssb = - static_cast(b); - if (defaultValue != ssb.defaultValue) { - return defaultValue < ssb.defaultValue ? -1 : 1; - } - return 0; - } + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override; }; class SymbolicSizeConstantAddressSource : public SymbolicSource { public: - const unsigned defaultValue; const unsigned version; - SymbolicSizeConstantAddressSource(unsigned _defaultValue, unsigned _version) - : defaultValue(_defaultValue), version(_version) {} + const KValue *allocSite; + ref size; + + SymbolicSizeConstantAddressSource(unsigned _version, const KValue *_allocSite, + ref _size) + : version(_version), allocSite(_allocSite), size(_size) {} Kind getKind() const override { return Kind::SymbolicSizeConstantAddress; } virtual std::string getName() const override { @@ -144,20 +152,7 @@ class SymbolicSizeConstantAddressSource : public SymbolicSource { virtual unsigned computeHash() override; - virtual int internalCompare(const SymbolicSource &b) const override { - if (getKind() != b.getKind()) { - return getKind() < b.getKind() ? -1 : 1; - } - const SymbolicSizeConstantAddressSource &ssb = - static_cast(b); - if (defaultValue != ssb.defaultValue) { - return defaultValue < ssb.defaultValue ? -1 : 1; - } - if (version != ssb.version) { - return version < ssb.version ? -1 : 1; - } - return 0; - } + virtual int internalCompare(const SymbolicSource &b) const override; }; class MakeSymbolicSource : public SymbolicSource { @@ -361,6 +356,93 @@ class IrreproducibleSource : public SymbolicSource { } }; +class AlphaSource : public SymbolicSource { +public: + const unsigned index; + + AlphaSource(unsigned _index) : index(_index) {} + [[nodiscard]] Kind getKind() const override { return Kind::Alpha; } + [[nodiscard]] virtual std::string getName() const override { return "alpha"; } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::Alpha; + } + static bool classof(const AlphaSource *) { return true; } + + virtual unsigned computeHash() override { + unsigned res = getKind(); + hashValue = res ^ (index * SymbolicSource::MAGIC_HASH_CONSTANT); + return hashValue; + } + + virtual int internalCompare(const SymbolicSource &b) const override { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const AlphaSource &amb = static_cast(b); + if (index != amb.index) { + return index < amb.index ? -1 : 1; + } + return 0; + } +}; + +class MockSource : public SymbolicSource { +public: + const KModule *km; + const llvm::Function &function; + MockSource(const KModule *_km, const llvm::Function &_function) + : km(_km), function(_function) {} + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::MockNaive || + S->getKind() == Kind::MockDeterministic; + } +}; + +class MockNaiveSource : public MockSource { +public: + const unsigned version; + + MockNaiveSource(const KModule *km, const llvm::Function &function, + unsigned _version) + : MockSource(km, function), version(_version) {} + + [[nodiscard]] Kind getKind() const override { return Kind::MockNaive; } + [[nodiscard]] std::string getName() const override { return "mockNaive"; } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::MockNaive; + } + + unsigned computeHash() override; + + [[nodiscard]] int internalCompare(const SymbolicSource &b) const override; +}; + +class MockDeterministicSource : public MockSource { +public: + const std::vector> args; + + MockDeterministicSource(const KModule *_km, const llvm::Function &_function, + const std::vector> &_args); + + [[nodiscard]] Kind getKind() const override { + return Kind::MockDeterministic; + } + [[nodiscard]] std::string getName() const override { + return "mockDeterministic"; + } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::MockDeterministic; + } + + unsigned computeHash() override; + + [[nodiscard]] int internalCompare(const SymbolicSource &b) const override; +}; + } // namespace klee #endif /* KLEE_SYMBOLICSOURCE_H */ diff --git a/include/klee/Expr/Symcrete.h b/include/klee/Expr/Symcrete.h index 6646c4cf16..65b70b20f7 100644 --- a/include/klee/Expr/Symcrete.h +++ b/include/klee/Expr/Symcrete.h @@ -75,6 +75,8 @@ class Symcrete { return id < rhs.id ? -1 : 1; } + unsigned hash() { return id; } + bool operator<(const Symcrete &rhs) const { return compare(rhs) < 0; }; }; diff --git a/include/klee/Module/Annotation.h b/include/klee/Module/Annotation.h new file mode 100644 index 0000000000..d94c591091 --- /dev/null +++ b/include/klee/Module/Annotation.h @@ -0,0 +1,140 @@ +//===-- Annotation.h --------------------------------------------*- C++ -*-===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#ifndef KLEE_ANNOTATION_H +#define KLEE_ANNOTATION_H + +#include "map" +#include "set" +#include "string" +#include "vector" + +#include "nlohmann/json.hpp" +#include + +#include "klee/Config/config.h" + +#include "llvm/IR/Module.h" + +using json = nlohmann::json; + +namespace klee { + +namespace Statement { +enum class Kind { + Unknown, + + Deref, + InitNull, + MaybeInitNull, + // TODO: rename to alloc + AllocSource, + Free +}; + +enum class Property { + Unknown, + + Deterministic, + Noreturn, +}; + +struct Unknown { +protected: + std::string rawAnnotation; + std::string rawOffset; + std::string rawValue; + +public: + std::vector offset; + + explicit Unknown(const std::string &str = "Unknown"); + virtual ~Unknown(); + + virtual bool operator==(const Unknown &other) const; + [[nodiscard]] virtual Kind getKind() const; + + [[nodiscard]] const std::vector &getOffset() const; + [[nodiscard]] std::string toString() const; +}; + +struct Deref final : public Unknown { + explicit Deref(const std::string &str = "Deref"); + + [[nodiscard]] Kind getKind() const override; +}; + +struct InitNull final : public Unknown { +public: + explicit InitNull(const std::string &str = "InitNull"); + + [[nodiscard]] Kind getKind() const override; +}; + +struct MaybeInitNull final : public Unknown { +public: + explicit MaybeInitNull(const std::string &str = "MaybeInitNull"); + + [[nodiscard]] Kind getKind() const override; +}; + +struct Alloc final : public Unknown { +public: + enum Type { + ALLOC = 1, // malloc, calloc, realloc + NEW = 2, // operator new + NEW_BRACKETS = 3, // operator new[] + OPEN_FILE = 4, // open file (fopen, open) + MUTEX_LOCK = 5 // mutex lock (pthread_mutex_lock) + }; + + Type value = Alloc::Type::ALLOC; + + explicit Alloc(const std::string &str = "AllocSource::1"); + + [[nodiscard]] Kind getKind() const override; +}; + +struct Free final : public Unknown { +public: + enum Type { + FREE = 1, // Kind of free function + DELETE = 2, // operator delete + DELETE_BRACKETS = 3, // operator delete[] + CLOSE_FILE = 4, // close file + MUTEX_UNLOCK = 5 // mutex unlock (pthread_mutex_unlock) + }; + + Type value = Free::Type::FREE; + + explicit Free(const std::string &str = "FreeSource::1"); + + [[nodiscard]] Kind getKind() const override; +}; + +using Ptr = std::shared_ptr; +bool operator==(const Ptr &first, const Ptr &second); +} // namespace Statement + +// Annotation format: https://github.com/UnitTestBot/klee/discussions/92 +struct Annotation { + std::string functionName; + std::vector returnStatements; + std::vector> argsStatements; + std::set properties; + + bool operator==(const Annotation &other) const; +}; + +using AnnotationsMap = std::map; + +AnnotationsMap parseAnnotationsJson(const json &annotationsJson); +AnnotationsMap parseAnnotations(const std::string &path); +} // namespace klee + +#endif // KLEE_ANNOTATION_H diff --git a/include/klee/Module/CodeGraphInfo.h b/include/klee/Module/CodeGraphInfo.h index c13a7a0337..549964287a 100644 --- a/include/klee/Module/CodeGraphInfo.h +++ b/include/klee/Module/CodeGraphInfo.h @@ -16,68 +16,71 @@ namespace klee { +using Block = llvm::BasicBlock; +using BlockDistanceMap = std::unordered_map; +using FunctionDistanceMap = std::unordered_map; +using SortedBlockDistances = std::vector>; +using SortedFunctionDistances = + std::vector>; + class CodeGraphInfo { - using blockDistanceMap = - std::unordered_map>; - using blockDistanceList = - std::unordered_map>>; + using blockToDistanceMap = std::unordered_map; + using blockDistanceList = std::unordered_map; - using functionDistanceMap = - std::unordered_map>; + using functionToDistanceMap = + std::unordered_map; using functionDistanceList = - std::unordered_map>>; + std::unordered_map; using functionBranchesSet = std::unordered_map>>; private: - blockDistanceMap blockDistance; - blockDistanceMap blockBackwardDistance; + blockToDistanceMap blockDistance; + blockToDistanceMap blockBackwardDistance; + std::set blockCycles; blockDistanceList blockSortedDistance; blockDistanceList blockSortedBackwardDistance; - functionDistanceMap functionDistance; - functionDistanceMap functionBackwardDistance; + functionToDistanceMap functionDistance; + functionToDistanceMap functionBackwardDistance; functionDistanceList functionSortedDistance; functionDistanceList functionSortedBackwardDistance; functionBranchesSet functionBranches; + functionBranchesSet functionConditionalBranches; + functionBranchesSet functionBlocks; private: - void calculateDistance(KBlock *bb); - void calculateBackwardDistance(KBlock *bb); + void calculateDistance(Block *bb); + void calculateBackwardDistance(Block *bb); - void calculateDistance(KFunction *kf); - void calculateBackwardDistance(KFunction *kf); + void calculateDistance(KFunction *f); + void calculateBackwardDistance(KFunction *f); void calculateFunctionBranches(KFunction *kf); + void calculateFunctionConditionalBranches(KFunction *kf); + void calculateFunctionBlocks(KFunction *kf); public: - const std::unordered_map &getDistance(KBlock *kb); - const std::unordered_map & - getBackwardDistance(KBlock *kb); - const std::vector> & - getSortedDistance(KBlock *kb); - const std::vector> & - getSortedBackwardDistance(KBlock *kb); - - const std::unordered_map & - getDistance(KFunction *kf); - const std::unordered_map & - getBackwardDistance(KFunction *kf); - const std::vector> & - getSortedDistance(KFunction *kf); - const std::vector> & - getSortedBackwardDistance(KFunction *kf); + const BlockDistanceMap &getDistance(Block *b); + const BlockDistanceMap &getDistance(KBlock *kb); + const BlockDistanceMap &getBackwardDistance(KBlock *kb); + bool hasCycle(KBlock *kb); + + const FunctionDistanceMap &getDistance(KFunction *kf); + const FunctionDistanceMap &getBackwardDistance(KFunction *kf); void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate, std::set &result); const std::map> & getFunctionBranches(KFunction *kf); + const std::map> & + getFunctionConditionalBranches(KFunction *kf); + const std::map> & + getFunctionBlocks(KFunction *kf); }; } // namespace klee diff --git a/include/klee/Module/InstructionInfoTable.h b/include/klee/Module/InstructionInfoTable.h deleted file mode 100644 index 8b91c0d8c8..0000000000 --- a/include/klee/Module/InstructionInfoTable.h +++ /dev/null @@ -1,113 +0,0 @@ -//===-- InstructionInfoTable.h ----------------------------------*- C++ -*-===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef KLEE_INSTRUCTIONINFOTABLE_H -#define KLEE_INSTRUCTIONINFOTABLE_H - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/ADT/Optional.h" -#include "llvm/Support/raw_ostream.h" -DISABLE_WARNING_POP - -#include -#include -#include -#include -#include - -namespace llvm { -class Function; -class Instruction; -class Module; -} // namespace llvm - -namespace klee { - -/// @brief InstructionInfo stores debug information for a KInstruction. -struct InstructionInfo { - /// @brief The instruction id. - unsigned id; - /// @brief Line number in source file. - unsigned line; - /// @brief Column number in source file. - unsigned column; - /// @brief Line number in generated assembly.ll. - llvm::Optional assemblyLine; - /// @brief Source file name. - const std::string &file; - -public: - InstructionInfo(unsigned id, const std::string &file, unsigned line, - unsigned column, llvm::Optional assemblyLine) - : id{id}, line{line}, column{column}, - assemblyLine{assemblyLine}, file{file} {} -}; - -/// @brief FunctionInfo stores debug information for a KFunction. -struct FunctionInfo { - /// @brief The function id. - unsigned id; - /// @brief Line number in source file. - unsigned line; - /// @brief Line number in generated assembly.ll. - llvm::Optional assemblyLine; - /// @brief Source file name. - const std::string &file; - -public: - FunctionInfo(unsigned id, const std::string &file, unsigned line, - llvm::Optional assemblyLine) - : id{id}, line{line}, assemblyLine{assemblyLine}, file{file} {} - - FunctionInfo(const FunctionInfo &) = delete; - FunctionInfo &operator=(FunctionInfo const &) = delete; - - FunctionInfo(FunctionInfo &&) = default; -}; - -class InstructionInfoTable { -public: - using Instructions = std::unordered_map< - std::string, - std::unordered_map< - unsigned int, - std::unordered_map>>>; - using LocationToFunctionsMap = - std::unordered_map>; - -private: - std::unordered_map> - infos; - std::unordered_map> - functionInfos; - LocationToFunctionsMap fileNameToFunctions; - std::vector> internedStrings; - std::unordered_set filesNames; - Instructions insts; - -public: - explicit InstructionInfoTable( - const llvm::Module &m, std::unique_ptr assemblyFS, - bool withInstructions = false); - - unsigned getMaxID() const; - const InstructionInfo &getInfo(const llvm::Instruction &) const; - const FunctionInfo &getFunctionInfo(const llvm::Function &) const; - const LocationToFunctionsMap &getFileNameToFunctions() const; - const std::unordered_set &getFilesNames() const; - Instructions getInstructions(); -}; - -} // namespace klee - -#endif /* KLEE_INSTRUCTIONINFOTABLE_H */ diff --git a/include/klee/Module/KCallable.h b/include/klee/Module/KCallable.h index ade28cfc82..72ae9f5b44 100644 --- a/include/klee/Module/KCallable.h +++ b/include/klee/Module/KCallable.h @@ -10,8 +10,7 @@ #ifndef KLEE_KCALLABLE_H #define KLEE_KCALLABLE_H -#include - +#include "klee/Module/KValue.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS @@ -19,57 +18,64 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Support/Casting.h" DISABLE_WARNING_POP +#include +#include + namespace klee { /// Wrapper for callable objects passed in callExternalFunction -class KCallable { -public: - enum CallableKind { CK_Function, CK_InlineAsm }; - -private: - const CallableKind Kind; +struct KCallable : public KValue { +protected: + KCallable(llvm::Value *value, KValue::Kind kind) : KValue(value, kind) {} public: - KCallable(CallableKind Kind) : Kind(Kind) {} - - CallableKind getKind() const { return Kind; } - - virtual llvm::StringRef getName() const = 0; virtual llvm::FunctionType *getFunctionType() const = 0; - virtual llvm::Value *getValue() = 0; - virtual ~KCallable() = default; + static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::FUNCTION || + rhs->getKind() == KValue::Kind::INLINE_ASM; + } }; -class KInlineAsm : public KCallable { +struct KInlineAsm : public KCallable { private: + /* Prepared name of ASM code */ + std::string name; + static unsigned getFreshAsmId() { static unsigned globalId = 0; return globalId++; } - llvm::InlineAsm *value; - std::string name; - public: - KInlineAsm(llvm::InlineAsm *value) - : KCallable(CK_InlineAsm), value(value), + KInlineAsm(llvm::InlineAsm *inlineAsm) + : KCallable(inlineAsm, KValue::Kind::INLINE_ASM), name("__asm__" + llvm::Twine(getFreshAsmId()).str()) {} llvm::StringRef getName() const override { return name; } llvm::FunctionType *getFunctionType() const override { - return value->getFunctionType(); + return inlineAsm()->getFunctionType(); } - llvm::Value *getValue() override { return value; } + static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::INLINE_ASM; + } - static bool classof(const KCallable *callable) { - return callable->getKind() == CK_InlineAsm; + [[nodiscard]] llvm::InlineAsm *inlineAsm() const { + return llvm::dyn_cast(value); } - llvm::InlineAsm *getInlineAsm() { return value; } + [[nodiscard]] bool operator<(const KValue &rhs) const override { + return getKind() == rhs.getKind() + ? getName() < llvm::cast(rhs).getName() + : getKind() < rhs.getKind(); + } + [[nodiscard]] unsigned hash() const override { + return std::hash{}(name); + } }; } // namespace klee diff --git a/include/klee/Module/KInstruction.h b/include/klee/Module/KInstruction.h index 865a752bfd..872f433d63 100644 --- a/include/klee/Module/KInstruction.h +++ b/include/klee/Module/KInstruction.h @@ -10,16 +10,19 @@ #ifndef KLEE_KINSTRUCTION_H #define KLEE_KINSTRUCTION_H -#include "klee/Config/Version.h" -#include "klee/Module/InstructionInfoTable.h" +#include "KModule.h" +#include "KValue.h" +#include "klee/Config/Version.h" #include "klee/Support/CompilerWarning.h" +#include "llvm/IR/Argument.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" DISABLE_WARNING_POP +#include #include namespace llvm { @@ -28,34 +31,110 @@ class Instruction; namespace klee { class Executor; -struct InstructionInfo; class KModule; struct KBlock; +struct KFunction; + +static const unsigned MAGIC_HASH_CONSTANT = 39; /// KInstruction - Intermediate instruction representation used /// during execution. -struct KInstruction { - llvm::Instruction *inst; - const InstructionInfo *info; +struct KInstruction : public KValue { + + struct Index { + unsigned long instID; + unsigned long blockID; + unsigned long funcID; + + bool operator==(const Index &other) const { + return std::tie(instID, blockID, funcID) == + std::tie(other.instID, other.blockID, other.funcID); + } + + bool operator<(const Index &other) const { + return std::tie(instID, blockID, funcID) < + std::tie(other.instID, other.blockID, other.funcID); + } + + unsigned hash() const { + unsigned res = instID; + res = res * MAGIC_HASH_CONSTANT + blockID; + res = res * MAGIC_HASH_CONSTANT + funcID; + return res; + } + + void print(llvm::raw_ostream &os) const { + os << "[" << instID << ", " << blockID << ", " << funcID << "]"; + } + }; + + llvm::Instruction *inst() const { + return llvm::dyn_cast_or_null(value); + } /// Value numbers for each operand. -1 is an invalid value, /// otherwise negative numbers are indices (negated and offset by /// 2) into the module constant table and positive numbers are /// register indices. int *operands; - /// Destination register index. - unsigned dest; KBlock *parent; +private: // Instruction index in the basic block - unsigned index; + const unsigned globalIndex; public: - KInstruction() = default; - explicit KInstruction(const KInstruction &ki); + /// Unique index for KFunction and KInstruction inside KModule + /// from 0 to [KFunction + KInstruction] + [[nodiscard]] unsigned getGlobalIndex() const; + /// Instruction index in the basic block + [[nodiscard]] unsigned getIndex() const; + /// Destination register index. + [[nodiscard]] unsigned getDest() const; + + KInstruction(const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc); + + KInstruction() = delete; + explicit KInstruction(const KInstruction &ki) = delete; virtual ~KInstruction(); std::string getSourceLocation() const; - std::string toString() const; + + [[nodiscard]] size_t getLine() const; + [[nodiscard]] size_t getColumn() const; + [[nodiscard]] std::string getSourceFilepath() const; + Index getID() const; + + [[nodiscard]] std::string getSourceLocationString() const; + [[nodiscard]] std::string toString() const; + bool operator==(const KInstruction &other) const { + return getID() == other.getID(); + } + + [[nodiscard]] inline KBlock *getKBlock() const { return parent; } + [[nodiscard]] inline KFunction *getKFunction() const { + return getKBlock()->parent; + } + + [[nodiscard]] bool operator<(const KValue &rhs) const override { + if (getKind() == rhs.getKind()) { + return getID() < cast(rhs).getID(); + } else { + return getKind() < rhs.getKind(); + } + } + + [[nodiscard]] inline KModule *getKModule() const { + return getKFunction()->parent; + } + + [[nodiscard]] unsigned hash() const override { return getID().hash(); } + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::INSTRUCTION; + } }; struct KGEPInstruction : KInstruction { @@ -70,8 +149,14 @@ struct KGEPInstruction : KInstruction { uint64_t offset; public: - KGEPInstruction() = default; - explicit KGEPInstruction(const KGEPInstruction &ki); + KGEPInstruction(const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc) + : KInstruction(_instructionToRegisterMap, _inst, _km, _kb, + _globalIndexInc) {} + KGEPInstruction() = delete; + explicit KGEPInstruction(const KGEPInstruction &ki) = delete; }; } // namespace klee diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index e601d91e43..5b8871b2e2 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -12,14 +12,15 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KCallable.h" +#include "klee/Module/KValue.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/CFG.h" +#include "llvm/Support/Casting.h" DISABLE_WARNING_POP #include @@ -58,93 +59,124 @@ template class ref; enum KBlockType { Base, Call, Return }; -struct KBlock { +struct KBlock : public KValue { KFunction *parent; - llvm::BasicBlock *basicBlock; - - unsigned numInstructions; KInstruction **instructions; - /// Whether instructions in this function should count as - /// "coverable" for statistics and search heuristics. - bool trackCoverage; + [[nodiscard]] llvm::BasicBlock *basicBlock() const { + return llvm::dyn_cast_or_null(value); + } - unsigned id; +private: + const KBlockType blockKind; -public: +protected: KBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, KInstruction **); + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc, KBlockType blockType); KBlock(const KBlock &) = delete; KBlock &operator=(const KBlock &) = delete; - virtual ~KBlock() = default; - - virtual KBlockType getKBlockType() const { return KBlockType::Base; } - static bool classof(const KBlock *) { return true; } - void handleKInstruction(std::unordered_map - &instructionToRegisterMap, - llvm::Instruction *inst, KModule *km, - KInstruction *ki); +public: + unsigned getNumInstructions() const noexcept { return basicBlock()->size(); } KInstruction *getFirstInstruction() const noexcept { return instructions[0]; } KInstruction *getLastInstruction() const noexcept { - return instructions[numInstructions - 1]; + return instructions[getNumInstructions() - 1]; } std::string getLabel() const; std::string toString() const; + + /// Block number in function + [[nodiscard]] uintptr_t getId() const; + + // Block number in module + [[nodiscard]] unsigned getGlobalIndex() const; + + /// Util methods defined for KValue + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; + + /// For LLVM RTTI purposes in KBlock inheritance system + [[nodiscard]] KBlockType getKBlockType() const { return blockKind; } + static bool classof(const KBlock *) { return true; } + + /// For LLVM RTTI purposes in KValue inheritance system + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); + } }; typedef std::function KBlockPredicate; +struct KBasicBlock : public KBlock { +public: + KBasicBlock(KFunction *, llvm::BasicBlock *, KModule *, + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); + + /// For LLVM RTTI purposes in KBlock inheritance system + static bool classof(const KBlock *rhs) { + return rhs->getKBlockType() == KBlockType::Base; + } + + /// For LLVM RTTI purposes in KValue inheritance system + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); + } +}; + struct KCallBlock : KBlock { KInstruction *kcallInstruction; std::set calledFunctions; public: KCallBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, - std::set, KInstruction **); + const std::unordered_map &, + std::set, KInstruction **, + unsigned &globalIndexInc); static bool classof(const KCallBlock *) { return true; } static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Call; } - KBlockType getKBlockType() const override { return KBlockType::Call; }; bool intrinsic() const; bool internal() const; bool kleeHandled() const; KFunction *getKFunction() const; + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); + } }; struct KReturnBlock : KBlock { public: KReturnBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, KInstruction **); + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); static bool classof(const KReturnBlock *) { return true; } static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Return; } - KBlockType getKBlockType() const override { return KBlockType::Return; }; + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); + } }; struct KFunction : public KCallable { private: std::unordered_map labelMap; + const unsigned globalIndex; public: KModule *parent; - llvm::Function *function; - - unsigned numArgs, numRegisters; - unsigned id; - - std::unordered_map registerToInstructionMap; - unsigned numInstructions; - unsigned numBlocks; KInstruction **instructions; - bool kleeHandled = false; + [[nodiscard]] llvm::Function *function() const { + return llvm::dyn_cast_or_null(value); + } + + [[nodiscard]] KInstruction *getInstructionByRegister(size_t reg) const; std::unordered_map instructionMap; std::vector> blocks; @@ -153,24 +185,24 @@ struct KFunction : public KCallable { std::vector returnKBlocks; std::vector kCallBlocks; - /// Whether instructions in this function should count as - /// "coverable" for statistics and search heuristics. - bool trackCoverage; + /// count of instructions in function + unsigned numInstructions; + [[nodiscard]] size_t getNumArgs() const; + [[nodiscard]] size_t getNumRegisters() const; + unsigned id; + + bool kleeHandled = false; - explicit KFunction(llvm::Function *, KModule *); + explicit KFunction(llvm::Function *, KModule *, unsigned &); KFunction(const KFunction &) = delete; KFunction &operator=(const KFunction &) = delete; - ~KFunction(); + ~KFunction() override; unsigned getArgRegister(unsigned index) const { return index; } - llvm::StringRef getName() const override { - return function ? function->getName() : ""; - } - llvm::FunctionType *getFunctionType() const override { - return function->getFunctionType(); + return function()->getFunctionType(); } const std::unordered_map &getLabelMap() { @@ -182,24 +214,41 @@ struct KFunction : public KCallable { return labelMap; } - llvm::Value *getValue() override { return function; } - - static bool classof(const KCallable *callable) { - return callable->getKind() == CK_Function; + static bool classof(const KValue *callable) { + return callable->getKind() == KValue::Kind::FUNCTION; } + + [[nodiscard]] size_t getLine() const; + [[nodiscard]] std::string getSourceFilepath() const; + + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; + + /// Unique index for KFunction and KInstruction inside KModule + /// from 0 to [KFunction + KInstruction] + [[nodiscard]] inline unsigned getGlobalIndex() const { return globalIndex; } }; struct KBlockCompare { bool operator()(const KBlock *a, const KBlock *b) const { - return a->parent->id < b->parent->id || - (a->parent->id == b->parent->id && a->id < b->id); + return a->parent->getGlobalIndex() < b->parent->getGlobalIndex() || + (a->parent->getGlobalIndex() == b->parent->getGlobalIndex() && + a->getId() < b->getId()); + } +}; + +struct KFunctionCompare { + bool operator()(const KFunction *a, const KFunction *b) const { + return a->id < b->id; } }; -class KConstant { +struct KConstant : public KValue { public: /// Actual LLVM constant this represents. - llvm::Constant *ct; + [[nodiscard]] llvm::Constant *ct() const { + return llvm::dyn_cast_or_null(value); + }; /// The constant ID. unsigned id; @@ -209,11 +258,43 @@ class KConstant { KInstruction *ki; KConstant(llvm::Constant *, unsigned, KInstruction *); + + [[nodiscard]] static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::CONSTANT; + } + + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; +}; + +struct KGlobalVariable : public KValue { +public: + // ID of the global variable + const unsigned id; + + KGlobalVariable(llvm::GlobalVariable *global, unsigned id); + + [[nodiscard]] llvm::GlobalVariable *globalVariable() const { + return llvm::dyn_cast_or_null(value); + } + + [[nodiscard]] static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::GLOBAL_VARIABLE; + } + + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; + + // Filename where the global variable is defined + [[nodiscard]] std::string getSourceFilepath() const; + // Line number where the global variable is defined + [[nodiscard]] size_t getLine() const; }; class KModule { private: - bool withPosixRuntime; + bool withPosixRuntime; // TODO move to opts + unsigned maxGlobalIndex; public: std::unique_ptr module; @@ -224,30 +305,34 @@ class KModule { std::unordered_map functionMap; std::unordered_map> callMap; std::unordered_map functionNameMap; - std::unordered_map functionIDMap; + [[nodiscard]] unsigned getFunctionId(const llvm::Function *) const; // Functions which escape (may be called indirectly) // XXX change to KFunction std::set escapingFunctions; - std::unordered_set mainModuleFunctions; - - std::unordered_set mainModuleGlobals; - - InstructionInfoTable::Instructions origInfos; + std::set mainModuleFunctions; + std::set mainModuleGlobals; - std::unique_ptr infos; + FLCtoOpcode origInstructions; std::vector constants; std::unordered_map> constantMap; KConstant *getKConstant(const llvm::Constant *c); + std::unordered_map> + globalMap; + std::unique_ptr constantTable; // Functions which are part of KLEE runtime std::set internalFunctions; + // instruction to assembly.ll line empty if no statistic enabled + std::unordered_map asmLineMap; + // Mark function with functionName as part of the KLEE runtime void addInternalFunction(const char *functionName); // Replace std functions with KLEE intrinsics @@ -294,13 +379,21 @@ class KModule { /// expected by KLEE's Executor hold. void checkModule(); - KBlock *getKBlock(llvm::BasicBlock *bb); + KBlock *getKBlock(const llvm::BasicBlock *bb); bool inMainModule(const llvm::Function &f); bool inMainModule(const llvm::GlobalVariable &v); bool WithPOSIXRuntime() { return withPosixRuntime; } + + std::optional getAsmLine(const uintptr_t ref) const; + std::optional getAsmLine(const llvm::Function *func) const; + std::optional getAsmLine(const llvm::Instruction *inst) const; + + inline unsigned getMaxGlobalIndex() const { return maxGlobalIndex; } + unsigned getGlobalIndex(const llvm::Function *func) const; + unsigned getGlobalIndex(const llvm::Instruction *inst) const; }; } // namespace klee diff --git a/include/klee/Module/KValue.h b/include/klee/Module/KValue.h new file mode 100644 index 0000000000..278ebed39d --- /dev/null +++ b/include/klee/Module/KValue.h @@ -0,0 +1,53 @@ +#ifndef KVALUE_H +#define KVALUE_H + +namespace llvm { +class Value; +class StringRef; +} // namespace llvm + +namespace klee { + +struct KValue { +public: + /* Enum of kinds for llvm rtti purposes */ + enum Kind { + BLOCK, + CONSTANT, + GLOBAL_VARIABLE, + FUNCTION, + INLINE_ASM, + INSTRUCTION, + }; + +protected: + /* Wrapped llvm::Value */ + llvm::Value *const value; + + /* Kind of KValue required for llvm rtti purposes */ + const Kind kind; + + /* Inner constructor for setting value and kind */ + KValue(llvm::Value *const value, const Kind kind) + : value(value), kind(kind) {} + +public: + /* Unwraps KValue to receive inner value. */ + [[nodiscard]] llvm::Value *unwrap() const; + + /* Returns name of inner value if so exists. */ + [[nodiscard]] virtual llvm::StringRef getName() const; + + [[nodiscard]] virtual bool operator<(const KValue &rhs) const = 0; + [[nodiscard]] virtual unsigned hash() const = 0; + + /* Kind of value. Serves for llvm rtti purposes. */ + [[nodiscard]] Kind getKind() const { return kind; } + [[nodiscard]] static bool classof(const KValue *rhs) { return true; } + + virtual ~KValue() = default; +}; + +} // namespace klee + +#endif // KVALUE_H diff --git a/include/klee/Module/LocationInfo.h b/include/klee/Module/LocationInfo.h new file mode 100644 index 0000000000..6aaa84b8a2 --- /dev/null +++ b/include/klee/Module/LocationInfo.h @@ -0,0 +1,37 @@ +////===-- LocationInfo.h ----------------------------------*- C++ -*-===// +//// +//// The KLEE Symbolic Virtual Machine +//// +//// This file is distributed under the University of Illinois Open Source +//// License. See LICENSE.TXT for details. +//// +////===----------------------------------------------------------------------===// + +#ifndef KLEE_LOCATIONINFO_H +#define KLEE_LOCATIONINFO_H + +#include +#include + +namespace llvm { +class Function; +class GlobalVariable; +class Instruction; +class Module; +} // namespace llvm + +namespace klee { + +struct LocationInfo { + std::string file; + size_t line; + size_t column; +}; + +LocationInfo getLocationInfo(const llvm::Function *func); +LocationInfo getLocationInfo(const llvm::Instruction *inst); +LocationInfo getLocationInfo(const llvm::GlobalVariable *global); + +} // namespace klee + +#endif /* KLEE_LOCATIONINFO_H */ diff --git a/include/klee/Module/SarifReport.h b/include/klee/Module/SarifReport.h index 09a59d4d25..09652206dd 100644 --- a/include/klee/Module/SarifReport.h +++ b/include/klee/Module/SarifReport.h @@ -10,31 +10,31 @@ #ifndef KLEE_SARIF_REPORT_H #define KLEE_SARIF_REPORT_H +#include #include #include #include #include #include "klee/ADT/Ref.h" -#include -#include +#include "nlohmann/json.hpp" +#include "llvm/IR/Function.h" using json = nlohmann::json; -using nonstd::optional; namespace nlohmann { -template struct adl_serializer> { - static void to_json(json &j, const nonstd::optional &opt) { - if (opt == nonstd::nullopt) { +template struct adl_serializer> { + static void to_json(json &j, const std::optional &opt) { + if (opt == std::nullopt) { j = nullptr; } else { j = *opt; } } - static void from_json(const json &j, nonstd::optional &opt) { + static void from_json(const json &j, std::optional &opt) { if (j.is_null()) { - opt = nonstd::nullopt; + opt = std::nullopt; } else { opt = j.get(); } @@ -60,28 +60,28 @@ struct FunctionInfo; struct KBlock; struct ArtifactLocationJson { - optional uri; + std::optional uri; }; struct RegionJson { - optional startLine; - optional endLine; - optional startColumn; - optional endColumn; + std::optional startLine; + std::optional endLine; + std::optional startColumn; + std::optional endColumn; }; struct PhysicalLocationJson { - optional artifactLocation; - optional region; + std::optional artifactLocation; + std::optional region; }; struct LocationJson { - optional physicalLocation; + std::optional physicalLocation; }; struct ThreadFlowLocationJson { - optional location; - optional metadata; + std::optional location; + std::optional metadata; }; struct ThreadFlowJson { @@ -109,10 +109,10 @@ static void from_json(const json &j, Fingerprints &p) { } struct ResultJson { - optional ruleId; - optional message; - optional id; - optional fingerprints; + std::optional ruleId; + std::optional message; + std::optional id; + std::optional fingerprints; std::vector locations; std::vector codeFlows; }; @@ -186,13 +186,13 @@ struct Location { std::string filename; unsigned int startLine; unsigned int endLine; - optional startColumn; - optional endColumn; + std::optional startColumn; + std::optional endColumn; static ref create(std::string filename_, unsigned int startLine_, - optional endLine_, - optional startColumn_, - optional endColumn_); + std::optional endLine_, + std::optional startColumn_, + std::optional endColumn_); ~Location(); std::size_t hash() const { return hashValue; } @@ -214,6 +214,8 @@ struct Location { bool isInside(KBlock *block, const Instructions &origInsts) const; + bool isInside(const llvm::Function *f, const Instructions &origInsts) const; + std::string toString() const; private: @@ -240,8 +242,9 @@ struct Location { } Location(std::string filename_, unsigned int startLine_, - optional endLine_, optional startColumn_, - optional endColumn_) + std::optional endLine_, + std::optional startColumn_, + std::optional endColumn_) : filename(filename_), startLine(startLine_), endLine(endLine_.has_value() ? *endLine_ : startLine_), startColumn(startColumn_), @@ -262,7 +265,7 @@ struct RefLocationCmp { struct Result { std::vector> locations; - std::vector> metadatas; + std::vector> metadatas; std::string id; std::vector errors; }; diff --git a/include/klee/Module/Target.h b/include/klee/Module/Target.h index 98eb3c900a..2475584259 100644 --- a/include/klee/Module/Target.h +++ b/include/klee/Module/Target.h @@ -28,19 +28,19 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS DISABLE_WARNING_POP #include +#include #include #include #include #include namespace klee { -using nonstd::optional; struct ErrorLocation { unsigned int startLine; unsigned int endLine; - optional startColumn; - optional endColumn; + std::optional startColumn; + std::optional endColumn; ErrorLocation(const klee::ref &loc); ErrorLocation(const KInstruction *ki); diff --git a/include/klee/Module/TargetHash.h b/include/klee/Module/TargetHash.h index 2c2c2f81bd..1962ba906c 100644 --- a/include/klee/Module/TargetHash.h +++ b/include/klee/Module/TargetHash.h @@ -31,13 +31,8 @@ struct TargetCmp { bool operator()(const ref &a, const ref &b) const; }; -typedef std::pair Transition; typedef std::pair Branch; -struct TransitionHash { - std::size_t operator()(const Transition &p) const; -}; - struct BranchHash { std::size_t operator()(const Branch &p) const; }; diff --git a/include/klee/Solver/Common.h b/include/klee/Solver/Common.h index 57ebad547d..2a43b9eb67 100644 --- a/include/klee/Solver/Common.h +++ b/include/klee/Solver/Common.h @@ -29,7 +29,7 @@ std::unique_ptr constructSolverChain( std::unique_ptr coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath, - AddressGenerator *addressGenerator); + AddressGenerator *addressGenerator, ArrayCache &arrayCache); } // namespace klee #endif /* KLEE_COMMON_H */ diff --git a/include/klee/Solver/Solver.h b/include/klee/Solver/Solver.h index c39d8a2ae3..93fad34f54 100644 --- a/include/klee/Solver/Solver.h +++ b/include/klee/Solver/Solver.h @@ -244,6 +244,14 @@ std::unique_ptr createFastCexSolver(std::unique_ptr s); /// \param s - The underlying solver to use. std::unique_ptr createIndependentSolver(std::unique_ptr s); +/// createAlphaEquivalenceSolver - Create a solver which will change +/// independent queries to their alpha-equvalent version +/// +/// \param s - The underlying solver to use. +/// \param arrayCache - Class to create new arrays. +std::unique_ptr createAlphaEquivalenceSolver(std::unique_ptr s, + ArrayCache &arrayCache); + /// createKQueryLoggingSolver - Create a solver which will forward all queries /// after writing them to the given path in .kquery format. std::unique_ptr createKQueryLoggingSolver(std::unique_ptr s, diff --git a/include/klee/Solver/SolverCmdLine.h b/include/klee/Solver/SolverCmdLine.h index 6bd0c285bb..e4e5fdcf03 100644 --- a/include/klee/Solver/SolverCmdLine.h +++ b/include/klee/Solver/SolverCmdLine.h @@ -32,6 +32,8 @@ extern llvm::cl::opt UseCexCache; extern llvm::cl::opt UseBranchCache; +extern llvm::cl::opt UseAlphaEquivalence; + extern llvm::cl::opt UseConcretizingSolver; extern llvm::cl::opt UseIndependentSolver; @@ -63,6 +65,8 @@ enum QueryLoggingSolverType { extern llvm::cl::bits QueryLoggingOptions; enum CoreSolverType { + BITWUZLA_SOLVER, + BITWUZLA_TREE_SOLVER, STP_SOLVER, METASMT_SOLVER, DUMMY_SOLVER, diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index bb66e7a179..9be7d0f2d2 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -254,11 +254,7 @@ class InvalidResponse : public SolverResponse { if (result.bindings.count(object)) { values.push_back(result.bindings.at(object)); } else { - ref constantSize = - dyn_cast(result.evaluate(object->size)); - assert(constantSize); - values.push_back( - SparseStorage(constantSize->getZExtValue(), 0)); + values.push_back(SparseStorage(0)); } } return true; @@ -306,9 +302,9 @@ class InvalidResponse : public SolverResponse { return result.satisfies(key.begin(), key.end(), allowFreeValues); } - bool satisfiesNonBoolean(const std::set> &key, + bool satisfiesOrConstant(const std::set> &key, bool allowFreeValues = true) { - return result.satisfiesNonBoolean(key.begin(), key.end(), allowFreeValues); + return result.satisfiesOrConstant(key.begin(), key.end(), allowFreeValues); } void dump() { result.dump(); } diff --git a/include/klee/Support/ErrorHandling.h b/include/klee/Support/ErrorHandling.h index 4cc57c9744..098293d2e5 100644 --- a/include/klee/Support/ErrorHandling.h +++ b/include/klee/Support/ErrorHandling.h @@ -16,7 +16,7 @@ #endif #endif -#include +#include namespace klee { diff --git a/include/klee/Support/ModuleUtil.h b/include/klee/Support/ModuleUtil.h index 4d385c4c42..7ff0e36bd2 100644 --- a/include/klee/Support/ModuleUtil.h +++ b/include/klee/Support/ModuleUtil.h @@ -39,19 +39,16 @@ bool linkModules(llvm::Module *composite, std::vector> &modules, const unsigned Flags, std::string &errorMsg); -#if defined(__x86_64__) || defined(__i386__) -#define addFunctionReplacement(from, to) \ - {#from "f", #to "f"}, {#from "", #to ""}, { "" #from "l", #to "l" } +void replaceOrRenameFunction(llvm::Module *module, const char *old_name, + const char *new_name); +#if defined(__x86_64__) || defined(__i386__) #define addIntrinsicReplacement(from, to) \ {"llvm." #from ".f32", #to "f"}, {"llvm." #from ".f64", #to}, { \ "llvm." #from ".f80", #to "l" \ } #else -#define addFunctionReplacement(from, to) \ - {#from "f", #to "f"}, { "" #from, "" #to } - #define addIntrinsicReplacement(from, to) \ {"llvm." #from ".f32", #to "f"}, { "llvm." #from ".f64", #to } @@ -62,33 +59,15 @@ bool linkModules(llvm::Module *composite, /// implementations in runtime/klee-fp, but not explicitly replaced here. Should /// we rename them and complete the list? const std::vector> floatReplacements = { - addFunctionReplacement(__isnan, klee_internal_isnan), - addFunctionReplacement(isnan, klee_internal_isnan), - addFunctionReplacement(__isinf, klee_internal_isinf), - addFunctionReplacement(isinf, klee_internal_isinf), - addFunctionReplacement(__fpclassify, klee_internal_fpclassify), - addFunctionReplacement(fpclassify, klee_internal_fpclassify), - addFunctionReplacement(__finite, klee_internal_finite), - addFunctionReplacement(finite, klee_internal_finite), - addFunctionReplacement(sqrt, klee_internal_sqrt), - addFunctionReplacement(fabs, klee_internal_fabs), - addFunctionReplacement(rint, klee_internal_rint), - addFunctionReplacement(round, klee_internal_rint), - addFunctionReplacement(__signbit, klee_internal_signbit), - addIntrinsicReplacement(sqrt, klee_internal_sqrt), - addIntrinsicReplacement(rint, klee_internal_rint), - addIntrinsicReplacement(round, klee_internal_rint), + addIntrinsicReplacement(sqrt, sqrt), + addIntrinsicReplacement(rint, rint), + addIntrinsicReplacement(round, rint), addIntrinsicReplacement(nearbyint, nearbyint), addIntrinsicReplacement(copysign, copysign), - addIntrinsicReplacement(floor, klee_floor), + addIntrinsicReplacement(floor, floor), addIntrinsicReplacement(ceil, ceil)}; -#undef addFunctionReplacement #undef addIntrinsicReplacement -const std::vector> feRoundReplacements{ - {"fegetround", "klee_internal_fegetround"}, - {"fesetround", "klee_internal_fesetround"}}; - /// Return the Function* target of a Call or Invoke instruction, or /// null if it cannot be determined (should be only for indirect /// calls, although complicated constant expressions might be diff --git a/include/klee/Support/OptionCategories.h b/include/klee/Support/OptionCategories.h index da1d0d4934..ed8c23c880 100644 --- a/include/klee/Support/OptionCategories.h +++ b/include/klee/Support/OptionCategories.h @@ -24,7 +24,6 @@ namespace klee { extern llvm::cl::OptionCategory TestCompCat; extern llvm::cl::OptionCategory ExecCat; extern llvm::cl::OptionCategory DebugCat; -extern llvm::cl::OptionCategory ExecCat; extern llvm::cl::OptionCategory MiscCat; extern llvm::cl::OptionCategory ModuleCat; extern llvm::cl::OptionCategory SeedingCat; diff --git a/include/klee/Support/PrintContext.h b/include/klee/Support/PrintContext.h index e397367683..5196b9a35f 100644 --- a/include/klee/Support/PrintContext.h +++ b/include/klee/Support/PrintContext.h @@ -72,6 +72,8 @@ class PrintContext { return *this; } + llvm::raw_ostream &getStream() { return os; } + /// Pop the top off the indent stack /// \return The PrintContext object so the method is chainable PrintContext &popIndent() { diff --git a/include/klee/util/APFloatEval.h b/include/klee/Utilities/APFloatEval.h similarity index 100% rename from include/klee/util/APFloatEval.h rename to include/klee/Utilities/APFloatEval.h diff --git a/include/klee/Utilities/Math.h b/include/klee/Utilities/Math.h new file mode 100644 index 0000000000..a7739cadc6 --- /dev/null +++ b/include/klee/Utilities/Math.h @@ -0,0 +1,32 @@ +//===-- Math.h --------------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_MATH_H +#define KLEE_MATH_H + +#include + +namespace klee { +namespace util { +static unsigned int ulog2(unsigned int val) { + if (val == 0) + return UINT_MAX; + if (val == 1) + return 0; + unsigned int ret = 0; + while (val > 1) { + val >>= 1; + ret++; + } + return ret; +} +} // namespace util +} // namespace klee + +#endif /* KLEE_MATH_H */ diff --git a/include/klee/klee.h b/include/klee/klee.h index 9c40ef335c..5995ff2e24 100644 --- a/include/klee/klee.h +++ b/include/klee/klee.h @@ -201,5 +201,6 @@ long double klee_rintl(long double d); // stdin/stdout void klee_init_env(int *argcPtr, char ***argvPtr); void check_stdin_read(); +void *__klee_wrapped_malloc(size_t size); #endif /* KLEE_H */ diff --git a/json b/json deleted file mode 160000 index 6af826d0bd..0000000000 --- a/json +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6af826d0bdb55e4b69e3ad817576745335f243ca diff --git a/lib/ADT/CMakeLists.txt b/lib/ADT/CMakeLists.txt new file mode 100644 index 0000000000..4afa541dd6 --- /dev/null +++ b/lib/ADT/CMakeLists.txt @@ -0,0 +1,16 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +add_library(kleeADT + SparseStorage.cpp +) + +llvm_config(kleeADT "${USE_LLVM_SHARED}" support) +target_include_directories(kleeADT PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) +target_compile_options(kleeADT PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) +target_compile_definitions(kleeADT PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) diff --git a/lib/ADT/SparseStorage.cpp b/lib/ADT/SparseStorage.cpp new file mode 100644 index 0000000000..1cfe3319b4 --- /dev/null +++ b/lib/ADT/SparseStorage.cpp @@ -0,0 +1,86 @@ +#include "klee/ADT/SparseStorage.h" +#include "klee/Expr/Expr.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" + +namespace klee { + +template <> +void SparseStorage::print(llvm::raw_ostream &os, + Density d) const { + if (d == Density::Sparse) { + // "Sparse representation" + os << "{"; + bool firstPrinted = false; + auto ordered = calculateOrderedStorage(); + for (const auto &element : ordered) { + if (firstPrinted) { + os << ", "; + } + os << element.first << ": " << llvm::utostr(element.second); + firstPrinted = true; + } + os << "} default: "; + } else { + // "Dense representation" + os << "["; + bool firstPrinted = false; + for (size_t i = 0; i < sizeOfSetRange(); i++) { + if (firstPrinted) { + os << ", "; + } + os << llvm::utostr(load(i)); + firstPrinted = true; + } + os << "] default: "; + } + os << llvm::utostr(defaultValue); +} + +template <> +void SparseStorage>::print(llvm::raw_ostream &os, + Density d) const { + if (d == Density::Sparse) { + // "Sparse representation" + os << "{"; + bool firstPrinted = false; + auto ordered = calculateOrderedStorage(); + for (const auto &element : ordered) { + if (firstPrinted) { + os << ", "; + } + os << element.first << ": "; + if (element.second) { + os << element.second; + } else { + os << "null"; + } + firstPrinted = true; + } + os << "} default: "; + } else { + // "Dense representation" + os << "["; + bool firstPrinted = false; + for (size_t i = 0; i < sizeOfSetRange(); i++) { + if (firstPrinted) { + os << ", "; + } + auto expr = load(i); + if (expr) { + os << expr; + } else { + os << "null"; + } + firstPrinted = true; + } + os << "] default: "; + } + if (defaultValue) { + os << defaultValue; + } else { + os << "null"; + } +} +} // namespace klee diff --git a/lib/Basic/Statistics.cpp b/lib/Basic/Statistics.cpp index 170ea839e0..50d9e8bf1f 100644 --- a/lib/Basic/Statistics.cpp +++ b/lib/Basic/Statistics.cpp @@ -50,7 +50,7 @@ Statistic *StatisticManager::getStatisticByName(const std::string &name) const { return 0; } -StatisticManager *klee::theStatisticManager = 0; +StatisticManager *klee::theStatisticManager = nullptr; static StatisticManager &getStatisticManager() { static StatisticManager sm; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8a0749324a..cc0279a12e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -6,6 +6,7 @@ # License. See LICENSE.TXT for details. # #===------------------------------------------------------------------------===# +add_subdirectory(ADT) add_subdirectory(Basic) add_subdirectory(Support) add_subdirectory(Expr) diff --git a/lib/Core/AddressManager.cpp b/lib/Core/AddressManager.cpp index f763e0d3e0..c89e0adce4 100644 --- a/lib/Core/AddressManager.cpp +++ b/lib/Core/AddressManager.cpp @@ -21,13 +21,20 @@ void *AddressManager::allocate(ref address, uint64_t size) { newMO = sizeLocation->second; } else { newMO = nullptr; + objects[size] = newMO; } } else { if (sizeLocation == objects.end() || !sizeLocation->second) { - uint64_t newSize = (uint64_t)1 - << (sizeof(size) * CHAR_BIT - - __builtin_clzll(std::max((uint64_t)1, size))); + uint64_t newSize = std::max((uint64_t)1, size); + int clz = __builtin_clzll(std::max((uint64_t)1, newSize)); + int popcount = __builtin_popcountll(std::max((uint64_t)1, newSize)); + if (popcount > 1) { + newSize = (uint64_t)1 << (sizeof(newSize) * CHAR_BIT - clz); + } + if (newSize > maxSize) { + newSize = std::max((uint64_t)1, size); + } assert(!objects.empty()); MemoryObject *mo = objects.begin()->second; newMO = memory->allocate(newSize, mo->isLocal, mo->isGlobal, diff --git a/lib/Core/AddressSpace.cpp b/lib/Core/AddressSpace.cpp index 1d33e574fc..2e1b9593bc 100644 --- a/lib/Core/AddressSpace.cpp +++ b/lib/Core/AddressSpace.cpp @@ -364,30 +364,37 @@ bool AddressSpace::resolve(ExecutionState &state, TimingSolver *solver, // transparently avoid screwing up symbolics (if the byte is symbolic // then its concrete cache byte isn't being used) but is just a hack. -void AddressSpace::copyOutConcretes() { +void AddressSpace::copyOutConcretes(const Assignment &assignment) { for (const auto &object : objects) { auto &mo = object.first; auto &os = object.second; - if (!mo->isUserSpecified && !os->readOnly && os->size != 0) { - copyOutConcrete(mo, os.get()); + if (!mo->isUserSpecified && !os->readOnly && mo->size != 0) { + copyOutConcrete(mo, os.get(), assignment); } } } void AddressSpace::copyOutConcrete(const MemoryObject *mo, - const ObjectState *os) const { + const ObjectState *os, + const Assignment &assignment) const { auto address = reinterpret_cast(mo->address); - std::memcpy(address, os->concreteStore, mo->size); + AssignmentEvaluator ae(assignment, false); + std::vector concreteStore(mo->size); + for (size_t i = 0; i < mo->size; i++) { + auto byte = ae.visit(os->read8(i)); + concreteStore[i] = cast(byte)->getZExtValue(8); + } + std::memcpy(address, concreteStore.data(), mo->size); } -bool AddressSpace::copyInConcretes() { +bool AddressSpace::copyInConcretes(const Assignment &assignment) { for (auto &obj : objects) { const MemoryObject *mo = obj.first; if (!mo->isUserSpecified) { const auto &os = obj.second; - if (!copyInConcrete(mo, os.get(), mo->address)) + if (!copyInConcrete(mo, os.get(), mo->address, assignment)) return false; } } @@ -396,14 +403,23 @@ bool AddressSpace::copyInConcretes() { } bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os, - uint64_t src_address) { + uint64_t src_address, + const Assignment &assignment) { auto address = reinterpret_cast(src_address); - if (memcmp(address, os->concreteStore, mo->size) != 0) { + AssignmentEvaluator ae(assignment, false); + std::vector concreteStore(mo->size); + for (size_t i = 0; i < mo->size; i++) { + auto byte = ae.visit(os->read8(i)); + concreteStore[i] = cast(byte)->getZExtValue(8); + } + if (memcmp(address, concreteStore.data(), mo->size) != 0) { if (os->readOnly) { return false; } else { ObjectState *wos = getWriteable(mo, os); - memcpy(wos->concreteStore, address, mo->size); + for (size_t i = 0; i < mo->size; i++) { + wos->write(i, ConstantExpr::create(address[i], Expr::Int8)); + } } } return true; diff --git a/lib/Core/AddressSpace.h b/lib/Core/AddressSpace.h index 0acd1c1208..11d2de8130 100644 --- a/lib/Core/AddressSpace.h +++ b/lib/Core/AddressSpace.h @@ -13,6 +13,7 @@ #include "Memory.h" #include "klee/ADT/ImmutableMap.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/System/Time.h" @@ -137,9 +138,10 @@ class AddressSpace { /// actual system memory location they were allocated at. /// Returns the (hypothetical) number of pages needed provided each written /// object occupies (at least) a single page. - void copyOutConcretes(); + void copyOutConcretes(const Assignment &assignment); - void copyOutConcrete(const MemoryObject *mo, const ObjectState *os) const; + void copyOutConcrete(const MemoryObject *mo, const ObjectState *os, + const Assignment &assignment) const; /// \brief Obtain an ObjectState suitable for writing. /// @@ -161,7 +163,7 @@ class AddressSpace { /// /// \retval true The copy succeeded. /// \retval false The copy failed because a read-only object was modified. - bool copyInConcretes(); + bool copyInConcretes(const Assignment &assignment); /// Updates the memory object with the raw memory from the address /// @@ -170,7 +172,7 @@ class AddressSpace { /// @param src_address the address to copy from /// @return bool copyInConcrete(const MemoryObject *mo, const ObjectState *os, - uint64_t src_address); + uint64_t src_address, const Assignment &assignment); }; } // namespace klee diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 9d94da9169..9e0dbb715c 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(kleeCore Memory.cpp MemoryManager.cpp PForest.cpp + MockBuilder.cpp PTree.cpp Searcher.cpp SeedInfo.cpp diff --git a/lib/Core/DistanceCalculator.cpp b/lib/Core/DistanceCalculator.cpp index ebfdb7eec6..c5877bb09a 100644 --- a/lib/Core/DistanceCalculator.cpp +++ b/lib/Core/DistanceCalculator.cpp @@ -56,18 +56,23 @@ DistanceResult DistanceCalculator::getDistance(const ExecutionState &state, DistanceResult DistanceCalculator::getDistance(KBlock *kb, TargetKind kind, KBlock *target) { SpeculativeState specState(kb, kind); - if (distanceResultCache.count(target) == 0 || - distanceResultCache.at(target).count(specState) == 0) { + auto it1 = distanceResultCache.find(target); + if (it1 == distanceResultCache.end()) { + SpeculativeStateToDistanceResultMap m; + it1 = distanceResultCache.emplace(target, std::move(m)).first; + } + auto &m = it1->second; + auto it2 = m.find(specState); + if (it2 == m.end()) { auto result = computeDistance(kb, kind, target); - distanceResultCache[target][specState] = result; + m.emplace(specState, result); + return result; } - return distanceResultCache.at(target).at(specState); + return it2->second; } DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, KBlock *target) const { - const auto &distanceToTargetFunction = - codeGraphInfo.getBackwardDistance(target->parent); weight_type weight = 0; WeightResult res = Miss; bool isInsideFunction = true; @@ -77,7 +82,7 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, break; case PreTarget: - res = tryGetPreTargetWeight(kb, weight, distanceToTargetFunction, target); + res = tryGetPreTargetWeight(kb, weight, target); isInsideFunction = false; break; @@ -95,35 +100,28 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, DistanceResult DistanceCalculator::getDistance( const KInstruction *prevPC, const KInstruction *pc, const ExecutionStack::call_stack_ty &frames, KBlock *target) { - weight_type weight = 0; - KBlock *kb = pc->parent; const auto &distanceToTargetFunction = codeGraphInfo.getBackwardDistance(target->parent); unsigned int minCallWeight = UINT_MAX, minSfNum = UINT_MAX, sfNum = 0; auto sfi = frames.rbegin(), sfe = frames.rend(); bool strictlyAfterKB = - sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function); - for (; sfi != sfe; sfi++) { + sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function()); + for (; sfi != sfe; sfi++, sfNum++) { unsigned callWeight; if (distanceInCallGraph(sfi->kf, kb, callWeight, distanceToTargetFunction, target, strictlyAfterKB && sfNum != 0)) { - callWeight *= 2; - callWeight += sfNum; + callWeight = 2 * callWeight + sfNum; if (callWeight < UINT_MAX) { minCallWeight = callWeight; minSfNum = sfNum; + break; } } - if (sfi->caller) { + if (sfi->caller) kb = sfi->caller->parent; - } - sfNum++; - - if (minCallWeight < UINT_MAX) - break; } TargetKind kind = NoneTarget; @@ -140,72 +138,38 @@ DistanceResult DistanceCalculator::getDistance( bool DistanceCalculator::distanceInCallGraph( KFunction *kf, KBlock *origKB, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target, bool strictlyAfterKB) const { - distance = UINT_MAX; - const std::unordered_map &dist = - codeGraphInfo.getDistance(origKB); - KBlock *targetBB = target; - KFunction *targetF = targetBB->parent; - - if (kf == targetF && dist.count(targetBB) != 0) { + const FunctionDistanceMap &distanceToTargetFunction, KBlock *targetKB, + bool strictlyAfterKB) const { + auto &dist = codeGraphInfo.getDistance(origKB->basicBlock()); + if (kf == targetKB->parent && dist.count(targetKB->basicBlock())) { distance = 0; return true; } - if (!strictlyAfterKB) - return distanceInCallGraph(kf, origKB, distance, distanceToTargetFunction, - target); - auto min_distance = UINT_MAX; - distance = UINT_MAX; - for (auto bb : successors(origKB->basicBlock)) { - auto kb = kf->blockMap[bb]; - distanceInCallGraph(kf, kb, distance, distanceToTargetFunction, target); - if (distance < min_distance) - min_distance = distance; - } - distance = min_distance; - return distance != UINT_MAX; -} - -bool DistanceCalculator::distanceInCallGraph( - KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const { distance = UINT_MAX; - const std::unordered_map &dist = - codeGraphInfo.getDistance(kb); - - for (auto &kCallBlock : kf->kCallBlocks) { - if (dist.count(kCallBlock) == 0) + bool cannotReachItself = strictlyAfterKB && !codeGraphInfo.hasCycle(origKB); + for (auto kCallBlock : kf->kCallBlocks) { + if (!dist.count(kCallBlock->basicBlock()) || + (cannotReachItself && origKB == kCallBlock)) continue; - for (auto &calledFunction : kCallBlock->calledFunctions) { - KFunction *calledKFunction = kf->parent->functionMap[calledFunction]; - if (distanceToTargetFunction.count(calledKFunction) != 0 && - distance > distanceToTargetFunction.at(calledKFunction) + 1) { - distance = distanceToTargetFunction.at(calledKFunction) + 1; - } + for (auto calledFunction : kCallBlock->calledFunctions) { + auto it = distanceToTargetFunction.find(calledFunction); + if (it != distanceToTargetFunction.end() && distance > it->second + 1) + distance = it->second + 1; } } return distance != UINT_MAX; } -WeightResult -DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, - const std::vector &localTargets, - KBlock *target) const { - KFunction *currentKF = kb->parent; - KBlock *currentKB = kb; - const std::unordered_map &dist = - codeGraphInfo.getDistance(currentKB); +WeightResult DistanceCalculator::tryGetLocalWeight( + KBlock *kb, weight_type &weight, + const std::vector &localTargets) const { + const auto &dist = codeGraphInfo.getDistance(kb); weight = UINT_MAX; - for (auto &end : localTargets) { - if (dist.count(end) > 0) { - unsigned int w = dist.at(end); - weight = std::min(w, weight); - } + for (auto end : localTargets) { + auto it = dist.find(end->basicBlock()); + if (it != dist.end()) + weight = std::min(it->second, weight); } if (weight == UINT_MAX) @@ -217,19 +181,18 @@ DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, return Continue; } -WeightResult DistanceCalculator::tryGetPreTargetWeight( - KBlock *kb, weight_type &weight, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const { +WeightResult DistanceCalculator::tryGetPreTargetWeight(KBlock *kb, + weight_type &weight, + KBlock *target) const { + auto &distanceToTargetFunction = + codeGraphInfo.getBackwardDistance(target->parent); KFunction *currentKF = kb->parent; std::vector localTargets; - for (auto &kCallBlock : currentKF->kCallBlocks) { - for (auto &calledFunction : kCallBlock->calledFunctions) { - KFunction *calledKFunction = - currentKF->parent->functionMap[calledFunction]; - if (distanceToTargetFunction.count(calledKFunction) > 0) { + for (auto kCallBlock : currentKF->kCallBlocks) { + for (auto calledFunction : kCallBlock->calledFunctions) { + if (distanceToTargetFunction.count(calledFunction)) { localTargets.push_back(kCallBlock); + break; } } } @@ -237,7 +200,7 @@ WeightResult DistanceCalculator::tryGetPreTargetWeight( if (localTargets.empty()) return Miss; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res == Done ? Continue : res; } @@ -250,7 +213,7 @@ WeightResult DistanceCalculator::tryGetPostTargetWeight(KBlock *kb, if (localTargets.empty()) return Miss; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res == Done ? Continue : res; } @@ -258,6 +221,6 @@ WeightResult DistanceCalculator::tryGetTargetWeight(KBlock *kb, weight_type &weight, KBlock *target) const { std::vector localTargets = {target}; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res; } diff --git a/lib/Core/DistanceCalculator.h b/lib/Core/DistanceCalculator.h index 77da2254f1..ed6b5170f8 100644 --- a/lib/Core/DistanceCalculator.h +++ b/lib/Core/DistanceCalculator.h @@ -11,6 +11,7 @@ #define KLEE_DISTANCE_CALCULATOR_H #include "ExecutionState.h" +#include "klee/Module/CodeGraphInfo.h" namespace llvm { class BasicBlock; @@ -107,22 +108,14 @@ class DistanceCalculator { KBlock *target) const; bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const; - bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, + const FunctionDistanceMap &distanceToTargetFunction, KBlock *target, bool strictlyAfterKB) const; - WeightResult tryGetLocalWeight(KBlock *kb, weight_type &weight, - const std::vector &localTargets, - KBlock *target) const; WeightResult - tryGetPreTargetWeight(KBlock *kb, weight_type &weight, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const; + tryGetLocalWeight(KBlock *kb, weight_type &weight, + const std::vector &localTargets) const; + WeightResult tryGetPreTargetWeight(KBlock *kb, weight_type &weight, + KBlock *target) const; WeightResult tryGetTargetWeight(KBlock *kb, weight_type &weight, KBlock *target) const; WeightResult tryGetPostTargetWeight(KBlock *kb, weight_type &weight, diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index f1152938e7..3fd5a29996 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -14,7 +14,6 @@ #include "klee/Expr/ArrayExprVisitor.h" #include "klee/Expr/Expr.h" #include "klee/Module/Cell.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Support/Casting.h" @@ -31,10 +30,8 @@ DISABLE_WARNING_POP #include #include #include -#include #include #include -#include #include using namespace llvm; @@ -76,6 +73,7 @@ void ExecutionStack::pushFrame(KInstIterator caller, KFunction *kf) { ++stackBalance; assert(valueStack_.size() == callStack_.size()); assert(valueStack_.size() == infoStack_.size()); + stackSize += kf->getNumRegisters(); } void ExecutionStack::popFrame() { @@ -95,20 +93,21 @@ void ExecutionStack::popFrame() { --stackBalance; assert(valueStack_.size() == callStack_.size()); assert(valueStack_.size() == infoStack_.size()); + stackSize -= kf->getNumRegisters(); } bool CallStackFrame::equals(const CallStackFrame &other) const { return kf == other.kf && caller == other.caller; } -StackFrame::StackFrame(KFunction *kf) : kf(kf), varargs(0) { - locals = new Cell[kf->numRegisters]; +StackFrame::StackFrame(KFunction *kf) : kf(kf), varargs(nullptr) { + locals = new Cell[kf->getNumRegisters()]; } StackFrame::StackFrame(const StackFrame &s) : kf(s.kf), allocas(s.allocas), varargs(s.varargs) { - locals = new Cell[kf->numRegisters]; - for (unsigned i = 0; i < kf->numRegisters; i++) + locals = new Cell[kf->getNumRegisters()]; + for (unsigned i = 0; i < kf->getNumRegisters(); i++) locals[i] = s.locals[i]; } @@ -119,10 +118,10 @@ InfoStackFrame::InfoStackFrame(KFunction *kf) : kf(kf) {} /***/ ExecutionState::ExecutionState() : initPC(nullptr), pc(nullptr), prevPC(nullptr), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), - coveredNew(new box(false)), forkDisabled(false), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + coveredNewError(new box(false)), forkDisabled(false), prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { setID(); @@ -130,10 +129,10 @@ ExecutionState::ExecutionState() ExecutionState::ExecutionState(KFunction *kf) : initPC(kf->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), - coveredNew(new box(false)), forkDisabled(false), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + coveredNewError(new box(false)), forkDisabled(false), prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); @@ -142,10 +141,10 @@ ExecutionState::ExecutionState(KFunction *kf) ExecutionState::ExecutionState(KFunction *kf, KBlock *kb) : initPC(kb->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), - coveredNew(new box(false)), forkDisabled(false), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + coveredNewError(new box(false)), forkDisabled(false), prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); @@ -161,11 +160,11 @@ ExecutionState::ExecutionState(const ExecutionState &state) : initPC(state.initPC), pc(state.pc), prevPC(state.prevPC), stack(state.stack), stackBalance(state.stackBalance), incomingBBIndex(state.incomingBBIndex), depth(state.depth), - level(state.level), transitionLevel(state.transitionLevel), - addressSpace(state.addressSpace), constraints(state.constraints), - targetForest(state.targetForest), pathOS(state.pathOS), - symPathOS(state.symPathOS), coveredLines(state.coveredLines), - symbolics(state.symbolics), resolvedPointers(state.resolvedPointers), + level(state.level), addressSpace(state.addressSpace), + constraints(state.constraints), targetForest(state.targetForest), + pathOS(state.pathOS), symPathOS(state.symPathOS), + coveredLines(state.coveredLines), symbolics(state.symbolics), + resolvedPointers(state.resolvedPointers), cexPreferences(state.cexPreferences), arrayNames(state.arrayNames), steppedInstructions(state.steppedInstructions), steppedMemoryInstructions(state.steppedMemoryInstructions), @@ -174,11 +173,12 @@ ExecutionState::ExecutionState(const ExecutionState &state) unwindingInformation(state.unwindingInformation ? state.unwindingInformation->clone() : nullptr), - coveredNew(state.coveredNew), forkDisabled(state.forkDisabled), - returnValue(state.returnValue), gepExprBases(state.gepExprBases), - prevTargets_(state.prevTargets_), targets_(state.targets_), - prevHistory_(state.prevHistory_), history_(state.history_), - isTargeted_(state.isTargeted_) { + coveredNew(state.coveredNew), coveredNewError(state.coveredNewError), + forkDisabled(state.forkDisabled), returnValue(state.returnValue), + gepExprBases(state.gepExprBases), prevTargets_(state.prevTargets_), + targets_(state.targets_), prevHistory_(state.prevHistory_), + history_(state.history_), isTargeted_(state.isTargeted_) { + constraints.fork(); queryMetaData.id = state.id; } @@ -193,8 +193,8 @@ ExecutionState *ExecutionState::branch() { } bool ExecutionState::inSymbolics(const MemoryObject *mo) const { - for (auto i : symbolics) { - if (mo->id == i.memoryObject->id) { + for (const auto &symbolic : symbolics) { + if (mo->id == symbolic.memoryObject->id) { return true; } } @@ -206,7 +206,7 @@ ExecutionState *ExecutionState::withStackFrame(KInstIterator caller, ExecutionState *newState = new ExecutionState(*this); newState->setID(); newState->pushFrame(caller, kf); - newState->initPC = kf->blockMap[&*kf->function->begin()]->instructions; + newState->initPC = kf->blockMap[&*kf->function()->begin()]->instructions; newState->pc = newState->initPC; newState->prevPC = newState->pc; return newState; @@ -254,13 +254,12 @@ void ExecutionState::popFrame() { void ExecutionState::addSymbolic(const MemoryObject *mo, const Array *array, KType *type) { - symbolics.emplace_back(ref(mo), array, type); + symbolics.push_back({mo, array, type}); } ref ExecutionState::findMemoryObject(const Array *array) const { - for (unsigned i = 0; i != symbolics.size(); ++i) { - const auto &symbolic = symbolics[i]; + for (const auto &symbolic : symbolics) { if (array == symbolic.array) { return symbolic.memoryObject; } @@ -363,26 +362,6 @@ void ExecutionState::addUniquePointerResolution(ref address, } } -bool ExecutionState::resolveOnSymbolics(const ref &addr, - IDType &result) const { - uint64_t address = addr->getZExtValue(); - - for (const auto &res : symbolics) { - const auto &mo = res.memoryObject; - // Check if the provided address is between start and end of the object - // [mo->address, mo->address + mo->size) or the object is a 0-sized object. - ref size = cast( - constraints.cs().concretization().evaluate(mo->getSizeExpr())); - if ((size->getZExtValue() == 0 && address == mo->address) || - (address - mo->address < size->getZExtValue())) { - result = mo->id; - return true; - } - } - - return false; -} - /**/ llvm::raw_ostream &klee::operator<<(llvm::raw_ostream &os, @@ -406,14 +385,13 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { const CallStackFrame &csf = stack.callStack().at(ri); const StackFrame &sf = stack.valueStack().at(ri); - Function *f = csf.kf->function; - const InstructionInfo &ii = *target->info; + Function *f = csf.kf->function(); out << "\t#" << i; - if (ii.assemblyLine.hasValue()) { - std::stringstream AssStream; - AssStream << std::setw(8) << std::setfill('0') - << ii.assemblyLine.getValue(); - out << AssStream.str(); + auto assemblyLine = target->getKModule()->getAsmLine(target->inst()); + if (assemblyLine.has_value()) { + std::stringstream AsmStream; + AsmStream << std::setw(8) << std::setfill('0') << assemblyLine.value(); + out << AsmStream.str(); } out << " in " << f->getName().str() << "("; // Yawn, we could go up and print varargs if we wanted to. @@ -434,8 +412,9 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { } } out << ")"; - if (ii.file != "") - out << " at " << ii.file << ":" << ii.line; + std::string filepath = target->getSourceFilepath(); + if (!filepath.empty()) + out << " at " << filepath << ":" << target->getLine(); out << "\n"; target = csf.caller; } @@ -450,14 +429,16 @@ void ExecutionState::addCexPreference(const ref &cond) { } BasicBlock *ExecutionState::getInitPCBlock() const { - return initPC->inst->getParent(); + return initPC->inst()->getParent(); } BasicBlock *ExecutionState::getPrevPCBlock() const { - return prevPC->inst->getParent(); + return prevPC->inst()->getParent(); } -BasicBlock *ExecutionState::getPCBlock() const { return pc->inst->getParent(); } +BasicBlock *ExecutionState::getPCBlock() const { + return pc->inst()->getParent(); +} void ExecutionState::increaseLevel() { llvm::BasicBlock *srcbb = getPrevPCBlock(); @@ -465,14 +446,12 @@ void ExecutionState::increaseLevel() { KFunction *kf = prevPC->parent->parent; KModule *kmodule = kf->parent; - if (prevPC->inst->isTerminator() && kmodule->inMainModule(*kf->function)) { + if (prevPC->inst()->isTerminator() && + kmodule->inMainModule(*kf->function())) { auto srcLevel = stack.infoStack().back().multilevel[srcbb].second; stack.infoStack().back().multilevel.replace({srcbb, srcLevel + 1}); level.insert(prevPC->parent); } - if (srcbb != dstbb) { - transitionLevel.insert(std::make_pair(srcbb, dstbb)); - } } bool ExecutionState::isGEPExpr(ref expr) const { diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index a40c6a0982..dd0fd13427 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -12,6 +12,7 @@ #include "AddressSpace.h" +#include "klee/ADT/ImmutableList.h" #include "klee/ADT/ImmutableSet.h" #include "klee/ADT/PersistentMap.h" #include "klee/ADT/PersistentSet.h" @@ -28,6 +29,7 @@ #include "klee/Module/TargetHash.h" #include "klee/Solver/Solver.h" #include "klee/System/Time.h" +#include "klee/Utilities/Math.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -35,6 +37,8 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" DISABLE_WARNING_POP +#include +#include #include #include #include @@ -53,9 +57,7 @@ struct KBlock; struct KInstruction; class MemoryObject; class PTreeNode; -struct InstructionInfo; class Target; -struct TranstionHash; llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const MemoryMap &mm); @@ -118,6 +120,7 @@ struct ExecutionStack { call_stack_ty callStack_; info_stack_ty infoStack_; call_stack_ty uniqueFrames_; + size_t stackSize = 0; unsigned stackBalance = 0; public: @@ -127,10 +130,12 @@ struct ExecutionStack { inline value_stack_ty &valueStack() { return valueStack_; } inline const value_stack_ty &valueStack() const { return valueStack_; } inline const call_stack_ty &callStack() const { return callStack_; } + inline const info_stack_ty &infoStack() const { return infoStack_; } inline info_stack_ty &infoStack() { return infoStack_; } inline const call_stack_ty &uniqueFrames() const { return uniqueFrames_; } inline unsigned size() const { return callStack_.size(); } + inline size_t stackRegisterSize() const { return stackSize; } inline bool empty() const { return callStack_.empty(); } }; @@ -216,7 +221,8 @@ struct Symbolic { const Array *array; KType *type; Symbolic(ref mo, const Array *a, KType *t) - : memoryObject(mo), array(a), type(t) {} + : memoryObject(std::move(mo)), array(a), type(t) {} + Symbolic(const Symbolic &other) = default; Symbolic &operator=(const Symbolic &other) = default; friend bool operator==(const Symbolic &lhs, const Symbolic &rhs) { @@ -287,8 +293,7 @@ class ExecutionState { std::uint32_t depth = 0; /// @brief Exploration level, i.e., number of times KLEE cycled for this state - std::set level; - std::unordered_set transitionLevel; + PersistentSet level; /// @brief Address space used by this state (e.g. Global and Heap) AddressSpace addressSpace; @@ -317,16 +322,14 @@ class ExecutionState { TreeOStream symPathOS; /// @brief Set containing which lines in which files are covered by this state - std::map> coveredLines; + std::map> coveredLines; /// @brief Pointer to the process tree of the current state /// Copies of ExecutionState should not copy ptreeNode PTreeNode *ptreeNode = nullptr; /// @brief Ordered list of symbolics: used to generate test cases. - // - // FIXME: Move to a shared list structure (not critical). - std::vector symbolics; + ImmutableList symbolics; /// @brief map from memory accesses to accessed objects and access offsets. ExprHashMap> resolvedPointers; @@ -366,7 +369,8 @@ class ExecutionState { std::uint32_t id = 0; /// @brief Whether a new instruction was covered in this state - mutable ref> coveredNew; + mutable std::deque>> coveredNew; + mutable ref> coveredNewError; /// @brief Disables forking for this state. Set by user code bool forkDisabled = false; @@ -376,7 +380,7 @@ class ExecutionState { ExprHashMap, llvm::Type *>> gepExprBases; - ReachWithError error = ReachWithError::None; + mutable ReachWithError error = ReachWithError::None; std::atomic terminationReasonType{ HaltExecution::NotHalt}; @@ -428,7 +432,6 @@ class ExecutionState { unsigned size = 0); void addUniquePointerResolution(ref address, const MemoryObject *mo, unsigned size = 0); - bool resolveOnSymbolics(const ref &addr, IDType &result) const; void addConstraint(ref e, const Assignment &c); void addCexPreference(const ref &cond); @@ -492,19 +495,49 @@ class ExecutionState { bool reachedTarget(ref target) const; static std::uint32_t getLastID() { return nextID - 1; }; - inline bool isStuck(unsigned long long bound) { - KInstruction *prevKI = prevPC; - if (prevKI->inst->isTerminator() && stack.size() > 0) { - auto level = stack.infoStack().back().multilevel[getPCBlock()].second; - return bound && level > bound; + inline bool isCycled(unsigned long long bound) const { + if (bound == 0) + return false; + if (prevPC->inst()->isTerminator() && stack.size() > 0) { + auto &ml = stack.infoStack().back().multilevel; + auto level = ml.find(getPCBlock()); + return level != ml.end() && level->second > bound; } if (pc == pc->parent->getFirstInstruction() && pc->parent == pc->parent->parent->entryKBlock) { - auto level = stack.multilevel[stack.callStack().back().kf].second; - return bound && level > bound; + auto level = stack.multilevel.at(stack.callStack().back().kf); + return level > bound; } return false; } + + inline bool isStuck(unsigned long long bound) const { + if (depth == 0) + return false; + return isCycled(bound) && klee::util::ulog2(depth) > bound; + } + + bool isCoveredNew() const { + return !coveredNew.empty() && coveredNew.back()->value; + } + bool isCoveredNewError() const { return coveredNewError->value; } + void coverNew() const { + coveredNew.push_back(new box(true)); + coveredNewError->value = false; + coveredNewError = new box(true); + } + void updateCoveredNew() const { + while (!coveredNew.empty() && !coveredNew.front()->value) { + coveredNew.pop_front(); + } + } + void clearCoveredNew() const { + for (auto signal : coveredNew) { + signal->value = false; + } + coveredNew.clear(); + } + void clearCoveredNewError() const { coveredNewError->value = false; } }; struct ExecutionStateIDCompare { diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 63130c38d8..51e2d6f849 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -32,13 +32,14 @@ #include "TimingSolver.h" #include "TypeManager.h" #include "UserSearcher.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Core/Context.h" #include "klee/ADT/KTest.h" -#include "klee/ADT/RNG.h" #include "klee/Config/Version.h" #include "klee/Config/config.h" #include "klee/Core/Interpreter.h" +#include "klee/Core/MockBuilder.h" #include "klee/Expr/ArrayExprOptimizer.h" #include "klee/Expr/ArrayExprVisitor.h" #include "klee/Expr/Assignment.h" @@ -47,11 +48,11 @@ #include "klee/Expr/ExprPPrinter.h" #include "klee/Expr/ExprSMTLIBPrinter.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/Cell.h" #include "klee/Module/CodeGraphInfo.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KCallable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" @@ -161,8 +162,8 @@ cl::opt UseTypeBasedAliasAnalysis( cl::opt AlignSymbolicPointers("align-symbolic-pointers", cl::desc("Makes symbolic pointers aligned according" - "to the used type system (default=true)"), - cl::init(true), cl::cat(ExecCat)); + "to the used type system (default=false)"), + cl::init(false), cl::cat(ExecCat)); cl::opt ExternCallsCanReturnNull("extern-calls-can-return-null", cl::init(false), @@ -170,24 +171,20 @@ cl::opt "and return null (default=false)"), cl::cat(ExecCat)); -enum class MockMutableGlobalsPolicy { - None, - PrimitiveFields, - All, -}; +cl::opt OSCopySizeMemoryCheckThreshold( + "os-copy-size-mem-check-threshold", cl::init(10000), + cl::desc("Check memory usage when this amount of bytes dense OS is copied"), + cl::cat(ExecCat)); -cl::opt MockMutableGlobals( - "mock-mutable-globals", - cl::values(clEnumValN(MockMutableGlobalsPolicy::None, "none", - "No mutable global object are allowed o mock except " - "external (default)"), - clEnumValN(MockMutableGlobalsPolicy::PrimitiveFields, - "primitive-fields", - "Only primitive fileds of mutable global objects are " - "allowed to mock."), - clEnumValN(MockMutableGlobalsPolicy::All, "all", - "All mutable global object are allowed o mock.")), - cl::init(MockMutableGlobalsPolicy::None), cl::cat(ExecCat)); +cl::opt StackCopySizeMemoryCheckThreshold( + "stack-copy-size-mem-check-threshold", cl::init(10000), + cl::desc("Check memory usage when state with stack this big (in bytes) is " + "copied"), + cl::cat(ExecCat)); + +namespace { + +/*** Lazy initialization options ***/ enum class LazyInitializationPolicy { None, @@ -216,22 +213,36 @@ llvm::cl::opt MinNumberElementsLazyInit( llvm::cl::desc("Minimum number of array elements for one lazy " "initialization (default 4)"), llvm::cl::init(4), llvm::cl::cat(LazyInitCat)); +} // namespace cl::opt FunctionCallReproduce( "function-call-reproduce", cl::init(""), cl::desc("Marks mentioned function as target for error-guided mode."), cl::cat(ExecCat)); + +llvm::cl::opt X86FPAsX87FP80( + "x86FP-as-x87FP80", cl::init(false), + cl::desc("Convert X86 fp values to X87FP80 during computation according to " + "GCC behavior (default=false)"), + cl::cat(ExecCat)); + +cl::opt DumpStatesOnHalt( + "dump-states-on-halt", cl::init(HaltExecution::Reason::Unspecified), + cl::values( + clEnumValN(HaltExecution::Reason::NotHalt, "none", + "Do not dump test cases for all active states on exit."), + clEnumValN(HaltExecution::Reason::UnreachedTarget, "unreached", + "Dump test cases for all active states on exit if error not " + "reached."), + clEnumValN(HaltExecution::Reason::Unspecified, "all", + "Dump test cases for all active states on exit (default)")), + cl::cat(TestGenCat)); } // namespace klee namespace { /*** Test generation options ***/ -cl::opt DumpStatesOnHalt( - "dump-states-on-halt", cl::init(true), - cl::desc("Dump test cases for all active states on exit (default=true)"), - cl::cat(TestGenCat)); - cl::opt OnlyOutputStatesCoveringNew( "only-output-states-covering-new", cl::init(false), cl::desc("Only output test cases covering new code (default=false)"), @@ -246,13 +257,26 @@ cl::opt EmitAllErrors( cl::opt CoverOnTheFly( "cover-on-the-fly", cl::init(false), cl::desc("Generate tests cases for each new covered block or branch " - "(default=false, i.e. one per (error,instruction) pair)"), + "(default=false)"), cl::cat(TestGenCat)); -cl::opt DelayCoverOnTheFly( - "delay-cover-on-the-fly", cl::init(10000), - cl::desc("Start on the fly tests generation after this many instructions " - "(default=10000)"), +cl::opt MemoryTriggerCoverOnTheFly( + "mem-trigger-cof", cl::init(false), + cl::desc("Start on the fly tests generation after approaching memory cup" + "(default=false)"), + cl::cat(TestGenCat)); + +cl::opt DelayCoverOnTheFly( + "delay-cover-on-the-fly", cl::init("0s"), + cl::desc("Start on the fly tests generation after the specified duration. " + "Set to 0s to disable (default=0s)"), + cl::cat(TestGenCat)); + +cl::opt UninitMemoryTestMultiplier( + "uninit-memory-test-multiplier", cl::init(6), + cl::desc("Generate additional number of duplicate tests due to " + "irreproducibility of uninitialized memory " + "(default=6)"), cl::cat(TestGenCat)); /* Constraint solving options */ @@ -311,18 +335,6 @@ cl::opt AllExternalWarnings( "as opposed to once per function (default=false)"), cl::cat(ExtCallsCat)); -cl::opt - MockExternalCalls("mock-external-calls", cl::init(false), - cl::desc("If true, failed external calls are mocked, " - "i.e. return values are made symbolic " - "and then added to generated test cases. " - "If false, fails on externall calls."), - cl::cat(ExtCallsCat)); - -cl::opt MockAllExternals("mock-all-externals", cl::init(false), - cl::desc("If true, all externals are mocked."), - cl::cat(ExtCallsCat)); - /*** Seeding options ***/ cl::opt AlwaysOutputSeeds( @@ -446,6 +458,7 @@ bool allLeafsAreConstant(const ref &expr) { extern llvm::cl::opt MaxConstantAllocationSize; extern llvm::cl::opt MaxSymbolicAllocationSize; extern llvm::cl::opt UseSymbolicSizeAllocation; +extern llvm::cl::opt TrackCoverage; // XXX hack extern "C" unsigned dumpStates, dumpPForest; @@ -479,8 +492,19 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, targetedExecutionManager( new TargetedExecutionManager(*codeGraphInfo, *targetManager)), replayKTest(0), replayPath(0), usingSeeds(0), atMemoryLimit(false), - inhibitForking(false), haltExecution(HaltExecution::NotHalt), - ivcEnabled(false), debugLogBuffer(debugBufferString) { + inhibitForking(false), coverOnTheFly(false), + haltExecution(HaltExecution::NotHalt), ivcEnabled(false), + debugLogBuffer(debugBufferString) { + if (interpreterOpts.MockStrategy == MockStrategyKind::Deterministic && + CoreSolverToUse != Z3_SOLVER) { + klee_error("Deterministic mocks can be generated with Z3 solver only.\n"); + } + if (interpreterOpts.MockStrategy == MockStrategyKind::Deterministic && + interpreterOpts.Mock != MockPolicy::All) { + klee_error("Deterministic mocks can be generated only with " + "`--mock-policy=all`.\n"); + } + const time::Span maxTime{MaxTime}; if (maxTime) timers.add(std::make_unique(maxTime, [&] { @@ -488,6 +512,13 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, setHaltExecution(HaltExecution::MaxTime); })); + if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance) { + const time::Span delayTime{DelayCoverOnTheFly}; + if (delayTime) + timers.add( + std::make_unique(delayTime, [&] { coverOnTheFly = true; })); + } + coreSolverTimeout = time::Span{MaxCoreSolverTime}; if (coreSolverTimeout) UseForkedCoreSolver = true; @@ -507,7 +538,7 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, interpreterHandler->getOutputFilename(SOLVER_QUERIES_SMT2_FILE_NAME), interpreterHandler->getOutputFilename(ALL_QUERIES_KQUERY_FILE_NAME), interpreterHandler->getOutputFilename(SOLVER_QUERIES_KQUERY_FILE_NAME), - addressManager.get()); + addressManager.get(), arrayCache); this->solver = std::make_unique(std::move(solver), optimizer, EqualitySubstitution); @@ -536,20 +567,20 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, } } -llvm::Module * -Executor::setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) { +llvm::Module *Executor::setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals, + std::vector> redefinitions) { assert(!kmodule && !userModules.empty() && "can only register one module"); // XXX gross kmodule = std::make_unique(); // 1.) Link the modules together && 2.) Apply different instrumentation - kmodule->link(userModules, 0); + kmodule->link(userModules, 1); kmodule->instrument(opts); kmodule->link(libsModules, 2); @@ -570,6 +601,33 @@ Executor::setModule(std::vector> &userModules, kmodule->instrument(opts); } + if (interpreterOpts.Mock == MockPolicy::All || + interpreterOpts.MockMutableGlobals == MockMutableGlobalsPolicy::All || + !opts.AnnotationsFile.empty()) { + MockBuilder mockBuilder(kmodule->module.get(), opts, interpreterOpts, + ignoredExternals, redefinitions, interpreterHandler, + mainModuleFunctions, mainModuleGlobals); + std::unique_ptr mockModule = mockBuilder.build(); + + std::vector> mockModules; + mockModules.push_back(std::move(mockModule)); + // std::swap(mockModule, kmodule->module); + kmodule->link(mockModules, 1); + klee_message("Mock linkage: done"); + + for (auto &global : kmodule->module->globals()) { + if (global.isDeclaration()) { + llvm::Constant *zeroInitializer = + llvm::Constant::getNullValue(global.getValueType()); + if (!zeroInitializer) { + klee_error("Unable to get zero initializer for '%s'", + global.getName().str().c_str()); + } + global.setInitializer(zeroInitializer); + } + } + } + // 3.) Optimise and prepare for KLEE // Create a list of functions that should be preserved if used @@ -577,35 +635,42 @@ Executor::setModule(std::vector> &userModules, specialFunctionHandler = new SpecialFunctionHandler(*this); specialFunctionHandler->prepare(preservedFunctions); - preservedFunctions.push_back(opts.EntryPoint.c_str()); - // Preserve the free-standing library calls preservedFunctions.push_back("memset"); preservedFunctions.push_back("memcpy"); preservedFunctions.push_back("memcmp"); preservedFunctions.push_back("memmove"); + for (const auto &p : klee::floatReplacements) { + preservedFunctions.push_back(p.second.c_str()); + } + if (FunctionCallReproduce != "") { - // prevent elimination of the function - auto f = kmodule->module->getFunction(FunctionCallReproduce); - if (f) + preservedFunctions.push_back(FunctionCallReproduce.c_str()); + } + + // prevent elimination of the preservedFunctions functions + for (auto pf : preservedFunctions) { + auto f = kmodule->module->getFunction(pf); + if (f) { f->addFnAttr(Attribute::OptimizeNone); + f->addFnAttr(Attribute::NoInline); + } } + // except the entry point + preservedFunctions.push_back(opts.EntryPoint.c_str()); + kmodule->optimiseAndPrepare(opts, preservedFunctions); kmodule->checkModule(); // 4.) Manifest the module - kmodule->mainModuleFunctions.insert(mainModuleFunctions.begin(), - mainModuleFunctions.end()); - kmodule->mainModuleGlobals.insert(mainModuleGlobals.begin(), - mainModuleGlobals.end()); + std::swap(kmodule->mainModuleFunctions, mainModuleFunctions); + std::swap(kmodule->mainModuleGlobals, mainModuleGlobals); kmodule->manifest(interpreterHandler, interpreterOpts.Guidance, StatsTracker::useStatistics()); - if (origInfos) { - kmodule->origInfos = origInfos->getInstructions(); - } + kmodule->origInstructions = origInstructions; specialFunctionHandler->bind(); @@ -634,6 +699,39 @@ Executor::~Executor() { /***/ +ref X87FP80ToFPTrunc(ref arg, Expr::Width type, + llvm::APFloat::roundingMode rm) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = type; + if (Context::get().getPointerWidth() == 32 && arg->getWidth() == Expr::Fl80) { + result = FPTruncExpr::create(arg, resultType, rm); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif + return result; +} + +ref FPToX87FP80Ext(ref arg) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = Expr::Fl80; + if (Context::get().getPointerWidth() == 32) { + result = FPExtExpr::create(arg, resultType); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif + return result; +} + void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, const Constant *c, unsigned offset) { const auto targetData = kmodule->targetData.get(); @@ -667,12 +765,18 @@ void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, offset + i * elementSize); } else if (!isa(c) && !isa(c)) { unsigned StoreBits = targetData->getTypeStoreSizeInBits(c->getType()); - ref C = evalConstant(c, state.roundingMode); + ref C = evalConstant(c, state.roundingMode); + + if (c->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + C = X87FP80ToFPTrunc(C, getWidthForLLVMType(c->getType()), + state.roundingMode); + } // Extend the constant if necessary; assert(StoreBits >= C->getWidth() && "Invalid store size!"); if (StoreBits > C->getWidth()) - C = C->ZExt(StoreBits); + C = ZExtExpr::create(C, StoreBits); os->write(offset, C); } @@ -750,9 +854,9 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { true, nullptr, 8); errnoObj->isFixed = true; - ObjectState *os = bindObjectInState( - state, errnoObj, typeSystemManager->getWrappedType(pointerErrnoAddr), - false); + bindObjectInState(state, errnoObj, + typeSystemManager->getWrappedType(pointerErrnoAddr), + false); errno_addr = reinterpret_cast(errnoObj->address); } else { errno_addr = getErrnoLocation(state); @@ -813,10 +917,10 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { for (const GlobalVariable &v : m->globals()) { std::size_t globalObjectAlignment = getAllocationAlignment(&v); Type *ty = v.getValueType(); - std::uint64_t size = 0; + ref size = Expr::createPointer(0); if (ty->isSized()) { // size includes padding - size = kmodule->targetData->getTypeAllocSize(ty); + size = Expr::createPointer(kmodule->targetData->getTypeAllocSize(ty)); } if (v.isDeclaration()) { // FIXME: We have no general way of handling unknown external @@ -832,30 +936,33 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { // XXX - DWD - hardcode some things until we decide how to fix. #ifndef WINDOWS if (v.getName() == "_ZTVN10__cxxabiv117__class_type_infoE") { - size = 0x2C; + size = Expr::createPointer(0x2C); } else if (v.getName() == "_ZTVN10__cxxabiv120__si_class_type_infoE") { - size = 0x2C; + size = Expr::createPointer(0x2C); } else if (v.getName() == "_ZTVN10__cxxabiv121__vmi_class_type_infoE") { - size = 0x2C; + size = Expr::createPointer(0x2C); } #endif - if (size == 0) { - klee_warning("Unable to find size for global variable: %.*s (use will " - "result in out of bounds access)", + if (size->isZero()) { + const Array *array = makeArray( + Expr::createPointer(Context::get().getPointerWidthInBytes()), + SourceBuilder::irreproducible(v.getName().str())); + size = Expr::createTempRead(array, Context::get().getPointerWidth()); + klee_warning("Unable to find size for global variable: %.*s (model " + "size as symbolic with irreproducible content)", static_cast(v.getName().size()), v.getName().data()); } } - MemoryObject *mo = - memory->allocate(size, /*isLocal=*/false, - /*isGlobal=*/true, false, /*allocSite=*/&v, - /*alignment=*/globalObjectAlignment); + MemoryObject *mo = allocate(state, size, /*isLocal=*/false, + /*isGlobal=*/true, /*allocSite=*/&v, + /*alignment=*/globalObjectAlignment); if (!mo) klee_error("out of memory"); globalObjects.emplace(&v, mo); - globalAddresses.emplace(&v, mo->getBaseConstantExpr()); + globalAddresses.emplace(&v, mo->getBaseExpr()); } } @@ -905,45 +1012,39 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { for (const GlobalVariable &v : m->globals()) { MemoryObject *mo = globalObjects.find(&v)->second; ObjectState *os = bindObjectInState( - state, mo, typeSystemManager->getWrappedType(v.getType()), false); - - if (v.isDeclaration() && mo->size) { - // Program already running -> object already initialized. - // Read concrete value and write it to our copy. - void *addr; - if (v.getName() == "__dso_handle") { - addr = &__dso_handle; // wtf ? + state, mo, typeSystemManager->getWrappedType(v.getType()), false, + nullptr); + + if (v.isDeclaration()) { + if (isa(mo->getSizeExpr())) { + // Program already running -> object already initialized. + // Read concrete value and write it to our copy. + void *addr; + if (v.getName() == "__dso_handle") { + addr = &__dso_handle; // wtf ? + } else { + addr = externalDispatcher->resolveSymbol(v.getName().str()); + } + if (!addr) { + klee_error("Unable to load symbol(%.*s) while initializing globals", + static_cast(v.getName().size()), v.getName().data()); + } else { + for (unsigned offset = 0; offset < mo->size; offset++) { + os->write8(offset, static_cast(addr)[offset]); + } + } } else { - addr = externalDispatcher->resolveSymbol(v.getName().str()); - } - if (MockAllExternals && !addr) { executeMakeSymbolic( state, mo, typeSystemManager->getWrappedType(v.getType()), - SourceBuilder::irreproducible("mockExternGlobalObject"), false); - } else if (!addr) { - klee_error("Unable to load symbol(%.*s) while initializing globals", - static_cast(v.getName().size()), v.getName().data()); - } else { - for (unsigned offset = 0; offset < mo->size; offset++) { - os->write8(offset, static_cast(addr)[offset]); - } + SourceBuilder::irreproducible("unsizedGlobal"), false); } } else if (v.hasInitializer()) { - if (!v.isConstant() && kmodule->inMainModule(v) && - MockMutableGlobals == MockMutableGlobalsPolicy::All) { - executeMakeSymbolic( - state, mo, typeSystemManager->getWrappedType(v.getType()), - SourceBuilder::irreproducible("mockMutableGlobalObject"), false); - } else { - initializeGlobalObject(state, os, v.getInitializer(), 0); - if (v.isConstant()) { - os->setReadOnly(true); - // initialise constant memory that may be used with external calls - state.addressSpace.copyOutConcrete(mo, os); - } + initializeGlobalObject(state, os, v.getInitializer(), 0); + if (v.isConstant()) { + os->setReadOnly(true); + // initialise constant memory that may be used with external calls + state.addressSpace.copyOutConcrete(mo, os, {}); } - } else { - os->initializeToRandom(); } } } @@ -1108,7 +1209,7 @@ ref Executor::maxStaticPctChecks(ExecutionState ¤t, std::string msg("skipping fork and concretizing condition (MaxStatic*Pct " "limit reached) at "); llvm::raw_string_ostream os(msg); - os << current.prevPC->getSourceLocation(); + os << current.prevPC->getSourceLocationString(); klee_warning_once(0, "%s", os.str().c_str()); addConstraint(current, EqExpr::create(value, condition)); @@ -1439,9 +1540,9 @@ void Executor::addConstraint(ExecutionState &state, ref condition) { if (!concretization.isEmpty()) { // Update memory objects if arrays have affected them. + updateStateWithSymcretes(state, concretization); Assignment delta = state.constraints.cs().concretization().diffWith(concretization); - updateStateWithSymcretes(state, delta); state.addConstraint(condition, delta); } else { state.addConstraint(condition, {}); @@ -1455,7 +1556,7 @@ void Executor::addConstraint(ExecutionState &state, ref condition) { const Cell &Executor::eval(const KInstruction *ki, unsigned index, ExecutionState &state, StackFrame &sf, bool isSymbolic) { - assert(index < ki->inst->getNumOperands()); + assert(index < ki->inst()->getNumOperands()); int vnumber = ki->operands[index]; assert(vnumber != -1 && @@ -1526,8 +1627,8 @@ ref Executor::toConstant(ExecutionState &state, ref e, std::string str; llvm::raw_string_ostream os(str); os << "silently concretizing (reason: " << reason << ") expression " << e - << " to value " << value << " (" << (*(state.pc)).info->file << ":" - << (*(state.pc)).info->line << ")"; + << " to value " << value << " (" << state.pc->getSourceFilepath() << ":" + << state.pc->getLine() << ")"; if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -1606,10 +1707,13 @@ void Executor::printDebugInstructions(ExecutionState &state) { // [src] src location:asm line:state ID if (!DebugPrintInstructions.isSet(STDERR_COMPACT) && !DebugPrintInstructions.isSet(FILE_COMPACT)) { - (*stream) << " " << state.pc->getSourceLocation() << ':'; + (*stream) << " " << state.pc->getSourceLocationString() << ':'; } - if (state.pc->info->assemblyLine.hasValue()) { - (*stream) << state.pc->info->assemblyLine.getValue() << ':'; + { + auto asmLine = state.pc->getKModule()->getAsmLine(state.pc->inst()); + if (asmLine.has_value()) { + (*stream) << asmLine.value() << ':'; + } } (*stream) << state.getID() << ":"; (*stream) << "["; @@ -1620,7 +1724,7 @@ void Executor::printDebugInstructions(ExecutionState &state) { if (DebugPrintInstructions.isSet(STDERR_ALL) || DebugPrintInstructions.isSet(FILE_ALL)) - (*stream) << ':' << *(state.pc->inst); + (*stream) << ':' << *(state.pc->inst()); (*stream) << '\n'; @@ -1641,7 +1745,7 @@ void Executor::stepInstruction(ExecutionState &state) { ++stats::instructions; ++state.steppedInstructions; - if (isa(state.pc->inst) || isa(state.pc->inst)) { + if (isa(state.pc->inst()) || isa(state.pc->inst())) { ++state.steppedMemoryInstructions; } state.prevPC = state.pc; @@ -1691,7 +1795,11 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state, llvm::GlobalValue *clause_type = dyn_cast(clause_bitcast->getOperand(0)); - ti_addr = globalAddresses[clause_type]->getZExtValue(); + // Since global variable may have symbolic address, + // here we must guarantee that the address of clause is + // constant (which seems to be true). + ti_addr = + cast(globalAddresses[clause_type])->getZExtValue(); } else if (current_clause->isNullValue()) { ti_addr = 0; } else { @@ -1751,8 +1859,10 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state, return nullptr; } + // We assume again that the clause_value is a + // constant global. std::uint64_t const ti_addr = - globalAddresses[clause_value]->getZExtValue(); + cast(globalAddresses[clause_value])->getZExtValue(); const std::size_t old_size = serialized.size(); serialized.resize(old_size + 8); @@ -1777,9 +1887,9 @@ void Executor::unwindToNextLandingpad(ExecutionState &state) { UnwindingInformation *ui = state.unwindingInformation.get(); assert(ui && "unwinding without unwinding information"); - std::size_t startIndex; - std::size_t lowestStackIndex; - bool popFrames; + std::size_t startIndex = 0; + std::size_t lowestStackIndex = 0; + bool popFrames = false; if (auto *sui = dyn_cast(ui)) { startIndex = sui->unwindingProgress; @@ -1796,7 +1906,7 @@ void Executor::unwindToNextLandingpad(ExecutionState &state) { for (std::size_t i = startIndex; i > lowestStackIndex; i--) { auto const &sf = state.stack.callStack().at(i); - Instruction *inst = sf.caller ? sf.caller->inst : nullptr; + Instruction *inst = sf.caller ? sf.caller->inst() : nullptr; if (popFrames) { state.popFrame(); @@ -1901,7 +2011,7 @@ ref Executor::getEhTypeidFor(ref type_info) { void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, std::vector> &arguments) { - Instruction *i = ki->inst; + Instruction *i = ki->inst(); if (isa_and_nonnull(i)) return; if (f && f->isDeclaration()) { @@ -1954,6 +2064,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, #endif break; } +#ifdef ENABLE_FP case Intrinsic::sqrt: { ref op = eval(ki, 1, state).value; ref result = FSqrtExpr::create(op, state.roundingMode); @@ -1996,6 +2107,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, bindLocal(ki, state, result); break; } +#endif case Intrinsic::fma: case Intrinsic::fmuladd: { @@ -2222,7 +2334,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, KFunction *kf = kmodule->functionMap[f]; state.pushFrame(state.prevPC, kf); - transferToBasicBlock(&*kf->function->begin(), state.getPrevPCBlock(), + transferToBasicBlock(&*kf->function()->begin(), state.getPrevPCBlock(), state); if (statsTracker) @@ -2307,7 +2419,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, StackFrame &sf = state.stack.valueStack().back(); MemoryObject *mo = sf.varargs = - memory->allocate(size, true, false, false, state.prevPC->inst, + memory->allocate(size, true, false, false, state.prevPC->inst(), (requires16ByteAlignment ? 16 : 8)); if (!mo && size) { terminateStateOnExecError(state, "out of memory (varargs)"); @@ -2341,7 +2453,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, const ObjectState *osarg = state.addressSpace.findObject(idObject).second; assert(osarg); - for (unsigned i = 0; i < osarg->size; i++) + for (unsigned i = 0; i < osarg->getObject()->size; i++) os->write(offsets[k] + i, osarg->read8(i)); } if (ati != f->arg_end()) { @@ -2390,8 +2502,8 @@ void Executor::transferToBasicBlock(KBlock *kdst, BasicBlock *src, // XXX this lookup has to go ? state.pc = kdst->instructions; state.increaseLevel(); - if (state.pc->inst->getOpcode() == Instruction::PHI) { - PHINode *first = static_cast(state.pc->inst); + if (state.pc->inst()->getOpcode() == Instruction::PHI) { + PHINode *first = static_cast(state.pc->inst()); state.incomingBBIndex = first->getBasicBlockIndex(src); } increaseProgressVelocity(state, kdst); @@ -2431,7 +2543,7 @@ void Executor::checkNullCheckAfterDeref(ref cond, ExecutionState &state, } void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { - Instruction *i = ki->inst; + Instruction *i = ki->inst(); if (guidanceKind == GuidanceKind::ErrorGuidance) { for (auto kvp : state.targetForest) { @@ -2451,7 +2563,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::Ret: { ReturnInst *ri = cast(i); KInstIterator kcaller = state.stack.callStack().back().caller; - Instruction *caller = kcaller ? kcaller->inst : nullptr; + Instruction *caller = kcaller ? kcaller->inst() : nullptr; bool isVoidReturn = (ri->getNumOperands() == 0); ref result = ConstantExpr::alloc(0, Expr::Bool); @@ -2522,6 +2634,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Expr::Width from = result->getWidth(); Expr::Width to = getWidthForLLVMType(t); + if (X86FPAsX87FP80 && t->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + to = Expr::Fl80; + } + if (from != to) { const CallBase &cb = cast(*caller); @@ -2570,11 +2687,17 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Executor::StatePair branches = fork(state, cond, ifTrueBlock, ifFalseBlock, BranchType::Conditional); + if (branches.first && branches.second) { + maxNewStateStackSize = + std::max(maxNewStateStackSize, + branches.first->stack.stackRegisterSize() * 8); + } + // NOTE: There is a hidden dependency here, markBranchVisited // requires that we still be in the context of the branch // instruction (it reuses its statistic id). Should be cleaned // up with convenient instruction specific data. - if (statsTracker && state.stack.callStack().back().kf->trackCoverage) + if (statsTracker) statsTracker->markBranchVisited(branches.first, branches.second); if (branches.first) @@ -2877,18 +3000,19 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { } else { ref v = eval(ki, 0, state).value; - if (!isa(v) && MockExternalCalls) { - if (ki->inst->getType()->isSized()) { - prepareMockValue(state, "mockExternResult", ki); - } - } else { - ExecutionState *free = &state; - bool hasInvalid = false, first = true; - - /* XXX This is wasteful, no need to do a full evaluate since we - have already got a value. But in the end the caches should - handle it for us, albeit with some overhead. */ - do { + ExecutionState *free = &state; + bool hasInvalid = false, first = true; + + /* XXX This is wasteful, no need to do a full evaluate since we + have already got a value. But in the end the caches should + handle it for us, albeit with some overhead. */ + do { + if (!first && interpreterOpts.Mock == MockPolicy::Failed) { + free = nullptr; + if (ki->inst()->getType()->isSized()) { + prepareMockValue(state, "mockExternResult", ki); + } + } else { v = optimizer.optimizeExpr(v, true); ref value; bool success = solver->getValue(free->constraints.cs(), v, value, @@ -2921,8 +3045,8 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { first = false; free = res.second; timers.invoke(); - } while (free && !haltExecution); - } + } + } while (free && !haltExecution); } break; } @@ -3174,7 +3298,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { executeMemoryOperation( state, false, typeSystemManager->getWrappedType( - cast(ki->inst)->getPointerOperandType()), + cast(ki->inst())->getPointerOperandType()), base, 0, ki); break; } @@ -3184,14 +3308,15 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { executeMemoryOperation( state, true, typeSystemManager->getWrappedType( - cast(ki->inst)->getPointerOperandType()), + cast(ki->inst())->getPointerOperandType()), base, value, ki); break; } case Instruction::GetElementPtr: { KGEPInstruction *kgepi = static_cast(ki); - GetElementPtrInst *gepInst = static_cast(kgepi->inst); + GetElementPtrInst *gepInst = + static_cast(kgepi->inst()); ref base = eval(ki, 0, state).value; ref offset = ConstantExpr::create(0, base->getWidth()); @@ -3262,9 +3387,23 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::BitCast: { ref result = eval(ki, 0, state).value; - BitCastInst *bc = cast(ki->inst); + BitCastInst *bc = cast(ki->inst()); llvm::Type *castToType = bc->getType(); + + if (X86FPAsX87FP80 && result->getWidth() == Expr::Fl80 && + !castToType->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = X87FP80ToFPTrunc( + result, getWidthForLLVMType(bc->getOperand(0)->getType()), + state.roundingMode); + } + + if (X86FPAsX87FP80 && castToType->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (castToType->isPointerTy()) { castToType = castToType->getPointerElementType(); } @@ -3642,9 +3781,12 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { ref arg = eval(ki, 0, state).value; if (!fpWidthToSemantics(arg->getWidth()) || !fpWidthToSemantics(resultType)) return terminateStateOnExecError(state, "Unsupported FPTrunc operation"); - if (arg->getWidth() <= resultType) - return terminateStateOnExecError(state, "Invalid FPTrunc"); - ref result = FPTruncExpr::create(arg, resultType, state.roundingMode); + ref result = arg; + if (arg->getWidth() > resultType) + result = FPTruncExpr::create(arg, resultType, state.roundingMode); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } bindLocal(ki, state, result); break; } @@ -3655,9 +3797,14 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { ref arg = eval(ki, 0, state).value; if (!fpWidthToSemantics(arg->getWidth()) || !fpWidthToSemantics(resultType)) return terminateStateOnExecError(state, "Unsupported FPExt operation"); - if (arg->getWidth() >= resultType) - return terminateStateOnExecError(state, "Invalid FPExt"); - ref result = FPExtExpr::create(arg, resultType); + ref result = arg; + if (arg->getWidth() < resultType) { + // return terminateStateOnExecError(state, "Invalid FPExt"); + result = FPExtExpr::create(arg, resultType); + } + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } bindLocal(ki, state, result); break; } @@ -3691,6 +3838,9 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::UIToFP: { UIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + resultType = Expr::Fl80; + } ref arg = eval(ki, 0, state).value; const llvm::fltSemantics *semantics = fpWidthToSemantics(resultType); if (!semantics) @@ -3703,6 +3853,9 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::SIToFP: { SIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + resultType = Expr::Fl80; + } ref arg = eval(ki, 0, state).value; const llvm::fltSemantics *semantics = fpWidthToSemantics(resultType); if (!semantics) @@ -3956,6 +4109,10 @@ void Executor::updateStates(ExecutionState *current) { targetedExecutionManager->update(current, addedStates, removedStates); } + if (targetCalculator) { + targetCalculator->update(current, addedStates, removedStates); + } + if (searcher) { searcher->update(current, addedStates, removedStates); } @@ -3991,7 +4148,7 @@ void Executor::computeOffsetsSeqTy(KGEPInstruction *kgepi, const Value *operand = it.getOperand(); if (const Constant *c = dyn_cast(operand)) { ref index = - evalConstant(c, llvm::APFloat::rmNearestTiesToEven) + cast(evalConstant(c, llvm::APFloat::rmNearestTiesToEven)) ->SExt(Context::get().getPointerWidth()); ref addend = index->Mul( ConstantExpr::alloc(elementSize, Context::get().getPointerWidth())); @@ -4023,14 +4180,14 @@ void Executor::computeOffsets(KGEPInstruction *kgepi, TypeIt ib, TypeIt ie) { } void Executor::bindInstructionConstants(KInstruction *KI) { - if (GetElementPtrInst *gepi = dyn_cast(KI->inst)) { + if (GetElementPtrInst *gepi = dyn_cast(KI->inst())) { KGEPInstruction *kgepi = static_cast(KI); computeOffsets(kgepi, gep_type_begin(gepi), gep_type_end(gepi)); - } else if (InsertValueInst *ivi = dyn_cast(KI->inst)) { + } else if (InsertValueInst *ivi = dyn_cast(KI->inst())) { KGEPInstruction *kgepi = static_cast(KI); computeOffsets(kgepi, iv_type_begin(ivi), iv_type_end(ivi)); assert(kgepi->indices.empty() && "InsertValue constant offset expected"); - } else if (ExtractValueInst *evi = dyn_cast(KI->inst)) { + } else if (ExtractValueInst *evi = dyn_cast(KI->inst())) { KGEPInstruction *kgepi = static_cast(KI); computeOffsets(kgepi, ev_type_begin(evi), ev_type_end(evi)); assert(kgepi->indices.empty() && "ExtractValue constant offset expected"); @@ -4059,13 +4216,24 @@ bool Executor::checkMemoryUsage() { // We need to avoid calling GetTotalMallocUsage() often because it // is O(elts on freelist). This is really bad since we start // to pummel the freelist once we hit the memory cap. - if ((stats::instructions & 0xFFFFU) != 0) // every 65536 instructions + // every 65536 instructions + if ((stats::instructions & 0xFFFFU) != 0 && + maxNewWriteableOSSize < OSCopySizeMemoryCheckThreshold && + maxNewStateStackSize < StackCopySizeMemoryCheckThreshold) return true; // check memory limit const auto mallocUsage = util::GetTotalMallocUsage() >> 20U; const auto mmapUsage = memory->getUsedDeterministicSize() >> 20U; const auto totalUsage = mallocUsage + mmapUsage; + + if (MemoryTriggerCoverOnTheFly && totalUsage > MaxMemory * 0.75) { + klee_warning_once(0, + "enabling cover-on-the-fly (close to memory cap: %luMB)", + totalUsage); + coverOnTheFly = true; + } + atMemoryLimit = totalUsage > MaxMemory; // inhibit forking if (!atMemoryLimit) return true; @@ -4087,7 +4255,7 @@ bool Executor::checkMemoryUsage() { unsigned idx = theRNG.getInt32() % N; // Make two pulls to try and not hit a state that // covered new code. - if (arr[idx]->coveredNew->value) + if (arr[idx]->isCoveredNew()) idx = theRNG.getInt32() % N; std::swap(arr[idx], arr[N - 1]); @@ -4117,11 +4285,19 @@ void Executor::decreaseConfidenceFromStoppedStates( } void Executor::doDumpStates() { - if (!DumpStatesOnHalt || states.empty()) { + if (DumpStatesOnHalt == HaltExecution::Reason::NotHalt || + (DumpStatesOnHalt == HaltExecution::Reason::UnreachedTarget && + haltExecution == HaltExecution::Reason::ReachedTarget) || + states.empty()) { interpreterHandler->incPathsExplored(states.size()); return; } + if (FunctionCallReproduce != "" && + haltExecution != HaltExecution::Reason::ReachedTarget) { + haltExecution = HaltExecution::UnreachedTarget; + } + klee_message("halting execution, dumping remaining states"); for (const auto &state : pausedStates) terminateStateEarly(*state, "Execution halting (paused state).", @@ -4251,11 +4427,11 @@ void Executor::reportProgressTowardsTargets(std::string prefix, repr << ": "; } repr << "in function " + - target->getBlock()->parent->function->getName().str(); + target->getBlock()->parent->function()->getName().str(); repr << " (lines "; - repr << target->getBlock()->getFirstInstruction()->info->line; + repr << target->getBlock()->getFirstInstruction()->getLine(); repr << " to "; - repr << target->getBlock()->getLastInstruction()->info->line; + repr << target->getBlock()->getLastInstruction()->getLine(); repr << ")"; std::string targetString = repr.str(); klee_message("%s for %s", distance.toString().c_str(), @@ -4268,17 +4444,15 @@ void Executor::reportProgressTowardsTargets() const { reportProgressTowardsTargets("", states); } -void Executor::run(std::vector initialStates) { +void Executor::run(ExecutionState *initialState) { // Delay init till now so that ticks don't accrue during optimization and // such. if (guidanceKind != GuidanceKind::ErrorGuidance) timers.reset(); - states.insert(initialStates.begin(), initialStates.end()); + states.insert(initialState); if (usingSeeds) { - assert(initialStates.size() == 1); - ExecutionState *initialState = initialStates.back(); seed(*initialState); } @@ -4294,13 +4468,6 @@ void Executor::run(std::vector initialStates) { while (!states.empty() && !haltExecution) { while (!searcher->empty() && !haltExecution) { ExecutionState &state = searcher->selectState(); - KInstruction *prevKI = state.prevPC; - KFunction *kf = prevKI->parent->parent; - - if (prevKI->inst->isTerminator() && - kmodule->inMainModule(*kf->function)) { - targetCalculator->update(state); - } executeStep(state); } @@ -4359,9 +4526,9 @@ void Executor::initializeTypeManager() { typeSystemManager->initModule(); } -static bool shouldWriteTest(const ExecutionState &state) { - bool coveredNew = state.coveredNew->value; - state.coveredNew->value = false; +static bool shouldWriteTest(const ExecutionState &state, bool isError = false) { + state.updateCoveredNew(); + bool coveredNew = isError ? state.isCoveredNewError() : state.isCoveredNew(); return !OnlyOutputStatesCoveringNew || coveredNew; } @@ -4379,10 +4546,10 @@ static std::string terminationTypeFileExtension(StateTerminationType type) { }; void Executor::executeStep(ExecutionState &state) { - KInstruction *prevKI = state.prevPC; + KFunction *initKF = state.initPC->parent->parent; - if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance && - stats::instructions > DelayCoverOnTheFly && shouldWriteTest(state)) { + if (coverOnTheFly && shouldWriteTest(state)) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, nullptr, terminationTypeFileExtension(StateTerminationType::CoverOnTheFly) @@ -4392,16 +4559,12 @@ void Executor::executeStep(ExecutionState &state) { if (targetManager->isTargeted(state) && state.targets().empty()) { terminateStateEarlyAlgorithm(state, "State missed all it's targets.", StateTerminationType::MissedAllTargets); - } else if (prevKI->inst->isTerminator() && MaxCycles && - (state.stack.infoStack() - .back() - .multilevel[state.getPCBlock()] - .second > MaxCycles || - state.stack.multilevel[state.stack.callStack().back().kf].second > - MaxCycles)) { + } else if (state.isCycled(MaxCycles)) { terminateStateEarly(state, "max-cycles exceeded.", StateTerminationType::MaxCycles); } else { + maxNewWriteableOSSize = 0; + maxNewStateStackSize = 0; KInstruction *ki = state.pc; stepInstruction(state); executeInstruction(state, ki); @@ -4420,6 +4583,11 @@ void Executor::executeStep(ExecutionState &state) { // pressure updateStates(nullptr); } + + if (targetCalculator && TrackCoverage != TrackCoverageBy::None && + targetCalculator->isCovered(initKF)) { + haltExecution = HaltExecution::CovCheck; + } } void Executor::targetedRun(ExecutionState &initialState, KBlock *target, @@ -4568,7 +4736,6 @@ void Executor::terminateState(ExecutionState &state, interpreterHandler->incPathsExplored(); state.pc = state.prevPC; - targetCalculator->update(state); solver->notifyStateTermination(state.id); removedStates.push_back(&state); @@ -4577,9 +4744,11 @@ void Executor::terminateState(ExecutionState &state, void Executor::terminateStateOnExit(ExecutionState &state) { auto terminationType = StateTerminationType::Exit; ++stats::terminationExit; - if (shouldWriteTest(state) || (AlwaysOutputSeeds && seedMap.count(&state))) + if (shouldWriteTest(state) || (AlwaysOutputSeeds && seedMap.count(&state))) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, nullptr, terminationTypeFileExtension(terminationType).c_str()); + } interpreterHandler->incPathsCompleted(); terminateState(state, terminationType); @@ -4596,6 +4765,7 @@ void Executor::terminateStateEarly(ExecutionState &state, const Twine &message, reason == StateTerminationType::MissedAllTargets) && shouldWriteTest(state)) || (AlwaysOutputSeeds && seedMap.count(&state))) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, (message + "\n").str().c_str(), terminationTypeFileExtension(reason).c_str(), @@ -4620,24 +4790,21 @@ void Executor::terminateStateEarlyUser(ExecutionState &state, terminateStateEarly(state, message, StateTerminationType::SilentExit); } -const InstructionInfo & -Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, - Instruction **lastInstruction) { +const KInstruction * +Executor::getLastNonKleeInternalInstruction(const ExecutionState &state) { // unroll the stack of the applications state and find // the last instruction which is not inside a KLEE internal function - ExecutionStack::call_stack_ty::const_reverse_iterator - it = state.stack.callStack().rbegin(), - itE = state.stack.callStack().rend(); + auto it = state.stack.callStack().rbegin(); + auto itE = state.stack.callStack().rend(); // don't check beyond the outermost function (i.e. main()) itE--; - const InstructionInfo *ii = 0; - if (kmodule->internalFunctions.count(it->kf->function) == 0) { - ii = state.prevPC->info; - *lastInstruction = state.prevPC->inst; + const KInstruction *ki = nullptr; + if (kmodule->internalFunctions.count(it->kf->function()) == 0) { + ki = state.prevPC; // Cannot return yet because even though - // it->function is not an internal function it might of + // it->function() is not an internal function it might of // been called from an internal function. } @@ -4647,23 +4814,21 @@ Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, for (; it != itE; ++it) { // check calling instruction and if it is contained in a KLEE internal // function - const Function *f = (*it->caller).inst->getParent()->getParent(); + const Function *f = (*it->caller).inst()->getParent()->getParent(); if (kmodule->internalFunctions.count(f)) { - ii = 0; + ki = nullptr; continue; } - if (!ii) { - ii = (*it->caller).info; - *lastInstruction = (*it->caller).inst; + if (!ki) { + ki = it->caller; } } - if (!ii) { + if (!ki) { // something went wrong, play safe and return the current instruction info - *lastInstruction = state.prevPC->inst; - return *state.prevPC->info; + return state.prevPC; } - return *ii; + return ki; } bool shouldExitOn(StateTerminationType reason) { @@ -4722,14 +4887,15 @@ void Executor::terminateStateOnError(ExecutionState &state, const char *suffix) { std::string message = messaget.str(); static std::set> emittedErrors; - Instruction *lastInst; - const InstructionInfo &ii = - getLastNonKleeInternalInstruction(state, &lastInst); - - if (EmitAllErrors || - emittedErrors.insert(std::make_pair(lastInst, message)).second) { - if (!ii.file.empty()) { - klee_message("ERROR: %s:%d: %s", ii.file.c_str(), ii.line, + const KInstruction *ki = getLastNonKleeInternalInstruction(state); + Instruction *lastInst = ki->inst(); + + if ((EmitAllErrors || + emittedErrors.insert(std::make_pair(lastInst, message)).second) && + shouldWriteTest(state, true)) { + std::string filepath = ki->getSourceFilepath(); + if (!filepath.empty()) { + klee_message("ERROR: %s:%zu: %s", filepath.c_str(), ki->getLine(), message.c_str()); } else { klee_message("ERROR: (location information missing) %s", message.c_str()); @@ -4740,10 +4906,13 @@ void Executor::terminateStateOnError(ExecutionState &state, std::string MsgString; llvm::raw_string_ostream msg(MsgString); msg << "Error: " << message << '\n'; - if (!ii.file.empty()) { - msg << "File: " << ii.file << '\n' << "Line: " << ii.line << '\n'; - if (ii.assemblyLine.hasValue()) { - msg << "assembly.ll line: " << ii.assemblyLine.getValue() << '\n'; + if (!filepath.empty()) { + msg << "File: " << filepath << '\n' << "Line: " << ki->getLine() << '\n'; + { + auto asmLine = ki->getKModule()->getAsmLine(ki->inst()); + if (asmLine.has_value()) { + msg << "assembly.ll line: " << asmLine.value() << '\n'; + } } msg << "State: " << state.getID() << '\n'; } @@ -4754,6 +4923,8 @@ void Executor::terminateStateOnError(ExecutionState &state, if (!info_str.empty()) msg << "Info: \n" << info_str; + state.clearCoveredNewError(); + const std::string ext = terminationTypeFileExtension(terminationType); // use user provided suffix from klee_report_error() const char *file_suffix = suffix ? suffix : ext.c_str(); @@ -4810,7 +4981,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, std::vector> &arguments) { // check if specialFunctionHandler wants it if (const auto *func = dyn_cast(callable)) { - if (specialFunctionHandler->handle(state, func->function, target, + if (specialFunctionHandler->handle(state, func->function(), target, arguments)) return; } @@ -4823,28 +4994,6 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - if (ExternalCalls == ExternalCallPolicy::All && MockAllExternals) { - std::string TmpStr; - llvm::raw_string_ostream os(TmpStr); - os << "calling external: " << callable->getName().str() << "("; - for (unsigned i = 0; i < arguments.size(); i++) { - os << arguments[i]; - if (i != arguments.size() - 1) - os << ", "; - } - os << ") at " << state.pc->getSourceLocation(); - - if (AllExternalWarnings) - klee_warning("%s", os.str().c_str()); - else if (!SuppressExternalWarnings) - klee_warning_once(callable->getValue(), "%s", os.str().c_str()); - - if (target->inst->getType()->isSized()) { - prepareMockValue(state, "mockExternResult", target); - } - return; - } - // normal external function handling path // allocate 512 bits for each argument (+return value) to support // fp80's and SIMD vectors as parameters for external calls; @@ -4873,19 +5022,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, assert(success && "FIXME: Unhandled solver failure"); (void)success; ce->toMemory(&args[wordIndex]); - IDType result; addConstraint(state, EqExpr::create(ce, *ai)); - // Checking to see if the argument is a pointer to something - llvm::Type *argumentType = nullptr; - if (ati != functionType->param_end()) { - argumentType = const_cast(*ati); - } - if (ce->getWidth() == Context::get().getPointerWidth() && - state.addressSpace.resolveOne( - ce, typeSystemManager->getWrappedType(argumentType), result)) { - state.addressSpace.findObject(result).second->flushToConcreteStore( - solver.get(), state); - } wordIndex += (ce->getWidth() + 63) / 64; } else { ref arg = toUnique(state, *ai); @@ -4910,7 +5047,12 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, } // Prepare external memory for invoking the function - state.addressSpace.copyOutConcretes(); + auto arrays = state.constraints.cs().gatherArrays(); + std::vector> values; + solver->getInitialValues(state.constraints.cs(), arrays, values, + state.queryMetaData); + Assignment assignment(arrays, values); + state.addressSpace.copyOutConcretes(assignment); #ifndef WINDOWS // Update external errno state with local state value IDType idResult; @@ -4950,12 +5092,12 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (i != arguments.size() - 1) os << ", "; } - os << ") at " << state.pc->getSourceLocation(); + os << ") at " << state.pc->getSourceLocationString(); if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); else - klee_warning_once(callable->getValue(), "%s", os.str().c_str()); + klee_warning_once(callable->unwrap(), "%s", os.str().c_str()); } int roundingMode = LLVMRoundingModeToCRoundingMode(state.roundingMode); @@ -4966,12 +5108,12 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - bool success = externalDispatcher->executeCall(callable, target->inst, args, + bool success = externalDispatcher->executeCall(callable, target->inst(), args, roundingMode); if (!success) { - if (MockExternalCalls) { - if (target->inst->getType()->isSized()) { + if (interpreterOpts.Mock == MockPolicy::Failed) { + if (target->inst()->getType()->isSized()) { prepareMockValue(state, "mockExternResult", target); } } else { @@ -4982,7 +5124,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - if (!state.addressSpace.copyInConcretes()) { + if (!state.addressSpace.copyInConcretes(assignment)) { terminateStateOnExecError(state, "external modified read-only object", StateTerminationType::External); return; @@ -4992,10 +5134,10 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, // Update errno memory object with the errno value from the call int error = externalDispatcher->getLastErrno(); state.addressSpace.copyInConcrete(result.first, result.second, - (uint64_t)&error); + (uint64_t)&error, assignment); #endif - Type *resultType = target->inst->getType(); + Type *resultType = target->inst()->getType(); if (resultType != Type::getVoidTy(kmodule->module->getContext())) { ref e = ConstantExpr::fromMemory((void *)args, getWidthForLLVMType(resultType)); @@ -5061,7 +5203,7 @@ ObjectState *Executor::bindObjectInState(ExecutionState &state, // will put multiple copies on this list, but it doesn't really // matter because all we use this list for is to unbind the object // on function return. - if (isLocal && state.stack.size() > 0) { + if (isLocal && !state.stack.empty()) { state.stack.valueStack().back().allocas.push_back(mo->id); } return os; @@ -5071,7 +5213,8 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, KInstruction *target, KType *type, bool zeroMemory, const ObjectState *reallocFrom, size_t allocationAlignment, bool checkOutOfMemory) { - const llvm::Value *allocSite = state.prevPC->inst; + static unsigned allocations = 0; + const llvm::Value *allocSite = state.prevPC->inst(); if (allocationAlignment == 0) { allocationAlignment = getAllocationAlignment(allocSite); } @@ -5112,12 +5255,15 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, if (!mo) { bindLocal(target, state, Expr::createPointer(0)); } else { - ObjectState *os = bindObjectInState(state, mo, type, isLocal); + ref source = nullptr; if (zeroMemory) { - os->initializeToZero(); + source = SourceBuilder::constant( + SparseStorage(ConstantExpr::create(0, Expr::Int8))); } else { - os->initializeToRandom(); + source = SourceBuilder::uninitialized(allocations++, target); } + auto array = makeArray(size, source); + ObjectState *os = bindObjectInState(state, mo, type, isLocal, array); ref address = mo->getBaseExpr(); if (checkOutOfMemory) { @@ -5131,10 +5277,7 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, bindLocal(target, state, address); if (reallocFrom) { - unsigned count = std::min(reallocFrom->size, os->size); - for (unsigned i = 0; i < count; i++) { - os->write(i, reallocFrom->read8(i)); - } + os->write(reallocFrom); state.removePointerResolutions(reallocFrom->getObject()); state.addressSpace.unbindObject(reallocFrom->getObject()); } @@ -5429,14 +5572,29 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, Expr::Width pointerWidthInBits = Context::get().getPointerWidth(); - /* Create symbol for array */ + /// Determine source for address array: + /// * LI source if allocate occures on lazi initialization + /// * Otherwise choose source depending on the allocation site + ref sourceAddressArray; + if (!lazyInitializationSource) { + if (auto inst = dyn_cast(allocSite)) { + KInstruction *ki = + kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + sourceAddressArray = SourceBuilder::symbolicSizeConstantAddress( + updateNameVersion(state, "const_arr"), ki, size); + } else if (auto global = dyn_cast(allocSite)) { + KGlobalVariable *kgb = kmodule->globalMap[global].get(); + sourceAddressArray = SourceBuilder::symbolicSizeConstantAddress( + updateNameVersion(state, "const_arr"), kgb, size); + } + } else { + sourceAddressArray = + SourceBuilder::lazyInitializationAddress(lazyInitializationSource); + } + /* Create symbol for array */ const Array *addressArray = makeArray( - Expr::createPointer(pointerWidthInBits / CHAR_BIT), - lazyInitializationSource - ? SourceBuilder::lazyInitializationAddress(lazyInitializationSource) - : SourceBuilder::symbolicSizeConstantAddress( - 0, updateNameVersion(state, "const_arr"))); + Expr::createPointer(pointerWidthInBits / CHAR_BIT), sourceAddressArray); ref addressExpr = Expr::createTempRead(addressArray, pointerWidthInBits); @@ -5875,7 +6033,7 @@ void Executor::collectReads( const std::vector &resolvedMemoryObjects, const std::vector &resolveConcretizations, std::vector> &results) { - ref base = address; + ref base = address; // TODO: unused unsigned size = bytes; if (state.isGEPExpr(address)) { base = state.gepExprBases[address].first; @@ -5893,12 +6051,10 @@ void Executor::collectReads( ref result = os->read(mo->getOffsetExpr(address), type); - if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && - mo->isGlobal && !os->readOnly && isa(result) && - !targetType->getRawType()->isPointerTy()) { - result = makeMockValue(state, "mockGlobalValue", result->getWidth()); - ObjectState *wos = state.addressSpace.getWriteable(mo, os); - wos->write(mo->getOffsetExpr(address), result); + if (X86FPAsX87FP80 && + state.prevPC->inst()->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); } results.push_back(result); @@ -5909,8 +6065,19 @@ void Executor::executeMemoryOperation( ExecutionState &estate, bool isWrite, KType *targetType, ref address, ref value /* undef if read */, KInstruction *target /* undef if write */) { + KInstruction *ki = estate.prevPC; + if (X86FPAsX87FP80 && isWrite) { + auto valueOperand = + cast(ki->inst())->getValueOperand(); + if (valueOperand->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + value = + X87FP80ToFPTrunc(value, getWidthForLLVMType(valueOperand->getType()), + estate.roundingMode); + } + } Expr::Width type = (isWrite ? value->getWidth() - : getWidthForLLVMType(target->inst->getType())); + : getWidthForLLVMType(target->inst()->getType())); unsigned bytes = Expr::getMinBytesForWidth(type); ref base = address; @@ -6019,13 +6186,13 @@ void Executor::executeMemoryOperation( bool success = solver->getResponse(state->constraints.cs(), inBounds, response, state->queryMetaData); solver->setTimeout(time::Span()); - bool mustBeInBounds = !isa(response); if (!success) { state->pc = state->prevPC; terminateStateOnSolverError(*state, "Query timed out (bounds check)."); return; } + bool mustBeInBounds = !isa(response); if (mustBeInBounds) { if (isa(response)) { addConstraint(*state, inBounds); @@ -6037,6 +6204,8 @@ void Executor::executeMemoryOperation( state->addPointerResolution(address, mo); if (isWrite) { ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->getDynamicType()->handleMemoryAccess( targetType, mo->getOffsetExpr(address), ConstantExpr::alloc(size, Context::get().getPointerWidth()), true); @@ -6049,17 +6218,14 @@ void Executor::executeMemoryOperation( } else { result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && ki->inst()->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (interpreterOpts.MakeConcreteSymbolic) result = replaceReadWithSymbolic(*state, result); - if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && - mo->isGlobal && !os->readOnly && isa(result) && - !targetType->getRawType()->isPointerTy()) { - result = makeMockValue(*state, "mockGlobalValue", result->getWidth()); - ObjectState *wos = state->addressSpace.getWriteable(mo, os); - wos->write(mo->getOffsetExpr(address), result); - } - bindLocal(target, *state, result); } @@ -6152,6 +6318,8 @@ void Executor::executeMemoryOperation( const ObjectState *os = op.second; ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); if (wos->readOnly) { branches = forkInternal(*state, Expr::createIsZero(unboundConditions[i]), @@ -6221,6 +6389,8 @@ void Executor::executeMemoryOperation( if (isWrite) { ObjectState *wos = bound->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->getDynamicType()->handleMemoryAccess( targetType, mo->getOffsetExpr(address), ConstantExpr::alloc(size, Context::get().getPointerWidth()), true); @@ -6233,12 +6403,9 @@ void Executor::executeMemoryOperation( } else { ref result = os->read(mo->getOffsetExpr(address), type); - if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && - mo->isGlobal && !os->readOnly && isa(result) && - !targetType->getRawType()->isPointerTy()) { - result = makeMockValue(*bound, "mockGlobalValue", result->getWidth()); - ObjectState *wos = bound->addressSpace.getWriteable(mo, os); - wos->write(mo->getOffsetExpr(address), result); + if (X86FPAsX87FP80 && ki->inst()->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); } bindLocal(target, *bound, result); @@ -6268,7 +6435,7 @@ bool Executor::lazyInitializeObject(ExecutionState &state, ref address, KType *targetType, uint64_t size, bool isLocal, IDType &id, bool isSymbolic) { assert(!isa(address)); - const llvm::Value *allocSite = target ? target->inst : nullptr; + const llvm::Value *allocSite = target ? target->inst() : nullptr; std::pair, ref> moBasePair; unsigned timestamp = 0; if (state.getBase(address, moBasePair)) { @@ -6343,7 +6510,7 @@ bool Executor::lazyInitializeObject(ExecutionState &state, ref address, IDType Executor::lazyInitializeLocalObject(ExecutionState &state, StackFrame &sf, ref address, const KInstruction *target) { - AllocaInst *ai = cast(target->inst); + AllocaInst *ai = cast(target->inst()); unsigned elementSize = kmodule->targetData->getTypeStoreSize(ai->getAllocatedType()); ref size = Expr::createPointer(elementSize); @@ -6388,7 +6555,7 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, * assign. We want to update only objects, whose size were changed. */ std::vector> updatedSizeSymcretes; - const Assignment &diffAssignment = + Assignment diffAssignment = state.constraints.cs().concretization().diffWith(assignment); for (const ref &symcrete : state.constraints.cs().symcretes()) { @@ -6415,19 +6582,23 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, continue; } - ObjectPair oldOp = state.addressSpace.findObject(newMO->id); - ref oldMO(oldOp.first); - ref oldOS(oldOp.second); - if (!oldOS) { + ObjectPair op = state.addressSpace.findObject(newMO->id); + + if (!op.second) { continue; } + /* Create a new ObjectState with the new size and new owning memory * object. */ - /* Order of operations critical here. */ - state.addressSpace.unbindObject(oldMO.get()); - state.addressSpace.bindObject(newMO, new ObjectState(newMO, *oldOS.get())); + auto wos = new ObjectState( + *(state.addressSpace.getWriteable(op.first, op.second))); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); + wos->swapObjectHack(newMO); + state.addressSpace.unbindObject(op.first); + state.addressSpace.bindObject(newMO, wos); } } @@ -6456,8 +6627,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, ObjectState *os = bindObjectInState(state, mo, type, isLocal, array); if (AlignSymbolicPointers) { - if (ref alignmentRestrictions = - type->getContentRestrictions(os->read(0, os->size * CHAR_BIT))) { + if (ref alignmentRestrictions = type->getContentRestrictions( + os->read(0, os->getObject()->size * CHAR_BIT))) { addConstraint(state, alignmentRestrictions); } } @@ -6476,7 +6647,7 @@ void Executor::executeMakeSymbolic(ExecutionState &state, if (!obj) { if (ZeroSeedExtension) { si.assignment.bindings.replace( - {array, SparseStorage(mo->size, 0)}); + {array, SparseStorage(0)}); } else if (!AllowSeedExtension) { terminateStateOnUserError(state, "ran out of inputs during seeding"); @@ -6501,12 +6672,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, si.assignment.bindings.end()) { values = si.assignment.bindings.at(array); } - values.resize(std::min(mo->size, obj->numBytes)); values.store(0, obj->bytes, obj->bytes + std::min(obj->numBytes, mo->size)); - if (ZeroSeedExtension) { - values.resize(mo->size); - } si.assignment.bindings.replace({array, values}); } } @@ -6610,7 +6777,7 @@ ExecutionState *Executor::formState(Function *f, int argc, char **argv, MemoryObject *arg = allocate(*state, Expr::createPointer(len + 1), /*isLocal=*/false, /*isGlobal=*/true, - /*allocSite=*/state->pc->inst, /*alignment=*/8); + /*allocSite=*/state->pc->inst(), /*alignment=*/8); if (!arg) klee_error("Could not allocate memory for function arguments"); @@ -6651,63 +6818,40 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, ExecutionState *state = formState(f, argc, argv, envp); bindModuleConstants(llvm::APFloat::rmNearestTiesToEven); - std::vector states; + KFunction *kEntryFunction = kmodule->functionMap.at(f); if (guidanceKind == GuidanceKind::ErrorGuidance) { - std::map, - klee::TargetedExecutionManager::KFunctionLess> - prepTargets; + ref forest; if (FunctionCallReproduce == "") { auto &paths = interpreterOpts.Paths.value(); - prepTargets = targetedExecutionManager->prepareTargets(kmodule.get(), - std::move(paths)); + forest = targetedExecutionManager->prepareTargets( + kmodule.get(), kEntryFunction, std::move(paths)); } else { /* Find all calls to function specified in .prp file * and combine them to single target forest */ - KFunction *kEntryFunction = kmodule->functionMap.at(f); - ref forest = new TargetForest(kEntryFunction); - auto kfunction = kmodule->functionNameMap.at(FunctionCallReproduce); - KBlock *kCallBlock = kfunction->entryKBlock; - forest->add(ReproduceErrorTarget::create( - {ReachWithError::Reachable}, "", - ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); - prepTargets.emplace(kEntryFunction, forest); + auto kfIt = kmodule->functionNameMap.find(FunctionCallReproduce); + if (kfIt == kmodule->functionNameMap.end()) { + klee_warning("%s was eliminated by LLVM passes, so it is unreachable", + FunctionCallReproduce.c_str()); + } else { + auto kCallBlock = kfIt->second->entryKBlock; + forest = new TargetForest(kEntryFunction); + forest->add(ReproduceErrorTarget::create( + {ReachWithError::Reachable}, "", + ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); + } } - if (prepTargets.empty()) { + if (forest->empty()) { klee_warning( "No targets found in error-guided mode after prepare targets"); delete state; return; } - KInstIterator caller; - if (kmodule->WithPOSIXRuntime()) { - state = prepareStateForPOSIX(caller, state->copy()); - } else { - state->popFrame(); - } - - for (auto &startFunctionAndWhiteList : prepTargets) { - auto kf = - kmodule->functionMap.at(startFunctionAndWhiteList.first->function); - if (startFunctionAndWhiteList.second->empty()) { - klee_warning("No targets found for %s", - kf->function->getName().str().c_str()); - continue; - } - auto whitelist = startFunctionAndWhiteList.second; - targets.emplace(kf, TargetedHaltsOnTraces(whitelist)); - ExecutionState *initialState = state->withStackFrame(caller, kf); - prepareSymbolicArgs(*initialState); - prepareTargetedExecution(*initialState, whitelist); - states.push_back(initialState); - } - delete state; - } else { - states.push_back(state); + targets.emplace(kEntryFunction, TargetedHaltsOnTraces(forest)); + prepareTargetedExecution(*state, forest); } - state = nullptr; TreeOStream pathOS; TreeOStream symPathOS; @@ -6720,19 +6864,18 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, } processForest = std::make_unique(); - for (auto &state : states) { - if (statsTracker) - statsTracker->framePushed(*state, 0); - if (pathWriter) - state->pathOS = pathOS; - if (symPathWriter) - state->symPathOS = symPathOS; + if (statsTracker) + statsTracker->framePushed(*state, 0); + + if (pathWriter) + state->pathOS = pathOS; + if (symPathWriter) + state->symPathOS = symPathOS; - processForest->addRoot(state); - } + processForest->addRoot(state); - run(states); + run(state); processForest = nullptr; if (statsTracker) @@ -6799,7 +6942,7 @@ bool isReturnValueFromInitBlock(const ExecutionState &state, const llvm::Value *value) { return state.initPC->parent->getKBlockType() == KBlockType::Call && state.initPC == state.initPC->parent->getLastInstruction() && - state.initPC->parent->getFirstInstruction()->inst == value; + state.initPC->parent->getFirstInstruction()->inst() == value; } ref Executor::makeSymbolicValue(llvm::Value *value, @@ -6821,9 +6964,9 @@ ref Executor::makeSymbolicValue(llvm::Value *value, void Executor::prepareSymbolicValue(ExecutionState &state, StackFrame &frame, KInstruction *target) { - ref result = makeSymbolicValue(target->inst, state); + ref result = makeSymbolicValue(target->inst(), state); bindLocal(target, frame, result); - if (isa(target->inst)) { + if (isa(target->inst())) { lazyInitializeLocalObject(state, frame, result, target); } } @@ -6833,7 +6976,7 @@ void Executor::prepareMockValue(ExecutionState &state, StackFrame &frame, KInstruction *target) { ref result = makeMockValue(state, name, width); bindLocal(target, frame, result); - if (isa(target->inst)) { + if (isa(target->inst())) { lazyInitializeLocalObject(state, frame, result, target); } } @@ -6841,7 +6984,7 @@ void Executor::prepareMockValue(ExecutionState &state, StackFrame &frame, void Executor::prepareMockValue(ExecutionState &state, const std::string &name, KInstruction *target) { Expr::Width width = - kmodule->targetData->getTypeSizeInBits(target->inst->getType()); + kmodule->targetData->getTypeSizeInBits(target->inst()->getType()); prepareMockValue(state, state.stack.valueStack().back(), name, width, target); } @@ -6852,7 +6995,7 @@ void Executor::prepareSymbolicValue(ExecutionState &state, void Executor::prepareSymbolicRegister(ExecutionState &state, StackFrame &sf, unsigned regNum) { - KInstruction *allocInst = sf.kf->registerToInstructionMap[regNum]; + KInstruction *allocInst = sf.kf->getInstructionByRegister(regNum); prepareSymbolicValue(state, sf, allocInst); } @@ -6860,9 +7003,9 @@ void Executor::prepareSymbolicArg(ExecutionState &state, StackFrame &frame, unsigned index) { KFunction *kf = frame.kf; #if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) - Argument *arg = kf->function->getArg(index); + Argument *arg = kf->function()->getArg(index); #else - Argument *arg = &kf->function->arg_begin()[index]; + Argument *arg = &kf->function()->arg_begin()[index]; #endif ref result = makeSymbolicValue(arg, state); bindArgument(kf, index, frame, result); @@ -6870,7 +7013,7 @@ void Executor::prepareSymbolicArg(ExecutionState &state, StackFrame &frame, void Executor::prepareSymbolicArgs(ExecutionState &state, StackFrame &frame) { KFunction *kf = frame.kf; - unsigned argSize = kf->function->arg_size(); + unsigned argSize = kf->function()->arg_size(); for (unsigned argNo = 0; argNo < argSize; ++argNo) { prepareSymbolicArg(state, frame, argNo); } @@ -6935,7 +7078,7 @@ void Executor::logState(const ExecutionState &state, int id, *f << state.symbolics.size() << " symbolics total. " << "Symbolics:\n"; size_t sc = 0; - for (auto &symbolic : state.symbolics) { + for (const auto &symbolic : state.symbolics) { *f << "Symbolic number " << sc++ << "\n"; *f << "Associated memory object: " << symbolic.memoryObject.get()->id << "\n"; @@ -6949,19 +7092,43 @@ void Executor::logState(const ExecutionState &state, int id, } } -void Executor::setInitializationGraph(const ExecutionState &state, - const Assignment &model, KTest &ktest) { +bool resolveOnSymbolics(const std::vector &symbolics, + const Assignment &assn, + const ref &addr, IDType &result) { + uint64_t address = addr->getZExtValue(); + + for (const auto &res : symbolics) { + const auto &mo = res.memoryObject; + // Check if the provided address is between start and end of the object + // [mo->address, mo->address + mo->size) or the object is a 0-sized object. + ref size = + cast(assn.evaluate(mo->getSizeExpr())); + if ((size->getZExtValue() == 0 && address == mo->address) || + (address - mo->address < size->getZExtValue())) { + result = mo->id; + return true; + } + } + + return false; +} + +void Executor::setInitializationGraph( + const ExecutionState &state, const std::vector &symbolics, + const Assignment &model, KTest &ktest) { std::map> pointers; std::map>> s; ExprHashMap>> resolvedPointers; std::unordered_map> idToSymbolics; - for (const auto &symbolic : state.symbolics) { + for (const auto &symbolic : symbolics) { ref mo = symbolic.memoryObject; idToSymbolics[mo->id] = mo; } - for (const auto &symbolic : state.symbolics) { + const klee::Assignment &assn = state.constraints.cs().concretization(); + + for (const auto &symbolic : symbolics) { KType *symbolicType = symbolic.type; if (!symbolicType->getRawType()) { continue; @@ -6989,7 +7156,7 @@ void Executor::setInitializationGraph(const ExecutionState &state, ref constantAddress = cast(addressInModel); IDType idResult; - if (state.resolveOnSymbolics(constantAddress, idResult)) { + if (resolveOnSymbolics(symbolics, assn, constantAddress, idResult)) { ref mo = idToSymbolics[idResult]; resolvedPointers[address] = std::make_pair(idResult, mo->getOffsetExpr(address)); @@ -7024,15 +7191,17 @@ void Executor::setInitializationGraph(const ExecutionState &state, // The objects have to be symbolic bool pointerFound = false, pointeeFound = false; size_t pointerIndex = 0, pointeeIndex = 0; - for (size_t i = 0; i < state.symbolics.size(); i++) { - if (state.symbolics[i].memoryObject == pointerResolution.first) { + size_t i = 0; + for (auto &symbolic : symbolics) { + if (symbolic.memoryObject == pointerResolution.first) { pointerIndex = i; pointerFound = true; } - if (state.symbolics[i].memoryObject->id == pointer.second.first) { + if (symbolic.memoryObject->id == pointer.second.first) { pointeeIndex = i; pointeeFound = true; } + ++i; } if (pointerFound && pointeeFound) { ref offset = model.evaluate(pointerResolution.second); @@ -7081,6 +7250,32 @@ Assignment Executor::computeConcretization(const ConstraintSet &constraints, return concretization; } +bool isReproducible(const klee::Symbolic &symb) { + auto arr = symb.array; + bool bad = IrreproducibleSource::classof(arr->source.get()); + if (auto liSource = dyn_cast(arr->source.get())) { + std::vector arrays; + findObjects(liSource->pointer, arrays); + for (auto innerArr : arrays) { + bad |= IrreproducibleSource::classof(innerArr->source.get()); + } + } + if (bad) + klee_warning_once(arr->source.get(), + "A irreproducible symbolic %s reaches a test", + arr->getIdentifier().c_str()); + return !bad; +} + +bool isUninitialized(const klee::Array *array) { + bool bad = isa(array->source); + if (bad) + klee_warning_once(array->source.get(), + "A uninitialized array %s reaches a test", + array->getIdentifier().c_str()); + return bad; +} + bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); @@ -7093,34 +7288,61 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { // the preferred constraints. See test/Features/PreferCex.c for // an example) While this process can be very expensive, it can // also make understanding individual test cases much easier. - for (auto &pi : state.cexPreferences) { - bool mustBeTrue; - // Attempt to bound byte to constraints held in cexPreferences - bool success = - solver->mustBeTrue(extendedConstraints.cs(), Expr::createIsZero(pi), - mustBeTrue, state.queryMetaData); - // If it isn't possible to add the condition without making the entire - // list UNSAT, then just continue to the next condition - if (!success) - break; - // If the particular constraint operated on in this iteration through - // the loop isn't implied then add it to the list of constraints. - if (!mustBeTrue) { - Assignment concretization = computeConcretization( - extendedConstraints.cs(), pi, state.queryMetaData); - - if (!concretization.isEmpty()) { - extendedConstraints.addConstraint(pi, concretization); - } else { - extendedConstraints.addConstraint(pi, {}); + const size_t cexPreferencesBound = 16; + if (state.cexPreferences.size() > cexPreferencesBound) { + klee_warning_once(0, "skipping cex preffering (size of restrictons > %zu).", + cexPreferencesBound); + } else { + for (auto &pi : state.cexPreferences) { + bool mustBeTrue; + // Attempt to bound byte to constraints held in cexPreferences + bool success = + solver->mustBeTrue(extendedConstraints.cs(), Expr::createIsZero(pi), + mustBeTrue, state.queryMetaData); + // If it isn't possible to add the condition without making the entire + // list UNSAT, then just continue to the next condition + if (!success) + break; + // If the particular constraint operated on in this iteration through + // the loop isn't implied then add it to the list of constraints. + if (!mustBeTrue) { + Assignment concretization = computeConcretization( + extendedConstraints.cs(), pi, state.queryMetaData); + + if (!concretization.isEmpty()) { + extendedConstraints.addConstraint(pi, concretization); + } else { + extendedConstraints.addConstraint(pi, {}); + } } } } + std::vector allObjects; + findSymbolicObjects(state.constraints.cs().cs().begin(), + state.constraints.cs().cs().end(), allObjects); + std::vector uninitObjects; + std::copy_if(allObjects.begin(), allObjects.end(), + std::back_inserter(uninitObjects), isUninitialized); + + std::vector symbolics; + std::copy_if(state.symbolics.begin(), state.symbolics.end(), + std::back_inserter(symbolics), isReproducible); + + // we cannot be sure that an irreproducible state proves the presence of an + // error + if (uninitObjects.size() > 0 || state.symbolics.size() != symbolics.size()) { + state.error = ReachWithError::None; + } else if (FunctionCallReproduce != "" && + state.error == ReachWithError::Reachable) { + setHaltExecution(HaltExecution::ReachedTarget); + } + std::vector> values; std::vector objects; - for (unsigned i = 0; i != state.symbolics.size(); ++i) - objects.push_back(state.symbolics[i].array); + for (auto &symbolic : symbolics) { + objects.push_back(symbolic.array); + } bool success = solver->getInitialValues(extendedConstraints.cs(), objects, values, state.queryMetaData); solver->setTimeout(time::Span()); @@ -7131,19 +7353,27 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { return false; } - res.objects = new KTestObject[state.symbolics.size()]; - res.numObjects = state.symbolics.size(); + res.numObjects = symbolics.size(); + res.objects = new KTestObject[res.numObjects]; + res.uninitCoeff = uninitObjects.size() * UninitMemoryTestMultiplier; - for (unsigned i = 0; i != state.symbolics.size(); ++i) { - auto mo = state.symbolics[i].memoryObject; - KTestObject *o = &res.objects[i]; - o->name = const_cast(mo->name.c_str()); - o->address = mo->address; - o->numBytes = values[i].size(); - o->bytes = new unsigned char[o->numBytes]; - std::copy(values[i].begin(), values[i].end(), o->bytes); - o->numPointers = 0; - o->pointers = nullptr; + { + size_t i = 0; + // Remove mo->size, evaluate size expr in array + for (auto &symbolic : symbolics) { + auto mo = symbolic.memoryObject; + KTestObject *o = &res.objects[i]; + o->name = const_cast(mo->name.c_str()); + o->address = mo->address; + o->numBytes = mo->size; + o->bytes = new unsigned char[o->numBytes]; + for (size_t j = 0; j < mo->size; j++) { + o->bytes[j] = values[i].load(j); + } + o->numPointers = 0; + o->pointers = nullptr; + i++; + } } Assignment model = Assignment(objects, values); @@ -7151,14 +7381,13 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { model.bindings.insert(binding); } - setInitializationGraph(state, model, res); + setInitializationGraph(state, symbolics, model, res); return true; } -void Executor::getCoveredLines( - const ExecutionState &state, - std::map> &res) { +void Executor::getCoveredLines(const ExecutionState &state, + std::map> &res) { res = state.coveredLines; } @@ -7194,6 +7423,8 @@ void Executor::doImpliedValueConcretization(ExecutionState &state, ref e, assert(!os->readOnly && "not possible? read only object with static read?"); ObjectState *wos = state.addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(CE, it->second); } } @@ -7315,11 +7546,11 @@ void Executor::dumpStates() { for (auto sfIt = es->stack.callStack().begin(), sf_ie = es->stack.callStack().end(); sfIt != sf_ie; ++sfIt) { - *os << "('" << sfIt->kf->function->getName().str() << "',"; + *os << "('" << sfIt->kf->function()->getName().str() << "',"; if (next == es->stack.callStack().end()) { - *os << es->prevPC->info->line << "), "; + *os << es->prevPC->getLine() << "), "; } else { - *os << next->caller->info->line << "), "; + *os << next->caller->getLine() << "), "; ++next; } } @@ -7328,15 +7559,15 @@ void Executor::dumpStates() { InfoStackFrame &sf = es->stack.infoStack().back(); uint64_t md2u = computeMinDistToUncovered(es->pc, sf.minDistToUncoveredOnReturn); - uint64_t icnt = theStatisticManager->getIndexedValue(stats::instructions, - es->pc->info->id); + uint64_t icnt = theStatisticManager->getIndexedValue( + stats::instructions, es->pc->getGlobalIndex()); uint64_t cpicnt = sf.callPathNode->statistics.getValue(stats::instructions); *os << "{"; *os << "'depth' : " << es->depth << ", "; *os << "'queryCost' : " << es->queryMetaData.queryCost << ", "; - *os << "'coveredNew' : " << es->coveredNew->value << ", "; + *os << "'coveredNew' : " << es->isCoveredNew() << ", "; *os << "'instsSinceCovNew' : " << es->instsSinceCovNew << ", "; *os << "'md2u' : " << md2u << ", "; *os << "'icnt' : " << icnt << ", "; diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 1cd6c1c4a0..d6cbb17352 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -78,7 +78,6 @@ class ExecutionState; class ExternalDispatcher; class Expr; template class ExprHashMap; -class InstructionInfoTable; class KCallable; struct KFunction; struct KInstruction; @@ -124,6 +123,9 @@ class Executor : public Interpreter { private: int *errno_addr; + size_t maxNewWriteableOSSize = 0; + size_t maxNewStateStackSize = 0; + using SetOfStates = std::set; /* Set of Intrinsic::ID. Plain type is used here to avoid including llvm in * the header */ @@ -178,7 +180,7 @@ class Executor : public Interpreter { /// Map of globals to their bound address. This also includes /// globals that have no representative object (i.e. functions). - std::map> globalAddresses; + std::map> globalAddresses; /// Map of legal function addresses to the corresponding Function. /// Used to validate and dereference function pointers. @@ -209,6 +211,9 @@ class Executor : public Interpreter { /// Disables forking, set by client. \see setInhibitForking() bool inhibitForking; + /// Should it generate test cases for each new covered block or branch + bool coverOnTheFly; + /// Signals the executor to halt execution at the next instruction /// step. HaltExecution::Reason haltExecution = HaltExecution::NotHalt; @@ -257,7 +262,7 @@ class Executor : public Interpreter { ExecutionState **resultState = nullptr); void seed(ExecutionState &initialState); - void run(std::vector initialStates); + void run(ExecutionState *initialState); void runWithTarget(ExecutionState &state, KFunction *kf, KBlock *target); void initializeTypeManager(); @@ -288,7 +293,7 @@ class Executor : public Interpreter { ObjectState *bindObjectInState(ExecutionState &state, const MemoryObject *mo, KType *dynamicType, bool IsAlloca, - const Array *array = 0); + const Array *array = nullptr); /// Resolve a pointer to the memory objects it could point to the /// start of, forking execution when necessary and generating errors @@ -482,7 +487,7 @@ class Executor : public Interpreter { ref readDest(ExecutionState &state, StackFrame &frame, const KInstruction *target) { - unsigned index = target->dest; + unsigned index = target->getDest(); ref reg = frame.locals[index].value; if (!reg) { prepareSymbolicRegister(state, frame, index); @@ -496,7 +501,7 @@ class Executor : public Interpreter { } Cell &getDestCell(const StackFrame &frame, const KInstruction *target) { - return frame.locals[target->dest]; + return frame.locals[target->getDest()]; } const Cell &eval(const KInstruction *ki, unsigned index, @@ -526,9 +531,9 @@ class Executor : public Interpreter { /// Evaluates an LLVM constant expression. The optional argument ki /// is the instruction where this constant was encountered, or NULL /// if not applicable/unavailable. - ref evalConstantExpr(const llvm::ConstantExpr *c, - llvm::APFloat::roundingMode rm, - const KInstruction *ki = NULL); + ref evalConstantExpr(const llvm::ConstantExpr *c, + llvm::APFloat::roundingMode rm, + const KInstruction *ki = NULL); /// Evaluates an LLVM float comparison. the operands are two float /// expressions. @@ -538,9 +543,9 @@ class Executor : public Interpreter { /// Evaluates an LLVM constant. The optional argument ki is the /// instruction where this constant was encountered, or NULL if /// not applicable/unavailable. - ref evalConstant(const llvm::Constant *c, - llvm::APFloat::roundingMode rm, - const KInstruction *ki = NULL); + ref evalConstant(const llvm::Constant *c, + llvm::APFloat::roundingMode rm, + const KInstruction *ki = NULL); /// Return a unique constant value for the given expression in the /// given state, if it has one (i.e. it provably only has a single @@ -567,10 +572,9 @@ class Executor : public Interpreter { const MemoryObject *mo = nullptr) const; // Determines the \param lastInstruction of the \param state which is not KLEE - // internal and returns its InstructionInfo - const InstructionInfo & - getLastNonKleeInternalInstruction(const ExecutionState &state, - llvm::Instruction **lastInstruction); + // internal and returns its KInstruction + const KInstruction * + getLastNonKleeInternalInstruction(const ExecutionState &state); /// Remove state from queue and delete state void terminateState(ExecutionState &state, @@ -725,13 +729,13 @@ class Executor : public Interpreter { replayPosition = 0; } - llvm::Module * - setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) override; + llvm::Module *setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals, + std::vector> redefinitions) override; void useSeeds(const std::vector *seeds) override { usingSeeds = seeds; @@ -778,6 +782,8 @@ class Executor : public Interpreter { haltExecution = value; } + HaltExecution::Reason getHaltExecution() override { return haltExecution; } + void setInhibitForking(bool value) override { inhibitForking = value; } void prepareForEarlyExit() override; @@ -793,6 +799,7 @@ class Executor : public Interpreter { Interpreter::LogType logFormat = Interpreter::STP) override; void setInitializationGraph(const ExecutionState &state, + const std::vector &symbolics, const Assignment &model, KTest &tc); void logState(const ExecutionState &state, int id, @@ -800,9 +807,8 @@ class Executor : public Interpreter { bool getSymbolicSolution(const ExecutionState &state, KTest &res) override; - void getCoveredLines( - const ExecutionState &state, - std::map> &res) override; + void getCoveredLines(const ExecutionState &state, + std::map> &res) override; void getBlockPath(const ExecutionState &state, std::string &blockPath) override; diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index 467982c81f..534f264fee 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -35,10 +35,43 @@ DISABLE_WARNING_POP using namespace llvm; namespace klee { +extern llvm::cl::opt X86FPAsX87FP80; +ref X87FP80ToFPTrunc(ref arg, Expr::Width type, + llvm::APFloat::roundingMode rm) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = type; + if (Context::get().getPointerWidth() == 32 && arg->getWidth() == Expr::Fl80) { + result = FPTruncExpr::create(arg, resultType, rm); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif // ENABLE_FP + return result; +} + +ref FPToX87FP80Ext(ref arg) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = Expr::Fl80; + if (Context::get().getPointerWidth() == 32) { + result = FPExtExpr::create(arg, resultType); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif // ENABLE_FP + return result; +} -ref Executor::evalConstant(const Constant *c, - llvm::APFloat::roundingMode rm, - const KInstruction *ki) { +ref Executor::evalConstant(const Constant *c, + llvm::APFloat::roundingMode rm, + const KInstruction *ki) { if (!ki) { KConstant *kc = kmodule->getKConstant(c); if (kc) @@ -51,7 +84,12 @@ ref Executor::evalConstant(const Constant *c, if (const ConstantInt *ci = dyn_cast(c)) { return ConstantExpr::alloc(ci->getValue()); } else if (const ConstantFP *cf = dyn_cast(c)) { - return ConstantExpr::alloc(cf->getValueAPF()); + ref result = ConstantExpr::alloc(cf->getValueAPF()); + if (X86FPAsX87FP80 && c->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast(FPToX87FP80Ext(result)); + } + return result; } else if (const GlobalValue *gv = dyn_cast(c)) { auto it = globalAddresses.find(gv); assert(it != globalAddresses.end()); @@ -60,7 +98,7 @@ ref Executor::evalConstant(const Constant *c, return Expr::createPointer(0); } else if (isa(c) || isa(c)) { if (getWidthForLLVMType(c->getType()) == 0) { - if (isa(ki->inst)) { + if (isa(ki->inst())) { klee_warning_once( 0, "Using zero size array fix for landingpad instruction filter"); return ConstantExpr::create(0, 1); @@ -134,7 +172,7 @@ ref Executor::evalConstant(const Constant *c, std::string msg("Cannot handle constant "); llvm::raw_string_ostream os(msg); os << "'" << *c << "' at location " - << (ki ? ki->getSourceLocation() : "[unknown]"); + << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } } @@ -236,12 +274,12 @@ ref Executor::evaluateFCmp(unsigned int predicate, return result; } -ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, - llvm::APFloat::roundingMode rm, - const KInstruction *ki) { +ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, + llvm::APFloat::roundingMode rm, + const KInstruction *ki) { llvm::Type *type = ce->getType(); - ref op1(0), op2(0), op3(0); + ref op1(0), op2(0), op3(0); int numOperands = ce->getNumOperands(); if (numOperands > 0) @@ -256,23 +294,28 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, case Instruction::SDiv: case Instruction::UDiv: case Instruction::SRem: - case Instruction::URem: - if (op2->getLimitedValue() == 0) { - std::string msg( - "Division/modulo by zero during constant folding at location "); - llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocation() : "[unknown]"); - klee_error("%s", os.str().c_str()); + case Instruction::URem: { + if (auto op2Const = dyn_cast(op2)) { + if (op2Const->getLimitedValue() == 0) { + std::string msg( + "Division/modulo by zero during constant folding at location "); + llvm::raw_string_ostream os(msg); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); + klee_error("%s", os.str().c_str()); + } } break; + } case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: - if (op2->getLimitedValue() >= op1->getWidth()) { - std::string msg("Overshift during constant folding at location "); - llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocation() : "[unknown]"); - klee_error("%s", os.str().c_str()); + if (auto op2Const = dyn_cast(op2)) { + if (op2Const->getLimitedValue() >= op1->getWidth()) { + std::string msg("Overshift during constant folding at location "); + llvm::raw_string_ostream os(msg); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); + klee_error("%s", os.str().c_str()); + } } } @@ -282,76 +325,96 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, switch (ce->getOpcode()) { default: os << "'" << *ce << "' at location " - << (ki ? ki->getSourceLocation() : "[unknown]"); + << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); case Instruction::Trunc: - return op1->Extract(0, getWidthForLLVMType(type)); + return ExtractExpr::create(op1, 0, getWidthForLLVMType(type)); case Instruction::ZExt: - return op1->ZExt(getWidthForLLVMType(type)); + return ZExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::SExt: - return op1->SExt(getWidthForLLVMType(type)); + return SExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::Add: - return op1->Add(op2); + return AddExpr::create(op1, op2); case Instruction::Sub: - return op1->Sub(op2); + return SubExpr::create(op1, op2); case Instruction::Mul: - return op1->Mul(op2); + return MulExpr::create(op1, op2); case Instruction::SDiv: - return op1->SDiv(op2); + return SDivExpr::create(op1, op2); case Instruction::UDiv: - return op1->UDiv(op2); + return UDivExpr::create(op1, op2); case Instruction::SRem: - return op1->SRem(op2); + return SRemExpr::create(op1, op2); case Instruction::URem: - return op1->URem(op2); + return URemExpr::create(op1, op2); case Instruction::And: - return op1->And(op2); + return AndExpr::create(op1, op2); case Instruction::Or: - return op1->Or(op2); + return OrExpr::create(op1, op2); case Instruction::Xor: - return op1->Xor(op2); + return XorExpr::create(op1, op2); case Instruction::Shl: - return op1->Shl(op2); + return ShlExpr::create(op1, op2); case Instruction::LShr: - return op1->LShr(op2); + return LShrExpr::create(op1, op2); case Instruction::AShr: - return op1->AShr(op2); - case Instruction::BitCast: - return op1; + return AShrExpr::create(op1, op2); + case Instruction::BitCast: { + ref result = op1; + + if (X86FPAsX87FP80 && result->getWidth() == Expr::Fl80 && + !ce->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast( + X87FP80ToFPTrunc(result, getWidthForLLVMType(type), rm)); + } + + if (X86FPAsX87FP80 && ce->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast(FPToX87FP80Ext(result)); + } + return result; + } case Instruction::IntToPtr: - return op1->ZExt(getWidthForLLVMType(type)); + return ZExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::PtrToInt: - return op1->ZExt(getWidthForLLVMType(type)); + return ZExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::GetElementPtr: { - ref base = op1->ZExt(Context::get().getPointerWidth()); + ref base = ZExtExpr::create(op1, Context::get().getPointerWidth()); for (gep_type_iterator ii = gep_type_begin(ce), ie = gep_type_end(ce); ii != ie; ++ii) { - ref indexOp = - evalConstant(cast(ii.getOperand()), rm, ki); + ref indexOp = evalConstant(cast(ii.getOperand()), rm, ki); if (indexOp->isZero()) continue; // Handle a struct index, which adds its field offset to the pointer. if (auto STy = ii.getStructTypeOrNull()) { - unsigned ElementIdx = indexOp->getZExtValue(); + auto indexOpConst = dyn_cast(indexOp); + if (!indexOpConst) { + klee_error( + "Found non-constant index in evaluation of llvm::ConstantExpr"); + } + unsigned ElementIdx = indexOpConst->getZExtValue(); const StructLayout *SL = kmodule->targetData->getStructLayout(STy); - base = base->Add( - ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), - SL->getElementOffset(ElementIdx)))); + base = AddExpr::create( + base, ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), + SL->getElementOffset(ElementIdx)))); continue; } // For array or vector indices, scale the index by the size of the type. // Indices can be negative - base = base->Add(indexOp->SExt(Context::get().getPointerWidth()) - ->Mul(ConstantExpr::alloc( - APInt(Context::get().getPointerWidth(), - kmodule->targetData->getTypeAllocSize( - ii.getIndexedType()))))); + base = AddExpr::create( + base, + MulExpr::create( + SExtExpr::create(indexOp, Context::get().getPointerWidth()), + ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), + kmodule->targetData->getTypeAllocSize( + ii.getIndexedType()))))); } return base; } @@ -361,25 +424,25 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, default: assert(0 && "unhandled ICmp predicate"); case ICmpInst::ICMP_EQ: - return op1->Eq(op2); + return EqExpr::create(op1, op2); case ICmpInst::ICMP_NE: - return op1->Ne(op2); + return NeExpr::create(op1, op2); case ICmpInst::ICMP_UGT: - return op1->Ugt(op2); + return UgtExpr::create(op1, op2); case ICmpInst::ICMP_UGE: - return op1->Uge(op2); + return UgeExpr::create(op1, op2); case ICmpInst::ICMP_ULT: - return op1->Ult(op2); + return UltExpr::create(op1, op2); case ICmpInst::ICMP_ULE: - return op1->Ule(op2); + return UleExpr::create(op1, op2); case ICmpInst::ICMP_SGT: - return op1->Sgt(op2); + return SgtExpr::create(op1, op2); case ICmpInst::ICMP_SGE: - return op1->Sge(op2); + return SgeExpr::create(op1, op2); case ICmpInst::ICMP_SLT: - return op1->Slt(op2); + return SltExpr::create(op1, op2); case ICmpInst::ICMP_SLE: - return op1->Sle(op2); + return SleExpr::create(op1, op2); } } @@ -387,46 +450,43 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, return op1->isTrue() ? op2 : op3; case Instruction::FAdd: - return op1->FAdd(op2, rm); + return FAddExpr::create(op1, op2, rm); case Instruction::FSub: - return op1->FSub(op2, rm); + return FSubExpr::create(op1, op2, rm); case Instruction::FMul: - return op1->FMul(op2, rm); + return FMulExpr::create(op1, op2, rm); case Instruction::FDiv: - return op1->FDiv(op2, rm); + return FDivExpr::create(op1, op2, rm); case Instruction::FRem: { - return op1->FRem(op2, rm); + return FRemExpr::create(op1, op2, rm); } case Instruction::FPTrunc: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPTrunc(width, rm); + return FPTruncExpr::create(op1, width, rm); } case Instruction::FPExt: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPExt(width); + return FPExtExpr::create(op1, width); } case Instruction::UIToFP: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->UIToFP(width, rm); + return UIToFPExpr::create(op1, width, rm); } case Instruction::SIToFP: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->SIToFP(width, rm); + return SIToFPExpr::create(op1, width, rm); } case Instruction::FPToUI: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPToUI(width, rm); + return FPToUIExpr::create(op1, width, rm); } case Instruction::FPToSI: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPToSI(width, rm); + return FPToSIExpr::create(op1, width, rm); } case Instruction::FCmp: { - ref result = evaluateFCmp(ce->getPredicate(), op1, op2); - if (ConstantExpr *CE = dyn_cast(result)) { - return ref(CE); - } + return evaluateFCmp(ce->getPredicate(), op1, op2); } assert(0 && "floating point ConstantExprs unsupported"); } diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp index 551c121f9d..642dd7a7ae 100644 --- a/lib/Core/ExternalDispatcher.cpp +++ b/lib/Core/ExternalDispatcher.cpp @@ -346,11 +346,11 @@ Function *ExternalDispatcherImpl::createDispatcher(KCallable *target, llvm::CallInst *result; if (auto *func = dyn_cast(target)) { auto dispatchTarget = module->getOrInsertFunction( - target->getName(), FTy, func->function->getAttributes()); + target->getName(), FTy, func->function()->getAttributes()); result = Builder.CreateCall(dispatchTarget, llvm::ArrayRef(args, args + i)); } else if (auto *asmValue = dyn_cast(target)) { - result = Builder.CreateCall(asmValue->getInlineAsm(), + result = Builder.CreateCall(asmValue->inlineAsm(), llvm::ArrayRef(args, args + i)); } else { assert(0 && "Unhandled KCallable derived class"); diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp index f85ea95b3b..16a49c6938 100644 --- a/lib/Core/Memory.cpp +++ b/lib/Core/Memory.cpp @@ -39,14 +39,6 @@ DISABLE_WARNING_POP using namespace llvm; using namespace klee; -namespace { -cl::opt - UseConstantArrays("use-constant-arrays", - cl::desc("Use constant arrays instead of updates when " - "possible (default=true)\n"), - cl::init(true), cl::cat(SolvingCat)); -} - /***/ IDType MemoryObject::counter = 1; @@ -81,99 +73,21 @@ void MemoryObject::getAllocInfo(std::string &result) const { /***/ -ObjectState::ObjectState(const MemoryObject *mo, KType *dt) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(nullptr), knownSymbolics(nullptr), unflushedMask(nullptr), - updates(nullptr, nullptr), lastUpdate(nullptr), dynamicType(dt), - size(mo->size), readOnly(false) { - if (!UseConstantArrays) { - static unsigned id = 0; - const Array *array = getArrayCache()->CreateArray( - mo->getSizeExpr(), SourceBuilder::makeSymbolic("tmp_arr", ++id)); - updates = UpdateList(array, 0); - } - memset(concreteStore, 0, size); -} - ObjectState::ObjectState(const MemoryObject *mo, const Array *array, KType *dt) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(nullptr), knownSymbolics(nullptr), unflushedMask(nullptr), - updates(array, nullptr), lastUpdate(nullptr), dynamicType(dt), - size(mo->size), readOnly(false) { - makeSymbolic(); - memset(concreteStore, 0, size); -} - -ObjectState::ObjectState(const ObjectState &os) - : copyOnWriteOwner(0), object(os.object), - concreteStore(new uint8_t[os.size]), - concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, os.size) - : nullptr), - knownSymbolics(nullptr), - unflushedMask(os.unflushedMask ? new BitArray(*os.unflushedMask, os.size) - : nullptr), - updates(os.updates), wasZeroInitialized(os.wasZeroInitialized), - lastUpdate(os.lastUpdate), dynamicType(os.dynamicType), size(os.size), - readOnly(os.readOnly) { - if (os.knownSymbolics) { - knownSymbolics = new ref[size]; - for (unsigned i = 0; i < size; i++) - knownSymbolics[i] = os.knownSymbolics[i]; - } + : copyOnWriteOwner(0), object(mo), knownSymbolics(nullptr), + unflushedMask(false), updates(array, nullptr), lastUpdate(nullptr), + size(array->size), dynamicType(dt), readOnly(false) {} - memcpy(concreteStore, os.concreteStore, size * sizeof(*concreteStore)); -} - -ObjectState::ObjectState(const MemoryObject *mo, const ObjectState &os) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, mo->size) - : nullptr), - knownSymbolics(nullptr), - unflushedMask(os.unflushedMask ? new BitArray(*os.unflushedMask, mo->size) - : nullptr), - updates(os.updates), wasZeroInitialized(os.wasZeroInitialized), - lastUpdate(os.lastUpdate), dynamicType(os.getDynamicType()), - size(mo->size), readOnly(os.readOnly) { - /* This constructor should be used when we extend or truncate the memory - for MemoryObject and want to leave content from previous ObjectState. Maybe - it is good to make it a method, not a constructor. */ - unsigned copyingRange = std::min(size, os.size); - - if (os.knownSymbolics) { - knownSymbolics = new ref[size]; - for (unsigned i = 0; i < copyingRange; ++i) { - knownSymbolics[i] = os.knownSymbolics[i]; - } - } - - if (updates.root && - (isa_and_nonnull(updates.root->source) || - isa_and_nonnull( - updates.root->source))) { - /* As now we cannot make only a part of object symbolic, - we will mark all remain bytes as symbolic. */ - for (unsigned i = copyingRange; i < size; ++i) { - markByteSymbolic(i); - setKnownSymbolic(i, 0); - markByteFlushed(i); - } - } - - memcpy(concreteStore, os.concreteStore, - copyingRange * sizeof(*concreteStore)); - // FIXME: 0xAB is a magical number here... Move to constant. - memset(reinterpret_cast(concreteStore) + - copyingRange * sizeof(*concreteStore), - os.wasZeroInitialized ? 0 : 0xAB, - (size - copyingRange) * sizeof(*concreteStore)); -} +ObjectState::ObjectState(const MemoryObject *mo, KType *dt) + : copyOnWriteOwner(0), object(mo), knownSymbolics(nullptr), + unflushedMask(false), updates(nullptr, nullptr), lastUpdate(nullptr), + size(mo->getSizeExpr()), dynamicType(dt), readOnly(false) {} -ObjectState::~ObjectState() { - delete concreteMask; - delete unflushedMask; - delete[] knownSymbolics; - delete[] concreteStore; -} +ObjectState::ObjectState(const ObjectState &os) + : copyOnWriteOwner(0), object(os.object), knownSymbolics(os.knownSymbolics), + unflushedMask(os.unflushedMask), updates(os.updates), + lastUpdate(os.lastUpdate), size(os.size), dynamicType(os.dynamicType), + readOnly(os.readOnly) {} ArrayCache *ObjectState::getArrayCache() const { assert(object && "object was NULL"); @@ -184,248 +98,66 @@ ArrayCache *ObjectState::getArrayCache() const { const UpdateList &ObjectState::getUpdates() const { // Constant arrays are created lazily. - if (!updates.root) { - // Collect the list of writes, with the oldest writes first. - - // FIXME: We should be able to do this more efficiently, we just need to be - // careful to get the interaction with the cache right. In particular we - // should avoid creating UpdateNode instances we never use. - unsigned NumWrites = updates.head ? updates.head->getSize() : 0; - std::vector, ref>> Writes(NumWrites); - const auto *un = updates.head.get(); - for (unsigned i = NumWrites; i != 0; un = un->next.get()) { - --i; - Writes[i] = std::make_pair(un->index, un->value); - } - - /* For objects of symbolic size we will leave last constant - sizes for every index and create constant array (in terms of - Z3 solver) filled with zeros. This part is required for reads - from unitialzed memory. */ - std::vector> Contents(size); - - // Initialize to zeros. - for (unsigned i = 0, e = size; i != e; ++i) - Contents[i] = ConstantExpr::create(0, Expr::Int8); - - // Pull off as many concrete writes as we can. - unsigned Begin = 0, End = Writes.size(); - for (; Begin != End; ++Begin) { - // Push concrete writes into the constant array. - ConstantExpr *Index = dyn_cast(Writes[Begin].first); - if (!Index) - break; - - ConstantExpr *Value = dyn_cast(Writes[Begin].second); - if (!Value) - break; - - Contents[Index->getZExtValue()] = Value; - } - static unsigned id = 0; - std::string arrayName = "const_arr" + llvm::utostr(++id); - const Array *array = nullptr; - - if (object->hasSymbolicSize()) { - /* Extend updates with last written non-zero constant values. - ConstantValues must be empty in constant array. */ - array = getArrayCache()->CreateArray( - object->getSizeExpr(), SourceBuilder::symbolicSizeConstant(0)); - updates = UpdateList(array, 0); - for (unsigned idx = 0; idx < size; ++idx) { - if (!Contents[idx]->getZExtValue()) { - updates.extend(ConstantExpr::create(idx, Expr::Int32), Contents[idx]); + if (auto sizeExpr = dyn_cast(size)) { + auto size = sizeExpr->getZExtValue(); + if (knownSymbolics.storage().size() == size) { + SparseStorage> values( + ConstantExpr::create(0, Expr::Int8)); + UpdateList symbolicUpdates = UpdateList(nullptr, nullptr); + for (unsigned i = 0; i < size; i++) { + auto value = knownSymbolics.load(i); + assert(value); + if (isa(value)) { + values.store(i, cast(value)); + } else { + symbolicUpdates.extend(ConstantExpr::create(i, Expr::Int32), value); } } - } else { - array = getArrayCache()->CreateArray(object->getSizeExpr(), - SourceBuilder::constant(Contents)); - updates = UpdateList(array, 0); - } - - // Apply the remaining (non-constant) writes. - for (; Begin != End; ++Begin) - updates.extend(Writes[Begin].first, Writes[Begin].second); - } - - return updates; -} - -void ObjectState::flushToConcreteStore(TimingSolver *solver, - const ExecutionState &state) const { - for (unsigned i = 0; i < size; i++) { - if (isByteKnownSymbolic(i)) { - ref ce; - bool success = solver->getValue(state.constraints.cs(), read8(i), ce, - state.queryMetaData); - if (!success) - klee_warning("Solver timed out when getting a value for external call, " - "byte %p+%u will have random value", - (void *)object->address, i); - else - ce->toMemory(concreteStore + i); - } - } -} - -void ObjectState::makeConcrete() { - delete concreteMask; - delete unflushedMask; - delete[] knownSymbolics; - concreteMask = nullptr; - unflushedMask = nullptr; - knownSymbolics = nullptr; -} - -void ObjectState::makeSymbolic() { - assert(!updates.head && - "XXX makeSymbolic of objects with symbolic values is unsupported"); - // XXX simplify this, can just delete various arrays I guess - for (unsigned i = 0; i < size; i++) { - markByteSymbolic(i); - setKnownSymbolic(i, 0); - markByteFlushed(i); - } -} - -void ObjectState::initializeToZero() { - makeConcrete(); - wasZeroInitialized = true; - memset(concreteStore, 0, size); -} - -void ObjectState::initializeToRandom() { - makeConcrete(); - wasZeroInitialized = false; - memset(concreteStore, 0xAB, size); -} - -/* -Cache Invariants --- -isByteKnownSymbolic(i) => !isByteConcrete(i) -isByteConcrete(i) => !isByteKnownSymbolic(i) -isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i)) - */ - -void ObjectState::fastRangeCheckOffset(ref offset, unsigned *base_r, - unsigned *size_r) const { - *base_r = 0; - *size_r = size; -} - -void ObjectState::flushRangeForRead(unsigned rangeBase, - unsigned rangeSize) const { - if (!unflushedMask) - unflushedMask = new BitArray(size, true); - - for (unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) { - if (isByteUnflushed(offset)) { - if (isByteConcrete(offset)) { - updates.extend(ConstantExpr::create(offset, Expr::Int32), - ConstantExpr::create(concreteStore[offset], Expr::Int8)); - } else { - assert(isByteKnownSymbolic(offset) && - "invalid bit set in unflushedMask"); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics[offset]); - } - - unflushedMask->unset(offset); + auto array = getArrayCache()->CreateArray( + sizeExpr, SourceBuilder::constant(values)); + updates = UpdateList(array, symbolicUpdates.head); + knownSymbolics.reset(); + unflushedMask.reset(); } } -} - -void ObjectState::flushRangeForWrite(unsigned rangeBase, unsigned rangeSize) { - if (!unflushedMask) - unflushedMask = new BitArray(size, true); - - for (unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) { - if (isByteUnflushed(offset)) { - if (isByteConcrete(offset)) { - updates.extend(ConstantExpr::create(offset, Expr::Int32), - ConstantExpr::create(concreteStore[offset], Expr::Int8)); - markByteSymbolic(offset); - } else { - assert(isByteKnownSymbolic(offset) && - "invalid bit set in unflushedMask"); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics[offset]); - setKnownSymbolic(offset, 0); - } - unflushedMask->unset(offset); - } else { - // flushed bytes that are written over still need - // to be marked out - if (isByteConcrete(offset)) { - markByteSymbolic(offset); - } else if (isByteKnownSymbolic(offset)) { - setKnownSymbolic(offset, 0); - } - } + if (!updates.root) { + SparseStorage> values( + ConstantExpr::create(0, Expr::Int8)); + auto array = + getArrayCache()->CreateArray(size, SourceBuilder::constant(values)); + updates = UpdateList(array, updates.head); } -} -bool ObjectState::isByteConcrete(unsigned offset) const { - return !concreteMask || concreteMask->get(offset); -} - -bool ObjectState::isByteUnflushed(unsigned offset) const { - return !unflushedMask || unflushedMask->get(offset); -} - -bool ObjectState::isByteKnownSymbolic(unsigned offset) const { - return knownSymbolics && knownSymbolics[offset].get(); -} + assert(updates.root); -void ObjectState::markByteConcrete(unsigned offset) { - if (concreteMask) - concreteMask->set(offset); -} - -void ObjectState::markByteSymbolic(unsigned offset) { - if (!concreteMask) - concreteMask = new BitArray(size, true); - concreteMask->unset(offset); -} - -void ObjectState::markByteUnflushed(unsigned offset) { - if (unflushedMask) - unflushedMask->set(offset); + return updates; } -void ObjectState::markByteFlushed(unsigned offset) { - if (!unflushedMask) { - unflushedMask = new BitArray(size, false); - } else { - unflushedMask->unset(offset); +void ObjectState::flushForRead() const { + for (const auto &unflushed : unflushedMask.storage()) { + auto offset = unflushed.first; + auto value = knownSymbolics.load(offset); + assert(value); + updates.extend(ConstantExpr::create(offset, Expr::Int32), value); } + unflushedMask.reset(false); } -void ObjectState::setKnownSymbolic(unsigned offset, - Expr *value /* can be null */) { - if (knownSymbolics) { - knownSymbolics[offset] = value; - } else { - if (value) { - knownSymbolics = new ref[size]; - knownSymbolics[offset] = value; - } - } +void ObjectState::flushForWrite() { + flushForRead(); + // The write is symbolic offset and might overwrite any byte + knownSymbolics.reset(nullptr); } /***/ ref ObjectState::read8(unsigned offset) const { - if (isByteConcrete(offset)) { - return ConstantExpr::create(concreteStore[offset], Expr::Int8); - } else if (isByteKnownSymbolic(offset)) { - return knownSymbolics[offset]; + if (auto byte = knownSymbolics.load(offset)) { + return byte; } else { - assert(!isByteUnflushed(offset) && "unflushed byte without cache value"); - + assert(!unflushedMask.load(offset) && "unflushed byte without cache value"); return ReadExpr::create(getUpdates(), ConstantExpr::create(offset, Expr::Int32)); } @@ -434,11 +166,9 @@ ref ObjectState::read8(unsigned offset) const { ref ObjectState::read8(ref offset) const { assert(!isa(offset) && "constant offset passed to symbolic read8"); - unsigned base, size; - fastRangeCheckOffset(offset, &base, &size); - flushRangeForRead(base, size); + flushForRead(); - if (size > 4096) { + if (object && object->size > 4096) { std::string allocInfo; object->getAllocInfo(allocInfo); klee_warning_once( @@ -446,19 +176,15 @@ ref ObjectState::read8(ref offset) const { "Symbolic memory access will send the following array of %d bytes to " "the constraint solver -- large symbolic arrays may cause significant " "performance issues: %s", - size, allocInfo.c_str()); + object->size, allocInfo.c_str()); } return ReadExpr::create(getUpdates(), ZExtExpr::create(offset, Expr::Int32)); } void ObjectState::write8(unsigned offset, uint8_t value) { - // assert(read_only == false && "writing to read-only object!"); - concreteStore[offset] = value; - setKnownSymbolic(offset, 0); - - markByteConcrete(offset); - markByteUnflushed(offset); + knownSymbolics.store(offset, ConstantExpr::create(value, Expr::Int8)); + unflushedMask.store(offset, true); } void ObjectState::write8(unsigned offset, ref value) { @@ -466,21 +192,17 @@ void ObjectState::write8(unsigned offset, ref value) { if (ConstantExpr *CE = dyn_cast(value)) { write8(offset, (uint8_t)CE->getZExtValue(8)); } else { - setKnownSymbolic(offset, value.get()); - - markByteSymbolic(offset); - markByteUnflushed(offset); + knownSymbolics.store(offset, value); + unflushedMask.store(offset, true); } } void ObjectState::write8(ref offset, ref value) { assert(!isa(offset) && "constant offset passed to symbolic write8"); - unsigned base, size; - fastRangeCheckOffset(offset, &base, &size); - flushRangeForWrite(base, size); + flushForWrite(); - if (size > 4096) { + if (object && object->size > 4096) { std::string allocInfo; object->getAllocInfo(allocInfo); klee_warning_once( @@ -488,12 +210,19 @@ void ObjectState::write8(ref offset, ref value) { "Symbolic memory access will send the following array of %d bytes to " "the constraint solver -- large symbolic arrays may cause significant " "performance issues: %s", - size, allocInfo.c_str()); + object->size, allocInfo.c_str()); } updates.extend(ZExtExpr::create(offset, Expr::Int32), value); } +void ObjectState::write(ref os) { + knownSymbolics = os->knownSymbolics; + unflushedMask = os->unflushedMask; + updates = UpdateList(updates.root, os->updates.head); + lastUpdate = os->lastUpdate; +} + /***/ ref ObjectState::read(ref offset, Expr::Width width) const { @@ -642,14 +371,13 @@ void ObjectState::print() const { llvm::errs() << "-- ObjectState --\n"; llvm::errs() << "\tMemoryObject ID: " << object->id << "\n"; llvm::errs() << "\tRoot Object: " << updates.root << "\n"; - llvm::errs() << "\tSize: " << size << "\n"; + llvm::errs() << "\tSize: " << object->size << "\n"; llvm::errs() << "\tBytes:\n"; - for (unsigned i = 0; i < size; i++) { + for (unsigned i = 0; i < object->size; i++) { llvm::errs() << "\t\t[" << i << "]" - << " concrete? " << isByteConcrete(i) << " known-sym? " - << isByteKnownSymbolic(i) << " unflushed? " - << isByteUnflushed(i) << " = "; + << " known? " << !knownSymbolics.load(i).isNull() + << " unflushed? " << unflushedMask.load(i) << " = "; ref e = read8(i); llvm::errs() << e << "\n"; } diff --git a/lib/Core/Memory.h b/lib/Core/Memory.h index e43e4d015b..6d3bb3b987 100644 --- a/lib/Core/Memory.h +++ b/lib/Core/Memory.h @@ -12,6 +12,8 @@ #include "MemoryManager.h" #include "TimingSolver.h" +#include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Core/Context.h" #include "klee/Expr/Assignment.h" @@ -125,7 +127,7 @@ class MemoryObject { /// Get an identifying string for this allocation. void getAllocInfo(std::string &result) const; - void setName(std::string name) const { this->name = name; } + void setName(const std::string &_name) const { this->name = _name; } void updateTimestamp() const { this->timestamp = time++; } @@ -209,57 +211,46 @@ class ObjectState { ref object; - /// @brief Holds all known concrete bytes - uint8_t *concreteStore; - - /// @brief concreteMask[byte] is set if byte is known to be concrete - BitArray *concreteMask; - - /// knownSymbolics[byte] holds the symbolic expression for byte, - /// if byte is known to be symbolic - ref *knownSymbolics; + /// knownSymbolics[byte] holds the expression for byte, + /// if byte is known + mutable SparseStorage, OptionalRefEq> knownSymbolics; /// unflushedMask[byte] is set if byte is unflushed /// mutable because may need flushed during read of const - mutable BitArray *unflushedMask; + mutable SparseStorage unflushedMask; // mutable because we may need flush during read of const mutable UpdateList updates; - bool wasZeroInitialized = true; - ref lastUpdate; + ref size; + KType *dynamicType; public: - unsigned size; - bool readOnly; public: - /// Create a new object state for the given memory object with concrete - /// contents. The initial contents are undefined, it is the callers - /// responsibility to initialize the object contents appropriately. + /// Create a new object state for the given memory + // For objects in memory + ObjectState(const MemoryObject *mo, const Array *array, KType *dt); ObjectState(const MemoryObject *mo, KType *dt); - /// Create a new object state for the given memory object with symbolic - /// contents. - ObjectState(const MemoryObject *mo, const Array *array, KType *dt); - ObjectState(const MemoryObject *mo, const ObjectState &os); + // For symbolic objects not in memory (hack) ObjectState(const ObjectState &os); - ~ObjectState(); + ~ObjectState() = default; const MemoryObject *getObject() const { return object.get(); } void setReadOnly(bool ro) { readOnly = ro; } - /// Make contents all concrete and zero - void initializeToZero(); + size_t getSparseStorageEntries() { + return knownSymbolics.storage().size() + unflushedMask.storage().size(); + } - /// Make contents all concrete and random - void initializeToRandom(); + void swapObjectHack(MemoryObject *mo) { object = mo; } ref read(ref offset, Expr::Width width) const; ref read(unsigned offset, Expr::Width width) const; @@ -267,6 +258,7 @@ class ObjectState { void write(unsigned offset, ref value); void write(ref offset, ref value); + void write(ref os); void write8(unsigned offset, uint8_t value); void write16(unsigned offset, uint16_t value); @@ -274,13 +266,6 @@ class ObjectState { void write64(unsigned offset, uint64_t value); void print() const; - /* - Looks at all the symbolic bytes of this object, gets a value for them - from the solver and puts them in the concreteStore. - */ - void flushToConcreteStore(TimingSolver *solver, - const ExecutionState &state) const; - bool isAccessableFrom(KType *) const; KType *getDynamicType() const; @@ -290,31 +275,12 @@ class ObjectState { void makeConcrete(); - void makeSymbolic(); - ref read8(ref offset) const; void write8(unsigned offset, ref value); void write8(ref offset, ref value); - void fastRangeCheckOffset(ref offset, unsigned *base_r, - unsigned *size_r) const; - void flushRangeForRead(unsigned rangeBase, unsigned rangeSize) const; - void flushRangeForWrite(unsigned rangeBase, unsigned rangeSize); - - /// isByteConcrete ==> !isByteKnownSymbolic - bool isByteConcrete(unsigned offset) const; - - /// isByteKnownSymbolic ==> !isByteConcrete - bool isByteKnownSymbolic(unsigned offset) const; - - /// isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i)) - bool isByteUnflushed(unsigned offset) const; - - void markByteConcrete(unsigned offset); - void markByteSymbolic(unsigned offset); - void markByteFlushed(unsigned offset); - void markByteUnflushed(unsigned offset); - void setKnownSymbolic(unsigned offset, Expr *value); + void flushForRead() const; + void flushForWrite(); ArrayCache *getArrayCache() const; }; diff --git a/lib/Core/MockBuilder.cpp b/lib/Core/MockBuilder.cpp new file mode 100644 index 0000000000..de06f5e463 --- /dev/null +++ b/lib/Core/MockBuilder.cpp @@ -0,0 +1,672 @@ +//===-- MockBuilder.cpp ---------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#include "klee/Core/MockBuilder.h" + +#include "klee/Config/Version.h" +#include "klee/Module/Annotation.h" +#include "klee/Support/ErrorHandling.h" +#include "klee/Support/ModuleUtil.h" + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + +namespace klee { + +template +void inline removeAliases(const llvm::Module *userModule, + std::map &externals) { + for (const auto &alias : userModule->aliases()) { + auto it = externals.find(alias.getName().str()); + if (it != externals.end()) { + externals.erase(it); + } + } +} + +void MockBuilder::buildCallKleeMakeSymbolic( + const std::string &kleeMakeSymbolicFunctionName, llvm::Value *source, + llvm::Type *type, const std::string &symbolicName) { + auto *kleeMakeSymbolicName = llvm::FunctionType::get( + llvm::Type::getVoidTy(ctx), + {llvm::Type::getInt8PtrTy(ctx), llvm::Type::getInt64Ty(ctx), + llvm::Type::getInt8PtrTy(ctx)}, + false); + auto kleeMakeSymbolicCallee = mockModule->getOrInsertFunction( + kleeMakeSymbolicFunctionName, kleeMakeSymbolicName); + auto bitCastInst = + builder->CreateBitCast(source, llvm::Type::getInt8PtrTy(ctx)); + auto globalSymbolicName = builder->CreateGlobalString("@" + symbolicName); + auto gep = builder->CreateConstInBoundsGEP2_64( + globalSymbolicName->getValueType(), globalSymbolicName, 0, 0); + auto sz = llvm::APInt(64, mockModule->getDataLayout().getTypeStoreSize(type), + false); + builder->CreateCall(kleeMakeSymbolicCallee, + {bitCastInst, llvm::ConstantInt::get(ctx, sz), gep}); +} + +std::map +MockBuilder::getExternalFunctions() { + std::map externals; + for (const auto &f : userModule->functions()) { + if (f.isDeclaration() && !f.use_empty() && + !ignoredExternals.count(f.getName().str())) { + // NOTE: here we detect all the externals, even linked. + externals.insert(std::make_pair(f.getName(), f.getFunctionType())); + } + } + removeAliases(userModule, externals); + + return externals; +} + +std::map MockBuilder::getExternalGlobals() { + std::map externals; + for (const auto &global : userModule->globals()) { + if (global.isDeclaration() && + !ignoredExternals.count(global.getName().str())) { + externals.insert(std::make_pair(global.getName(), global.getType())); + } + } + removeAliases(userModule, externals); + return externals; +} + +MockBuilder::MockBuilder( + const llvm::Module *initModule, const Interpreter::ModuleOptions &opts, + const Interpreter::InterpreterOptions &interpreterOptions, + const std::set &ignoredExternals, + std::vector> &redefinitions, + InterpreterHandler *interpreterHandler, + std::set &mainModuleFunctions, + std::set &mainModuleGlobals) + : userModule(initModule), ctx(initModule->getContext()), opts(opts), + interpreterOptions(interpreterOptions), + ignoredExternals(ignoredExternals), redefinitions(redefinitions), + interpreterHandler(interpreterHandler), + mainModuleFunctions(mainModuleFunctions), + mainModuleGlobals(mainModuleGlobals) { + annotations = parseAnnotations(opts.AnnotationsFile); +} + +std::unique_ptr MockBuilder::build() { + initMockModule(); + buildMockMain(); + buildExternalFunctionsDefinitions(); + + if (!mockModule) { + klee_error("Unable to generate mocks"); + } + + { + const std::string redefinitionsFileName = "redefinitions.txt"; + auto os(interpreterHandler->openOutputFile(redefinitionsFileName)); + if (!os) { + klee_error("Mock: can't open %s file", redefinitionsFileName.c_str()); + } + for (const auto &i : redefinitions) { + *os << i.first << " " << i.second << "\n"; + } + } + + const std::string externalsFileName = "externals.ll"; + std::string extFile = + interpreterHandler->getOutputFilename(externalsFileName); + + { + auto mainFn = mockModule->getFunction(opts.MainCurrentName); + mainFn->setName(opts.EntryPoint); + auto os = interpreterHandler->openOutputFile(externalsFileName); + if (!os) { + klee_error("Mock: can't open '%s' file", externalsFileName.c_str()); + } + *os << *mockModule; + mockModule.reset(); + } + + { + std::string errorMsg; + std::vector> loadedUserModules; + loadFileAsOneModule(extFile, ctx, loadedUserModules, errorMsg); + std::swap(loadedUserModules.front(), mockModule); + + auto mainFn = mockModule->getFunction(opts.MainCurrentName); + mainFn->setName(opts.MainCurrentName); + } + + return std::move(mockModule); +} + +void MockBuilder::initMockModule() { + mockModule = std::make_unique( + userModule->getName().str() + "__klee_externals", ctx); + mockModule->setTargetTriple(userModule->getTargetTriple()); + mockModule->setDataLayout(userModule->getDataLayout()); + builder = std::make_unique>(ctx); +} + +// Set up entrypoint in new module. Here we'll define external globals and then +// call user's entrypoint. +void MockBuilder::buildMockMain() { + mainModuleFunctions.insert(opts.MainNameAfterMock); + llvm::Function *userMainFn = userModule->getFunction(opts.MainCurrentName); + if (!userMainFn) { + klee_error("Entry function '%s' not found in module.", + opts.MainCurrentName.c_str()); + } + userMainFn->setName(opts.MainNameAfterMock); + + mockModule->getOrInsertFunction(opts.MainCurrentName, + userMainFn->getFunctionType(), + userMainFn->getAttributes()); + llvm::Function *mockMainFn = mockModule->getFunction(opts.MainCurrentName); + if (!mockMainFn) { + klee_error("Mock: Entry function '%s' not found in module", + opts.MainCurrentName.c_str()); + } + mockMainFn->setDSOLocal(true); + auto globalsInitBlock = llvm::BasicBlock::Create(ctx, "", mockMainFn); + builder->SetInsertPoint(globalsInitBlock); + // Define all the external globals + if (interpreterOptions.Mock == MockPolicy::All || + interpreterOptions.MockMutableGlobals == MockMutableGlobalsPolicy::All) { + buildExternalGlobalsDefinitions(); + } + + auto userMainCallee = mockModule->getOrInsertFunction( + opts.MainNameAfterMock, userMainFn->getFunctionType()); + std::vector args; + args.reserve(userMainFn->arg_size()); + for (auto &arg : mockMainFn->args()) { + args.push_back(&arg); + } + + auto callUserMain = builder->CreateCall(userMainCallee, args); + if (!userMainFn->getReturnType()->isSized()) { + builder->CreateRet(nullptr); + return; + } else { + builder->CreateRet(callUserMain); + } +} + +void MockBuilder::buildExternalGlobalsDefinitions() { + auto externalGlobals = getExternalGlobals(); + for (const auto &[extName, type] : externalGlobals) { + auto elementType = type->getPointerElementType(); + klee_message("Mocking external variable %s", extName.c_str()); + llvm::GlobalVariable *global = dyn_cast_or_null( + mockModule->getOrInsertGlobal(extName, elementType)); + if (!global) { + klee_error("Mock: Unable to add global variable '%s' to module", + extName.c_str()); + } + + mainModuleGlobals.insert(extName); + if (!elementType->isSized()) { + continue; + } + + auto *zeroInitializer = llvm::GlobalValue::getNullValue(elementType); + if (!zeroInitializer) { + klee_error("Mock: Unable to get zero initializer for '%s'", + extName.c_str()); + } + global->setInitializer(zeroInitializer); + global->setDSOLocal(true); + auto *localPointer = builder->CreateAlloca(elementType, nullptr); + buildCallKleeMakeSymbolic("klee_make_symbolic", localPointer, elementType, + "external_" + extName); + llvm::Value *localValue = builder->CreateLoad(elementType, localPointer); + builder->CreateStore(localValue, global); + } +} + +// standard functions that must be ignored +const std::set StandartIgnoredFunctions = { + "_ZNSt8ios_base4InitC1Ev", "_ZNSt8ios_base4InitD1Ev"}; + +void MockBuilder::buildExternalFunctionsDefinitions() { + std::map externalFunctions; + if (interpreterOptions.Mock == MockPolicy::All) { + externalFunctions = getExternalFunctions(); + } + + if (!opts.AnnotateOnlyExternal) { + for (const auto &annotation : annotations) { + llvm::Function *func = userModule->getFunction(annotation.first); + if (func) { + auto ext = externalFunctions.find(annotation.first); + if (ext == externalFunctions.end()) { + externalFunctions[annotation.first] = func->getFunctionType(); + } + } + } + } + + for (const auto &[extName, type] : externalFunctions) { + mockModule->getOrInsertFunction(extName, type); + llvm::Function *func = mockModule->getFunction(extName); + if (!func) { + klee_error("Mock: Unable to find function '%s' in module", + extName.c_str()); + } + if (func->isIntrinsic()) { + klee_message("Mock: Skip intrinsic function '%s'", extName.c_str()); + continue; + } + if (StandartIgnoredFunctions.count(extName)) { + klee_message("Mock: Skip function '%s'", extName.c_str()); + continue; + } + mainModuleFunctions.insert(extName); + if (!func->empty()) { + continue; + } + auto *BB = llvm::BasicBlock::Create(ctx, "entry", func); + builder->SetInsertPoint(BB); + + const auto nameToAnnotations = annotations.find(extName); + if (nameToAnnotations != annotations.end()) { + klee_message("Annotation function %s", extName.c_str()); + const auto &annotation = nameToAnnotations->second; + + buildAnnotationForExternalFunctionArgs(func, annotation.argsStatements); + buildAnnotationForExternalFunctionReturn(func, + annotation.returnStatements); + buildAnnotationForExternalFunctionProperties(func, annotation.properties); + } else { + klee_message("Mocking external function %s", extName.c_str()); + // Default annotation for externals return + buildAnnotationForExternalFunctionReturn( + func, {std::make_shared()}); + } + } +} + +std::pair +MockBuilder::goByOffset(llvm::Value *value, + const std::vector &offset) { + llvm::Value *prev = nullptr; + llvm::Value *current = value; + for (const auto &inst : offset) { + if (inst == "*") { + if (!current->getType()->isPointerTy()) { + klee_error("Incorrect annotation offset."); + } + prev = current; + current = builder->CreateLoad(current->getType()->getPointerElementType(), + current); + } else if (inst == "&") { + auto addr = builder->CreateAlloca(current->getType()); + prev = current; + current = builder->CreateStore(current, addr); + } else { + const size_t index = std::stol(inst); + if (!(current->getType()->isPointerTy() || + current->getType()->isArrayTy())) { + klee_error("Incorrect annotation offset."); + } + prev = current; + current = builder->CreateConstInBoundsGEP1_64(current->getType(), current, + index); + } + } + return {prev, current}; +} + +inline llvm::Type *getTypeByOffset(llvm::Type *value, + const std::vector &offset) { + llvm::Type *current = value; + for (const auto &inst : offset) { + if (inst == "*") { + if (!current->isPointerTy()) { + return nullptr; + } + current = current->getPointerElementType(); + } else if (inst == "&") { + // Not change + } else { + const size_t index = std::stol(inst); + if (current->isArrayTy() || current->isPointerTy()) { + current = current->getContainedType(index); + } else { + return nullptr; + } + } + } + return current; +} + +inline bool isCorrectStatements(const std::vector &statements, + const llvm::Argument *arg) { + return std::any_of(statements.begin(), statements.end(), + [arg](const Statement::Ptr &statement) { + auto argType = + getTypeByOffset(arg->getType(), statement->offset); + switch (statement->getKind()) { + case Statement::Kind::Deref: + case Statement::Kind::InitNull: + return argType->isPointerTy(); + case Statement::Kind::AllocSource: + assert(false); + case Statement::Kind::Unknown: + default: + return true; + } + }); +} + +bool tryAlign(llvm::Function *func, + const std::vector> &statements, + std::vector> &res) { + if (func->arg_size() == statements.size()) { + res = statements; + return true; + } + + for (size_t i = 0, j = 0; j < func->arg_size() && i < statements.size();) { + while (true) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) + auto arg = func->getArg(j); +#else + auto arg = &func->arg_begin()[j]; +#endif + if (isCorrectStatements(statements[i], arg)) { + break; + } + res.emplace_back(); + j++; + if (j >= func->arg_size()) { + break; + } + } + res.push_back(statements[i]); + j++; + i++; + } + if (func->arg_size() == statements.size()) { + return true; + } + return false; +} + +std::map, std::vector> +unifyByOffset(const std::vector &statements) { + std::map, std::vector> res; + for (const auto &i : statements) { + res[i->offset].push_back(i); + } + return res; +} + +void MockBuilder::buildAnnotationForExternalFunctionArgs( + llvm::Function *func, + const std::vector> &statementsNotAlign) { + std::vector> statements; + bool flag = tryAlign(func, statementsNotAlign, statements); + if (!flag) { + klee_warning("Annotation: can't align function arguments %s", + func->getName().str().c_str()); + return; + } + for (size_t i = 0; i < statements.size(); i++) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) + const auto arg = func->getArg(i); +#else + const auto arg = &func->arg_begin()[i]; +#endif + auto statementsMap = unifyByOffset(statements[i]); + for (const auto &[offset, statementsOffset] : statementsMap) { + auto [prev, elem] = goByOffset(arg, offset); + + Statement::Alloc *allocSourcePtr = nullptr; + Statement::Free *freePtr = nullptr; + Statement::InitNull *initNullPtr = nullptr; + + for (const auto &statement : statementsOffset) { + switch (statement->getKind()) { + case Statement::Kind::Deref: { + if (!elem->getType()->isPointerTy()) { + klee_error("Annotation: Deref arg not pointer"); + } + + std::string derefCondName = "condition_deref_arg_" + + std::to_string(i) + "_deref_" + + func->getName().str(); + + auto intType = llvm::IntegerType::get(ctx, 1); + auto *derefCond = builder->CreateAlloca(intType, nullptr); + buildCallKleeMakeSymbolic("klee_make_mock", derefCond, intType, + derefCondName); + + llvm::BasicBlock *fromIf = builder->GetInsertBlock(); + llvm::Function *curFunc = fromIf->getParent(); + + llvm::BasicBlock *derefBB = + llvm::BasicBlock::Create(ctx, derefCondName, curFunc); + llvm::BasicBlock *contBB = + llvm::BasicBlock::Create(ctx, "continue_" + derefCondName); + auto brValue = builder->CreateLoad(intType, derefCond); + builder->CreateCondBr(brValue, derefBB, contBB); + + builder->SetInsertPoint(derefBB); + builder->CreateLoad(elem->getType()->getPointerElementType(), elem); + builder->CreateBr(contBB); + + curFunc->getBasicBlockList().push_back(contBB); + builder->SetInsertPoint(contBB); + break; + } + case Statement::Kind::AllocSource: { + if (prev != nullptr) { + allocSourcePtr = (Statement::Alloc *)statement.get(); + } else { + klee_message("Annotation: not valid annotation %s", + statement->toString().c_str()); + } + break; + } + case Statement::Kind::InitNull: { + if (prev != nullptr) { + initNullPtr = (Statement::InitNull *)statement.get(); + } else { + klee_message("Annotation: not valid annotation %s", + statement->toString().c_str()); + } + break; + } + case Statement::Kind::Free: { + if (elem->getType()->isPointerTy()) { + freePtr = (Statement::Free *)statement.get(); + } else { + klee_message("Annotation: not valid annotation %s", + statement->toString().c_str()); + } + break; + } + case Statement::Kind::Unknown: + default: + klee_message("Annotation: not implemented %s", + statement->toString().c_str()); + break; + } + } + if (freePtr) { + buildFree(elem, freePtr); + } + processingValue(prev, elem->getType(), allocSourcePtr, initNullPtr); + } + } +} + +void MockBuilder::processingValue(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr, + bool initNullPtr) { + if (initNullPtr) { + auto intType = llvm::IntegerType::get(ctx, 1); + auto *allocCond = builder->CreateAlloca(intType, nullptr); + buildCallKleeMakeSymbolic("klee_make_mock", allocCond, intType, + "initPtrCond"); + + llvm::BasicBlock *fromIf = builder->GetInsertBlock(); + llvm::Function *curFunc = fromIf->getParent(); + + llvm::BasicBlock *initNullBB = llvm::BasicBlock::Create(ctx, "initNullBR"); + llvm::BasicBlock *contBB = llvm::BasicBlock::Create(ctx, "continueBR"); + auto brValue = builder->CreateLoad(intType, allocCond); + if (allocSourcePtr) { + llvm::BasicBlock *allocBB = + llvm::BasicBlock::Create(ctx, "allocArg", curFunc); + builder->CreateCondBr(brValue, allocBB, initNullBB); + builder->SetInsertPoint(allocBB); + buildAllocSource(prev, elemType, allocSourcePtr); + builder->CreateBr(contBB); + } else { + builder->CreateCondBr(brValue, initNullBB, contBB); + } + curFunc->getBasicBlockList().push_back(initNullBB); + builder->SetInsertPoint(initNullBB); + builder->CreateStore( + llvm::ConstantPointerNull::get(llvm::cast(elemType)), + prev); + builder->CreateBr(contBB); + + curFunc->getBasicBlockList().push_back(contBB); + builder->SetInsertPoint(contBB); + } else if (allocSourcePtr) { + buildAllocSource(prev, elemType, allocSourcePtr); + } +} + +void MockBuilder::buildAllocSource(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr) { + if (allocSourcePtr->value != Statement::Alloc::ALLOC) { + klee_warning("Annotation: AllocSource \"%d\" not implemented use alloc", + allocSourcePtr->value); + } + auto valueType = elemType->getPointerElementType(); + auto sizeValue = llvm::ConstantInt::get( + ctx, + llvm::APInt(64, mockModule->getDataLayout().getTypeStoreSize(valueType), + false)); + auto int8PtrTy = llvm::IntegerType::getInt64Ty(ctx); + auto mallocInstr = + llvm::CallInst::CreateMalloc(builder->GetInsertBlock(), int8PtrTy, + valueType, sizeValue, nullptr, nullptr); + auto mallocValue = builder->Insert(mallocInstr, llvm::Twine("MallocValue")); + builder->CreateStore(mallocValue, prev); +} + +void MockBuilder::buildFree(llvm::Value *elem, const Statement::Free *freePtr) { + if (freePtr->value != Statement::Free::FREE) { + klee_warning("Annotation: AllocSource \"%d\" not implemented use free", + freePtr->value); + } + auto freeInstr = llvm::CallInst::CreateFree(elem, builder->GetInsertBlock()); + builder->Insert(freeInstr); +} + +void MockBuilder::buildAnnotationForExternalFunctionReturn( + llvm::Function *func, const std::vector &statements) { + auto returnType = func->getReturnType(); + if (!returnType->isSized()) { // void return type + builder->CreateRet(nullptr); + return; + } + + Statement::Alloc *allocSourcePtr = nullptr; + Statement::InitNull *mustInitNull = nullptr; + Statement::MaybeInitNull *maybeInitNull = nullptr; + + for (const auto &statement : statements) { + switch (statement->getKind()) { + case Statement::Kind::Deref: + klee_warning("Annotation: unused Deref for return function \"%s\"", + func->getName().str().c_str()); + break; + case Statement::Kind::AllocSource: { + allocSourcePtr = returnType->isPointerTy() + ? (Statement::Alloc *)statement.get() + : nullptr; + break; + } + case Statement::Kind::InitNull: { + mustInitNull = returnType->isPointerTy() + ? (Statement::InitNull *)statement.get() + : nullptr; + break; + } + case Statement::Kind::MaybeInitNull: { + maybeInitNull = returnType->isPointerTy() + ? (Statement::MaybeInitNull *)statement.get() + : nullptr; + break; + } + case Statement::Kind::Free: { + klee_warning("Annotation: unused \"Free\" for return"); + break; + } + case Statement::Kind::Unknown: + default: + klee_message("Annotation: not implemented %s", + statement->toString().c_str()); + break; + } + } + std::string retName = "ret_" + func->getName().str(); + llvm::Value *retValuePtr = builder->CreateAlloca(returnType, nullptr); + + if (returnType->isPointerTy() && (allocSourcePtr || mustInitNull)) { + processingValue(retValuePtr, returnType, allocSourcePtr, + mustInitNull || maybeInitNull); + } else { + buildCallKleeMakeSymbolic("klee_make_mock", retValuePtr, returnType, + func->getName().str()); + if (returnType->isPointerTy() && !maybeInitNull) { + llvm::Value *retValue = + builder->CreateLoad(returnType, retValuePtr, retName); + auto cmpResult = + builder->CreateICmpNE(retValue, + llvm::ConstantPointerNull::get( + llvm::cast(returnType)), + "condition_init_null" + retName); + + auto *kleeAssumeType = llvm::FunctionType::get( + llvm::Type::getVoidTy(ctx), {llvm::Type::getInt64Ty(ctx)}, false); + + auto kleeAssumeFunc = + mockModule->getOrInsertFunction("klee_assume", kleeAssumeType); + auto cmpResult64 = + builder->CreateZExt(cmpResult, llvm::Type::getInt64Ty(ctx)); + builder->CreateCall(kleeAssumeFunc, {cmpResult64}); + } + } + llvm::Value *retValue = builder->CreateLoad(returnType, retValuePtr, retName); + builder->CreateRet(retValue); +} + +void MockBuilder::buildAnnotationForExternalFunctionProperties( + llvm::Function *func, const std::set &properties) { + for (const auto &property : properties) { + switch (property) { + case Statement::Property::Deterministic: + case Statement::Property::Noreturn: + case Statement::Property::Unknown: + default: + klee_message("Property not implemented"); + break; + } + } +} + +} // namespace klee diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index 30adeb8ce7..f42f798141 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -19,13 +19,13 @@ #include "klee/ADT/DiscretePDF.h" #include "klee/ADT/RNG.h" #include "klee/ADT/WeightedQueue.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Module/Target.h" #include "klee/Statistics/Statistics.h" #include "klee/Support/ErrorHandling.h" #include "klee/System/Time.h" +#include "klee/Utilities/Math.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -48,8 +48,8 @@ using namespace llvm; ExecutionState &DFSSearcher::selectState() { return *states.back(); } void DFSSearcher::update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) { + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states states.insert(states.end(), addedStates.begin(), addedStates.end()); @@ -74,8 +74,8 @@ void DFSSearcher::printName(llvm::raw_ostream &os) { os << "DFSSearcher\n"; } ExecutionState &BFSSearcher::selectState() { return *states.front(); } void BFSSearcher::update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) { + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current state // Assumption: If new states were added KLEE forked, therefore states evolved. // constraints were added to the current state, it evolved. @@ -115,9 +115,9 @@ ExecutionState &RandomSearcher::selectState() { return *states[theRNG.getInt32() % states.size()]; } -void RandomSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void RandomSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states states.insert(states.end(), addedStates.begin(), addedStates.end()); @@ -137,21 +137,6 @@ void RandomSearcher::printName(llvm::raw_ostream &os) { /// -static unsigned int ulog2(unsigned int val) { - if (val == 0) - return UINT_MAX; - if (val == 1) - return 0; - unsigned int ret = 0; - while (val > 1) { - val >>= 1; - ret++; - } - return ret; -} - -/// - TargetedSearcher::~TargetedSearcher() {} bool TargetedSearcher::empty() { return states->empty(); } @@ -168,9 +153,9 @@ TargetedSearcher::TargetedSearcher(ref target, ExecutionState &TargetedSearcher::selectState() { return *states->choose(0); } -void TargetedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void TargetedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current if (current && std::find(removedStates.begin(), removedStates.end(), @@ -190,13 +175,14 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { KBlock *kb = es->pc->parent; KInstruction *ki = es->pc; weight_type weight; - if (!target->shouldFailOnThisTarget() && kb->numInstructions && + if (!target->shouldFailOnThisTarget() && kb->getNumInstructions() && !isa(kb) && kb->getFirstInstruction() != ki && states->tryGetWeight(es, weight)) { return weight; } auto distRes = distanceCalculator.getDistance(*es, target->getBlock()); - weight = ulog2(distRes.weight + es->steppedMemoryInstructions + 1); // [0, 32) + weight = klee::util::ulog2(distRes.weight + es->steppedMemoryInstructions + + 1); // [0, 32) if (!distRes.isInsideFunction) { weight += 32; // [32, 64) } @@ -207,12 +193,12 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { ExecutionState &GuidedSearcher::selectState() { unsigned size = historiesAndTargets.size(); - index = theRNG.getInt32() % (size + 1); + interleave ^= 1; ExecutionState *state = nullptr; - if (index == size) { + if (interleave || !size) { state = &baseSearcher->selectState(); } else { - index = index % size; + index = theRNG.getInt32() % size; auto &historyTargetPair = historiesAndTargets[index]; ref history = historyTargetPair.first; ref target = historyTargetPair.second; @@ -225,9 +211,9 @@ ExecutionState &GuidedSearcher::selectState() { return *state; } -void GuidedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void GuidedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { if (current) { ref history = current->history(); @@ -389,8 +375,8 @@ double WeightedRandomSearcher::getWeight(ExecutionState *es) { case RP: return std::pow(0.5, es->depth); case InstCount: { - uint64_t count = theStatisticManager->getIndexedValue(stats::instructions, - es->pc->info->id); + uint64_t count = theStatisticManager->getIndexedValue( + stats::instructions, es->pc->getGlobalIndex()); double inv = 1. / std::max((uint64_t)1, count); return inv * inv; } @@ -422,9 +408,9 @@ double WeightedRandomSearcher::getWeight(ExecutionState *es) { } } -void WeightedRandomSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void WeightedRandomSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current if (current && updateWeights && @@ -515,11 +501,11 @@ ExecutionState &RandomPathSearcher::selectState() { return *n->state; } -void RandomPathSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void RandomPathSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states - for (auto &es : addedStates) { + for (auto es : addedStates) { PTreeNode *pnode = es->ptreeNode, *parent = pnode->parent; PTreeNodePtr &root = processForest.getPTrees().at(pnode->getTreeID())->root; PTreeNodePtr *childPtr; @@ -619,9 +605,9 @@ ExecutionState &BatchingSearcher::selectState() { return *lastState; } -void BatchingSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void BatchingSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // drop memoized state if it is marked for deletion if (std::find(removedStates.begin(), removedStates.end(), lastState) != removedStates.end()) @@ -641,63 +627,106 @@ void BatchingSearcher::printName(llvm::raw_ostream &os) { /// -IterativeDeepeningTimeSearcher::IterativeDeepeningTimeSearcher( - Searcher *baseSearcher) - : baseSearcher{baseSearcher} {}; +class TimeMetric final : public IterativeDeepeningSearcher::Metric { + time::Point startTime; + time::Span time{time::seconds(1)}; + +public: + void selectState() final { startTime = time::getWallTime(); } + bool exceeds(const ExecutionState &state) const final { + return time::getWallTime() - startTime > time; + } + void increaseLimit() final { + time *= 2U; + klee_message("increased time budget to %f seconds", time.toSeconds()); + } +}; + +class MaxCyclesMetric final : public IterativeDeepeningSearcher::Metric { +public: + using ty = unsigned long long; + +private: + ty maxCycles; + +public: + explicit MaxCyclesMetric(ty maxCycles) : maxCycles(maxCycles){}; + explicit MaxCyclesMetric() : MaxCyclesMetric(1ULL){}; + + bool exceeds(const ExecutionState &state) const final { + return state.isCycled(maxCycles); + } + void increaseLimit() final { + maxCycles *= 4ULL; + klee_message("increased max-cycles to %llu", maxCycles); + } +}; + +IterativeDeepeningSearcher::IterativeDeepeningSearcher( + Searcher *baseSearcher, TargetManagerSubscriber *tms, + HaltExecution::Reason m) + : baseSearcher{baseSearcher}, tms{tms} { + switch (m) { + case HaltExecution::Reason::MaxTime: + metric = std::make_unique(); + return; + case HaltExecution::Reason::MaxCycles: + metric = std::make_unique(); + return; + default: + klee_error("Illegal metric for iterative deepening searcher: %d", m); + } +} -ExecutionState &IterativeDeepeningTimeSearcher::selectState() { +ExecutionState &IterativeDeepeningSearcher::selectState() { ExecutionState &res = baseSearcher->selectState(); - startTime = time::getWallTime(); + metric->selectState(); return res; } -void IterativeDeepeningTimeSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void IterativeDeepeningSearcher::update( + const TargetHistoryTargetPairToStatesMap &added, + const TargetHistoryTargetPairToStatesMap &removed) { + if (!tms) + return; + added.setWithout(&pausedStates); + removed.setWithout(&pausedStates); + tms->update(added, removed); + added.clearWithout(); + removed.clearWithout(); +} - const auto elapsed = time::getWallTime() - startTime; +void IterativeDeepeningSearcher::update(ExecutionState *current, + const StateIterable &added, + const StateIterable &removed) { + removed.setWithout(&pausedStates); + baseSearcher->update(current, added, removed); + removed.clearWithout(); - // update underlying searcher (filter paused states unknown to underlying - // searcher) - if (!removedStates.empty()) { - std::vector alt = removedStates; - for (const auto state : removedStates) { - auto it = pausedStates.find(state); - if (it != pausedStates.end()) { - pausedStates.erase(it); - alt.erase(std::remove(alt.begin(), alt.end(), state), alt.end()); - } - } - baseSearcher->update(current, addedStates, alt); - } else { - baseSearcher->update(current, addedStates, removedStates); - } + for (auto state : removed) + pausedStates.erase(state); - // update current: pause if time exceeded if (current && - std::find(removedStates.begin(), removedStates.end(), current) == - removedStates.end() && - elapsed > time) { + std::find(removed.begin(), removed.end(), current) == removed.end() && + metric->exceeds(*current)) { pausedStates.insert(current); baseSearcher->update(nullptr, {}, {current}); } // no states left in underlying searcher: fill with paused states - if (baseSearcher->empty()) { - time *= 2U; - klee_message("increased time budget to %f\n", time.toSeconds()); - std::vector ps(pausedStates.begin(), pausedStates.end()); - baseSearcher->update(nullptr, ps, std::vector()); + if (baseSearcher->empty() && !pausedStates.empty()) { + metric->increaseLimit(); + baseSearcher->update(nullptr, pausedStates, {}); pausedStates.clear(); } } -bool IterativeDeepeningTimeSearcher::empty() { +bool IterativeDeepeningSearcher::empty() { return baseSearcher->empty() && pausedStates.empty(); } -void IterativeDeepeningTimeSearcher::printName(llvm::raw_ostream &os) { - os << "IterativeDeepeningTimeSearcher\n"; +void IterativeDeepeningSearcher::printName(llvm::raw_ostream &os) { + os << "IterativeDeepeningSearcher\n"; } /// @@ -716,9 +745,9 @@ ExecutionState &InterleavedSearcher::selectState() { return s->selectState(); } -void InterleavedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void InterleavedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update underlying searchers for (auto &searcher : searchers) diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h index 0a6c734f73..f0b7e8d2b5 100644 --- a/lib/Core/Searcher.h +++ b/lib/Core/Searcher.h @@ -63,9 +63,8 @@ class Searcher { /// \param current The currently selected state for exploration. /// \param addedStates The newly branched states with `current` as common /// ancestor. \param removedStates The states that will be terminated. - virtual void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) = 0; + virtual void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) = 0; /// \return True if no state left for exploration, False otherwise virtual bool empty() = 0; @@ -96,9 +95,8 @@ class DFSSearcher final : public Searcher { public: ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -112,9 +110,8 @@ class BFSSearcher final : public Searcher { public: ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -127,9 +124,8 @@ class RandomSearcher final : public Searcher { public: explicit RandomSearcher(RNG &rng); ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -148,9 +144,8 @@ class TargetedSearcher final : public Searcher { ~TargetedSearcher() override; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -160,17 +155,10 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { using TargetHistoryTargetPairHashMap = std::unordered_map; - - using TargetHistoryTargetPair = - std::pair, ref>; using TargetHistoryTargetPairToSearcherMap = std::unordered_map, TargetHistoryTargetHash, TargetHistoryTargetCmp>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; using TargetForestHisoryTargetVector = std::vector; using TargetForestHistoryTargetSet = std::unordered_set baseAddedStates; @@ -204,9 +193,8 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { theRNG(rng) {} ~GuidedSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; void update(const TargetHistoryTargetPairToStatesMap &added, const TargetHistoryTargetPairToStatesMap &removed) override; void updateTargets(ExecutionState *current); @@ -245,9 +233,8 @@ class WeightedRandomSearcher final : public Searcher { ~WeightedRandomSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -282,9 +269,8 @@ class RandomPathSearcher final : public Searcher { ~RandomPathSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -316,33 +302,45 @@ class BatchingSearcher final : public Searcher { ~BatchingSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; -/// IterativeDeepeningTimeSearcher implements time-based deepening. States -/// are selected from an underlying searcher. When a state reaches its time -/// limit it is paused (removed from underlying searcher). When the underlying -/// searcher runs out of states, the time budget is increased and all paused +/// IterativeDeepeningSearcher implements a metric-based deepening. States +/// are selected from an underlying searcher. When a state exceeds its metric +/// limit, it is paused (removed from underlying searcher). When the underlying +/// searcher runs out of states, the metric limit is increased and all paused /// states are revived (added to underlying searcher). -class IterativeDeepeningTimeSearcher final : public Searcher { +class IterativeDeepeningSearcher final : public Searcher, + public TargetManagerSubscriber { +public: + struct Metric { + virtual ~Metric() = default; + virtual void selectState(){}; + virtual bool exceeds(const ExecutionState &state) const = 0; + virtual void increaseLimit() = 0; + }; + +private: std::unique_ptr baseSearcher; - time::Point startTime; - time::Span time{time::seconds(1)}; + TargetManagerSubscriber *tms; + std::unique_ptr metric; std::set pausedStates; public: /// \param baseSearcher The underlying searcher (takes ownership). - explicit IterativeDeepeningTimeSearcher(Searcher *baseSearcher); - ~IterativeDeepeningTimeSearcher() override = default; + explicit IterativeDeepeningSearcher(Searcher *baseSearcher, + TargetManagerSubscriber *tms, + HaltExecution::Reason metric); + ~IterativeDeepeningSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; + void update(const TargetHistoryTargetPairToStatesMap &added, + const TargetHistoryTargetPairToStatesMap &removed) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -360,9 +358,8 @@ class InterleavedSearcher final : public Searcher { ~InterleavedSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 6138eabe1b..ae4a7b358c 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -112,6 +112,7 @@ static SpecialFunctionHandler::HandlerInfo handlerInfo[] = { #endif add("klee_is_symbolic", handleIsSymbolic, true), add("klee_make_symbolic", handleMakeSymbolic, false), + add("klee_make_mock", handleMakeMock, false), add("klee_mark_global", handleMarkGlobal, false), add("klee_prefer_cex", handlePreferCex, false), add("klee_posix_prefer_cex", handlePosixPreferCex, false), @@ -269,7 +270,7 @@ bool SpecialFunctionHandler::handle(ExecutionState &state, Function *f, Handler h = it->second.first; bool hasReturnValue = it->second.second; // FIXME: Check this... add test? - if (!hasReturnValue && !target->inst->use_empty()) { + if (!hasReturnValue && !target->inst()->use_empty()) { executor.terminateStateOnExecError( state, "expected return value from void special function"); } else { @@ -626,7 +627,7 @@ void SpecialFunctionHandler::handleWarning(ExecutionState &state, std::string msg_str = readStringAtAddress(state, arguments[0]); klee_warning("%s: %s", - state.stack.callStack().back().kf->function->getName().data(), + state.stack.callStack().back().kf->function()->getName().data(), msg_str.c_str()); } @@ -639,7 +640,7 @@ void SpecialFunctionHandler::handleWarningOnce( std::string msg_str = readStringAtAddress(state, arguments[0]); klee_warning_once( 0, "%s: %s", - state.stack.callStack().back().kf->function->getName().data(), + state.stack.callStack().back().kf->function()->getName().data(), msg_str.c_str()); } @@ -692,7 +693,7 @@ void SpecialFunctionHandler::handleGetObjSize( target, *it->second, ConstantExpr::create(mo->size, executor.kmodule->targetData->getTypeSizeInBits( - target->inst->getType()))); + target->inst()->getType()))); } } @@ -744,7 +745,7 @@ void SpecialFunctionHandler::handleErrnoLocation( target, state, ConstantExpr::create((uint64_t)errno_addr, executor.kmodule->targetData->getTypeSizeInBits( - target->inst->getType()))); + target->inst()->getType()))); } void SpecialFunctionHandler::handleCalloc(ExecutionState &state, KInstruction *target, @@ -864,7 +865,7 @@ void SpecialFunctionHandler::handleDefineFixedObject( uint64_t address = cast(arguments[0])->getZExtValue(); uint64_t size = cast(arguments[1])->getZExtValue(); MemoryObject *mo = - executor.memory->allocateFixed(address, size, state.prevPC->inst); + executor.memory->allocateFixed(address, size, state.prevPC->inst()); executor.bindObjectInState( state, mo, executor.typeSystemManager->getUnknownType(), false); mo->isUserSpecified = true; // XXX hack; @@ -921,7 +922,7 @@ void SpecialFunctionHandler::handleMakeSymbolic( assert(success && "FIXME: Unhandled solver failure"); if (res) { - uint64_t sid = 0; + uint64_t sid = 0; // TODO: unused variable if (state.arrayNames.count(name)) { sid = state.arrayNames[name]; } @@ -937,6 +938,83 @@ void SpecialFunctionHandler::handleMakeSymbolic( } } +void SpecialFunctionHandler::handleMakeMock(ExecutionState &state, + KInstruction *target, + std::vector> &arguments) { + std::string name; + + if (arguments.size() != 3) { + executor.terminateStateOnUserError(state, + "Incorrect number of arguments to " + "klee_make_mock(void*, size_t, char*)"); + return; + } + + name = arguments[2]->isZero() ? "" : readStringAtAddress(state, arguments[2]); + + if (name.empty()) { + executor.terminateStateOnUserError( + state, "Empty name of function in klee_make_mock"); + return; + } + + KFunction *kf = target->parent->parent; + + Executor::ExactResolutionList rl; + executor.resolveExact(state, arguments[0], + executor.typeSystemManager->getUnknownType(), rl, + "make_symbolic"); + + for (auto &it : rl) { + ObjectPair op = it.second->addressSpace.findObject(it.first); + const MemoryObject *mo = op.first; + mo->setName(name); + mo->updateTimestamp(); + + const ObjectState *old = op.second; + ExecutionState *s = it.second; + + if (old->readOnly) { + executor.terminateStateOnUserError( + *s, "cannot make readonly object symbolic"); + return; + } + + bool res; + bool success __attribute__((unused)) = executor.solver->mustBeTrue( + s->constraints.cs(), + EqExpr::create( + ZExtExpr::create(arguments[1], Context::get().getPointerWidth()), + mo->getSizeExpr()), + res, s->queryMetaData); + assert(success && "FIXME: Unhandled solver failure"); + + if (res) { + ref source; + switch (executor.interpreterOpts.MockStrategy) { + case MockStrategyKind::Naive: + source = + SourceBuilder::mockNaive(executor.kmodule.get(), *kf->function(), + executor.updateNameVersion(state, name)); + break; + case MockStrategyKind::Deterministic: + std::vector> args(kf->getNumArgs()); + for (size_t i = 0; i < kf->getNumArgs(); i++) { + args[i] = executor.getArgumentCell(state, kf, i).value; + } + source = SourceBuilder::mockDeterministic(executor.kmodule.get(), + *kf->function(), args); + break; + } + executor.executeMakeSymbolic(state, mo, old->getDynamicType(), source, + false); + } else { + executor.terminateStateOnUserError(*s, + "Wrong size given to klee_make_mock"); + } + } +} + void SpecialFunctionHandler::handleMarkGlobal( ExecutionState &state, KInstruction *target, std::vector> &arguments) { diff --git a/lib/Core/SpecialFunctionHandler.h b/lib/Core/SpecialFunctionHandler.h index 78f920450e..6528b98c36 100644 --- a/lib/Core/SpecialFunctionHandler.h +++ b/lib/Core/SpecialFunctionHandler.h @@ -127,6 +127,7 @@ class SpecialFunctionHandler { HANDLER(handleGetValue); HANDLER(handleIsSymbolic); HANDLER(handleMakeSymbolic); + HANDLER(handleMakeMock); HANDLER(handleMalloc); HANDLER(handleMemalign); HANDLER(handleMarkGlobal); diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index e662644be3..4f25d8dbf0 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -13,9 +13,9 @@ #include "klee/Config/Version.h" #include "klee/Core/TerminationTypes.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Solver/SolverStats.h" #include "klee/Statistics/Statistics.h" #include "klee/Support/ErrorHandling.h" @@ -233,27 +233,25 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, } if (useStatistics() || userSearcherRequiresMD2U()) - theStatisticManager->useIndexedStats(km->infos->getMaxID()); + theStatisticManager->useIndexedStats(km->getMaxGlobalIndex()); for (auto &kfp : km->functions) { KFunction *kf = kfp.get(); - kf->trackCoverage = 1; for (unsigned i = 0; i < kf->numInstructions; ++i) { KInstruction *ki = kf->instructions[i]; if (OutputIStats) { - unsigned id = ki->info->id; + unsigned id = ki->getGlobalIndex(); theStatisticManager->setIndex(id); - if (kf->trackCoverage && instructionIsCoverable(ki->inst)) + if (instructionIsCoverable(ki->inst())) { ++stats::uncoveredInstructions; + } } - if (kf->trackCoverage) { - if (BranchInst *bi = dyn_cast(ki->inst)) - if (!bi->isUnconditional()) - numBranches++; - } + if (BranchInst *bi = dyn_cast(ki->inst())) + if (!bi->isUnconditional()) + numBranches++; } } @@ -392,25 +390,25 @@ void StatsTracker::stepInstruction(ExecutionState &es) { } } - Instruction *inst = es.pc->inst; - const InstructionInfo &ii = *es.pc->info; - InfoStackFrame &sf = es.stack.infoStack().back(); - theStatisticManager->setIndex(ii.id); + Instruction *inst = es.pc->inst(); + const KInstruction *ki = es.pc; + auto &sf = es.stack.infoStack().back(); + theStatisticManager->setIndex(ki->getGlobalIndex()); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); if (es.instsSinceCovNew) ++es.instsSinceCovNew; - if (sf.kf->trackCoverage && instructionIsCoverable(inst)) { + if (instructionIsCoverable(inst)) { if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, - ii.id)) { + ki->getGlobalIndex())) { // Checking for actual stoppoints avoids inconsistencies due // to line number propogation. // // FIXME: This trick no longer works, we should fix this in the line // number propogation. - es.coveredLines[&ii.file].insert(ii.line); + es.coveredLines[ki->getSourceFilepath()].insert(ki->getLine()); es.instsSinceCovNew = 1; ++stats::coveredInstructions; stats::uncoveredInstructions += (uint64_t)-1; @@ -446,7 +444,7 @@ void StatsTracker::framePushed(ExecutionState &es, if (UseCallPaths) { CallPathNode *parent = parentFrame ? parentFrame->callPathNode : 0; CallPathNode *cp = callPathManager.getCallPath( - parent, csf.caller ? csf.caller->inst : 0, csf.kf->function); + parent, csf.caller ? csf.caller->inst() : 0, csf.kf->function()); isf.callPathNode = cp; cp->count++; } @@ -695,8 +693,8 @@ void StatsTracker::updateStateStatistics(uint64_t addend) { ie = executor.states.end(); it != ie; ++it) { ExecutionState &state = **it; - const InstructionInfo &ii = *state.pc->info; - theStatisticManager->incrementIndexedValue(stats::states, ii.id, addend); + theStatisticManager->incrementIndexedValue( + stats::states, state.pc->getGlobalIndex(), addend); if (UseCallPaths) state.stack.infoStack().back().callPathNode->statistics.incrementValue( stats::states, addend); @@ -765,66 +763,70 @@ void StatsTracker::writeIStats() { of << "ob=" << llvm::sys::path::filename(objectFilename).str() << "\n"; - for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; - ++fnIt) { - if (!fnIt->isDeclaration()) { + for (auto &fn : *m) { + if (!fn.isDeclaration()) { // Always try to write the filename before the function name, as otherwise // KCachegrind can create two entries for the function, one with an // unnamed file and one without. - Function *fn = &*fnIt; - const FunctionInfo &ii = executor.kmodule->infos->getFunctionInfo(*fn); - if (ii.file != sourceFile) { - of << "fl=" << ii.file << "\n"; - sourceFile = ii.file; + auto fnlFile = getLocationInfo(&fn).file; + if (fnlFile != sourceFile) { + of << "fl=" << fnlFile << "\n"; + sourceFile = fnlFile; } - of << "fn=" << fnIt->getName().str() << "\n"; - for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); - bbIt != bb_ie; ++bbIt) { - for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); - it != ie; ++it) { - Instruction *instr = &*it; - const InstructionInfo &ii = executor.kmodule->infos->getInfo(*instr); - unsigned index = ii.id; - if (ii.file != sourceFile) { - of << "fl=" << ii.file << "\n"; - sourceFile = ii.file; + of << "fn=" << fn.getName().str() << "\n"; + for (auto &bb : fn) { + for (auto &instr : bb) { + Instruction *instrPtr = &instr; + + auto instrLI = getLocationInfo(instrPtr); + + unsigned index = executor.kmodule->getGlobalIndex(instrPtr); + if (instrLI.file != sourceFile) { + of << "fl=" << instrLI.file << "\n"; + sourceFile = instrLI.file; } - assert(ii.assemblyLine.hasValue()); - of << ii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(instrPtr); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << ii.line << " "; + of << instrLI.line << " "; for (unsigned i = 0; i < nStats; i++) if (istatsMask.test(i)) of << sm.getIndexedValue(sm.getStatistic(i), index) << " "; of << "\n"; if (UseCallPaths && - (isa(instr) || isa(instr))) { - CallSiteSummaryTable::iterator it = callSiteStats.find(instr); + (isa(instrPtr) || isa(instrPtr))) { + CallSiteSummaryTable::iterator it = callSiteStats.find(instrPtr); if (it != callSiteStats.end()) { - for (auto fit = it->second.begin(), fie = it->second.end(); - fit != fie; ++fit) { - const Function *f = fit->first; - CallSiteInfo &csi = fit->second; - const FunctionInfo &fii = - executor.kmodule->infos->getFunctionInfo(*f); - - if (fii.file != "" && fii.file != sourceFile) - of << "cfl=" << fii.file << "\n"; + for (auto &fit : it->second) { + const Function *f = fit.first; + CallSiteInfo &csi = fit.second; + auto fli = getLocationInfo(f); + if (fli.file != "" && fli.file != sourceFile) + of << "cfl=" << fli.file << "\n"; of << "cfn=" << f->getName().str() << "\n"; of << "calls=" << csi.count << " "; - assert(fii.assemblyLine.hasValue()); - of << fii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(f); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << fii.line << "\n"; + of << fli.line << "\n"; - assert(ii.assemblyLine.hasValue()); - of << ii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(instrPtr); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << ii.line << " "; + of << instrLI.line << " "; for (unsigned i = 0; i < nStats; i++) { if (istatsMask.test(i)) { Statistic &s = sm.getStatistic(i); @@ -889,12 +891,12 @@ uint64_t klee::computeMinDistToUncovered(const KInstruction *ki, uint64_t minDistAtRA) { StatisticManager &sm = *theStatisticManager; if (minDistAtRA == 0) { // unreachable on return, best is local - return sm.getIndexedValue(stats::minDistToUncovered, ki->info->id); + return sm.getIndexedValue(stats::minDistToUncovered, ki->getGlobalIndex()); } else { uint64_t minDistLocal = - sm.getIndexedValue(stats::minDistToUncovered, ki->info->id); + sm.getIndexedValue(stats::minDistToUncovered, ki->getGlobalIndex()); uint64_t distToReturn = - sm.getIndexedValue(stats::minDistToReturn, ki->info->id); + sm.getIndexedValue(stats::minDistToReturn, ki->getGlobalIndex()); if (distToReturn == 0) { // return unreachable, best is local return minDistLocal; @@ -910,7 +912,6 @@ void StatsTracker::computeReachableUncovered() { KModule *km = executor.kmodule.get(); const auto m = km->module.get(); static bool init = true; - const InstructionInfoTable &infos = *km->infos; StatisticManager &sm = *theStatisticManager; if (init) { @@ -973,11 +974,10 @@ void StatsTracker::computeReachableUncovered() { // Not sure if I should bother to preorder here. XXX I should. for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { - for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); - it != ie; ++it) { - Instruction *inst = &*it; + for (auto &it : *bbIt) { + Instruction *inst = ⁢ instructions.push_back(inst); - unsigned id = infos.getInfo(*inst).id; + unsigned id = km->getGlobalIndex(inst); sm.setIndexedValue(stats::minDistToReturn, id, isa(inst)); } } @@ -989,9 +989,8 @@ void StatsTracker::computeReachableUncovered() { bool changed; do { changed = false; - for (auto it = instructions.begin(), ie = instructions.end(); it != ie; - ++it) { - Instruction *inst = *it; + for (auto &instruction : instructions) { + Instruction *inst = instruction; unsigned bestThrough = 0; if (isa(inst) || isa(inst)) { @@ -1011,15 +1010,15 @@ void StatsTracker::computeReachableUncovered() { } if (bestThrough) { - unsigned id = infos.getInfo(*(*it)).id; + unsigned id = km->getGlobalIndex(instruction); uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToReturn, id); - std::vector succs = getSuccs(*it); + std::vector succs = getSuccs(instruction); for (std::vector::iterator it2 = succs.begin(), ie = succs.end(); it2 != ie; ++it2) { uint64_t dist = sm.getIndexedValue(stats::minDistToReturn, - infos.getInfo(*(*it2)).id); + km->getGlobalIndex(*it2)); if (dist) { uint64_t val = bestThrough + dist; if (best == 0 || val < best) @@ -1055,7 +1054,7 @@ void StatsTracker::computeReachableUncovered() { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { Instruction *inst = &*it; - unsigned id = infos.getInfo(*inst).id; + unsigned id = km->getGlobalIndex(inst); instructions.push_back(inst); sm.setIndexedValue( stats::minDistToUncovered, id, @@ -1070,29 +1069,24 @@ void StatsTracker::computeReachableUncovered() { bool changed; do { changed = false; - for (std::vector::iterator it = instructions.begin(), - ie = instructions.end(); - it != ie; ++it) { - Instruction *inst = *it; + for (auto inst : instructions) { uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToUncovered, - infos.getInfo(*inst).id); + km->getGlobalIndex(inst)); unsigned bestThrough = 0; if (isa(inst) || isa(inst)) { std::vector &targets = callTargets[inst]; - for (std::vector::iterator fnIt = targets.begin(), - ie = targets.end(); - fnIt != ie; ++fnIt) { - uint64_t dist = functionShortestPath[*fnIt]; + for (auto &target : targets) { + uint64_t dist = functionShortestPath[target]; if (dist) { dist = 1 + dist; // count instruction itself if (bestThrough == 0 || dist < bestThrough) bestThrough = dist; } - if (!(*fnIt)->isDeclaration()) { + if (!target->isDeclaration()) { uint64_t calleeDist = sm.getIndexedValue( - stats::minDistToUncovered, infos.getFunctionInfo(*(*fnIt)).id); + stats::minDistToUncovered, km->getGlobalIndex(target)); if (calleeDist) { calleeDist = 1 + calleeDist; // count instruction itself if (best == 0 || calleeDist < best) @@ -1106,11 +1100,9 @@ void StatsTracker::computeReachableUncovered() { if (bestThrough) { std::vector succs = getSuccs(inst); - for (std::vector::iterator it2 = succs.begin(), - ie = succs.end(); - it2 != ie; ++it2) { + for (auto &succ : succs) { uint64_t dist = sm.getIndexedValue(stats::minDistToUncovered, - infos.getInfo(*(*it2)).id); + km->getGlobalIndex(succ)); if (dist) { uint64_t val = bestThrough + dist; if (best == 0 || val < best) @@ -1120,7 +1112,7 @@ void StatsTracker::computeReachableUncovered() { } if (best != cur) { - sm.setIndexedValue(stats::minDistToUncovered, infos.getInfo(*inst).id, + sm.setIndexedValue(stats::minDistToUncovered, km->getGlobalIndex(inst), best); changed = true; } diff --git a/lib/Core/StatsTracker.h b/lib/Core/StatsTracker.h index be0f39ae5b..52a85d560c 100644 --- a/lib/Core/StatsTracker.h +++ b/lib/Core/StatsTracker.h @@ -27,7 +27,6 @@ class raw_fd_ostream; namespace klee { class ExecutionState; class Executor; -class InstructionInfoTable; class InterpreterHandler; struct KInstruction; struct InfoStackFrame; diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index 0c5d72fedb..1b19982b34 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -22,54 +22,49 @@ using namespace llvm; using namespace klee; -namespace klee { -llvm::cl::opt TargetCalculatorMode( - "target-calculator-kind", cl::desc("Specifiy the target calculator mode."), - cl::values( - clEnumValN(TargetCalculateBy::Default, "default", - "Looks for the closest uncovered block."), - clEnumValN( - TargetCalculateBy::Blocks, "blocks", - "Looks for the closest uncovered block by state blocks history."), - clEnumValN(TargetCalculateBy::Transitions, "transitions", - "Looks for the closest uncovered block by state transitions " - "history.")), - cl::init(TargetCalculateBy::Default), cl::cat(ExecCat)); -} // namespace klee +llvm::cl::opt TrackCoverage( + "track-coverage", cl::desc("Specifiy the track coverage mode."), + cl::values(clEnumValN(TrackCoverageBy::None, "none", "Not track coverage."), + clEnumValN(TrackCoverageBy::Blocks, "blocks", + "Track only covered block."), + clEnumValN(TrackCoverageBy::Branches, "branches", + "Track only covered conditional branches."), + clEnumValN(TrackCoverageBy::All, "all", "Track all.")), + cl::init(TrackCoverageBy::None), cl::cat(ExecCat)); void TargetCalculator::update(const ExecutionState &state) { Function *initialFunction = state.getInitPCBlock()->getParent(); - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - coveredBlocks[state.getPrevPCBlock()->getParent()].insert( - state.prevPC->parent); - } if (state.prevPC == state.prevPC->parent->getLastInstruction() && !fullyCoveredFunctions.count(state.prevPC->parent->parent)) { + auto &fBranches = getCoverageTargets(state.prevPC->parent->parent); if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { - unsigned index = 0; - if (!coveredBranches[state.prevPC->parent->parent].count( - state.prevPC->parent)) { - state.coveredNew->value = false; - state.coveredNew = new box(true); - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; - } - for (auto succ : successors(state.getPrevPCBlock())) { - if (succ == state.getPCBlock()) { - if (!coveredBranches[state.prevPC->parent->parent] - [state.prevPC->parent] - .count(index)) { - state.coveredNew->value = false; - state.coveredNew = new box(true); - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] - .insert(index); + if (fBranches.count(state.prevPC->parent) != 0) { + if (!coveredBranches[state.prevPC->parent->parent].count( + state.prevPC->parent)) { + state.coverNew(); + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + } + if (!fBranches.at(state.prevPC->parent).empty()) { + unsigned index = 0; + for (auto succ : successors(state.getPrevPCBlock())) { + if (succ == state.getPCBlock()) { + if (!coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .count(index)) { + state.coverNew(); + coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .insert(index); + } + break; + } + ++index; } - break; } - ++index; } - if (codeGraphInfo.getFunctionBranches(state.prevPC->parent->parent) == + if (getCoverageTargets(state.prevPC->parent->parent) == coveredBranches[state.prevPC->parent->parent]) { coveredFunctionsInBranches.insert(state.prevPC->parent->parent); } @@ -90,12 +85,14 @@ void TargetCalculator::update(const ExecutionState &state) { KFunction *calledKFunction = state.prevPC->parent->parent->parent ->functionMap[calledFunction]; if (calledKFunction->numInstructions != 0 && - coveredFunctionsInBranches.count(calledKFunction) == 0) { + coveredFunctionsInBranches.count(calledKFunction) == 0 && + !getCoverageTargets(calledKFunction).empty()) { covered = false; break; } if (!fnsTaken.count(calledKFunction) && - fullyCoveredFunctions.count(calledKFunction) == 0) { + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions != 0) { fns.push_back(calledKFunction); } } @@ -108,94 +105,74 @@ void TargetCalculator::update(const ExecutionState &state) { } } } +} - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.initPC->parent); - break; - - case TargetCalculateBy::Blocks: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.level.begin(), state.level.end()); - break; - - case TargetCalculateBy::Transitions: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.level.begin(), state.level.end()); - transitionsHistory[initialFunction][state.getPrevPCBlock()].insert( - state.transitionLevel.begin(), state.transitionLevel.end()); - break; +void TargetCalculator::update( + ExecutionState *current, const std::vector &addedStates, + const std::vector &removedStates) { + if (current && (std::find(removedStates.begin(), removedStates.end(), + current) == removedStates.end())) { + localStates.insert(current); + } + for (const auto state : addedStates) { + localStates.insert(state); } + for (const auto state : removedStates) { + localStates.insert(state); + } + for (auto state : localStates) { + KFunction *kf = state->prevPC->parent->parent; + KModule *km = kf->parent; + if (state->prevPC->inst()->isTerminator() && + km->inMainModule(*kf->function())) { + update(*state); + } + } + localStates.clear(); } -bool TargetCalculator::differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target) { - std::vector diff; - std::set left(state.level.begin(), state.level.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); - std::set_difference(left.begin(), left.end(), right.begin(), right.end(), - std::inserter(diff, diff.begin())); - return diff.empty(); -} +const std::map> & +TargetCalculator::getCoverageTargets(KFunction *kf) { + switch (TrackCoverage) { + case TrackCoverageBy::Blocks: + return codeGraphInfo.getFunctionBlocks(kf); + case TrackCoverageBy::Branches: + return codeGraphInfo.getFunctionConditionalBranches(kf); + case TrackCoverageBy::None: + case TrackCoverageBy::All: + return codeGraphInfo.getFunctionBranches(kf); -bool TargetCalculator::differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target) { - std::vector diff; - std::set left(state.transitionLevel.begin(), - state.transitionLevel.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); - std::set_difference(left.begin(), left.end(), right.begin(), right.end(), - std::inserter(diff, diff.begin())); - return diff.empty(); + default: + assert(0 && "not implemented"); + } } bool TargetCalculator::uncoveredBlockPredicate(ExecutionState *state, KBlock *kblock) { Function *initialFunction = state->getInitPCBlock()->getParent(); - std::unordered_map &history = - blocksHistory[initialFunction]; - std::unordered_map - &transitionHistory = transitionsHistory[initialFunction]; bool result = false; - if (coveredBranches[kblock->parent].count(kblock) == 0) { - result = true; - } else { - auto &cb = coveredBranches[kblock->parent][kblock]; - if (isa(kblock) && - cast(kblock)->calledFunctions.size() == 1) { - auto calledFunction = *cast(kblock)->calledFunctions.begin(); - KFunction *calledKFunction = - kblock->parent->parent->functionMap[calledFunction]; - result = fullyCoveredFunctions.count(calledKFunction) == 0 && - calledKFunction->numInstructions; - } - result |= - kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); - } - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: { - break; - } - case TargetCalculateBy::Blocks: { - if (history[kblock->basicBlock].size() != 0) { - result |= !differenceIsEmpty(*state, history, kblock); - } - break; - } - case TargetCalculateBy::Transitions: { - if (history[kblock->basicBlock].size() != 0) { - result |= !differenceIsEmpty(*state, transitionHistory, kblock); + auto &fBranches = getCoverageTargets(kblock->parent); + + if (fBranches.count(kblock) != 0 || isa(kblock)) { + if (coveredBranches[kblock->parent].count(kblock) == 0) { + result = true; + } else { + auto &cb = coveredBranches[kblock->parent][kblock]; + if (isa(kblock) && + cast(kblock)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(kblock)->calledFunctions.begin(); + KFunction *calledKFunction = + kblock->parent->parent->functionMap[calledFunction]; + result = fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (fBranches.at(kblock) != cb) { + result |= kblock->basicBlock()->getTerminator()->getNumSuccessors() > + cb.size(); + } } - break; - } } return result; @@ -208,7 +185,8 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { KBlock *kb = kf->blockMap[bb]; kb = !isa(kb) || (kb->getLastInstruction() != state.pc) ? kb - : kf->blockMap[state.pc->parent->basicBlock->getTerminator() + : kf->blockMap[state.pc->parent->basicBlock() + ->getTerminator() ->getSuccessor(0)]; for (auto sfi = state.stack.callStack().rbegin(), sfe = state.stack.callStack().rend(); @@ -224,29 +202,36 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { if (!blocks.empty()) { TargetHashSet targets; for (auto block : blocks) { - if (coveredBranches[block->parent].count(block) == 0) { - targets.insert(ReachBlockTarget::create(block, false)); - } else { - auto &cb = coveredBranches[block->parent][block]; - bool notCoveredFunction = false; - if (isa(block) && - cast(block)->calledFunctions.size() == 1) { - auto calledFunction = - *cast(block)->calledFunctions.begin(); - KFunction *calledKFunction = - block->parent->parent->functionMap[calledFunction]; - notCoveredFunction = - fullyCoveredFunctions.count(calledKFunction) == 0 && - calledKFunction->numInstructions; - } - if (notCoveredFunction) { - targets.insert(ReachBlockTarget::create(block, true)); + auto &fBranches = getCoverageTargets(block->parent); + + if (fBranches.count(block) != 0 || isa(block)) { + if (coveredBranches[block->parent].count(block) == 0) { + targets.insert(ReachBlockTarget::create(block, false)); } else { - for (unsigned index = 0; - index < block->basicBlock->getTerminator()->getNumSuccessors(); - ++index) { - if (!cb.count(index)) - targets.insert(CoverBranchTarget::create(block, index)); + auto &cb = coveredBranches[block->parent][block]; + bool notCoveredFunction = false; + if (isa(block) && + cast(block)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(block)->calledFunctions.begin(); + KFunction *calledKFunction = + block->parent->parent->functionMap[calledFunction]; + notCoveredFunction = + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (notCoveredFunction) { + targets.insert(ReachBlockTarget::create(block, true)); + } else { + if (fBranches.at(block) != cb) { + for (unsigned index = 0; + index < + block->basicBlock()->getTerminator()->getNumSuccessors(); + ++index) { + if (!cb.count(index)) + targets.insert(CoverBranchTarget::create(block, index)); + } + } } } } @@ -260,10 +245,15 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { kb = !isa(kb) || (kb->getLastInstruction() != sfi->caller) ? kb - : kf->blockMap[sfi->caller->parent->basicBlock->getTerminator() + : kf->blockMap[sfi->caller->parent->basicBlock() + ->getTerminator() ->getSuccessor(0)]; } } return {}; } + +bool TargetCalculator::isCovered(KFunction *kf) const { + return fullyCoveredFunctions.count(kf) != 0; +} diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index ba78a89f20..f337b879fd 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -34,61 +34,48 @@ DISABLE_WARNING_POP namespace klee { class CodeGraphInfo; class ExecutionState; -struct TransitionHash; -enum TargetCalculateBy { Default, Blocks, Transitions }; +enum class TrackCoverageBy { None, Blocks, Branches, All }; -typedef std::pair Transition; typedef std::pair Branch; class TargetCalculator { + using StatesSet = std::unordered_set; + typedef std::unordered_set VisitedBlocks; - typedef std::unordered_set VisitedTransitions; typedef std::unordered_set VisitedBranches; enum HistoryKind { Blocks, Transitions }; - typedef std::unordered_map< - llvm::Function *, std::unordered_map> - BlocksHistory; - typedef std::unordered_map< - llvm::Function *, - std::unordered_map> - TransitionsHistory; - typedef std::unordered_map>> CoveredBranches; typedef std::unordered_set CoveredFunctionsBranches; - typedef std::unordered_map CoveredBlocks; + void update(const ExecutionState &state); public: TargetCalculator(CodeGraphInfo &codeGraphInfo) : codeGraphInfo(codeGraphInfo) {} - void update(const ExecutionState &state); + void update(ExecutionState *current, + const std::vector &addedStates, + const std::vector &removedStates); TargetHashSet calculate(ExecutionState &state); + bool isCovered(KFunction *kf) const; + private: CodeGraphInfo &codeGraphInfo; - BlocksHistory blocksHistory; - TransitionsHistory transitionsHistory; CoveredBranches coveredBranches; CoveredFunctionsBranches coveredFunctionsInBranches; CoveredFunctionsBranches fullyCoveredFunctions; - CoveredBlocks coveredBlocks; - - bool differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target); - bool differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target); + StatesSet localStates; + + const std::map> & + getCoverageTargets(KFunction *kf); bool uncoveredBlockPredicate(ExecutionState *state, KBlock *kblock); }; diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index 9dcaedcd86..f72e329135 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -111,7 +111,8 @@ void TargetManager::updateReached(ExecutionState &state) { auto kf = prevKI->parent->parent; auto kmodule = kf->parent; - if (prevKI->inst->isTerminator() && kmodule->inMainModule(*kf->function)) { + if (prevKI->inst()->isTerminator() && + kmodule->inMainModule(*kf->function())) { ref target; if (state.getPrevPCBlock()->getTerminator()->getNumSuccessors() == 0) { @@ -262,9 +263,9 @@ bool TargetManager::isReachedTarget(const ExecutionState &state, if (isa(target)) { if (state.prevPC->parent == target->getBlock()) { if (state.prevPC == target->getBlock()->getLastInstruction() && - state.prevPC->inst->getSuccessor( + state.prevPC->inst()->getSuccessor( cast(target)->getBranchCase()) == - state.pc->parent->basicBlock) { + state.pc->parent->basicBlock()) { result = Done; } else { result = Continue; diff --git a/lib/Core/TargetManager.h b/lib/Core/TargetManager.h index 3d3188b1f6..ba2dea9ab3 100644 --- a/lib/Core/TargetManager.h +++ b/lib/Core/TargetManager.h @@ -25,15 +25,131 @@ namespace klee { class TargetCalculator; -class TargetManagerSubscriber { +using TargetHistoryTargetPair = + std::pair, ref>; +using StatesVector = std::vector; +using StateSet = std::set; + +class StateIterable final { +private: + using v = ExecutionState *; + const StatesVector *self; + mutable const StateSet *without = nullptr; + using vec_it = StatesVector::const_iterator; + bool shouldDestruct; + + class it : public std::iterator { + vec_it self; + const vec_it ie; + const StateSet *without = nullptr; + void goUntilRealNode() { + if (!without) + return; + for (; self != ie; self++) { + if (!without->count(*self)) + return; + } + } + + public: + it(vec_it i, vec_it ie, const StateSet *without) + : self(i), ie(ie), without(without) { + goUntilRealNode(); + } + bool operator==(const it &other) const noexcept { + return self == other.self; + }; + bool operator!=(const it &other) const noexcept { + return self != other.self; + }; + it &operator++() noexcept { + if (self != ie) { + self++; + goUntilRealNode(); + } + return *this; + } + v operator*() const noexcept { return *self; } + }; + +public: + StateIterable() : self(new StatesVector()), shouldDestruct(true) {} + StateIterable(v s) : self(new StatesVector({s})), shouldDestruct(true) {} + StateIterable(const StatesVector &v, const StateSet *without) + : self(&v), without(without), shouldDestruct(false) {} + StateIterable(const StatesVector &v) : StateIterable(v, nullptr) {} + StateIterable(const StateSet &s) + : self(new StatesVector(s.begin(), s.end())), shouldDestruct(true) {} + ~StateIterable() { + if (shouldDestruct) + delete self; + } + bool empty() const noexcept { + return without ? begin() == end() : self->empty(); + } + it begin() const noexcept { return it(self->begin(), self->end(), without); } + it end() const noexcept { return it(self->end(), self->end(), without); } + + void setWithout(const StateSet *w) const { without = w; } + void clearWithout() const { without = nullptr; } +}; + +class TargetHistoryTargetPairToStatesMap final { +private: + using k = TargetHistoryTargetPair; + using cv = StateIterable; + using p = std::pair; + using v = StatesVector; + using t = + std::unordered_map; + using map_it = t::iterator; + using map_cit = t::const_iterator; + t self; + mutable const StateSet *without = nullptr; + + class it : public std::iterator { + protected: + map_cit self; + const StateSet *without = nullptr; + + public: + it(map_cit i, const StateSet *without) : self(i), without(without) {} + bool operator==(const it &other) const noexcept { + return self == other.self; + }; + bool operator!=(const it &other) const noexcept { + return self != other.self; + }; + it &operator++() noexcept { + self++; + return *this; + } + p operator*() const noexcept { + return std::make_pair(self->first, StateIterable(self->second, without)); + } + }; + public: - using TargetHistoryTargetPair = - std::pair, ref>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; + inline v &operator[](const k &__k) { return self[__k]; } + inline v &operator[](k &&__k) { return self[std::move(__k)]; } + inline v &at(const k &__k) { return self.at(__k); } + inline map_it begin() noexcept { return self.begin(); } + inline map_it end() noexcept { return self.end(); } + + inline const cv at(const k &__k) const { + cv result = self.at(__k); + result.setWithout(without); + return result; + } + inline it begin() const noexcept { return it(self.begin(), without); }; + inline it end() const noexcept { return it(self.end(), without); }; + + void setWithout(const StateSet *w) const { without = w; } + void clearWithout() const { without = nullptr; } +}; +class TargetManagerSubscriber { +public: virtual ~TargetManagerSubscriber() = default; /// Selects a state for further exploration. @@ -47,12 +163,6 @@ class TargetManager { using StatesSet = std::unordered_set; using StateToDistanceMap = std::unordered_map>; - using TargetHistoryTargetPair = - std::pair, ref>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; using TargetForestHistoryTargetSet = std::unordered_set; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index 9f9b498738..37961c20f3 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -16,6 +16,7 @@ #include "klee/Core/TerminationTypes.h" #include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" +#include "klee/Module/KModule.h" #include "klee/Support/ErrorHandling.h" #include @@ -318,24 +319,27 @@ TargetedExecutionManager::LocationToBlocks TargetedExecutionManager::prepareAllLocations(KModule *kmodule, Locations &locations) const { LocationToBlocks locToBlocks; - const auto &infos = kmodule->infos; + std::unordered_map> + fileNameToFunctions; + + for (const auto &kfunc : kmodule->functions) { + fileNameToFunctions[kfunc->getSourceFilepath()].insert(kfunc->function()); + } + for (auto it = locations.begin(); it != locations.end(); ++it) { auto loc = *it; - for (const auto &fileName : infos->getFilesNames()) { - if (kmodule->origInfos.count(fileName) == 0) { + for (const auto &[fileName, origInstsInFile] : kmodule->origInstructions) { + if (kmodule->origInstructions.count(fileName) == 0) { continue; } if (!loc->isInside(fileName)) { continue; } - const auto &relatedFunctions = - infos->getFileNameToFunctions().at(fileName); + const auto &relatedFunctions = fileNameToFunctions.at(fileName); for (const auto func : relatedFunctions) { const auto kfunc = kmodule->functionMap[func]; - const auto &fi = infos->getFunctionInfo(*kfunc->function); - const auto &origInstsInFile = kmodule->origInfos.at(fi.file); for (const auto &kblock : kfunc->blocks) { auto b = kblock.get(); @@ -376,18 +380,18 @@ bool TargetedExecutionManager::canReach(const ref &from, } const auto &blockDist = codeGraphInfo.getDistance(fromBlock); - if (blockDist.count(toBlock) != 0) { + if (blockDist.count(toBlock->basicBlock()) != 0) { return true; } } else { const auto &funcDist = codeGraphInfo.getDistance(fromKf); - if (funcDist.count(toKf) != 0) { + if (funcDist.count(toKf->function()) != 0) { return true; } const auto &backwardFuncDist = codeGraphInfo.getBackwardDistance(fromKf); - if (backwardFuncDist.count(toKf) != 0) { + if (backwardFuncDist.count(toKf->function()) != 0) { return true; } } @@ -461,9 +465,9 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( KFunction *curKf = nullptr; for (size_t m = 0; m < currKFs.size() && !curKf; ++m) { curKf = currKFs.at(m); - if (funcDist.count(curKf) == 0) { + if (funcDist.count(curKf->function()) == 0) { const auto &curFuncDist = codeGraphInfo.getDistance(curKf); - if (curFuncDist.count(resKf) == 0) { + if (curFuncDist.count(resKf->function()) == 0) { curKf = nullptr; } else { i = j; @@ -490,14 +494,14 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( return resKf; } -std::map, - TargetedExecutionManager::KFunctionLess> -TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { +ref TargetedExecutionManager::prepareTargets(KModule *kmodule, + KFunction *entry, + SarifReport paths) { + ref forest = new TargetForest(entry); + Locations locations = collectAllLocations(paths); LocationToBlocks locToBlocks = prepareAllLocations(kmodule, locations); - std::map, KFunctionLess> whitelists; - for (auto &result : paths.results) { bool isFullyResolved = tryResolveLocations(result, locToBlocks); if (!isFullyResolved) { @@ -511,20 +515,16 @@ TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { continue; } - if (whitelists.count(kf) == 0) { - ref whitelist = new TargetForest(kf); - whitelists[kf] = whitelist; - } - whitelists[kf]->addTrace(result, locToBlocks); + forest->addTrace(result, locToBlocks); } - return whitelists; + return forest; } void TargetedExecutionManager::reportFalseNegative(ExecutionState &state, ReachWithError error) { klee_warning("100.00%% %s False Negative at: %s", getErrorString(error), - state.prevPC->getSourceLocation().c_str()); + state.prevPC->getSourceLocationString().c_str()); } bool TargetedExecutionManager::reportTruePositive(ExecutionState &state, diff --git a/lib/Core/TargetedExecutionManager.h b/lib/Core/TargetedExecutionManager.h index e5a66cbf32..edabcee1e8 100644 --- a/lib/Core/TargetedExecutionManager.h +++ b/lib/Core/TargetedExecutionManager.h @@ -96,12 +96,6 @@ class TargetedExecutionManager { using StatesSet = std::unordered_set; using TargetToStateUnorderedSetMap = TargetHashMap; - using Instructions = std::unordered_map< - std::string, - std::unordered_map< - unsigned int, - std::unordered_map>>>; - std::unordered_set brokenTraces; std::unordered_set reportedTraces; @@ -121,18 +115,13 @@ class TargetedExecutionManager { StatesSet localStates; public: - struct KFunctionLess { - bool operator()(const KFunction *a, const KFunction *b) const { - return a->id < b->id; - } - }; - explicit TargetedExecutionManager(CodeGraphInfo &codeGraphInfo_, TargetManager &targetManager_) : codeGraphInfo(codeGraphInfo_), targetManager(targetManager_) {} ~TargetedExecutionManager() = default; - std::map, KFunctionLess> - prepareTargets(KModule *kmodule, SarifReport paths); + + ref prepareTargets(KModule *kmodule, KFunction *entry, + SarifReport paths); void reportFalseNegative(ExecutionState &state, ReachWithError error); diff --git a/lib/Core/TypeManager.cpp b/lib/Core/TypeManager.cpp index c6e00f2f82..c053d449fa 100644 --- a/lib/Core/TypeManager.cpp +++ b/lib/Core/TypeManager.cpp @@ -37,6 +37,12 @@ KType *TypeManager::getWrappedType(llvm::Type *type) { if (typesMap.count(type) == 0) { types.emplace_back(new KType(type, this)); typesMap.emplace(type, types.back().get()); + if (type && type->isPointerTy()) { + getWrappedType(type->getPointerElementType()); + } + if (type && type->isArrayTy()) { + getWrappedType(type->getArrayElementType()); + } } return typesMap[type]; } @@ -61,15 +67,21 @@ void TypeManager::initTypesFromStructs() { * and pull types to top. */ - std::vector collectedStructTypes = - parent->module->getIdentifiedStructTypes(); - for (auto &structType : collectedStructTypes) { + for (auto &structType : parent->module->getIdentifiedStructTypes()) { getWrappedType(structType); } + std::unordered_set collectedStructTypes; + for (const auto &it : typesMap) { + if (llvm::StructType *itStruct = + llvm::dyn_cast(it.first)) { + collectedStructTypes.insert(itStruct); + } + } + for (auto &typesToOffsets : typesMap) { if (llvm::isa(typesToOffsets.first)) { - collectedStructTypes.emplace_back( + collectedStructTypes.insert( llvm::cast(typesToOffsets.first)); } } @@ -141,20 +153,13 @@ void TypeManager::initTypesFromGlobals() { */ void TypeManager::initTypesFromInstructions() { for (auto &function : *(parent->module)) { - auto kf = parent->functionMap[&function]; - for (auto &BasicBlock : function) { - unsigned numInstructions = kf->blockMap[&BasicBlock]->numInstructions; - KBlock *kb = kf->blockMap[&BasicBlock]; - - for (unsigned i = 0; i < numInstructions; ++i) { - llvm::Instruction *inst = kb->instructions[i]->inst; - + for (auto &inst : BasicBlock) { /* Register return type */ - getWrappedType(inst->getType()); + getWrappedType(inst.getType()); /* Register types for arguments */ - for (auto opb = inst->op_begin(), ope = inst->op_end(); opb != ope; + for (auto opb = inst.op_begin(), ope = inst.op_end(); opb != ope; ++opb) { getWrappedType((*opb)->getType()); } diff --git a/lib/Core/UserSearcher.cpp b/lib/Core/UserSearcher.cpp index 8de5273052..59674a84f7 100644 --- a/lib/Core/UserSearcher.cpp +++ b/lib/Core/UserSearcher.cpp @@ -55,11 +55,17 @@ cl::list CoreSearch( clEnumValN(Searcher::NURS_QC, "nurs:qc", "use NURS with Query-Cost")), cl::cat(SearchCat)); -cl::opt UseIterativeDeepeningTimeSearch( - "use-iterative-deepening-time-search", - cl::desc( - "Use iterative deepening time search (experimental) (default=false)"), - cl::init(false), cl::cat(SearchCat)); +cl::opt UseIterativeDeepeningSearch( + "use-iterative-deepening-search", + cl::desc("Use iterative deepening search based on metric (experimental) " + "(default=unspecified)"), + cl::values(clEnumValN(HaltExecution::Reason::Unspecified, "unspecified", + "Do not use iterative deepening search (default)"), + clEnumValN(HaltExecution::Reason::MaxTime, "max-time", + "metric is maximum time"), + clEnumValN(HaltExecution::Reason::MaxCycles, "max-cycles", + "metric is maximum cycles")), + cl::init(HaltExecution::Reason::Unspecified), cl::cat(SearchCat)); cl::opt UseBatchingSearch( "use-batching-search", @@ -172,16 +178,22 @@ Searcher *klee::constructUserSearcher(Executor &executor, BatchInstructions); } - if (UseIterativeDeepeningTimeSearch) { - searcher = new IterativeDeepeningTimeSearcher(searcher); - } - + TargetManagerSubscriber *tms = nullptr; if (executor.guidanceKind != Interpreter::GuidanceKind::NoGuidance) { searcher = new GuidedSearcher(searcher, *executor.distanceCalculator, executor.theRNG); - executor.targetManager->subscribe(*static_cast(searcher)); + tms = static_cast(searcher); } + if (UseIterativeDeepeningSearch != HaltExecution::Reason::Unspecified) { + searcher = new IterativeDeepeningSearcher(searcher, tms, + UseIterativeDeepeningSearch); + tms = static_cast(searcher); + } + + if (tms) + executor.targetManager->subscribe(*tms); + llvm::raw_ostream &os = executor.getHandler().getInfoStream(); os << "BEGIN searcher description\n"; diff --git a/lib/Expr/APFloatEval.cpp b/lib/Expr/APFloatEval.cpp index a1f49b28f9..49ae758d1c 100644 --- a/lib/Expr/APFloatEval.cpp +++ b/lib/Expr/APFloatEval.cpp @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include "klee/util/APFloatEval.h" +#include "klee/Utilities/APFloatEval.h" #include "klee/Config/Version.h" #include "klee/Support/CompilerWarning.h" diff --git a/lib/Expr/AlphaBuilder.cpp b/lib/Expr/AlphaBuilder.cpp new file mode 100644 index 0000000000..3056503669 --- /dev/null +++ b/lib/Expr/AlphaBuilder.cpp @@ -0,0 +1,106 @@ +//===-- AlphaBuilder.cpp ---------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Expr/AlphaBuilder.h" +#include "klee/Expr/ArrayCache.h" +#include "klee/Expr/SourceBuilder.h" + +#include + +namespace klee { + +const Array *AlphaBuilder::visitArray(const Array *arr) { + if (!reverse && alphaArrayMap.find(arr) == alphaArrayMap.end()) { + ref source = arr->source; + ref size = visit(arr->getSize()); + if (ref mockSource = + dyn_cast_or_null(source)) { + std::vector> args; + for (const auto &it : mockSource->args) { + args.push_back(visit(it)); + } + source = SourceBuilder::mockDeterministic(mockSource->km, + mockSource->function, args); + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else if (!arr->isConstantArray()) { + source = SourceBuilder::alpha(index); + index++; + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else if (size != arr->getSize()) { + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else { + alphaArrayMap[arr] = arr; + reverseAlphaArrayMap[arr] = arr; + } + } + if (reverse) { + return reverseAlphaArrayMap[arr]; + } else { + return alphaArrayMap[arr]; + } +} + +UpdateList AlphaBuilder::visitUpdateList(UpdateList u) { + const Array *root = visitArray(u.root); + std::vector> updates; + + for (auto un = u.head; un; un = un->next) { + updates.push_back(un); + } + + updates.push_back(nullptr); + + for (int i = updates.size() - 2; i >= 0; i--) { + ref index = visit(updates[i]->index); + ref value = visit(updates[i]->value); + updates[i] = new UpdateNode(updates[i + 1], index, value); + } + return UpdateList(root, updates[0]); +} + +ExprVisitor::Action AlphaBuilder::visitRead(const ReadExpr &re) { + ref v = visit(re.index); + UpdateList u = visitUpdateList(re.updates); + ref e = ReadExpr::create(u, v); + return Action::changeTo(e); +} + +AlphaBuilder::AlphaBuilder(ArrayCache &_arrayCache) : arrayCache(_arrayCache) {} + +constraints_ty AlphaBuilder::visitConstraints(const constraints_ty &cs) { + constraints_ty result; + for (const auto &arg : cs) { + ref v = visit(arg); + reverseExprMap[v] = arg; + reverseExprMap[Expr::createIsZero(v)] = Expr::createIsZero(arg); + result.insert(v); + } + return result; +} + +ref AlphaBuilder::build(ref v) { + ref e = visit(v); + reverseExprMap[e] = v; + reverseExprMap[Expr::createIsZero(e)] = Expr::createIsZero(v); + return e; +} +ref AlphaBuilder::reverseBuild(ref v) { + reverse = true; + ref e = visit(v); + reverse = false; + return e; +} + +} // namespace klee diff --git a/lib/Expr/ArrayCache.cpp b/lib/Expr/ArrayCache.cpp index afea585300..3962278f6c 100644 --- a/lib/Expr/ArrayCache.cpp +++ b/lib/Expr/ArrayCache.cpp @@ -11,41 +11,25 @@ ArrayCache::~ArrayCache() { ai != e; ++ai) { delete *ai; } - for (ArrayPtrVec::iterator ai = concreteArrays.begin(), - e = concreteArrays.end(); - ai != e; ++ai) { - delete *ai; - } } const Array *ArrayCache::CreateArray(ref _size, ref _source, Expr::Width _domain, Expr::Width _range) { - const Array *array = new Array(_size, _source, _domain, _range, getNextID()); - if (array->isSymbolicArray()) { - std::pair success = - cachedSymbolicArrays.insert(array); - if (success.second) { - // Cache miss - return array; - } - // Cache hit - delete array; - array = *(success.first); - assert(array->isSymbolicArray() && - "Cached symbolic array is no longer symbolic"); - return array; - } else { - // Treat every constant array as distinct so we never cache them - assert(array->isConstantArray()); - concreteArrays.push_back(array); // For deletion later + auto id = allocatedCount[_source->getKind()]; + const Array *array = new Array(_size, _source, _domain, _range, id); + std::pair success = + cachedSymbolicArrays.insert(array); + if (success.second) { + // Cache miss + allocatedCount[_source->getKind()]++; return array; } -} - -unsigned ArrayCache::getNextID() const { - return cachedSymbolicArrays.size() + concreteArrays.size(); + // Cache hit + delete array; + array = *(success.first); + return array; } } // namespace klee diff --git a/lib/Expr/ArrayExprOptimizer.cpp b/lib/Expr/ArrayExprOptimizer.cpp index d67bd3ddbd..205685fdd6 100644 --- a/lib/Expr/ArrayExprOptimizer.cpp +++ b/lib/Expr/ArrayExprOptimizer.cpp @@ -198,6 +198,7 @@ bool ExprOptimizer::computeIndexes(array2idx_ty &arrays, const ref &e, // For each constant array found for (auto &element : arrays) { const Array *arr = element.first; + auto arraySize = cast(arr->size)->getZExtValue(); assert(arr->isConstantArray() && "Array is not concrete"); assert(element.second.size() == 1 && "Multiple indexes on the same array"); @@ -224,8 +225,7 @@ bool ExprOptimizer::computeIndexes(array2idx_ty &arrays, const ref &e, // For each concrete value 'i' stored in the array if (ref constantSource = cast(arr->source)) { - for (size_t aIdx = 0; aIdx < constantSource->constantValues.size(); - aIdx += width) { + for (size_t aIdx = 0; aIdx < arraySize; aIdx += width) { auto *a = new Assignment(); std::vector objects; std::vector> values; @@ -302,7 +302,8 @@ ref ExprOptimizer::getSelectOptExpr( std::vector> arrayConstValues; if (ref constantSource = dyn_cast(read->updates.root->source)) { - arrayConstValues = constantSource->constantValues; + arrayConstValues = + constantSource->constantValues.getFirstNIndexes(size); } for (auto it = us.rbegin(); it != us.rend(); it++) { const UpdateNode *un = *it; @@ -377,7 +378,8 @@ ref ExprOptimizer::getSelectOptExpr( std::vector> arrayConstValues; if (ref constantSource = dyn_cast(read->updates.root->source)) { - arrayConstValues = constantSource->constantValues; + arrayConstValues = + constantSource->constantValues.getFirstNIndexes(size); } if (arrayConstValues.size() < size) { // We need to "force" initialization of the values diff --git a/lib/Expr/Assignment.cpp b/lib/Expr/Assignment.cpp index 1cc7a76e1c..860f1a0a50 100644 --- a/lib/Expr/Assignment.cpp +++ b/lib/Expr/Assignment.cpp @@ -22,10 +22,13 @@ void Assignment::dump() const { } for (bindings_ty::iterator i = bindings.begin(), e = bindings.end(); i != e; ++i) { - llvm::errs() << (*i).first->getName() << "\n["; - for (int j = 0, k = (*i).second.size(); j < k; ++j) - llvm::errs() << (int)(*i).second.load(j) << ","; - llvm::errs() << "]\n"; + llvm::errs() << (*i).first->getName() << "\n"; + Density d = + ((*i).second.storage().size() * 2 < (*i).second.sizeOfSetRange()) + ? Density::Sparse + : Density::Dense; + (*i).second.print(llvm::errs(), d); + llvm::errs() << "\n"; } } diff --git a/lib/Expr/CMakeLists.txt b/lib/Expr/CMakeLists.txt index 758a4ca743..6167bbf721 100644 --- a/lib/Expr/CMakeLists.txt +++ b/lib/Expr/CMakeLists.txt @@ -7,6 +7,7 @@ # #===------------------------------------------------------------------------===# add_library(kleaverExpr + AlphaBuilder.cpp APFloatEval.cpp ArrayCache.cpp ArrayExprOptimizer.cpp @@ -32,6 +33,10 @@ add_library(kleaverExpr Updates.cpp ) +target_link_libraries(kleaverExpr PRIVATE + kleeADT +) + llvm_config(kleaverExpr "${USE_LLVM_SHARED}" support) target_include_directories(kleaverExpr PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) target_compile_options(kleaverExpr PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index f14d612379..7669baad7d 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -15,6 +15,7 @@ #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" #include "klee/Expr/ExprVisitor.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" @@ -183,14 +184,18 @@ class ExprReplaceVisitor3 : public ExprVisitor { ConstraintSet::ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization) : _constraints(cs), _symcretes(symcretes), _concretization(concretization), - _independentElements(_constraints, _symcretes, _concretization) {} + _independentElements(new IndependentConstraintSetUnion( + _constraints, _symcretes, _concretization)) {} ConstraintSet::ConstraintSet(ref ics) : _constraints(ics->getConstraints()), _symcretes(ics->getSymcretes()), - _concretization(ics->concretization), _independentElements(ics) {} + _concretization(ics->concretization), + _independentElements(new IndependentConstraintSetUnion(ics)) {} ConstraintSet::ConstraintSet( - const std::vector> &factors) { + const std::vector> &factors) + : _independentElements(new IndependentConstraintSetUnion( + _constraints, _symcretes, _concretization)) { for (auto ics : factors) { constraints_ty constraints = ics->getConstraints(); SymcreteOrderedSet symcretes = ics->getSymcretes(); @@ -198,22 +203,28 @@ ConstraintSet::ConstraintSet( _constraints.insert(constraints.begin(), constraints.end()); _symcretes.insert(symcretes.begin(), symcretes.end()); _concretization.addIndependentAssignment(ics->concretization); - _independentElements.addIndependentConstraintSetUnion(icsu); + _independentElements->addIndependentConstraintSetUnion(icsu); } } ConstraintSet::ConstraintSet(constraints_ty cs) : ConstraintSet(cs, {}, {}) {} -ConstraintSet::ConstraintSet() {} +ConstraintSet::ConstraintSet() + : _independentElements(new IndependentConstraintSetUnion()) {} + +void ConstraintSet::fork() { + _independentElements = std::make_shared( + IndependentConstraintSetUnion(*_independentElements)); +} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { _constraints.insert(e); // Update bindings - for (auto i : delta.bindings) { + for (auto &i : delta.bindings) { _concretization.bindings.replace({i.first, i.second}); } - _independentElements.updateConcretization(delta); - _independentElements.addExpr(e); + _independentElements->updateConcretization(delta); + _independentElements->addExpr(e); } IDType Symcrete::idCounter = 0; @@ -221,14 +232,14 @@ IDType Symcrete::idCounter = 0; void ConstraintSet::addSymcrete(ref s, const Assignment &concretization) { _symcretes.insert(s); - _independentElements.addSymcrete(s); + _independentElements->addSymcrete(s); Assignment dependentConcretization; for (auto i : s->dependentArrays()) { _concretization.bindings.replace({i, concretization.bindings.at(i)}); dependentConcretization.bindings.replace( {i, concretization.bindings.at(i)}); } - _independentElements.updateConcretization(dependentConcretization); + _independentElements->updateConcretization(dependentConcretization); } bool ConstraintSet::isSymcretized(ref expr) const { @@ -246,16 +257,17 @@ void ConstraintSet::rewriteConcretization(const Assignment &a) { _concretization.bindings.replace({i.first, i.second}); } } - _independentElements.updateConcretization(a); + _independentElements->updateConcretization(a); } ConstraintSet ConstraintSet::getConcretizedVersion() const { ConstraintSet cs; - cs._independentElements = _independentElements.getConcretizedVersion(); + cs._independentElements = std::make_shared( + _independentElements->getConcretizedVersion()); - for (auto &e : cs._independentElements.is()) { - if (isa(e)) { - cs._constraints.insert(cast(e)->value()); + for (auto &e : cs._independentElements->is()) { + if (isa(e)) { + cs._constraints.insert(cast(e)->value()); } } return cs; @@ -264,10 +276,10 @@ ConstraintSet ConstraintSet::getConcretizedVersion() const { ConstraintSet ConstraintSet::getConcretizedVersion( const Assignment &newConcretization) const { ConstraintSet cs; - cs._independentElements = - _independentElements.getConcretizedVersion(newConcretization); - for (auto &e : cs._independentElements.is()) { - cs._constraints.insert(cast(e)->value()); + cs._independentElements = std::make_shared( + _independentElements->getConcretizedVersion(newConcretization)); + for (auto &e : cs._independentElements->is()) { + cs._constraints.insert(cast(e)->value()); } return cs; } @@ -292,8 +304,8 @@ void ConstraintSet::dump() const { this->print(llvm::errs()); } void ConstraintSet::changeCS(constraints_ty &cs) { _constraints = cs; - _independentElements = - IndependentConstraintSetUnion(_constraints, _symcretes, _concretization); + _independentElements = std::make_shared( + IndependentConstraintSetUnion(_constraints, _symcretes, _concretization)); } const constraints_ty &ConstraintSet::cs() const { return _constraints; } @@ -302,7 +314,7 @@ const symcretes_ty &ConstraintSet::symcretes() const { return _symcretes; } const IndependentConstraintSetUnion & ConstraintSet::independentElements() const { - return _independentElements; + return *_independentElements; } const Path &PathConstraints::path() const { return _path; } @@ -330,9 +342,7 @@ PathConstraints::orderedCS() const { void PathConstraints::advancePath(KInstruction *ki) { _path.advance(ki); } -void PathConstraints::advancePath(const Path &path) { - _path = Path::concat(_path, path); -} +void PathConstraints::fork() { constraints.fork(); } ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex) { @@ -352,7 +362,9 @@ ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, added.insert(expr); pathIndexes.insert({expr, currIndex}); _simplificationMap[expr].insert(expr); - orderedConstraints[currIndex].insert(expr); + auto indexConstraints = orderedConstraints[currIndex].second; + indexConstraints.insert(expr); + orderedConstraints.replace({currIndex, indexConstraints}); constraints.addConstraint(expr, delta); } } @@ -389,29 +401,6 @@ void PathConstraints::rewriteConcretization(const Assignment &a) { constraints.rewriteConcretization(a); } -PathConstraints PathConstraints::concat(const PathConstraints &l, - const PathConstraints &r) { - // TODO : How to handle symcretes and concretization? - PathConstraints path = l; - path._path = Path::concat(l._path, r._path); - auto offset = l._path.KBlockSize(); - for (const auto &i : r._original) { - path._original.insert(i); - auto index = r.pathIndexes.at(i); - index.block += offset; - path.pathIndexes.insert({i, index}); - path.orderedConstraints[index].insert(i); - } - for (const auto &i : r.constraints.cs()) { - path.constraints.addConstraint(i, {}); - if (r._simplificationMap.count(i)) { - path._simplificationMap.insert({i, r._simplificationMap.at(i)}); - } - } - // Run the simplificator on the newly constructed set? - return path; -} - Simplificator::ExprResult Simplificator::simplifyExpr(const constraints_ty &constraints, const ref &expr) { @@ -423,27 +412,23 @@ Simplificator::simplifyExpr(const constraints_ty &constraints, for (auto &constraint : constraints) { if (const EqExpr *ee = dyn_cast(constraint)) { - ref left = ee->left; - ref right = ee->right; - if (right < left) { - left = ee->right; - right = ee->left; - } - if (isa(ee->left)) { - equalities.insert(std::make_pair(ee->right, ee->left)); - equalitiesParents.insert({ee->right, constraint}); - } else { - equalities.insert(std::make_pair(constraint, Expr::createTrue())); - equalities.insert(std::make_pair(right, left)); - equalitiesParents.insert({constraint, constraint}); - equalitiesParents.insert({right, constraint}); + ref small = ee->left; + ref big = ee->right; + if (!isa(small)) { + auto hr = big->height(), hl = small->height(); + if (hr < hl || (hr == hl && big < small)) + std::swap(small, big); + equalities.emplace(constraint, Expr::createTrue()); + equalitiesParents.emplace(constraint, constraint); } + equalities.emplace(big, small); + equalitiesParents.emplace(big, constraint); } else { - equalities.insert(std::make_pair(constraint, Expr::createTrue())); - equalitiesParents.insert({constraint, constraint}); + equalities.emplace(constraint, Expr::createTrue()); + equalitiesParents.emplace(constraint, constraint); if (const NotExpr *ne = dyn_cast(constraint)) { - equalities.insert(std::make_pair(ne->expr, Expr::createFalse())); - equalitiesParents.insert({ne->expr, constraint}); + equalities.emplace(ne->expr, Expr::createFalse()); + equalitiesParents.emplace(ne->expr, constraint); } } } @@ -589,13 +574,13 @@ Simplificator::composeExprDependencies(const ExprHashMap &upper, void ConstraintSet::getAllIndependentConstraintsSets( ref queryExpr, std::vector> &result) const { - _independentElements.getAllIndependentConstraintSets(queryExpr, result); + _independentElements->getAllIndependentConstraintSets(queryExpr, result); } void ConstraintSet::getAllDependentConstraintsSets( ref queryExpr, std::vector> &result) const { - _independentElements.getAllDependentConstraintSets(queryExpr, result); + _independentElements->getAllDependentConstraintSets(queryExpr, result); } std::vector ConstraintSet::gatherArrays() const { diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index ccf6eab730..c6fa1b844d 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -16,7 +16,7 @@ #include "klee/Support/ErrorHandling.h" #include "klee/Support/OptionCategories.h" #include "klee/Support/RoundingModeUtil.h" -#include "klee/util/APFloatEval.h" +#include "klee/Utilities/APFloatEval.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -153,11 +153,13 @@ int Expr::compare(const Expr &b, ExprEquivSet &equivs) const { return 0; Kind ak = getKind(), bk = b.getKind(); - if (ak != bk) - return (ak < bk) ? -1 : 1; + int kc = (ak > bk) - (ak < bk); + if (kc) + return kc; - if (hashValue != b.hashValue) - return (hashValue < b.hashValue) ? -1 : 1; + int hc = (hashValue > b.hashValue) - (hashValue < b.hashValue); + if (hc) + return hc; if (int res = compareContents(b)) return res; @@ -260,6 +262,18 @@ unsigned Expr::computeHash() { return hashValue; } +unsigned Expr::computeHeight() { + unsigned maxKidHeight = 0; + + int n = getNumKids(); + for (int i = 0; i < n; i++) { + maxKidHeight = std::max(maxKidHeight, getKid(i)->height()); + } + + heightValue = maxKidHeight + 1; + return heightValue; +} + unsigned ConstantExpr::computeHash() { Expr::Width w = getWidth(); if (w <= 64) @@ -290,6 +304,11 @@ unsigned ReadExpr::computeHash() { return hashValue; } +unsigned ReadExpr::computeHeight() { + heightValue = std::max(index->height(), updates.height()) + 1; + return heightValue; +} + unsigned NotExpr::computeHash() { hashValue = expr->hash() * Expr::MAGIC_HASH_CONSTANT * Expr::Not; return hashValue; @@ -508,6 +527,10 @@ ref Expr::createTrue() { return ConstantExpr::create(1, Expr::Bool); } ref Expr::createFalse() { return ConstantExpr::create(0, Expr::Bool); } +Expr::ByteWidth Expr::getByteWidth() const { + return (getWidth() + CHAR_BIT - 1) / CHAR_BIT; +} + void Expr::print(llvm::raw_ostream &os) const { ExprPPrinter::printSingleExpr(os, const_cast(this)); } @@ -1465,22 +1488,7 @@ Array::Array(ref _size, ref _source, Expr::Width _domain, Expr::Width _range, unsigned _id) : size(_size), source(_source), domain(_domain), range(_range), id(_id) { ref constantSize = dyn_cast(size); - assert( - (!isa(_source) || - cast(_source)->size() == constantSize->getZExtValue()) && - "Invalid size for constant array!"); computeHash(); -#ifndef NDEBUG - if (isa(_source)) { - for (const ref * - it = cast(_source)->constantValues.data(), - *end = cast(_source)->constantValues.data() + - cast(_source)->constantValues.size(); - it != end; ++it) - assert((*it)->getWidth() == getRange() && - "Invalid initial constant value!"); - } -#endif // NDEBUG std::set allArrays = _source->getRelatedArrays(); std::vector sizeArrays; @@ -1529,6 +1537,22 @@ ref ReadExpr::create(const UpdateList &ul, ref index) { } } + // So that we return weird stuff like reads from consts that should have + // simplified to constant exprs if we read beyond size boundary. + if (auto source = dyn_cast(ul.root->source)) { + if (auto arraySizeExpr = dyn_cast(ul.root->size)) { + if (auto indexExpr = dyn_cast(index)) { + auto arraySize = arraySizeExpr->getZExtValue(); + auto concreteIndex = indexExpr->getZExtValue(); + if (concreteIndex >= arraySize) { + return ReadExpr::alloc(ul, index); + } + } + } else { + return ReadExpr::alloc(ul, index); + } + } + if (isa(ul.root->source) && !updateListHasSymbolicWrites) { // No updates with symbolic index to a constant array have been found if (ConstantExpr *CE = dyn_cast(index)) { @@ -1536,9 +1560,8 @@ ref ReadExpr::create(const UpdateList &ul, ref index) { ref constantSource = cast(ul.root->source); uint64_t concreteIndex = CE->getZExtValue(); - uint64_t size = constantSource->constantValues.size(); - if (concreteIndex < size) { - return constantSource->constantValues[concreteIndex]; + if (auto value = constantSource->constantValues.load(concreteIndex)) { + return value; } } } @@ -1802,9 +1825,13 @@ ref FPTruncExpr::create(const ref &e, Width w, return e; } else if (ConstantExpr *CE = dyn_cast(e)) { return CE->FPTrunc(w, rm); - } else { - return FPTruncExpr::alloc(e, w, rm); + } else if (FPExtExpr *ExtE = dyn_cast(e)) { + if (ExtE->src->getWidth() == w) { + return ExtE->src; + } } + + return FPTruncExpr::alloc(e, w, rm); } ref FPToUIExpr::create(const ref &e, Width w, @@ -2251,12 +2278,14 @@ static ref TryConstArrayOpt(const ref &cl, ReadExpr *rd) { // for now, just assume standard "flushing" of a concrete array, // where the concrete array has one update for each index, in order + auto arraySize = dyn_cast(rd->updates.root->size); + assert(arraySize); + auto size = arraySize->getZExtValue(); ref res = ConstantExpr::alloc(0, Expr::Bool); if (ref constantSource = dyn_cast(rd->updates.root->source)) { - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { - if (cl == constantSource->constantValues[i]) { + for (unsigned i = 0, e = size; i != e; ++i) { + if (cl == constantSource->constantValues.load(i)) { // Arbitrary maximum on the size of disjunction. if (++numMatches > 100) return EqExpr_create(cl, rd); diff --git a/lib/Expr/ExprEvaluator.cpp b/lib/Expr/ExprEvaluator.cpp index bcadb59156..418640769a 100644 --- a/lib/Expr/ExprEvaluator.cpp +++ b/lib/Expr/ExprEvaluator.cpp @@ -32,15 +32,10 @@ ExprVisitor::Action ExprEvaluator::evalRead(const UpdateList &ul, if (ref constantSource = dyn_cast(ul.root->source)) { - if (index < constantSource->constantValues.size()) { - return Action::changeTo(constantSource->constantValues[index]); + if (auto value = constantSource->constantValues.load(index)) { + return Action::changeTo(value); } } - if (ref symbolicSizeConstantSource = - dyn_cast(ul.root->source)) { - return Action::changeTo(ConstantExpr::create( - symbolicSizeConstantSource->defaultValue, ul.root->getRange())); - } return Action::changeTo(getInitialValue(*ul.root, index)); } diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index bde8d30d6d..83c6e0b782 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -385,19 +385,29 @@ class PPrinter : public ExprPPrinter { void printSource(ref source, PrintContext &PC) { PC << "("; PC << source->getName() << " "; + if (auto s = dyn_cast(source)) { - PC << " ["; - for (unsigned i = 0; i < s->constantValues.size(); i++) { - PC << s->constantValues[i]; - if (i != s->constantValues.size() - 1) { - PC << " "; - } - } - PC << "]"; - } else if (auto s = dyn_cast(source)) { - PC << s->defaultValue; + s->constantValues.print(PC.getStream(), Density::Sparse); } else if (auto s = dyn_cast(source)) { - PC << s->defaultValue << " " << s->version; + PC << s->version << " "; + switch (s->allocSite->getKind()) { + case KValue::Kind::INSTRUCTION: { + cast(s->allocSite)->getID().print(PC.getStream()); + break; + } + case KValue::Kind::GLOBAL_VARIABLE: { + PC.getStream() << "[" << cast(s->allocSite)->getName() + << "]"; + break; + } + default: { + llvm_unreachable("unknown kind of alloc site"); + } + } + PC << " " << s->size; + } else if (auto s = dyn_cast(source)) { + PC << s->version << " "; + s->allocSite->getID().print(PC.getStream()); } else if (auto s = dyn_cast(source)) { PC << s->name << " " << s->version; } else if (auto s = dyn_cast(source)) { @@ -409,10 +419,24 @@ class PPrinter : public ExprPPrinter { auto kf = s->km->functionMap.at(s->allocSite.getFunction()); auto ki = kf->instructionMap.at(&s->allocSite); auto kb = ki->parent; - PC << ki->index << " " << kb->getLabel() << " " << kf->getName().str() - << " " << s->index; + PC << ki->getIndex() << " " << kb->getLabel() << " " + << kf->getName().str() << " " << s->index; } else if (auto s = dyn_cast(source)) { PC << s->name; + } else if (auto s = dyn_cast(source)) { + PC << s->km->functionMap.at(&s->function)->getName() << ' ' << s->version; + } else if (auto s = dyn_cast(source)) { + PC << s->km->functionMap.at(&s->function)->getName() << ' '; + PC << "("; + for (unsigned i = 0; i < s->args.size(); i++) { + print(s->args[i], PC); + if (i != s->args.size() - 1) { + PC << " "; + } + } + PC << ')'; + } else if (auto s = dyn_cast(source)) { + PC << s->index; } else { assert(0 && "Not implemented"); } diff --git a/lib/Expr/ExprSMTLIBPrinter.cpp b/lib/Expr/ExprSMTLIBPrinter.cpp index e1a9b9aa89..ea0315ce4e 100644 --- a/lib/Expr/ExprSMTLIBPrinter.cpp +++ b/lib/Expr/ExprSMTLIBPrinter.cpp @@ -557,7 +557,11 @@ namespace { struct ArrayPtrsByName { bool operator()(const Array *a1, const Array *a2) const { - return a1->id < a2->id; + if (a1->source->getKind() != a2->source->getKind()) { + return a1->source->getKind() < a2->source->getKind(); + } else { + return a1->id < a2->id; + } } }; @@ -613,14 +617,8 @@ void ExprSMTLIBPrinter::printArrayDeclarations() { << " " << array->getDomain() << ") )"; printSeperator(); - if (ref symbolicSizeConstantSource = - dyn_cast(array->source)) { - printConstant(ConstantExpr::create( - symbolicSizeConstantSource->defaultValue, array->getRange())); - } else if (ref constantSource = - cast(array->source)) { - printConstant(constantSource->constantValues[byteIndex]); - } + auto source = dyn_cast(array->source); + printConstant(source->constantValues.load(byteIndex)); p->popIndent(); printSeperator(); diff --git a/lib/Expr/ExprUtil.cpp b/lib/Expr/ExprUtil.cpp index 87bed5d731..518e922dc8 100644 --- a/lib/Expr/ExprUtil.cpp +++ b/lib/Expr/ExprUtil.cpp @@ -54,6 +54,16 @@ void klee::findReads(ref e, bool visitUpdates, cast(re->updates.root->source)->pointer); } + if (ref mockSource = + dyn_cast_or_null( + re->updates.root->source)) { + for (auto arg : mockSource->args) { + if (visited.insert(arg).second) { + stack.push_back(arg); + } + } + } + if (visitUpdates) { // XXX this is probably suboptimal. We want to avoid a potential // explosion traversing update lists which can be quite diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index 01358e2623..ba0b57026c 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -1,5 +1,8 @@ #include "klee/Expr/IndependentConstraintSetUnion.h" +#include "klee/ADT/DisjointSetUnion.h" +#include "klee/Expr/IndependentSet.h" + namespace klee { IndependentConstraintSetUnion::IndependentConstraintSetUnion() {} @@ -20,14 +23,14 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( ref ics) { auto exprs = ics->exprs; for (ref e : exprs) { - auto v = ref(new ExprEitherSymcrete::left(e)); - rank.replace({v, 0}); + auto v = ref(new ExprOrSymcrete::left(e)); + rank.insert_or_assign(v, 0); internalStorage.insert(v); } for (ref s : ics->symcretes) { - auto v = ref(new ExprEitherSymcrete::right(s)); - rank.replace({v, 0}); + auto v = ref(new ExprOrSymcrete::right(s)); + rank.insert_or_assign(v, 0); internalStorage.insert(v); } @@ -37,11 +40,11 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( auto &first = *(internalStorage.begin()); for (auto &e : internalStorage) { - parent.replace({e, first}); + parent.insert_or_assign(e, first); } - rank.replace({first, 1}); + rank.insert_or_assign(first, 1); roots.insert(first); - disjointSets.replace({first, ics}); + disjointSets.insert_or_assign(first, ics); concretization = ics->concretization; } @@ -49,30 +52,48 @@ void IndependentConstraintSetUnion::addIndependentConstraintSetUnion( const IndependentConstraintSetUnion &icsu) { add(icsu); concretization.addIndependentAssignment(icsu.concretization); + updateQueue.addIndependentAssignment(icsu.updateQueue); + removeQueue.addIndependentAssignment(icsu.removeQueue); + constraintQueue.insert(constraintQueue.begin(), icsu.constraintQueue.begin(), + icsu.constraintQueue.end()); } void IndependentConstraintSetUnion::updateConcretization( const Assignment &delta) { + for (auto &it : delta.bindings) { + updateQueue.bindings.replace({it.first, it.second}); + removeQueue.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::removeConcretization( + const Assignment &remove) { + for (auto &it : remove.bindings) { + removeQueue.bindings.replace({it.first, it.second}); + updateQueue.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::calculateUpdateConcretizationQueue() { for (auto &e : roots) { ref ics = disjointSets.at(e); - Assignment part = delta.part(ics->getSymcretes()); + Assignment part = updateQueue.part(ics->getSymcretes()); ics = ics->updateConcretization(part, concretizedExprs); - disjointSets.replace({e, ics}); + disjointSets.insert_or_assign(e, ics); } - for (auto &it : delta.bindings) { + for (auto &it : updateQueue.bindings) { concretization.bindings.replace({it.first, it.second}); } } -void IndependentConstraintSetUnion::removeConcretization( - const Assignment &remove) { +void IndependentConstraintSetUnion::calculateRemoveConcretizationQueue() { for (auto &e : roots) { ref ics = disjointSets.at(e); - Assignment part = remove.part(ics->getSymcretes()); + Assignment part = removeQueue.part(ics->getSymcretes()); ics = ics->removeConcretization(part, concretizedExprs); - disjointSets.replace({e, ics}); + disjointSets.insert_or_assign(e, ics); } - for (auto &it : remove.bindings) { + for (auto &it : removeQueue.bindings) { concretization.bindings.remove(it.first); } } @@ -93,10 +114,10 @@ void IndependentConstraintSetUnion::reEvaluateConcretization( } void IndependentConstraintSetUnion::getAllIndependentConstraintSets( - ref e, - std::vector> &result) const { + ref e, std::vector> &result) { + calculateQueue(); ref compare = - new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); + new IndependentConstraintSet(new ExprOrSymcrete::left(e)); for (auto &r : roots) { ref ics = disjointSets.at(r); if (!IndependentConstraintSet::intersects(ics, compare)) { @@ -106,10 +127,10 @@ void IndependentConstraintSetUnion::getAllIndependentConstraintSets( } void IndependentConstraintSetUnion::getAllDependentConstraintSets( - ref e, - std::vector> &result) const { + ref e, std::vector> &result) { + calculateQueue(); ref compare = - new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); + new IndependentConstraintSet(new ExprOrSymcrete::left(e)); for (auto &r : roots) { ref ics = disjointSets.at(r); if (IndependentConstraintSet::intersects(ics, compare)) { @@ -119,36 +140,66 @@ void IndependentConstraintSetUnion::getAllDependentConstraintSets( } void IndependentConstraintSetUnion::addExpr(ref e) { - addValue(new ExprEitherSymcrete::left(e)); + constraintQueue.push_back(new ExprOrSymcrete::left(e)); } void IndependentConstraintSetUnion::addSymcrete(ref s) { - addValue(new ExprEitherSymcrete::right(s)); + constraintQueue.push_back(new ExprOrSymcrete::right(s)); } IndependentConstraintSetUnion -IndependentConstraintSetUnion::getConcretizedVersion() const { +IndependentConstraintSetUnion::getConcretizedVersion() { + calculateQueue(); IndependentConstraintSetUnion icsu; for (auto &i : roots) { ref root = disjointSets.at(i); if (root->concretization.bindings.empty()) { for (ref expr : root->exprs) { - icsu.addValue(new ExprEitherSymcrete::left(expr)); + icsu.addExpr(expr); } } else { - icsu.add(root->concretizedSets); + root->concretizedSets->calculateQueue(); + icsu.add(*root->concretizedSets.get()); } icsu.concretization.addIndependentAssignment(root->concretization); } icsu.concretizedExprs = concretizedExprs; + icsu.calculateQueue(); return icsu; } IndependentConstraintSetUnion IndependentConstraintSetUnion::getConcretizedVersion( - const Assignment &newConcretization) const { + const Assignment &newConcretization) { + calculateQueue(); IndependentConstraintSetUnion icsu = *this; icsu.reEvaluateConcretization(newConcretization); + icsu.calculateQueue(); return icsu.getConcretizedVersion(); } + +void IndependentConstraintSetUnion::calculateQueue() { + calculateUpdateConcretizationQueue(); + calculateRemoveConcretizationQueue(); + while (!constraintQueue.empty()) { + auto constraint = constraintQueue[constraintQueue.size() - 1]; + if (auto expr = dyn_cast(constraint)) { + if (auto ce = dyn_cast(expr->value())) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + constraintQueue.pop_back(); + continue; + } + } + addValue(constraint); + constraintQueue.pop_back(); + } + calculateUpdateConcretizationQueue(); + calculateRemoveConcretizationQueue(); + // Calculations are done twice for constraints already in dsu and for newly + // added constraints. Because IndependentSet update and remove concretization + // functions work only with difference between new and old concretization, no + // extra work is done + removeQueue.bindings = Assignment::bindings_ty(); + updateQueue.bindings = Assignment::bindings_ty(); +} } // namespace klee diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index 3acca539c9..9ff427baf7 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -5,12 +5,12 @@ #include "klee/Expr/Constraints.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Symcrete.h" -#include "klee/Solver/Solver.h" +#include "klee/Module/KModule.h" #include -#include #include #include #include @@ -23,29 +23,26 @@ IndependentConstraintSet::updateConcretization( if (delta.bindings.size() == 0) { return ics; } - for (auto i : delta.bindings) { + for (auto &i : delta.bindings) { ics->concretization.bindings.replace({i.first, i.second}); } InnerSetUnion DSU; for (ref i : exprs) { ref e = ics->concretization.evaluate(i); - if (auto ce = dyn_cast(e)) { - assert(ce->isTrue() && "Attempt to add invalid constraint"); - continue; - } concretizedExprs[i] = e; - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addExpr(e); } for (ref s : symcretes) { ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), s->symcretized); - if (auto ce = dyn_cast(e)) { - assert(ce->isTrue() && "Attempt to add invalid constraint"); - continue; - } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addExpr(e); + } + auto concretizationConstraints = + ics->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + DSU.addExpr(e); } - ics->concretizedSets = DSU; + ics->concretizedSets.reset(new InnerSetUnion(DSU)); return ics; } @@ -56,30 +53,27 @@ IndependentConstraintSet::removeConcretization( if (delta.bindings.size() == 0) { return ics; } - for (auto i : delta.bindings) { + for (auto &i : delta.bindings) { ics->concretization.bindings.remove(i.first); } InnerSetUnion DSU; for (ref i : exprs) { ref e = ics->concretization.evaluate(i); - if (auto ce = dyn_cast(e)) { - assert(ce->isTrue() && "Attempt to add invalid constraint"); - continue; - } concretizedExprs[i] = e; - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addExpr(e); } for (ref s : symcretes) { ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), s->symcretized); - if (auto ce = dyn_cast(e)) { - assert(ce->isTrue() && "Attempt to add invalid constraint"); - continue; - } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addExpr(e); + } + auto concretizationConstraints = + ics->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + DSU.addExpr(e); } - ics->concretizedSets = DSU; + ics->concretizedSets.reset(new InnerSetUnion(DSU)); return ics; } @@ -90,8 +84,6 @@ void IndependentConstraintSet::addValuesToAssignment( for (unsigned i = 0; i < objects.size(); i++) { if (assign.bindings.count(objects[i])) { SparseStorage value = assign.bindings.at(objects[i]); - assert(value.size() == values[i].size() && - "we're talking about the same array here"); DenseSet ds = (elements.find(objects[i]))->second; for (std::set::iterator it2 = ds.begin(); it2 != ds.end(); it2++) { @@ -107,11 +99,11 @@ void IndependentConstraintSet::addValuesToAssignment( IndependentConstraintSet::IndependentConstraintSet() {} -IndependentConstraintSet::IndependentConstraintSet(ref v) { - if (isa(v)) { - initIndependentConstraintSet(cast(v)->value()); +IndependentConstraintSet::IndependentConstraintSet(ref v) { + if (isa(v)) { + initIndependentConstraintSet(cast(v)->value()); } else { - initIndependentConstraintSet(cast(v)->value()); + initIndependentConstraintSet(cast(v)->value()); } } @@ -132,6 +124,11 @@ void IndependentConstraintSet::initIndependentConstraintSet(ref e) { if (re->updates.root->isConstantArray() && !re->updates.head) continue; + if (ref mockSource = + dyn_cast_or_null(array->source)) { + uninterpretedFunctions.insert(mockSource->function.getName().str()); + } + if (!wholeObjects.count(array)) { if (ConstantExpr *CE = dyn_cast(re->index)) { // if index constant, then add to set of constraints operating @@ -273,6 +270,11 @@ bool IndependentConstraintSet::intersects( return true; } } + for (const auto &uFn : a->uninterpretedFunctions) { + if (b->uninterpretedFunctions.count(uFn)) { + return true; + } + } } // No need to check symcretes here, arrays must be sufficient. return false; @@ -330,23 +332,20 @@ IndependentConstraintSet::merge(ref A, InnerSetUnion DSU; for (ref i : a->exprs) { ref e = a->concretization.evaluate(i); - if (auto ce = dyn_cast(e)) { - assert(ce->isTrue() && "Attempt to add invalid constraint"); - continue; - } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addExpr(e); } for (ref s : a->symcretes) { ref e = EqExpr::create(a->concretization.evaluate(s->symcretized), s->symcretized); - if (auto ce = dyn_cast(e)) { - assert(ce->isTrue() && "Attempt to add invalid constraint"); - continue; - } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addExpr(e); + } + auto concretizationConstraints = + a->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + DSU.addExpr(e); } - a->concretizedSets = DSU; + a->concretizedSets.reset(new InnerSetUnion(DSU)); } return a; @@ -380,7 +379,7 @@ void calculateArraysInFactors( } std::vector result; ref queryExprSet = - new IndependentConstraintSet(new ExprEitherSymcrete::left(queryExpr)); + new IndependentConstraintSet(new ExprOrSymcrete::left(queryExpr)); queryExprSet->calculateArrayReferences(result); returnSet.insert(result.begin(), result.end()); returnVector.insert(returnVector.begin(), returnSet.begin(), returnSet.end()); diff --git a/lib/Expr/Lexer.cpp b/lib/Expr/Lexer.cpp index 9be58ae5ce..acbb29b9dc 100644 --- a/lib/Expr/Lexer.cpp +++ b/lib/Expr/Lexer.cpp @@ -54,6 +54,10 @@ const char *Token::getKindName() const { return "KWQuery"; case KWPath: return "KWPath"; + case KWDefault: + return "KWDefault"; + case KWNull: + return "KWNull"; case KWReserved: return "KWReserved"; case KWSymbolic: @@ -180,6 +184,8 @@ Token &Lexer::SetIdentifierTokenKind(Token &Result) { return SetTokenKind(Result, Token::KWTrue); if (memcmp("path", Result.start, 4) == 0) return SetTokenKind(Result, Token::KWPath); + if (memcmp("null", Result.start, 4) == 0) + return SetTokenKind(Result, Token::KWNull); break; case 5: @@ -199,6 +205,8 @@ Token &Lexer::SetIdentifierTokenKind(Token &Result) { case 7: if (memcmp("declare", Result.start, 7) == 0) return SetTokenKind(Result, Token::KWReserved); + if (memcmp("default", Result.start, 7) == 0) + return SetTokenKind(Result, Token::KWDefault); break; case 8: diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index b072cec826..956f1fb876 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -280,6 +280,8 @@ class ParserImpl : public Parser { } } + ArrayCache &getArrayCache() { return *TheArrayCache; } + /*** Grammar productions ****/ /* Top level decls */ @@ -322,7 +324,6 @@ class ParserImpl : public Parser { SourceResult ParseSource(); SourceResult ParseConstantSource(); - SourceResult ParseSymbolicSizeConstantSource(); SourceResult ParseSymbolicSizeConstantAddressSource(); SourceResult ParseMakeSymbolicSource(); SourceResult ParseLazyInitializationContentSource(); @@ -330,6 +331,9 @@ class ParserImpl : public Parser { SourceResult ParseLazyInitializationSizeSource(); SourceResult ParseInstructionSource(); SourceResult ParseArgumentSource(); + SourceResult ParseMockNaiveSource(); + SourceResult ParseMockDeterministicSource(); + SourceResult ParseAlphaSource(); /*** Diagnostics ***/ @@ -483,8 +487,6 @@ SourceResult ParserImpl::ParseSource() { SourceResult source; if (type == "constant") { source = ParseConstantSource(); - } else if (type == "symbolicSizeConstant") { - source = ParseSymbolicSizeConstantSource(); } else if (type == "symbolicSizeConstantAddress") { source = ParseSymbolicSizeConstantAddressSource(); } else if (type == "makeSymbolic") { @@ -501,6 +503,14 @@ SourceResult ParserImpl::ParseSource() { } else if (type == "argument") { assert(km); source = ParseArgumentSource(); + } else if (type == "mockNaive") { + assert(km); + source = ParseMockNaiveSource(); + } else if (type == "mockDeterministic") { + assert(km); + source = ParseMockDeterministicSource(); + } else if (type == "alpha") { + source = ParseAlphaSource(); } else { assert(0); } @@ -509,39 +519,69 @@ SourceResult ParserImpl::ParseSource() { } SourceResult ParserImpl::ParseConstantSource() { - std::vector> Values; - ConsumeLSquare(); - while (Tok.kind != Token::RSquare) { - if (Tok.kind == Token::EndOfFile) { - Error("unexpected end of file."); - assert(0); + std::unordered_map> storage; + ref defaultValue = nullptr; + + if (Tok.kind == Token::LSquare) { + ConsumeLSquare(); + unsigned index = 0; + while (Tok.kind != Token::RSquare) { + if (Tok.kind == Token::EndOfFile) { + Error("unexpected end of file."); + assert(0); + } + ExprResult Res = ParseNumber(8).get(); // Should be Range Type + storage.insert({index, cast(Res.get())}); + if (Tok.kind == Token::Comma) { + ConsumeExpectedToken(Token::Comma); + } + index++; } - - ExprResult Res = ParseNumber(8); // Should be Range Type - if (Res.isValid()) - Values.push_back(cast(Res.get())); + ConsumeRSquare(); + } else if (Tok.kind == Token::LBrace) { + ConsumeExpectedToken(Token::LBrace); + while (Tok.kind != Token::RBrace) { + if (Tok.kind == Token::EndOfFile) { + Error("unexpected end of file."); + assert(0); + } + ExprResult Index = ParseNumber(64).get(); + ConsumeExpectedToken(Token::Colon); + ExprResult Res = ParseNumber(8).get(); // Should be Range Type + storage.insert({cast(Index.get())->getZExtValue(), + cast(Res.get())}); + if (Tok.kind == Token::Comma) { + ConsumeExpectedToken(Token::Comma); + } + } + ConsumeExpectedToken(Token::RBrace); + } else { + assert(0 && "Parsing error"); } - ConsumeRSquare(); - return SourceBuilder::constant(Values); -} -SourceResult ParserImpl::ParseSymbolicSizeConstantSource() { - auto valueExpr = ParseNumber(64).get(); - if (auto ce = dyn_cast(valueExpr)) { - return SourceBuilder::symbolicSizeConstant(ce->getZExtValue()); + ConsumeExpectedToken(Token::KWDefault); + ConsumeExpectedToken(Token::Colon); + + if (Tok.kind != Token::KWNull) { + ExprResult DV = ParseNumber(8).get(); // Should be Range Type + defaultValue = cast(DV.get()); } else { - assert(0); + ConsumeExpectedToken(Token::KWNull); } + + SparseStorage> Values(storage, defaultValue); + return SourceBuilder::constant(Values); } SourceResult ParserImpl::ParseSymbolicSizeConstantAddressSource() { - auto valueExpr = ParseNumber(64).get(); - auto versionExpr = ParseNumber(64).get(); - auto value = dyn_cast(valueExpr); - auto version = dyn_cast(versionExpr); - assert(value && version); - return SourceBuilder::symbolicSizeConstantAddress(value->getZExtValue(), - version->getZExtValue()); + assert(0 && "unimplemented"); + // auto valueExpr = ParseNumber(64).get(); + // auto versionExpr = ParseNumber(64).get(); + // auto value = dyn_cast(valueExpr); + // auto version = dyn_cast(versionExpr); + // assert(value && version); + // return SourceBuilder::symbolicSizeConstantAddress(value->getZExtValue(), + // version->getZExtValue()); } SourceResult ParserImpl::ParseMakeSymbolicSource() { @@ -576,10 +616,10 @@ SourceResult ParserImpl::ParseArgumentSource() { auto argNo = dyn_cast(argNoExpr.get())->getZExtValue(); auto index = dyn_cast(indexExpr.get())->getZExtValue(); #if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) - auto arg = km->functionNameMap[name.getString()]->function->getArg(argNo); + auto arg = km->functionNameMap[name.getString()]->function()->getArg(argNo); #else auto arg = - &km->functionNameMap[name.getString()]->function->arg_begin()[argNo]; + &km->functionNameMap[name.getString()]->function()->arg_begin()[argNo]; #endif return SourceBuilder::argument(*arg, index, km); } @@ -596,7 +636,41 @@ SourceResult ParserImpl::ParseInstructionSource() { auto KF = km->functionNameMap[FName.getString()]; auto KB = KF->getLabelMap().at(Label.getString()); auto KI = KB->instructions[KIIndex]; - return SourceBuilder::instruction(*KI->inst, index, km); + return SourceBuilder::instruction(*KI->inst(), index, km); +} + +SourceResult ParserImpl::ParseMockNaiveSource() { + auto name = Tok.getString(); + auto kf = km->functionNameMap[name]; + ConsumeExpectedToken(Token::Identifier); + auto versionExpr = ParseNumber(64).get(); + auto version = dyn_cast(versionExpr); + assert(version); + return SourceBuilder::mockNaive(km, *kf->function(), version->getZExtValue()); +} + +SourceResult ParserImpl::ParseMockDeterministicSource() { + auto name = Tok.getString(); + auto kf = km->functionNameMap[name]; + ConsumeExpectedToken(Token::Identifier); + ConsumeLParen(); + std::vector> args; + args.reserve(kf->getNumArgs()); + for (unsigned i = 0; i < kf->getNumArgs(); i++) { + auto expr = ParseExpr(TypeResult()); + if (!expr.isValid()) { + return {false, nullptr}; + } + args.push_back(expr.get()); + } + ConsumeRParen(); + return SourceBuilder::mockDeterministic(km, *kf->function(), args); +} + +SourceResult ParserImpl::ParseAlphaSource() { + auto indexExpr = ParseNumber(64).get(); + auto index = dyn_cast(indexExpr)->getZExtValue(); + return SourceBuilder::alpha(index); } /// ParseCommandDecl - Parse a command declaration. The lexer should diff --git a/lib/Expr/Path.cpp b/lib/Expr/Path.cpp index 7b578aa30c..e3be1e0d25 100644 --- a/lib/Expr/Path.cpp +++ b/lib/Expr/Path.cpp @@ -15,8 +15,8 @@ using namespace llvm; void Path::advance(KInstruction *ki) { if (KBlocks.empty()) { - firstInstruction = ki->index; - lastInstruction = ki->index; + firstInstruction = ki->getIndex(); + lastInstruction = ki->getIndex(); KBlocks.push_back(ki->parent); return; } @@ -24,8 +24,7 @@ void Path::advance(KInstruction *ki) { if (ki->parent != lastBlock) { KBlocks.push_back(ki->parent); } - lastInstruction = ki->index; - return; + lastInstruction = ki->getIndex(); } unsigned Path::KBlockSize() const { return KBlocks.size(); } @@ -40,67 +39,6 @@ Path::PathIndex Path::getCurrentIndex() const { return {KBlocks.size() - 1, lastInstruction}; } -std::vector Path::getStack(bool reversed) const { - std::vector stack; - for (unsigned i = 0; i < KBlocks.size(); i++) { - auto current = reversed ? KBlocks[KBlocks.size() - 1 - i] : KBlocks[i]; - // Previous for reversed is the next - KBlock *prev = nullptr; - if (i != 0) { - prev = reversed ? KBlocks[KBlocks.size() - i] : KBlocks[i - 1]; - } - if (i == 0) { - stack.push_back({nullptr, current->parent}); - continue; - } - if (reversed) { - auto kind = getTransitionKind(current, prev); - if (kind == TransitionKind::StepInto) { - if (!stack.empty()) { - stack.pop_back(); - } - } else if (kind == TransitionKind::StepOut) { - assert(isa(prev)); - stack.push_back({prev->getFirstInstruction(), current->parent}); - } - } else { - auto kind = getTransitionKind(prev, current); - if (kind == TransitionKind::StepInto) { - stack.push_back({prev->getFirstInstruction(), current->parent}); - } else if (kind == TransitionKind::StepOut) { - if (!stack.empty()) { - stack.pop_back(); - } - } - } - } - return stack; -} - -std::vector> -Path::asFunctionRanges() const { - assert(!KBlocks.empty()); - std::vector> ranges; - BlockRange range{0, 0}; - KFunction *function = KBlocks[0]->parent; - for (unsigned i = 1; i < KBlocks.size(); i++) { - if (getTransitionKind(KBlocks[i - 1], KBlocks[i]) == TransitionKind::None) { - if (i == KBlocks.size() - 1) { - range.last = i; - ranges.push_back({function, range}); - return ranges; - } else { - continue; - } - } - range.last = i - 1; - ranges.push_back({function, range}); - range.first = i; - function = KBlocks[i]->parent; - } - llvm_unreachable("asFunctionRanges reached the end of the for!"); -} - Path Path::concat(const Path &l, const Path &r) { Path path = l; for (auto block : r.KBlocks) { @@ -113,11 +51,16 @@ Path Path::concat(const Path &l, const Path &r) { std::string Path::toString() const { std::string blocks = ""; unsigned depth = 0; - for (unsigned i = 0; i < KBlocks.size(); i++) { - auto current = KBlocks[i]; + std::vector KBlocksVector; + KBlocksVector.reserve(KBlocks.size()); + for (auto kblock : KBlocks) { + KBlocksVector.push_back(kblock); + } + for (size_t i = 0; i < KBlocksVector.size(); i++) { + auto current = KBlocksVector[i]; KBlock *prev = nullptr; if (i != 0) { - prev = KBlocks[i - 1]; + prev = KBlocksVector[i - 1]; } auto kind = i == 0 ? TransitionKind::StepInto : getTransitionKind(prev, current); @@ -207,7 +150,7 @@ Path Path::parse(const std::string &str, const KModule &km) { Path::TransitionKind Path::getTransitionKind(KBlock *a, KBlock *b) { if (auto cb = dyn_cast(a)) { - if (cb->calledFunctions.count(b->parent->function) && + if (cb->calledFunctions.count(b->parent->function()) && b == b->parent->entryKBlock) { return TransitionKind::StepInto; } diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index a667a19ba2..47f5fdd823 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -1,28 +1,39 @@ #include "klee/Expr/SourceBuilder.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" +#include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/KValue.h" using namespace klee; ref -SourceBuilder::constant(const std::vector> &constantValues) { +SourceBuilder::constant(SparseStorage> constantValues) { ref r(new ConstantSource(constantValues)); r->computeHash(); return r; } -ref SourceBuilder::symbolicSizeConstant(unsigned defaultValue) { - ref r(new SymbolicSizeConstantSource(defaultValue)); +ref +SourceBuilder::uninitialized(unsigned version, const KInstruction *allocSite) { + ref r(new UninitializedSource(version, allocSite)); r->computeHash(); return r; } -ref -SourceBuilder::symbolicSizeConstantAddress(unsigned defaultValue, - unsigned version) { +ref SourceBuilder::symbolicSizeConstantAddress( + unsigned version, const KInstruction *allocSite, ref size) { + ref r = + new SymbolicSizeConstantAddressSource(version, allocSite, size); + r->computeHash(); + return r; +} + +ref SourceBuilder::symbolicSizeConstantAddress( + unsigned version, const KGlobalVariable *allocSite, ref size) { ref r( - new SymbolicSizeConstantAddressSource(defaultValue, version)); + new SymbolicSizeConstantAddressSource(version, allocSite, size)); r->computeHash(); return r; } @@ -86,4 +97,27 @@ ref SourceBuilder::irreproducible(const std::string &name) { ref r(new IrreproducibleSource(name + llvm::utostr(++id))); r->computeHash(); return r; -} \ No newline at end of file +} + +ref SourceBuilder::mockNaive(const KModule *km, + const llvm::Function &function, + unsigned int version) { + ref r(new MockNaiveSource(km, function, version)); + r->computeHash(); + return r; +} + +ref +SourceBuilder::mockDeterministic(const KModule *km, + const llvm::Function &function, + const std::vector> &args) { + ref r(new MockDeterministicSource(km, function, args)); + r->computeHash(); + return r; +} + +ref SourceBuilder::alpha(int _index) { + ref r(new AlphaSource(_index)); + r->computeHash(); + return r; +} diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index 0e7f8b1086..a1ea9a0de0 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -1,10 +1,10 @@ #include "klee/Expr/SymbolicSource.h" - #include "klee/Expr/Expr.h" #include "klee/Expr/ExprPPrinter.h" #include "klee/Expr/ExprUtil.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/KValue.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS @@ -46,27 +46,73 @@ std::set LazyInitializationSource::getRelatedArrays() const { } unsigned ConstantSource::computeHash() { - unsigned res = 0; - for (unsigned i = 0, e = constantValues.size(); i != e; ++i) { - res = - (res * SymbolicSource::MAGIC_HASH_CONSTANT) + constantValues[i]->hash(); + auto defaultV = constantValues.defaultV(); + auto ordered = constantValues.calculateOrderedStorage(); + + unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + + (defaultV ? defaultV->hash() : 0); + + for (auto kv : ordered) { + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kv.first; + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kv.second->hash(); } - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + getKind(); + hashValue = res; return hashValue; } -unsigned SymbolicSizeConstantSource::computeHash() { - unsigned res = - (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + defaultValue; +unsigned UninitializedSource::computeHash() { + unsigned res = getKind(); + res = res * SymbolicSource::MAGIC_HASH_CONSTANT + version; + res = res * SymbolicSource::MAGIC_HASH_CONSTANT + allocSite->hash(); hashValue = res; return hashValue; } +int UninitializedSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const UninitializedSource &ub = static_cast(b); + + if (version != ub.version) { + return version < ub.version ? -1 : 1; + } + + if (allocSite != ub.allocSite) { + return allocSite->getGlobalIndex() < ub.allocSite->getGlobalIndex() ? -1 + : 1; + } + + return 0; +} + +int SymbolicSizeConstantAddressSource::internalCompare( + const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const SymbolicSizeConstantAddressSource &ub = + static_cast(b); + + if (version != ub.version) { + return version < ub.version ? -1 : 1; + } + if (size != ub.size) { + return size < ub.size ? -1 : 1; + } + if (allocSite != ub.allocSite) { + return *allocSite < *ub.allocSite ? -1 : 1; + } + + return 0; +} + unsigned SymbolicSizeConstantAddressSource::computeHash() { - unsigned res = - (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + defaultValue; - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + version; + unsigned res = getKind(); + res = res * MAGIC_HASH_CONSTANT + version; + res = res * MAGIC_HASH_CONSTANT + allocSite->hash(); + res = res * MAGIC_HASH_CONSTANT + size->hash(); hashValue = res; return hashValue; } @@ -98,9 +144,8 @@ int ArgumentSource::internalCompare(const SymbolicSource &b) const { assert(km == ab.km); auto parent = allocSite.getParent(); auto bParent = ab.allocSite.getParent(); - if (km->functionIDMap.at(parent) != km->functionIDMap.at(bParent)) { - return km->functionIDMap.at(parent) < km->functionIDMap.at(bParent) ? -1 - : 1; + if (km->getFunctionId(parent) != km->getFunctionId(bParent)) { + return km->getFunctionId(parent) < km->getFunctionId(bParent) ? -1 : 1; } if (allocSite.getArgNo() != ab.allocSite.getArgNo()) { return allocSite.getArgNo() < ab.allocSite.getArgNo() ? -1 : 1; @@ -118,21 +163,14 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { } assert(km == ib.km); auto function = allocSite.getParent()->getParent(); - auto bFunction = ib.allocSite.getParent()->getParent(); - if (km->functionIDMap.at(function) != km->functionIDMap.at(bFunction)) { - return km->functionIDMap.at(function) < km->functionIDMap.at(bFunction) ? -1 - : 1; - } auto kf = km->functionMap.at(function); - auto block = allocSite.getParent(); - auto bBlock = ib.allocSite.getParent(); - if (kf->blockMap[block]->id != kf->blockMap[bBlock]->id) { - return kf->blockMap[block]->id < kf->blockMap[bBlock]->id ? -1 : 1; - } - if (kf->instructionMap[&allocSite]->index != - kf->instructionMap[&ib.allocSite]->index) { - return kf->instructionMap[&allocSite]->index < - kf->instructionMap[&ib.allocSite]->index + auto bfunction = ib.allocSite.getParent()->getParent(); + auto bkf = km->functionMap.at(bfunction); + + if (kf->instructionMap[&allocSite]->getGlobalIndex() != + bkf->instructionMap[&ib.allocSite]->getGlobalIndex()) { + return kf->instructionMap[&allocSite]->getGlobalIndex() < + bkf->instructionMap[&ib.allocSite]->getGlobalIndex() ? -1 : 1; } @@ -142,8 +180,7 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { unsigned ArgumentSource::computeHash() { unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + index; auto parent = allocSite.getParent(); - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(parent); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + km->getFunctionId(parent); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + allocSite.getArgNo(); hashValue = res; return hashValue; @@ -154,13 +191,75 @@ unsigned InstructionSource::computeHash() { auto function = allocSite.getParent()->getParent(); auto kf = km->functionMap.at(function); auto block = allocSite.getParent(); + res = + (res * SymbolicSource::MAGIC_HASH_CONSTANT) + km->getFunctionId(function); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(function); - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kf->blockMap[block]->id; + kf->blockMap[block]->getId(); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - kf->instructionMap[&allocSite]->index; + kf->instructionMap[&allocSite]->getIndex(); hashValue = res; return hashValue; } +unsigned MockNaiveSource::computeHash() { + unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + version; + unsigned funcID = km->getFunctionId(&function); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + funcID; + hashValue = res; + return res; +} + +int MockNaiveSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const MockNaiveSource &mnb = static_cast(b); + unsigned funcID = km->getFunctionId(&function); + unsigned bFuncID = mnb.km->getFunctionId(&mnb.function); + if (funcID != bFuncID) { + return funcID < bFuncID ? -1 : 1; + } + if (version != mnb.version) { + return version < mnb.version ? -1 : 1; + } + return 0; +} + +MockDeterministicSource::MockDeterministicSource( + const KModule *km, const llvm::Function &function, + const std::vector> &_args) + : MockSource(km, function), args(_args) {} + +unsigned MockDeterministicSource::computeHash() { + unsigned res = getKind(); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + + km->getFunctionId(&function); + for (const auto &arg : args) { + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + arg->hash(); + } + hashValue = res; + return res; +} + +int MockDeterministicSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const MockDeterministicSource &mdb = + static_cast(b); + unsigned funcID = km->getFunctionId(&function); + unsigned bFuncID = mdb.km->getFunctionId(&mdb.function); + if (funcID != bFuncID) { + return funcID < bFuncID ? -1 : 1; + } + assert(args.size() == mdb.args.size() && + "the same functions should have the same arguments number"); + for (unsigned i = 0; i < args.size(); i++) { + if (args[i] != mdb.args[i]) { + return args[i] < mdb.args[i] ? -1 : 1; + } + } + return 0; +} + } // namespace klee diff --git a/lib/Expr/Updates.cpp b/lib/Expr/Updates.cpp index 6b740e3a72..b7bbad8cbc 100644 --- a/lib/Expr/Updates.cpp +++ b/lib/Expr/Updates.cpp @@ -25,6 +25,7 @@ UpdateNode::UpdateNode(const ref &_next, const ref &_index, "Update value should be 8-bit wide."); */ computeHash(); + computeHeight(); size = next ? next->size + 1 : 1; } @@ -45,6 +46,14 @@ unsigned UpdateNode::computeHash() { return hashValue; } +unsigned UpdateNode::computeHeight() { + unsigned maxHeight = next ? next->height() : 0; + maxHeight = std::max(maxHeight, index->height()); + maxHeight = std::max(maxHeight, value->height()); + heightValue = maxHeight; + return heightValue; +} + /// UpdateList::UpdateList(const Array *_root, const ref &_head) @@ -95,3 +104,5 @@ unsigned UpdateList::hash() const { res = (res * Expr::MAGIC_HASH_CONSTANT) + head->hash(); return res; } + +unsigned UpdateList::height() const { return head ? head->height() : 0; } diff --git a/lib/Module/Annotation.cpp b/lib/Module/Annotation.cpp new file mode 100644 index 0000000000..bfc4b2abf4 --- /dev/null +++ b/lib/Module/Annotation.cpp @@ -0,0 +1,274 @@ +//===-- Annotation.cpp ----------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#include "klee/Module/Annotation.h" +#include "klee/Support/ErrorHandling.h" + +#include +#include + +namespace klee { + +static inline std::string toLower(const std::string &str) { + std::string strLower; + strLower.reserve(str.size()); + std::transform(str.begin(), str.end(), std::back_inserter(strLower), tolower); + return strLower; +} + +namespace Statement { + +Unknown::Unknown(const std::string &str) { + { + const size_t firstColonPos = str.find(':'); + const size_t startOffset = firstColonPos + 1; + const size_t secondColonPos = str.find(':', startOffset); + const size_t offsetLength = (secondColonPos == std::string::npos) + ? std::string::npos + : secondColonPos - startOffset; + + rawAnnotation = str.substr(0, firstColonPos); + if (firstColonPos == std::string::npos) { + return; + } + rawOffset = str.substr(startOffset, offsetLength); + if (secondColonPos != std::string::npos) { + rawValue = str.substr(secondColonPos + 1, std::string::npos); + } + } + + for (size_t pos = 0; pos < rawOffset.size(); pos++) { + switch (rawOffset[pos]) { + case '*': { + offset.emplace_back("*"); + break; + } + case '&': { + offset.emplace_back("&"); + break; + } + case '[': { + size_t posEndExpr = rawOffset.find(']', pos); + if (posEndExpr == std::string::npos) { + klee_error("Annotation: Incorrect offset format \"%s\"", str.c_str()); + } + offset.push_back(rawOffset.substr(pos + 1, posEndExpr - 1 - pos)); + pos = posEndExpr; + break; + } + default: { + klee_warning("Annotation: Incorrect offset format \"%s\"", str.c_str()); + break; + } + } + } +} + +Unknown::~Unknown() = default; + +Kind Unknown::getKind() const { return Kind::Unknown; } + +const std::vector &Unknown::getOffset() const { return offset; } + +std::string Unknown::toString() const { + if (rawValue.empty()) { + if (rawOffset.empty()) { + return rawAnnotation; + } else { + return rawAnnotation + ":" + rawOffset; + } + } + return rawAnnotation + ":" + rawOffset + ":" + rawValue; +} + +bool Unknown::operator==(const Unknown &other) const { + return this->getKind() == other.getKind() && toString() == other.toString(); +} + +/* + * Format: {kind}:{offset}:{data} + * Example: InitNull:*[5]: + */ + +Deref::Deref(const std::string &str) : Unknown(str) {} + +Kind Deref::getKind() const { return Kind::Deref; } + +InitNull::InitNull(const std::string &str) : Unknown(str) {} + +Kind InitNull::getKind() const { return Kind::InitNull; } + +MaybeInitNull::MaybeInitNull(const std::string &str) : Unknown(str) {} + +Kind MaybeInitNull::getKind() const { return Kind::MaybeInitNull; } + +Alloc::Alloc(const std::string &str) : Unknown(str) { + if (!std::all_of(rawValue.begin(), rawValue.end(), isdigit)) { + klee_error("Annotation: Incorrect value format \"%s\"", rawValue.c_str()); + } + if (!rawValue.empty()) { + value = static_cast(std::stoi(rawValue)); + } +} + +Kind Alloc::getKind() const { return Kind::AllocSource; } + +Free::Free(const std::string &str) : Unknown(str) { + if (!std::all_of(rawValue.begin(), rawValue.end(), isdigit)) { + klee_error("Annotation: Incorrect value format \"%s\"", rawValue.c_str()); + } + if (!rawValue.empty()) { + value = static_cast(std::stoi(rawValue)); + } +} + +Kind Free::getKind() const { return Kind::Free; } + +const std::map StringToKindMap = { + {"deref", Statement::Kind::Deref}, + {"initnull", Statement::Kind::InitNull}, + {"maybeinitnull", Statement::Kind::MaybeInitNull}, + {"allocsource", Statement::Kind::AllocSource}, + {"freesource", Statement::Kind::Free}, + {"freesink", Statement::Kind::Free}}; + +inline Statement::Kind stringToKind(const std::string &str) { + auto it = StringToKindMap.find(toLower(str)); + if (it != StringToKindMap.end()) { + return it->second; + } + return Statement::Kind::Unknown; +} + +Ptr stringToKindPtr(const std::string &str) { + std::string statementStr = toLower(str.substr(0, str.find(':'))); + switch (stringToKind(statementStr)) { + case Statement::Kind::Unknown: + return std::make_shared(str); + case Statement::Kind::Deref: + return std::make_shared(str); + case Statement::Kind::InitNull: + return std::make_shared(str); + case Statement::Kind::MaybeInitNull: + return std::make_shared(str); + case Statement::Kind::AllocSource: + return std::make_shared(str); + case Statement::Kind::Free: + return std::make_shared(str); + } +} + +const std::map StringToPropertyMap{ + {"deterministic", Property::Deterministic}, + {"noreturn", Property::Noreturn}, +}; + +inline Property stringToProperty(const std::string &str) { + auto it = StringToPropertyMap.find(toLower(str)); + if (it != StringToPropertyMap.end()) { + return it->second; + } + return Property::Unknown; +} + +void from_json(const json &j, Ptr &statement) { + if (!j.is_string()) { + klee_error("Annotation: Incorrect statement format"); + } + const std::string jStr = j.get(); + statement = Statement::stringToKindPtr(jStr); +} + +void from_json(const json &j, Property &property) { + if (!j.is_string()) { + klee_error("Annotation: Incorrect properties format"); + } + const std::string jStr = j.get(); + + property = Statement::Property::Unknown; + const auto propertyPtr = Statement::StringToPropertyMap.find(jStr); + if (propertyPtr != Statement::StringToPropertyMap.end()) { + property = propertyPtr->second; + } +} + +bool operator==(const Statement::Ptr &first, const Statement::Ptr &second) { + if (first->getKind() != second->getKind()) { + return false; + } + + return *first.get() == *second.get(); +} +} // namespace Statement + +bool Annotation::operator==(const Annotation &other) const { + return (functionName == other.functionName) && + (returnStatements == other.returnStatements) && + (argsStatements == other.argsStatements) && + (properties == other.properties); +} + +AnnotationsMap parseAnnotationsJson(const json &annotationsJson) { + AnnotationsMap annotations; + for (auto &item : annotationsJson.items()) { + Annotation annotation; + annotation.functionName = item.key(); + + const json &j = item.value(); + if (!j.is_object() || !j.contains("annotation") || + !j.contains("properties")) { + klee_error("Annotation: Incorrect file format"); + } + { + std::vector> allStatements = + j.at("annotation").get>>(); + + if (allStatements.empty()) { + klee_error("Annotation: function \"%s\" should has return", + annotation.functionName.c_str()); + } + annotation.returnStatements = allStatements[0]; + if (std::any_of(allStatements.begin() + 1, allStatements.end(), + [](const std::vector &statements) { + return std::any_of( + statements.begin(), statements.end(), + [](const Statement::Ptr &statement) { + return statement->getKind() == + Statement::Kind::MaybeInitNull; + }); + })) { + klee_error("Annotation: MaybeInitNull can annotate only return value"); + } + annotation.argsStatements = std::vector>( + allStatements.begin() + 1, allStatements.end()); + } + + annotation.properties = + j.at("properties").get>(); + annotations[item.key()] = annotation; + } + return annotations; +} + +AnnotationsMap parseAnnotations(const std::string &path) { + if (path.empty()) { + return {}; + } + std::ifstream annotationsFile(path); + if (!annotationsFile.good()) { + klee_error("Annotation: Opening %s failed.", path.c_str()); + } + json annotationsJson = json::parse(annotationsFile, nullptr, false); + if (annotationsJson.is_discarded()) { + klee_error("Annotation: Parsing JSON %s failed.", path.c_str()); + } + + return parseAnnotationsJson(annotationsJson); +} + +} // namespace klee diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index 81112acbe0..d185f53a72 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -7,16 +7,19 @@ # #===------------------------------------------------------------------------===# set(KLEE_MODULE_COMPONENT_SRCS + Annotation.cpp CallSplitter.cpp + CallRemover.cpp Checks.cpp CodeGraphInfo.cpp FunctionAlias.cpp - InstructionInfoTable.cpp + LocationInfo.cpp InstructionOperandTypeCheckPass.cpp IntrinsicCleaner.cpp KInstruction.cpp KModule.cpp KType.cpp + KValue.cpp LowerSwitch.cpp ModuleUtil.cpp Optimize.cpp diff --git a/lib/Module/CallRemover.cpp b/lib/Module/CallRemover.cpp new file mode 100644 index 0000000000..7c94f6d26e --- /dev/null +++ b/lib/Module/CallRemover.cpp @@ -0,0 +1,37 @@ +//===-- CallRemover.cpp----------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Passes.h" +#include + +namespace klee { + +using namespace llvm; + +char CallRemover::ID; + +bool CallRemover::runOnModule(llvm::Module &M) { + std::vector badFuncs = {"llvm.dbg.declare", "llvm.dbg.label", + "llvm.dbg.value"}; + + for (const auto &f : badFuncs) { + auto Declare = M.getFunction(f); + if (!Declare) + continue; + while (!Declare->use_empty()) { + auto CI = cast(Declare->user_back()); + assert(CI->use_empty() && "deleted function must have void result"); + CI->eraseFromParent(); + } + Declare->eraseFromParent(); + } + + return true; +} +} // namespace klee diff --git a/lib/Module/CallSplitter.cpp b/lib/Module/CallSplitter.cpp index 4c4a71c4f3..a90e17516d 100644 --- a/lib/Module/CallSplitter.cpp +++ b/lib/Module/CallSplitter.cpp @@ -1,5 +1,4 @@ -//===-- CallSplitter.cpp -//-------------------------------------------------------===// +//===-- CallSplitter.cpp --------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -46,8 +45,9 @@ bool CallSplitter::runOnFunction(Function &F) { if (callInst != firstInst) { fbb = fbb->splitBasicBlock(callInst); } - if (isa(afterCallInst) && - cast(afterCallInst)->isUnconditional()) { + if ((isa(afterCallInst) && + cast(afterCallInst)->isUnconditional()) || + isa(afterCallInst)) { break; } fbb = fbb->splitBasicBlock(afterCallInst); diff --git a/lib/Module/CodeGraphInfo.cpp b/lib/Module/CodeGraphInfo.cpp index 045c379932..4823460b87 100644 --- a/lib/Module/CodeGraphInfo.cpp +++ b/lib/Module/CodeGraphInfo.cpp @@ -20,43 +20,47 @@ DISABLE_WARNING_POP using namespace klee; -void CodeGraphInfo::calculateDistance(KBlock *bb) { - auto blockMap = bb->parent->blockMap; - std::unordered_map &dist = blockDistance[bb]; - std::vector> &sort = blockSortedDistance[bb]; - std::deque nodes; +void CodeGraphInfo::calculateDistance(Block *bb) { + auto &dist = blockDistance[bb]; + auto &sort = blockSortedDistance[bb]; + std::deque nodes; nodes.push_back(bb); dist[bb] = 0; sort.push_back({bb, 0}); - while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - for (auto const &succ : successors(currBB->basicBlock)) { - if (dist.count(blockMap[succ]) == 0) { - dist[blockMap[succ]] = dist[currBB] + 1; - sort.push_back({blockMap[succ], dist[currBB] + 1}); - nodes.push_back(blockMap[succ]); + bool hasCycle = false; + for (; !nodes.empty(); nodes.pop_front()) { + auto currBB = nodes.front(); + for (auto succ : successors(currBB)) { + if (succ == bb) { + hasCycle = true; + continue; } + if (dist.count(succ)) + continue; + auto d = dist[currBB] + 1; + dist.emplace(succ, d); + sort.push_back({succ, d}); + nodes.push_back(succ); } - nodes.pop_front(); } + if (hasCycle) + blockCycles.insert(bb); } -void CodeGraphInfo::calculateBackwardDistance(KBlock *bb) { - auto blockMap = bb->parent->blockMap; - std::unordered_map &bdist = blockBackwardDistance[bb]; - std::vector> &bsort = - blockSortedBackwardDistance[bb]; - std::deque nodes; +void CodeGraphInfo::calculateBackwardDistance(Block *bb) { + auto &bdist = blockBackwardDistance[bb]; + auto &bsort = blockSortedBackwardDistance[bb]; + std::deque nodes; nodes.push_back(bb); bdist[bb] = 0; bsort.push_back({bb, 0}); while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - for (auto const &pred : predecessors(currBB->basicBlock)) { - if (bdist.count(blockMap[pred]) == 0) { - bdist[blockMap[pred]] = bdist[currBB] + 1; - bsort.push_back({blockMap[pred], bdist[currBB] + 1}); - nodes.push_back(blockMap[pred]); + auto currBB = nodes.front(); + for (auto const &pred : predecessors(currBB)) { + if (bdist.count(pred) == 0) { + bdist[pred] = bdist[currBB] + 1; + bsort.push_back({pred, bdist[currBB] + 1}); + nodes.push_back(pred); } } nodes.pop_front(); @@ -64,25 +68,25 @@ void CodeGraphInfo::calculateBackwardDistance(KBlock *bb) { } void CodeGraphInfo::calculateDistance(KFunction *kf) { + auto f = kf->function(); auto &functionMap = kf->parent->functionMap; - std::unordered_map &dist = functionDistance[kf]; - std::vector> &sort = - functionSortedDistance[kf]; + auto &dist = functionDistance[f]; + auto &sort = functionSortedDistance[f]; std::deque nodes; nodes.push_back(kf); - dist[kf] = 0; - sort.push_back({kf, 0}); + dist[f] = 0; + sort.push_back({f, 0}); while (!nodes.empty()) { - KFunction *currKF = nodes.front(); - for (auto &callBlock : currKF->kCallBlocks) { - for (auto &calledFunction : callBlock->calledFunctions) { - if (!calledFunction || calledFunction->isDeclaration()) { + auto currKF = nodes.front(); + for (auto callBlock : currKF->kCallBlocks) { + for (auto calledFunction : callBlock->calledFunctions) { + if (!calledFunction || calledFunction->isDeclaration()) continue; - } - KFunction *callKF = functionMap[calledFunction]; - if (dist.count(callKF) == 0) { - dist[callKF] = dist[currKF] + 1; - sort.push_back({callKF, dist[currKF] + 1}); + if (dist.count(calledFunction) == 0) { + auto d = dist[currKF->function()] + 1; + dist[calledFunction] = d; + sort.emplace_back(calledFunction, d); + auto callKF = functionMap[calledFunction]; nodes.push_back(callKF); } } @@ -92,30 +96,26 @@ void CodeGraphInfo::calculateDistance(KFunction *kf) { } void CodeGraphInfo::calculateBackwardDistance(KFunction *kf) { - auto &functionMap = kf->parent->functionMap; + auto f = kf->function(); auto &callMap = kf->parent->callMap; - std::unordered_map &bdist = - functionBackwardDistance[kf]; - std::vector> &bsort = - functionSortedBackwardDistance[kf]; - std::deque nodes; - nodes.push_back(kf); - bdist[kf] = 0; - bsort.push_back({kf, 0}); - while (!nodes.empty()) { - KFunction *currKF = nodes.front(); - for (auto &cf : callMap[currKF->function]) { - if (cf->isDeclaration()) { + auto &bdist = functionBackwardDistance[f]; + auto &bsort = functionSortedBackwardDistance[f]; + std::deque nodes = {f}; + bdist[f] = 0; + bsort.emplace_back(f, 0); + for (; !nodes.empty(); nodes.pop_front()) { + auto currKF = nodes.front(); + for (auto cf : callMap[currKF]) { + if (cf->isDeclaration()) continue; - } - KFunction *callKF = functionMap[cf]; - if (bdist.count(callKF) == 0) { - bdist[callKF] = bdist[currKF] + 1; - bsort.push_back({callKF, bdist[currKF] + 1}); - nodes.push_back(callKF); + auto it = bdist.find(cf); + if (it == bdist.end()) { + auto d = bdist[currKF] + 1; + bdist.emplace_hint(it, cf, d); + bsort.emplace_back(cf, d); + nodes.push_back(cf); } } - nodes.pop_front(); } } @@ -124,67 +124,68 @@ void CodeGraphInfo::calculateFunctionBranches(KFunction *kf) { for (auto &kb : kf->blocks) { fbranches[kb.get()]; for (unsigned branch = 0; - branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + branch < kb->basicBlock()->getTerminator()->getNumSuccessors(); ++branch) { fbranches[kb.get()].insert(branch); } } } - -const std::unordered_map & -CodeGraphInfo::getDistance(KBlock *kb) { - if (blockDistance.count(kb) == 0) - calculateDistance(kb); - return blockDistance.at(kb); +void CodeGraphInfo::calculateFunctionConditionalBranches(KFunction *kf) { + std::map> &fbranches = + functionConditionalBranches[kf]; + for (auto &kb : kf->blocks) { + if (kb->basicBlock()->getTerminator()->getNumSuccessors() > 1) { + fbranches[kb.get()]; + for (unsigned branch = 0; + branch < kb->basicBlock()->getTerminator()->getNumSuccessors(); + ++branch) { + fbranches[kb.get()].insert(branch); + } + } + } } - -const std::unordered_map & -CodeGraphInfo::getBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb) == 0) - calculateBackwardDistance(kb); - return blockBackwardDistance.at(kb); +void CodeGraphInfo::calculateFunctionBlocks(KFunction *kf) { + std::map> &fbranches = functionBlocks[kf]; + for (auto &kb : kf->blocks) { + fbranches[kb.get()]; + } } -const std::vector> & -CodeGraphInfo::getSortedDistance(KBlock *kb) { - if (blockDistance.count(kb) == 0) - calculateDistance(kb); - return blockSortedDistance.at(kb); +const BlockDistanceMap &CodeGraphInfo::getDistance(Block *b) { + if (blockDistance.count(b) == 0) + calculateDistance(b); + return blockDistance.at(b); } -const std::vector> & -CodeGraphInfo::getSortedBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb) == 0) - calculateBackwardDistance(kb); - return blockSortedBackwardDistance.at(kb); +bool CodeGraphInfo::hasCycle(KBlock *kb) { + auto b = kb->basicBlock(); + if (!blockDistance.count(b)) + calculateDistance(b); + return blockCycles.count(b); } -const std::unordered_map & -CodeGraphInfo::getDistance(KFunction *kf) { - if (functionDistance.count(kf) == 0) - calculateDistance(kf); - return functionDistance.at(kf); +const BlockDistanceMap &CodeGraphInfo::getDistance(KBlock *kb) { + return getDistance(kb->basicBlock()); } -const std::unordered_map & -CodeGraphInfo::getBackwardDistance(KFunction *kf) { - if (functionBackwardDistance.count(kf) == 0) - calculateBackwardDistance(kf); - return functionBackwardDistance.at(kf); +const BlockDistanceMap &CodeGraphInfo::getBackwardDistance(KBlock *kb) { + if (blockBackwardDistance.count(kb->basicBlock()) == 0) + calculateBackwardDistance(kb->basicBlock()); + return blockBackwardDistance.at(kb->basicBlock()); } -const std::vector> & -CodeGraphInfo::getSortedDistance(KFunction *kf) { - if (functionDistance.count(kf) == 0) +const FunctionDistanceMap &CodeGraphInfo::getDistance(KFunction *kf) { + auto f = kf->function(); + if (functionDistance.count(f) == 0) calculateDistance(kf); - return functionSortedDistance.at(kf); + return functionDistance.at(f); } -const std::vector> & -CodeGraphInfo::getSortedBackwardDistance(KFunction *kf) { - if (functionBackwardDistance.count(kf) == 0) +const FunctionDistanceMap &CodeGraphInfo::getBackwardDistance(KFunction *kf) { + auto f = kf->function(); + if (functionBackwardDistance.count(f) == 0) calculateBackwardDistance(kf); - return functionSortedBackwardDistance.at(kf); + return functionBackwardDistance.at(f); } void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, @@ -203,7 +204,7 @@ void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, if (predicate(currBB) && currBB != from) { result.insert(currBB); } else { - for (auto const &succ : successors(currBB->basicBlock)) { + for (auto succ : successors(currBB->basicBlock())) { if (visited.count(blockMap[succ]) == 0) { nodes.push_back(blockMap[succ]); } @@ -219,3 +220,17 @@ CodeGraphInfo::getFunctionBranches(KFunction *kf) { calculateFunctionBranches(kf); return functionBranches.at(kf); } + +const std::map> & +CodeGraphInfo::getFunctionConditionalBranches(KFunction *kf) { + if (functionConditionalBranches.count(kf) == 0) + calculateFunctionConditionalBranches(kf); + return functionConditionalBranches.at(kf); +} + +const std::map> & +CodeGraphInfo::getFunctionBlocks(KFunction *kf) { + if (functionBlocks.count(kf) == 0) + calculateFunctionBlocks(kf); + return functionBlocks.at(kf); +} diff --git a/lib/Module/InstructionInfoTable.cpp b/lib/Module/InstructionInfoTable.cpp deleted file mode 100644 index ee66e91cbf..0000000000 --- a/lib/Module/InstructionInfoTable.cpp +++ /dev/null @@ -1,230 +0,0 @@ -//===-- InstructionInfoTable.cpp ------------------------------------------===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "klee/Module/InstructionInfoTable.h" -#include "klee/Config/Version.h" - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/AssemblyAnnotationWriter.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -DISABLE_WARNING_POP - -#include -#include -#include - -using namespace klee; - -class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { -private: - std::unordered_map mapping = {}; - -public: - void emitInstructionAnnot(const llvm::Instruction *i, - llvm::formatted_raw_ostream &os) override { - os.flush(); - mapping.emplace(reinterpret_cast(i), os.getLine() + 1); - } - - void emitFunctionAnnot(const llvm::Function *f, - llvm::formatted_raw_ostream &os) override { - os.flush(); - mapping.emplace(reinterpret_cast(f), os.getLine() + 1); - } - - std::unordered_map getMapping() const { return mapping; } -}; - -static std::unordered_map -buildInstructionToLineMap(const llvm::Module &m, - std::unique_ptr assemblyFS) { - - InstructionToLineAnnotator a; - - m.print(*assemblyFS, &a); - assemblyFS->flush(); - - return a.getMapping(); -} - -class DebugInfoExtractor { - std::vector> &internedStrings; - std::unordered_map lineTable; - - const llvm::Module &module; - bool withAsm = false; - -public: - DebugInfoExtractor( - std::vector> &_internedStrings, - const llvm::Module &_module, - std::unique_ptr assemblyFS) - : internedStrings(_internedStrings), module(_module) { - if (assemblyFS) { - withAsm = true; - lineTable = buildInstructionToLineMap(module, std::move(assemblyFS)); - } - } - - std::string &getInternedString(const std::string &s) { - auto found = std::find_if(internedStrings.begin(), internedStrings.end(), - [&s](const std::unique_ptr &item) { - return *item.get() == s; - }); - if (found != internedStrings.end()) - return *found->get(); - - auto newItem = std::unique_ptr(new std::string(s)); - auto result = newItem.get(); - - internedStrings.emplace_back(std::move(newItem)); - return *result; - } - - std::unique_ptr getFunctionInfo(const llvm::Function &Func) { - llvm::Optional asmLine; - if (withAsm) { - asmLine = lineTable.at(reinterpret_cast(&Func)); - } - auto dsub = Func.getSubprogram(); - - if (dsub != nullptr) { - auto path = dsub->getFilename(); - return std::make_unique(FunctionInfo( - 0, getInternedString(path.str()), dsub->getLine(), asmLine)); - } - - // Fallback: Mark as unknown - return std::make_unique( - FunctionInfo(0, getInternedString(""), 0, asmLine)); - } - - std::unique_ptr - getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo *f) { - llvm::Optional asmLine; - if (withAsm) { - asmLine = lineTable.at(reinterpret_cast(&Inst)); - } - - // Retrieve debug information associated with instruction - auto dl = Inst.getDebugLoc(); - - // Check if a valid debug location is assigned to the instruction. - if (dl.get() != nullptr) { - auto full_path = dl.get()->getFilename(); - auto line = dl.getLine(); - auto column = dl.getCol(); - - // Still, if the line is unknown, take the context of the instruction to - // narrow it down - if (line == 0) { - if (auto LexicalBlock = - llvm::dyn_cast(dl.getScope())) { - line = LexicalBlock->getLine(); - column = LexicalBlock->getColumn(); - } - } - return std::make_unique(InstructionInfo( - 0, getInternedString(full_path.str()), line, column, asmLine)); - } - - if (f != nullptr) - // If nothing found, use the surrounding function - return std::make_unique( - InstructionInfo(0, f->file, f->line, 0, asmLine)); - // If nothing found, use the surrounding function - return std::make_unique( - InstructionInfo(0, getInternedString(""), 0, 0, asmLine)); - } -}; - -InstructionInfoTable::InstructionInfoTable( - const llvm::Module &m, std::unique_ptr assemblyFS, - bool withInstructions) { - // Generate all debug instruction information - DebugInfoExtractor DI(internedStrings, m, std::move(assemblyFS)); - - for (const auto &Func : m) { - auto F = DI.getFunctionInfo(Func); - auto FR = F.get(); - functionInfos.emplace(&Func, std::move(F)); - - for (auto it = llvm::inst_begin(Func), ie = llvm::inst_end(Func); it != ie; - ++it) { - auto instr = &*it; - auto instInfo = DI.getInstructionInfo(*instr, FR); - if (withInstructions) { - insts[instInfo->file][instInfo->line][instInfo->column].insert( - instr->getOpcode()); - } - filesNames.insert(instInfo->file); - fileNameToFunctions[instInfo->file].insert(&Func); - infos.emplace(instr, std::move(instInfo)); - } - } - - // Make sure that every item has a unique ID - size_t idCounter = 0; - for (auto &item : infos) - item.second->id = idCounter++; - for (auto &item : functionInfos) - item.second->id = idCounter++; -} - -unsigned InstructionInfoTable::getMaxID() const { - return infos.size() + functionInfos.size(); -} - -const InstructionInfo & -InstructionInfoTable::getInfo(const llvm::Instruction &inst) const { - auto it = infos.find(&inst); - if (it == infos.end()) - llvm::report_fatal_error("invalid instruction, not present in " - "initial module!"); - return *it->second.get(); -} - -const FunctionInfo & -InstructionInfoTable::getFunctionInfo(const llvm::Function &f) const { - auto found = functionInfos.find(&f); - if (found == functionInfos.end()) - llvm::report_fatal_error("invalid instruction, not present in " - "initial module!"); - - return *found->second.get(); -} - -const InstructionInfoTable::LocationToFunctionsMap & -InstructionInfoTable::getFileNameToFunctions() const { - return fileNameToFunctions; -} - -const std::unordered_set & -InstructionInfoTable::getFilesNames() const { - return filesNames; -} - -InstructionInfoTable::Instructions InstructionInfoTable::getInstructions() { - return std::move(insts); -} diff --git a/lib/Module/KInstruction.cpp b/lib/Module/KInstruction.cpp index f7159c4bd6..97f9002385 100644 --- a/lib/Module/KInstruction.cpp +++ b/lib/Module/KInstruction.cpp @@ -9,11 +9,15 @@ #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/StringExtras.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include +#include DISABLE_WARNING_POP #include @@ -23,17 +27,96 @@ using namespace klee; /***/ +static int getOperandNum( + Value *v, + const std::unordered_map &instructionToRegisterMap, + KModule *km, KInstruction *ki) { + if (Instruction *inst = dyn_cast(v)) { + return instructionToRegisterMap.at(inst); + } else if (Argument *a = dyn_cast(v)) { + return a->getArgNo(); + } else if (isa(v) || isa(v) || + isa(v)) { + return -1; + } else { + assert(isa(v)); + Constant *c = cast(v); + return -(km->getConstantID(c, ki) + 2); + } +} + +KInstruction::KInstruction( + const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc) + : KValue(_inst, KValue::Kind::INSTRUCTION), parent(_kb), + globalIndex(_globalIndexInc++) { + if (isa(inst()) || isa(inst())) { + const llvm::CallBase &cs = cast(*inst()); + Value *val = cs.getCalledOperand(); + unsigned numArgs = cs.arg_size(); + operands = new int[numArgs + 1]; + operands[0] = getOperandNum(val, _instructionToRegisterMap, _km, this); + for (unsigned j = 0; j < numArgs; j++) { + Value *v = cs.getArgOperand(j); + operands[j + 1] = getOperandNum(v, _instructionToRegisterMap, _km, this); + } + } else { + unsigned numOperands = inst()->getNumOperands(); + operands = new int[numOperands]; + for (unsigned j = 0; j < numOperands; j++) { + Value *v = inst()->getOperand(j); + operands[j] = getOperandNum(v, _instructionToRegisterMap, _km, this); + } + } +} + KInstruction::~KInstruction() { delete[] operands; } -std::string KInstruction::getSourceLocation() const { - if (!info->file.empty()) - return info->file + ":" + std::to_string(info->line) + " " + - std::to_string(info->column); - else +size_t KInstruction::getLine() const { + auto locationInfo = getLocationInfo(inst()); + return locationInfo.line; +} + +size_t KInstruction::getColumn() const { + auto locationInfo = getLocationInfo(inst()); + return locationInfo.column; +} + +std::string KInstruction::getSourceFilepath() const { + auto locationInfo = getLocationInfo(inst()); + return locationInfo.file; +} + +std::string KInstruction::getSourceLocationString() const { + std::string filePath = getSourceFilepath(); + if (!filePath.empty()) { + // TODO change format to file:line:column + return filePath + ":" + std::to_string(getLine()) + " " + + std::to_string(getColumn()); + } else { return "[no debug info]"; + } } std::string KInstruction::toString() const { - return llvm::utostr(index) + " at " + parent->toString() + " (" + - inst->getOpcodeName() + ")"; + return llvm::utostr(getIndex()) + " at " + parent->toString() + " (" + + inst()->getOpcodeName() + ")"; +} + +unsigned KInstruction::getGlobalIndex() const { return globalIndex; } + +unsigned KInstruction::getIndex() const { + return getGlobalIndex() - getKFunction()->getGlobalIndex() - + getKBlock()->getId() - 1; +} + +unsigned KInstruction::getDest() const { + return parent->parent->getNumArgs() + getIndex() + + (parent->instructions - parent->parent->instructions); +} + +KInstruction::Index KInstruction::getID() const { + return {getGlobalIndex(), parent->getId(), parent->parent->id}; } diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 2ab1059a8f..f7ce474bdb 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -14,9 +14,9 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" #include "klee/Module/Cell.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/Debug.h" #include "klee/Support/ErrorHandling.h" #include "klee/Support/ModuleUtil.h" @@ -26,6 +26,7 @@ DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -37,6 +38,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/raw_ostream.h" @@ -46,7 +48,9 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Transforms/Utils/Cloning.h" DISABLE_WARNING_POP +#include #include +#include using namespace llvm; using namespace klee; @@ -113,6 +117,11 @@ cl::opt cl::desc("Split each call in own basic block (default=true)"), cl::init(true), cl::cat(klee::ModuleCat)); +static cl::opt + StripUnwantedCalls("strip-unwanted-calls", + cl::desc("Strip all unwanted calls (llvm.dbg.* stuff)"), + cl::init(false), cl::cat(klee::ModuleCat)); + cl::opt SplitReturns( "split-returns", cl::desc("Split each return in own basic block (default=true)"), @@ -226,19 +235,6 @@ bool KModule::link(std::vector> &modules, return true; } -void KModule::replaceFunction(const std::unique_ptr &m, - const char *original, const char *replacement) { - llvm::Function *originalFunc = m->getFunction(original); - llvm::Function *replacementFunc = m->getFunction(replacement); - if (!originalFunc) - return; - klee_message("Replacing function \"%s\" with \"%s\"", original, replacement); - assert(replacementFunc && "Replacement function not found"); - assert(!(replacementFunc->isDeclaration()) && "replacement must have body"); - originalFunc->replaceAllUsesWith(replacementFunc); - originalFunc->eraseFromParent(); -} - void KModule::instrument(const Interpreter::ModuleOptions &opts) { // Inject checks prior to optimization... we also perform the // invariant transformations that we will end up doing later so that @@ -292,12 +288,10 @@ void KModule::optimiseAndPrepare( if (opts.WithFPRuntime) { if (UseKleeFloatInternals) { for (const auto &p : klee::floatReplacements) { - replaceFunction(module, p.first.c_str(), p.second.c_str()); + replaceOrRenameFunction(module.get(), p.first.c_str(), + p.second.c_str()); } } - for (const auto &p : klee::feRoundReplacements) { - replaceFunction(module, p.first.c_str(), p.second.c_str()); - } } // Needs to happen after linking (since ctors/dtors can be modified) @@ -328,6 +322,8 @@ void KModule::optimiseAndPrepare( pm3.add(createScalarizerPass()); pm3.add(new PhiCleanerPass()); pm3.add(new FunctionAliasPass()); + if (StripUnwantedCalls) + pm3.add(new CallRemover()); if (SplitCalls) { pm3.add(new CallSplitter()); } @@ -337,6 +333,38 @@ void KModule::optimiseAndPrepare( pm3.run(*module); } +class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { +private: + std::unordered_map mapping = {}; + +public: + void emitInstructionAnnot(const llvm::Instruction *i, + llvm::formatted_raw_ostream &os) override { + os.flush(); + mapping.emplace(reinterpret_cast(i), os.getLine() + 1); + } + + void emitFunctionAnnot(const llvm::Function *f, + llvm::formatted_raw_ostream &os) override { + os.flush(); + mapping.emplace(reinterpret_cast(f), os.getLine() + 1); + } + + std::unordered_map getMapping() const { return mapping; } +}; + +static std::unordered_map +buildInstructionToLineMap(const llvm::Module &m, + std::unique_ptr assemblyFS) { + + InstructionToLineAnnotator a; + + m.print(*assemblyFS, &a); + assemblyFS->flush(); + + return a.getMapping(); +} + void KModule::manifest(InterpreterHandler *ih, Interpreter::GuidanceKind guidance, bool forceSourceOutput) { @@ -351,32 +379,21 @@ void KModule::manifest(InterpreterHandler *ih, std::unique_ptr assemblyFS; if (OutputSource || forceSourceOutput) { assemblyFS = ih->openOutputFile("assembly.ll"); + asmLineMap = buildInstructionToLineMap(*module, std::move(assemblyFS)); } - infos = - std::make_unique(*module, std::move(assemblyFS)); } std::vector declarations; unsigned functionID = 0; + maxGlobalIndex = 0; for (auto &Function : module->functions()) { if (Function.isDeclaration()) { declarations.push_back(&Function); } - auto kf = std::unique_ptr(new KFunction(&Function, this)); + auto kf = std::make_unique(&Function, this, maxGlobalIndex); - llvm::Function *function = &Function; - for (auto &BasicBlock : *function) { - unsigned numInstructions = kf->blockMap[&BasicBlock]->numInstructions; - KBlock *kb = kf->blockMap[&BasicBlock]; - for (unsigned i = 0; i < numInstructions; ++i) { - KInstruction *ki = kb->instructions[i]; - ki->info = &infos->getInfo(*ki->inst); - } - } - - functionIDMap.insert({&Function, functionID}); kf->id = functionID; functionID++; functionNameMap.insert({kf->getName().str(), kf.get()}); @@ -384,11 +401,17 @@ void KModule::manifest(InterpreterHandler *ih, functions.push_back(std::move(kf)); } + unsigned globalID = 0; + for (auto &global : module->globals()) { + globalMap.emplace(&global, new KGlobalVariable(&global, globalID++)); + } + /* Compute various interesting properties */ for (auto &kf : functions) { - if (functionEscapes(kf->function)) - escapingFunctions.insert(kf->function); + if (functionEscapes(kf->function())) { + escapingFunctions.insert(kf->function()); + } } for (auto &declaration : declarations) { @@ -397,20 +420,20 @@ void KModule::manifest(InterpreterHandler *ih, } for (auto &kfp : functions) { - for (auto kcb : kfp.get()->kCallBlocks) { + for (auto kcb : kfp->kCallBlocks) { bool isInlineAsm = false; - const CallBase &cs = cast(*kcb->kcallInstruction->inst); + const CallBase &cs = cast(*kcb->kcallInstruction->inst()); if (isa(cs.getCalledOperand())) { isInlineAsm = true; } if (kcb->calledFunctions.empty() && !isInlineAsm && (guidance != Interpreter::GuidanceKind::ErrorGuidance || - !inMainModule(*kfp.get()->function))) { + !inMainModule(*kfp->function()))) { kcb->calledFunctions.insert(escapingFunctions.begin(), escapingFunctions.end()); } - for (auto &calledFunction : kcb->calledFunctions) { - callMap[calledFunction].insert(kfp.get()->function); + for (auto calledFunction : kcb->calledFunctions) { + callMap[calledFunction].insert(kfp->function()); } } } @@ -426,6 +449,19 @@ void KModule::manifest(InterpreterHandler *ih, } } +std::optional KModule::getAsmLine(const uintptr_t ref) const { + if (!asmLineMap.empty()) { + return asmLineMap.at(ref); + } + return std::nullopt; +} +std::optional KModule::getAsmLine(const llvm::Function *func) const { + return getAsmLine(reinterpret_cast(func)); +} +std::optional KModule::getAsmLine(const llvm::Instruction *inst) const { + return getAsmLine(reinterpret_cast(inst)); +} + void KModule::checkModule() { InstructionOperandTypeCheckPass *operandTypeCheckPass = new InstructionOperandTypeCheckPass(); @@ -444,7 +480,7 @@ void KModule::checkModule() { } } -KBlock *KModule::getKBlock(llvm::BasicBlock *bb) { +KBlock *KModule::getKBlock(const llvm::BasicBlock *bb) { return functionMap[bb->getParent()]->blockMap[bb]; } @@ -502,86 +538,75 @@ unsigned KModule::getConstantID(Constant *c, KInstruction *ki) { return id; } +unsigned KModule::getFunctionId(const llvm::Function *func) const { + return functionMap.at(func)->id; +} +unsigned KModule::getGlobalIndex(const llvm::Function *func) const { + return functionMap.at(func)->getGlobalIndex(); +} +unsigned KModule::getGlobalIndex(const llvm::Instruction *inst) const { + return functionMap.at(inst->getFunction()) + ->instructionMap.at(inst) + ->getGlobalIndex(); +} + /***/ -KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) { - ct = _ct; +KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) + : KValue(_ct, Kind::CONSTANT) { id = _id; ki = _ki; } -/***/ +bool KConstant::operator<(const KValue &rhs) const { + return getKind() == rhs.getKind() ? id < cast(rhs).id + : getKind() < rhs.getKind(); +} -static int getOperandNum( - Value *v, - std::unordered_map &instructionToRegisterMap, - KModule *km, KInstruction *ki) { - if (Instruction *inst = dyn_cast(v)) { - return instructionToRegisterMap[inst]; - } else if (Argument *a = dyn_cast(v)) { - return a->getArgNo(); - } else if (isa(v) || isa(v) || - isa(v)) { - return -1; - } else { - assert(isa(v)); - Constant *c = cast(v); - return -(km->getConstantID(c, ki) + 2); - } +unsigned KConstant::hash() const { return id; } + +KGlobalVariable::KGlobalVariable(llvm::GlobalVariable *global, unsigned id) + : KValue(global, KValue::Kind::GLOBAL_VARIABLE), id(id) {} + +std::string KGlobalVariable::getSourceFilepath() const { + return getLocationInfo(globalVariable()).file; +} +// Line number where the global variable is defined +size_t KGlobalVariable::getLine() const { + return getLocationInfo(globalVariable()).line; } -void KBlock::handleKInstruction( - std::unordered_map &instructionToRegisterMap, - llvm::Instruction *inst, KModule *km, KInstruction *ki) { - ki->parent = this; - ki->inst = inst; - ki->dest = instructionToRegisterMap[inst]; - if (isa(inst) || isa(inst)) { - const CallBase &cs = cast(*inst); - Value *val = cs.getCalledOperand(); - unsigned numArgs = cs.arg_size(); - ki->operands = new int[numArgs + 1]; - ki->operands[0] = getOperandNum(val, instructionToRegisterMap, km, ki); - for (unsigned j = 0; j < numArgs; j++) { - Value *v = cs.getArgOperand(j); - ki->operands[j + 1] = getOperandNum(v, instructionToRegisterMap, km, ki); - } - } else { - unsigned numOperands = inst->getNumOperands(); - ki->operands = new int[numOperands]; - for (unsigned j = 0; j < numOperands; j++) { - Value *v = inst->getOperand(j); - ki->operands[j] = getOperandNum(v, instructionToRegisterMap, km, ki); - } - } +bool KGlobalVariable::operator<(const KValue &rhs) const { + return getKind() == rhs.getKind() ? id < cast(rhs).id + : getKind() < rhs.getKind(); +} +unsigned KGlobalVariable::hash() const { + // It is good enough value to use it as hash as ID of globals + // different. + return id; } -KFunction::KFunction(llvm::Function *_function, KModule *_km) - : KCallable(CK_Function), parent(_km), function(_function), - numArgs(function->arg_size()), numInstructions(0), numBlocks(0), - entryKBlock(nullptr), trackCoverage(true) { - for (auto &BasicBlock : *function) { +KFunction::KFunction(llvm::Function *_function, KModule *_km, + unsigned &globalIndexInc) + : KCallable(_function, Kind::FUNCTION), globalIndex(globalIndexInc++), + parent(_km), entryKBlock(nullptr), numInstructions(0) { + for (auto &BasicBlock : *function()) { numInstructions += BasicBlock.size(); - numBlocks++; } instructions = new KInstruction *[numInstructions]; std::unordered_map instructionToRegisterMap; // Assign unique instruction IDs to each basic block unsigned n = 0; // The first arg_size() registers are reserved for formals. - unsigned rnum = numArgs; - for (llvm::Function::iterator bbit = function->begin(), - bbie = function->end(); - bbit != bbie; ++bbit) { - for (llvm::BasicBlock::iterator it = bbit->begin(), ie = bbit->end(); - it != ie; ++it) - instructionToRegisterMap[&*it] = rnum++; + unsigned rnum = getNumArgs(); + for (auto &bb : *function()) { + for (auto &instr : bb) { + instructionToRegisterMap[&instr] = rnum++; + } } - numRegisters = rnum; - unsigned blockID = 0; - for (llvm::Function::iterator bbit = function->begin(), - bbie = function->end(); + for (llvm::Function::iterator bbit = function()->begin(), + bbie = function()->end(); bbit != bbie; ++bbit) { KBlock *kb; Instruction *fit = &bbit->front(); @@ -594,32 +619,42 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km) if (f) { calledFunctions.insert(f); } - KCallBlock *ckb = new KCallBlock( - this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, calledFunctions, &instructions[n]); + auto *ckb = new KCallBlock(this, &*bbit, parent, instructionToRegisterMap, + std::move(calledFunctions), &instructions[n], + globalIndexInc); kCallBlocks.push_back(ckb); kb = ckb; } else if (SplitReturns && isa(lit)) { kb = new KReturnBlock(this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, &instructions[n]); + &instructions[n], globalIndexInc); returnKBlocks.push_back(kb); - } else - kb = new KBlock(this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, &instructions[n]); - for (unsigned i = 0; i < kb->numInstructions; i++, n++) { - instructionMap[instructions[n]->inst] = instructions[n]; + } else { + kb = new KBasicBlock(this, &*bbit, parent, instructionToRegisterMap, + &instructions[n], globalIndexInc); + } + for (unsigned i = 0, ie = kb->getNumInstructions(); i < ie; i++, n++) { + instructionMap[instructions[n]->inst()] = instructions[n]; } - kb->id = blockID++; blockMap[&*bbit] = kb; blocks.push_back(std::unique_ptr(kb)); } - if (numBlocks > 0) { - assert(function->begin() != function->end()); - entryKBlock = blockMap[&*function->begin()]; + if (blocks.size() > 0) { + assert(function()->begin() != function()->end()); + entryKBlock = blockMap[&*function()->begin()]; } } +size_t KFunction::getLine() const { + auto locationInfo = getLocationInfo(function()); + return locationInfo.line; +} + +std::string KFunction::getSourceFilepath() const { + auto locationInfo = getLocationInfo(function()); + return locationInfo.file; +} + KFunction::~KFunction() { for (unsigned i = 0; i < numInstructions; ++i) delete instructions[i]; @@ -628,47 +663,58 @@ KFunction::~KFunction() { KBlock::KBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - KInstruction **instructionsKF) - : parent(_kfunction), basicBlock(block), numInstructions(0), - trackCoverage(true) { - numInstructions += block->size(); + const std::unordered_map &instructionToRegisterMap, + KInstruction **instructionsKF, unsigned &globalIndexInc, + KBlockType blockType) + : KValue(block, KValue::Kind::BLOCK), blockKind(blockType), + parent(_kfunction) { instructions = instructionsKF; - unsigned i = 0; - for (llvm::BasicBlock::iterator it = block->begin(), ie = block->end(); - it != ie; ++it) { + for (auto &it : *block) { KInstruction *ki; - switch (it->getOpcode()) { + switch (it.getOpcode()) { case Instruction::GetElementPtr: case Instruction::InsertValue: case Instruction::ExtractValue: - ki = new KGEPInstruction(); + ki = new KGEPInstruction(instructionToRegisterMap, &it, km, this, + globalIndexInc); break; default: - ki = new KInstruction(); + ki = new KInstruction(instructionToRegisterMap, &it, km, this, + globalIndexInc); break; } - - Instruction *inst = &*it; - handleKInstruction(instructionToRegisterMap, inst, km, ki); - ki->index = i; - instructions[i++] = ki; - registerToInstructionMap[instructionToRegisterMap[&*it]] = ki; + instructions[ki->getIndex()] = ki; } } +unsigned KBlock::getGlobalIndex() const { + return getFirstInstruction()->getGlobalIndex(); +} + +bool KBlock::operator<(const KValue &rhs) const { + // Additional comparison on block types is redundant, + // as getGlobalIndex defines the position of block. + return getKind() == rhs.getKind() + ? getGlobalIndex() < cast(rhs).getGlobalIndex() + : getKind() < rhs.getKind(); +} + +unsigned KBlock::hash() const { + // Use position of a block as a hash + return getGlobalIndex(); +} + KCallBlock::KCallBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - std::set _calledFunctions, KInstruction **instructionsKF) + const std::unordered_map &instructionToRegisterMap, + std::set _calledFunctions, KInstruction **instructionsKF, + unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - registerToInstructionMap, instructionsKF), + instructionsKF, globalIndexInc, KBlockType::Call), kcallInstruction(this->instructions[0]), - calledFunctions(_calledFunctions) {} + calledFunctions(std::move(_calledFunctions)) {} bool KCallBlock::intrinsic() const { if (calledFunctions.size() != 1) { @@ -693,22 +739,53 @@ KFunction *KCallBlock::getKFunction() const { : nullptr; } +KBasicBlock::KBasicBlock(KFunction *_kfunction, llvm::BasicBlock *block, + KModule *km, + const std::unordered_map + &instructionToRegisterMap, + KInstruction **instructionsKF, + unsigned &globalIndexInc) + : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, + instructionsKF, globalIndexInc, KBlockType::Base) {} + KReturnBlock::KReturnBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - KInstruction **instructionsKF) + const std::unordered_map &instructionToRegisterMap, + KInstruction **instructionsKF, unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - registerToInstructionMap, instructionsKF) {} + instructionsKF, globalIndexInc, KBlockType::Return) {} std::string KBlock::getLabel() const { std::string _label; llvm::raw_string_ostream label_stream(_label); - basicBlock->printAsOperand(label_stream, false); + basicBlock()->printAsOperand(label_stream, false); std::string label = label_stream.str(); return label; } std::string KBlock::toString() const { - return getLabel() + " in function " + parent->function->getName().str(); + return getLabel() + " in function " + parent->function()->getName().str(); +} + +uintptr_t KBlock::getId() const { return instructions - parent->instructions; } + +KInstruction *KFunction::getInstructionByRegister(size_t reg) const { + return instructions[reg - function()->arg_size()]; +} + +bool KFunction::operator<(const KValue &rhs) const { + return getKind() == rhs.getKind() + ? KFunctionCompare{}(this, cast(&rhs)) + : getKind() < rhs.getKind(); +} + +unsigned KFunction::hash() const { + // It is good enough value to use it as + // index is unique. + return id; +} + +size_t KFunction::getNumArgs() const { return function()->arg_size(); } +size_t KFunction::getNumRegisters() const { + return function()->arg_size() + numInstructions; } diff --git a/lib/Module/KValue.cpp b/lib/Module/KValue.cpp new file mode 100644 index 0000000000..d506e612e2 --- /dev/null +++ b/lib/Module/KValue.cpp @@ -0,0 +1,19 @@ +#include "klee/Module/KValue.h" +#include "klee/Support/CompilerWarning.h" + +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Value.h" +DISABLE_WARNING_POP + +#include +#include + +using namespace klee; + +llvm::Value *KValue::unwrap() const { return value; } + +llvm::StringRef KValue::getName() const { + return value && value->hasName() ? value->getName() : ""; +} diff --git a/lib/Module/LocationInfo.cpp b/lib/Module/LocationInfo.cpp new file mode 100644 index 0000000000..6395970b08 --- /dev/null +++ b/lib/Module/LocationInfo.cpp @@ -0,0 +1,86 @@ +//===-- LocationInfo.cpp ------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Module/LocationInfo.h" +#include "klee/Support/CompilerWarning.h" + +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FormattedStream.h" +DISABLE_WARNING_POP + +namespace klee { + +LocationInfo getLocationInfo(const llvm::Function *func) { + const auto dsub = func->getSubprogram(); + + if (dsub != nullptr) { + auto path = dsub->getFilename(); + return {path.str(), dsub->getLine(), 0}; // TODO why not use column here? + } + + return {"", 0, 0}; +} + +LocationInfo getLocationInfo(const llvm::Instruction *inst) { + // Retrieve debug information associated with instruction + const auto &dl = inst->getDebugLoc(); + + // Check if a valid debug location is assigned to the instruction. + if (dl.get() != nullptr) { + auto full_path = dl->getFilename(); + auto line = dl.getLine(); + auto column = dl.getCol(); + + // Still, if the line is unknown, take the context of the instruction to + // narrow it down + if (line == 0) { + if (auto LexicalBlock = + llvm::dyn_cast(dl.getScope())) { + line = LexicalBlock->getLine(); + column = LexicalBlock->getColumn(); + } + } + return {full_path.str(), line, column}; + } + + return getLocationInfo(inst->getParent()->getParent()); +} + +LocationInfo getLocationInfo(const llvm::GlobalVariable *globalVar) { + // Retrieve debug information associated with global variable. + // LLVM does not expose API for getting single DINode with location + // information. + llvm::SmallVector debugInfo; + globalVar->getDebugInfo(debugInfo); + + for (const llvm::DIGlobalVariableExpression *debugInfoEntry : debugInfo) { + // Return location from any debug info for global variable. + if (const llvm::DIGlobalVariable *debugInfoGlobalVar = + debugInfoEntry->getVariable()) { + // Assume that global variable declared at line 0. + return {debugInfoGlobalVar->getFilename().str(), + debugInfoGlobalVar->getLine(), 0}; + } + } + + // Fallback to empty location if there is no appropriate debug + // info. + return {"", 0, 0}; +} + +} // namespace klee diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index e64d628e71..d23e41a607 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -367,3 +367,19 @@ bool klee::loadFileAsOneModule( } return res; } + +void klee::replaceOrRenameFunction(llvm::Module *module, const char *old_name, + const char *new_name) { + Function *new_function, *old_function; + new_function = module->getFunction(new_name); + old_function = module->getFunction(old_name); + if (old_function) { + if (new_function) { + old_function->replaceAllUsesWith(new_function); + old_function->eraseFromParent(); + } else { + old_function->setName(new_name); + assert(old_function->getName() == new_name); + } + } +} \ No newline at end of file diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index dd97353391..e087ed2208 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -75,6 +75,15 @@ static cl::opt static cl::alias A1("S", cl::desc("Alias for --strip-debug"), cl::aliasopt(StripDebug)); +static cl::opt DeleteDeadLoops("delete-dead-loops", + cl::desc("Use LoopDeletionPass"), + cl::init(true), cl::cat(klee::ModuleCat)); + +static cl::opt + OptimizeAggressive("optimize-aggressive", + cl::desc("Use aggressive optimization passes"), + cl::init(true), cl::cat(klee::ModuleCat)); + // A utility function that adds a pass to the pass manager but will also add // a verifier pass after if we're supposed to verify. static inline void addPass(legacy::PassManager &PM, Pass *P) { @@ -131,8 +140,9 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { addPass(PM, createLoopUnswitchPass()); // Unswitch loops. // FIXME : Removing instcombine causes nestedloop regression. addPass(PM, createInstructionCombiningPass()); - addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars - addPass(PM, createLoopDeletionPass()); // Delete dead loops + addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars + if (DeleteDeadLoops) + addPass(PM, createLoopDeletionPass()); // Delete dead loops addPass(PM, createLoopUnrollPass()); // Unroll small loops addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller addPass(PM, createGVNPass()); // Remove redundancies @@ -144,43 +154,12 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { addPass(PM, createInstructionCombiningPass()); addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores - addPass(PM, createAggressiveDCEPass()); // Delete dead instructions addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs addPass(PM, createStripDeadPrototypesPass()); // Get rid of dead prototypes addPass(PM, createConstantMergePass()); // Merge dup global constants } -/// Optimize - Perform link time optimizations. This will run the scalar -/// optimizations, any loaded plugin-optimization modules, and then the -/// inter-procedural optimizations if applicable. -void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { - - // Instantiate the pass manager to organize the passes. - legacy::PassManager Passes; - - // If we're verifying, start off with a verification pass. - if (VerifyEach) - Passes.add(createVerifierPass()); - - // DWD - Run the opt standard pass list as well. - AddStandardCompilePasses(Passes); - - // Now that composite has been compiled, scan through the module, looking - // for a main function. If main is defined, mark all other functions - // internal. - if (!DisableInternalize) { - auto PreserveFunctions = [=](const GlobalValue &GV) { - StringRef GVName = GV.getName(); - - for (const char *fun : preservedFunctions) - if (GVName.equals(fun)) - return true; - - return false; - }; - ModulePass *pass = createInternalizePass(PreserveFunctions); - addPass(Passes, pass); - } +static void AddNonStandardCompilePasses(legacy::PassManager &Passes) { // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function @@ -252,6 +231,43 @@ void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { addPass(Passes, createCFGSimplificationPass()); addPass(Passes, createAggressiveDCEPass()); addPass(Passes, createGlobalDCEPass()); +} + +/// Optimize - Perform link time optimizations. This will run the scalar +/// optimizations, any loaded plugin-optimization modules, and then the +/// inter-procedural optimizations if applicable. +void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { + + // Instantiate the pass manager to organize the passes. + legacy::PassManager Passes; + + // If we're verifying, start off with a verification pass. + if (VerifyEach) + Passes.add(createVerifierPass()); + + // DWD - Run the opt standard pass list as well. + AddStandardCompilePasses(Passes); + + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + if (!DisableInternalize) { + auto PreserveFunctions = [=](const GlobalValue &GV) { + StringRef GVName = GV.getName(); + + for (const char *fun : preservedFunctions) + if (GVName.equals(fun)) + return true; + + return false; + }; + ModulePass *pass = createInternalizePass(PreserveFunctions); + addPass(Passes, pass); + } + + if (OptimizeAggressive) { + AddNonStandardCompilePasses(Passes); + } // Run our queue of passes all at once now, efficiently. Passes.run(*M); diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h index 76499428df..01983e0b85 100644 --- a/lib/Module/Passes.h +++ b/lib/Module/Passes.h @@ -206,6 +206,14 @@ class CallSplitter : public llvm::FunctionPass { bool runOnFunction(llvm::Function &F) override; }; +/// Remove unwanted calls +class CallRemover : public llvm::ModulePass { +public: + static char ID; + CallRemover() : llvm::ModulePass(ID) {} + bool runOnModule(llvm::Module &M) override; +}; + class ReturnSplitter : public llvm::FunctionPass { public: static char ID; diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index 075ce32417..377baf888d 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -11,6 +11,7 @@ #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/ErrorHandling.h" #include "klee/Support/CompilerWarning.h" @@ -25,23 +26,23 @@ using namespace klee; namespace { bool isOSSeparator(char c) { return c == '/' || c == '\\'; } -optional> +std::optional> tryConvertLocationJson(const LocationJson &locationJson) { const auto &physicalLocation = locationJson.physicalLocation; if (!physicalLocation.has_value()) { - return nonstd::nullopt; + return std::nullopt; } const auto &artifactLocation = physicalLocation->artifactLocation; if (!artifactLocation.has_value() || !artifactLocation->uri.has_value()) { - return nonstd::nullopt; + return std::nullopt; } const auto filename = std::move(*(artifactLocation->uri)); const auto ®ion = physicalLocation->region; if (!region.has_value() || !region->startLine.has_value()) { - return nonstd::nullopt; + return std::nullopt; } return Location::create(std::move(filename), *(region->startLine), @@ -51,7 +52,7 @@ tryConvertLocationJson(const LocationJson &locationJson) { std::vector tryConvertRuleJson(const std::string &ruleId, const std::string &toolName, - const optional &errorMessage) { + const std::optional &errorMessage) { if (toolName == "SecB") { if ("NullDereference" == ruleId) { return {ReachWithError::MustBeNullPointerException}; @@ -121,9 +122,9 @@ tryConvertRuleJson(const std::string &ruleId, const std::string &toolName, } } -optional tryConvertResultJson(const ResultJson &resultJson, - const std::string &toolName, - const std::string &id) { +std::optional tryConvertResultJson(const ResultJson &resultJson, + const std::string &toolName, + const std::string &id) { std::vector errors = {}; if (!resultJson.ruleId.has_value()) { errors = {ReachWithError::Reachable}; @@ -132,12 +133,12 @@ optional tryConvertResultJson(const ResultJson &resultJson, tryConvertRuleJson(*resultJson.ruleId, toolName, resultJson.message); if (errors.size() == 0) { klee_warning("undefined error in %s result", id.c_str()); - return nonstd::nullopt; + return std::nullopt; } } std::vector> locations; - std::vector> metadatas; + std::vector> metadatas; if (resultJson.codeFlows.size() > 0) { assert(resultJson.codeFlows.size() == 1); @@ -146,7 +147,7 @@ optional tryConvertResultJson(const ResultJson &resultJson, const auto &threadFlow = resultJson.codeFlows[0].threadFlows[0]; for (auto &threadFlowLocation : threadFlow.locations) { if (!threadFlowLocation.location.has_value()) { - return nonstd::nullopt; + return std::nullopt; } auto maybeLocation = tryConvertLocationJson(*threadFlowLocation.location); @@ -164,7 +165,7 @@ optional tryConvertResultJson(const ResultJson &resultJson, } if (locations.empty()) { - return nonstd::nullopt; + return std::nullopt; } return Result{std::move(locations), std::move(metadatas), id, @@ -288,9 +289,9 @@ Location::EquivLocationHashSet Location::cachedLocations; Location::LocationHashSet Location::locations; ref Location::create(std::string filename_, unsigned int startLine_, - optional endLine_, - optional startColumn_, - optional endColumn_) { + std::optional endLine_, + std::optional startColumn_, + std::optional endColumn_) { Location *loc = new Location(filename_, startLine_, endLine_, startColumn_, endColumn_); std::pair success = @@ -326,20 +327,22 @@ bool Location::isInside(const std::string &name) const { } bool Location::isInside(KBlock *block, const Instructions &origInsts) const { - auto first = block->getFirstInstruction()->info; - auto last = block->getLastInstruction()->info; + auto first = block->getFirstInstruction(); + auto last = block->getLastInstruction(); if (!startColumn.has_value()) { - if (first->line > endLine) + if (first->getLine() > endLine) return false; - return startLine <= last->line; // and `first <= line` from above + return startLine <= last->getLine(); // and `first <= line` from above } else { - for (size_t i = 0; i < block->numInstructions; ++i) { - auto inst = block->instructions[i]->info; - auto opCode = block->instructions[i]->inst->getOpcode(); - if (!isa(block->instructions[i]->inst) && - inst->line <= endLine && inst->line >= startLine && - inst->column <= *endColumn && inst->column >= *startColumn && - origInsts.at(inst->line).at(inst->column).count(opCode) != 0) { + for (unsigned i = 0, ie = block->getNumInstructions(); i < ie; ++i) { + auto inst = block->instructions[i]; + auto opCode = block->instructions[i]->inst()->getOpcode(); + if (!isa(block->instructions[i]->inst()) && + inst->getLine() <= endLine && inst->getLine() >= startLine && + inst->getColumn() <= *endColumn && + inst->getColumn() >= *startColumn && + origInsts.at(inst->getLine()).at(inst->getColumn()).count(opCode) != + 0) { return true; } } @@ -348,6 +351,37 @@ bool Location::isInside(KBlock *block, const Instructions &origInsts) const { } } +bool Location::isInside(const llvm::Function *f, + const Instructions &origInsts) const { + if (f->empty()) { + return false; + } + auto first = &f->front().front(); + auto last = &f->back().back(); + auto firstLoc = getLocationInfo(first); + auto lastLoc = getLocationInfo(last); + if (!startColumn.has_value()) { + if (firstLoc.line > endLine) { + return false; + } + return startLine <= lastLoc.line; + } + for (const auto &block : *f) { + for (const auto &inst : block) { + auto locInfo = getLocationInfo(&inst); + if (!isa(&inst) && locInfo.line <= endLine && + locInfo.line >= startLine && locInfo.column <= *endColumn && + locInfo.column >= *startColumn && + origInsts.at(locInfo.line) + .at(locInfo.column) + .count(inst.getOpcode()) != 0) { + return true; + } + } + } + return false; +} + std::string Location::toString() const { return filename + ":" + std::to_string(startLine); } diff --git a/lib/Module/Target.cpp b/lib/Module/Target.cpp index 7e6cfab36d..d2dde07919 100644 --- a/lib/Module/Target.cpp +++ b/lib/Module/Target.cpp @@ -31,8 +31,8 @@ ErrorLocation::ErrorLocation(const klee::ref &loc) startColumn(loc->startColumn), endColumn(loc->endColumn) {} ErrorLocation::ErrorLocation(const KInstruction *ki) { - startLine = (endLine = ki->info->line); - startColumn = (endColumn = ki->info->line); + startLine = (endLine = ki->getLine()); + startColumn = (endColumn = ki->getLine()); } std::string ReproduceErrorTarget::toString() const { @@ -102,11 +102,11 @@ ref CoverBranchTarget::create(KBlock *_block, unsigned _branchCase) { bool ReproduceErrorTarget::isTheSameAsIn(const KInstruction *instr) const { const auto &errLoc = loc; - return instr->info->line >= errLoc.startLine && - instr->info->line <= errLoc.endLine && + return instr->getLine() >= errLoc.startLine && + instr->getLine() <= errLoc.endLine && (!LocationAccuracy || !errLoc.startColumn.has_value() || - (instr->info->column >= *errLoc.startColumn && - instr->info->column <= *errLoc.endColumn)); + (instr->getColumn() >= *errLoc.startColumn && + instr->getColumn() <= *errLoc.endColumn)); } int Target::compare(const Target &b) const { return internalCompare(b); } @@ -126,8 +126,8 @@ int ReachBlockTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (atEnd != other.atEnd) { @@ -146,8 +146,8 @@ int CoverBranchTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (branchCase != other.branchCase) { @@ -170,8 +170,8 @@ int ReproduceErrorTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (errors.size() != other.errors.size()) { diff --git a/lib/Module/TargetHash.cpp b/lib/Module/TargetHash.cpp index 7f5b9be2eb..f7c3010689 100644 --- a/lib/Module/TargetHash.cpp +++ b/lib/Module/TargetHash.cpp @@ -22,11 +22,6 @@ bool TargetCmp::operator()(const ref &a, const ref &b) const { return a == b; } -std::size_t TransitionHash::operator()(const Transition &p) const { - return reinterpret_cast(p.first) * 31 + - reinterpret_cast(p.second); -} - std::size_t BranchHash::operator()(const Branch &p) const { return reinterpret_cast(p.first) * 31 + p.second; } diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp new file mode 100644 index 0000000000..d8b6011c78 --- /dev/null +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -0,0 +1,239 @@ +//===-- AlphaEquivalenceSolver.cpp-----------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Expr/SymbolicSource.h" +#include "klee/Solver/SolverUtil.h" + +#include "klee/Solver/Solver.h" + +#include "klee/Expr/AlphaBuilder.h" +#include "klee/Expr/Assignment.h" +#include "klee/Expr/Constraints.h" +#include "klee/Expr/ExprHashMap.h" +#include "klee/Solver/SolverImpl.h" +#include "klee/Support/Debug.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +DISABLE_WARNING_POP + +using namespace klee; +using namespace llvm; + +class AlphaEquivalenceSolver : public SolverImpl { +private: + std::unique_ptr solver; + ArrayCache &arrayCache; + +public: + AlphaEquivalenceSolver(std::unique_ptr solver, + ArrayCache &_arrayCache) + : solver(std::move(solver)), arrayCache(_arrayCache) {} + + bool computeTruth(const Query &, bool &isValid); + bool computeValidity(const Query &, PartialValidity &result); + bool computeValue(const Query &, ref &result); + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution); + bool check(const Query &query, ref &result); + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid); + SolverRunStatus getOperationStatusCode(); + char *getConstraintLog(const Query &); + void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); + ValidityCore changeVersion(const ValidityCore &validityCore, + AlphaBuilder &builder); + std::vector + changeVersion(const std::vector &objects, + AlphaBuilder &builder); + Assignment + changeVersion(const std::vector &objects, + const std::vector> &values, + const ArrayCache::ArrayHashMap &reverse); + Assignment + changeVersion(const Assignment &a, + const ArrayCache::ArrayHashMap &reverse); + ref changeVersion(ref res, + AlphaBuilder &builder); +}; + +ValidityCore +AlphaEquivalenceSolver::changeVersion(const ValidityCore &validityCore, + AlphaBuilder &builder) { + ValidityCore reverseValidityCore; + if (isa(validityCore.expr)) { + reverseValidityCore.expr = validityCore.expr; + } else { + reverseValidityCore.expr = builder.reverseBuild(validityCore.expr); + } + for (auto e : validityCore.constraints) { + reverseValidityCore.constraints.insert(builder.reverseBuild(e)); + } + return reverseValidityCore; +} + +Assignment AlphaEquivalenceSolver::changeVersion( + const std::vector &objects, + const std::vector> &values, + const ArrayCache::ArrayHashMap &reverse) { + std::vector reverseObjects; + std::vector> reverseValues; + for (size_t i = 0; i < objects.size(); i++) { + if (reverse.count(objects.at(i)) != 0) { + reverseObjects.push_back(reverse.at(objects.at(i))); + reverseValues.push_back(values.at(i)); + } + } + return Assignment(reverseObjects, reverseValues); +} + +std::vector +AlphaEquivalenceSolver::changeVersion(const std::vector &objects, + AlphaBuilder &builder) { + std::vector reverseObjects; + for (size_t i = 0; i < objects.size(); i++) { + reverseObjects.push_back(builder.buildArray(objects.at(i))); + } + return reverseObjects; +} + +Assignment AlphaEquivalenceSolver::changeVersion( + const Assignment &a, + const ArrayCache::ArrayHashMap &reverse) { + std::vector objects = a.keys(); + std::vector> values = a.values(); + return changeVersion(objects, values, reverse); +} + +ref +AlphaEquivalenceSolver::changeVersion(ref res, + AlphaBuilder &builder) { + ref reverseRes; + if (!isa(res) && !isa(res)) { + return res; + } + + if (isa(res)) { + Assignment a = cast(res)->initialValues(); + a = changeVersion(a, builder.reverseAlphaArrayMap); + reverseRes = new InvalidResponse(a.bindings); + } else { + ValidityCore validityCore; + res->tryGetValidityCore(validityCore); + validityCore = changeVersion(validityCore, builder); + reverseRes = new ValidResponse(validityCore); + } + return reverseRes; +} + +bool AlphaEquivalenceSolver::computeValidity(const Query &query, + PartialValidity &result) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + return solver->impl->computeValidity( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result); +} + +bool AlphaEquivalenceSolver::computeTruth(const Query &query, bool &isValid) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + return solver->impl->computeTruth( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + isValid); +} + +bool AlphaEquivalenceSolver::computeValue(const Query &query, + ref &result) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + return solver->impl->computeValue( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result); +} + +bool AlphaEquivalenceSolver::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + const std::vector newObjects = changeVersion(objects, builder); + + if (!solver->impl->computeInitialValues( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + newObjects, values, hasSolution)) { + return false; + } + return true; +} + +bool AlphaEquivalenceSolver::check(const Query &query, + ref &result) { + AlphaBuilder builder(arrayCache); + + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + if (!solver->impl->check( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result)) { + return false; + } + + result = changeVersion(result, builder); + return true; +} + +bool AlphaEquivalenceSolver::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + AlphaBuilder builder(arrayCache); + + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + if (!solver->impl->computeValidityCore( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + validityCore, isValid)) { + return false; + } + validityCore = changeVersion(validityCore, builder); + return true; +} + +SolverImpl::SolverRunStatus AlphaEquivalenceSolver::getOperationStatusCode() { + return solver->impl->getOperationStatusCode(); +} + +char *AlphaEquivalenceSolver::getConstraintLog(const Query &query) { + return solver->impl->getConstraintLog(query); +} + +void AlphaEquivalenceSolver::setCoreSolverTimeout(time::Span timeout) { + solver->impl->setCoreSolverTimeout(timeout); +} + +void AlphaEquivalenceSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + +std::unique_ptr +klee::createAlphaEquivalenceSolver(std::unique_ptr s, + ArrayCache &arrayCache) { + return std::make_unique( + std::make_unique(std::move(s), arrayCache)); +} diff --git a/lib/Solver/BitwuzlaBuilder.cpp b/lib/Solver/BitwuzlaBuilder.cpp new file mode 100644 index 0000000000..2c47a1440a --- /dev/null +++ b/lib/Solver/BitwuzlaBuilder.cpp @@ -0,0 +1,1314 @@ +//===-- BitwuzlaBuilder.cpp ---------------------------------*- C++ -*-====// +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "klee/Config/config.h" + +#ifdef ENABLE_BITWUZLA + +#include "BitwuzlaBuilder.h" +#include "BitwuzlaHashConfig.h" +#include "klee/ADT/Bits.h" + +#include "klee/Expr/Expr.h" +#include "klee/Solver/Solver.h" +#include "klee/Solver/SolverStats.h" +#include "klee/Support/ErrorHandling.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +DISABLE_WARNING_POP + +namespace klee { + +BitwuzlaArrayExprHash::~BitwuzlaArrayExprHash() {} + +void BitwuzlaArrayExprHash::clear() { + _update_node_hash.clear(); + _array_hash.clear(); +} + +void BitwuzlaArrayExprHash::clearUpdates() { _update_node_hash.clear(); } + +BitwuzlaBuilder::BitwuzlaBuilder(bool autoClearConstructCache) + : autoClearConstructCache(autoClearConstructCache) {} + +BitwuzlaBuilder::~BitwuzlaBuilder() { + _arr_hash.clearUpdates(); + clearSideConstraints(); +} + +Sort BitwuzlaBuilder::getBoolSort() { + // FIXME: cache these + return mk_bool_sort(); +} + +Sort BitwuzlaBuilder::getBvSort(unsigned width) { + // FIXME: cache these + return mk_bv_sort(width); +} + +Sort BitwuzlaBuilder::getArraySort(Sort domainSort, Sort rangeSort) { + // FIXME: cache these + return mk_array_sort(domainSort, rangeSort); +} + +Term BitwuzlaBuilder::buildFreshBoolConst() { return mk_const(getBoolSort()); } + +Term BitwuzlaBuilder::buildArray(const char *name, unsigned indexWidth, + unsigned valueWidth) { + Sort domainSort = getBvSort(indexWidth); + Sort rangeSort = getBvSort(valueWidth); + Sort t = getArraySort(domainSort, rangeSort); + return mk_const(t, std::string(name)); +} + +Term BitwuzlaBuilder::buildConstantArray(const char *name, unsigned indexWidth, + unsigned valueWidth, unsigned value) { + Sort domainSort = getBvSort(indexWidth); + Sort rangeSort = getBvSort(valueWidth); + return mk_const_array(getArraySort(domainSort, rangeSort), + bvConst32(valueWidth, value)); +} + +Term BitwuzlaBuilder::getTrue() { return mk_true(); } + +Term BitwuzlaBuilder::getFalse() { return mk_false(); } + +Term BitwuzlaBuilder::bvOne(unsigned width) { + return mk_bv_one(getBvSort(width)); +} +Term BitwuzlaBuilder::bvZero(unsigned width) { + return mk_bv_zero(getBvSort(width)); +} +Term BitwuzlaBuilder::bvMinusOne(unsigned width) { + return bvZExtConst(width, (uint64_t)-1); +} +Term BitwuzlaBuilder::bvConst32(unsigned width, uint32_t value) { + if (width < 32) { + value &= ((1 << width) - 1); + } + return mk_bv_value_uint64(getBvSort(width), value); +} +Term BitwuzlaBuilder::bvConst64(unsigned width, uint64_t value) { + if (width < 64) { + value &= ((uint64_t(1) << width) - 1); + } + return mk_bv_value_uint64(getBvSort(width), value); +} +Term BitwuzlaBuilder::bvZExtConst(unsigned width, uint64_t value) { + if (width <= 64) { + return bvConst64(width, value); + } + std::vector terms = {bvConst64(64, value)}; + for (width -= 64; width > 64; width -= 64) { + terms.push_back(bvConst64(64, 0)); + } + terms.push_back(bvConst64(width, 0)); + return mk_term(Kind::BV_CONCAT, terms); +} + +Term BitwuzlaBuilder::bvSExtConst(unsigned width, uint64_t value) { + if (width <= 64) { + return bvConst64(width, value); + } + + Sort t = getBvSort(width - 64); + if (value >> 63) { + return mk_term(Kind::BV_CONCAT, + {bvMinusOne(width - 64), bvConst64(64, value)}); + } + return mk_term(Kind::BV_CONCAT, {bvZero(width - 64), bvConst64(64, value)}); +} + +Term BitwuzlaBuilder::bvBoolExtract(Term expr, int bit) { + return mk_term(Kind::EQUAL, {bvExtract(expr, bit, bit), bvOne(1)}); +} + +Term BitwuzlaBuilder::bvExtract(Term expr, unsigned top, unsigned bottom) { + return mk_term(Kind::BV_EXTRACT, {castToBitVector(expr)}, {top, bottom}); +} + +Term BitwuzlaBuilder::eqExpr(Term a, Term b) { + // Handle implicit bitvector/float coercision + Sort aSort = a.sort(); + Sort bSort = b.sort(); + + if (aSort.is_bool() && bSort.is_fp()) { + // Coerce `b` to be a bitvector + b = castToBitVector(b); + } + + if (aSort.is_fp() && bSort.is_bool()) { + // Coerce `a` to be a bitvector + a = castToBitVector(a); + } + return mk_term(Kind::EQUAL, {a, b}); +} + +// logical right shift +Term BitwuzlaBuilder::bvRightShift(Term expr, unsigned shift) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return expr; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + return mk_term(Kind::BV_SHR, {exprAsBv, bvConst32(width, shift)}); + } +} + +// logical left shift +Term BitwuzlaBuilder::bvLeftShift(Term expr, unsigned shift) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return expr; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + return mk_term(Kind::BV_SHL, {exprAsBv, bvConst32(width, shift)}); + } +} + +// left shift by a variable amount on an expression of the specified width +Term BitwuzlaBuilder::bvVarLeftShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + Term res = mk_term(Kind::BV_SHL, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +// logical right shift by a variable amount on an expression of the specified +// width +Term BitwuzlaBuilder::bvVarRightShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + Term res = mk_term(Kind::BV_SHR, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +// arithmetic right shift by a variable amount on an expression of the specified +// width +Term BitwuzlaBuilder::bvVarArithRightShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + + Term res = mk_term(Kind::BV_ASHR, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +Term BitwuzlaBuilder::notExpr(Term expr) { return mk_term(Kind::NOT, {expr}); } +Term BitwuzlaBuilder::andExpr(Term lhs, Term rhs) { + return mk_term(Kind::AND, {lhs, rhs}); +} +Term BitwuzlaBuilder::orExpr(Term lhs, Term rhs) { + return mk_term(Kind::OR, {lhs, rhs}); +} +Term BitwuzlaBuilder::iffExpr(Term lhs, Term rhs) { + return mk_term(Kind::IFF, {lhs, rhs}); +} + +Term BitwuzlaBuilder::bvNotExpr(Term expr) { + return mk_term(Kind::BV_NOT, {castToBitVector(expr)}); +} + +Term BitwuzlaBuilder::bvAndExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_AND, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvOrExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_OR, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvXorExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_XOR, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvSignExtend(Term src, unsigned width) { + Term srcAsBv = castToBitVector(src); + unsigned src_width = srcAsBv.sort().bv_size(); + assert(src_width <= width && "attempted to extend longer data"); + + if (width <= 64) { + return mk_term(Kind::BV_SIGN_EXTEND, {srcAsBv}, {width - src_width}); + } + + Term signBit = bvBoolExtract(srcAsBv, src_width - 1); + Term zeroExtended = + mk_term(Kind::BV_CONCAT, {bvZero(width - src_width), src}); + Term oneExtended = + mk_term(Kind::BV_CONCAT, {bvMinusOne(width - src_width), src}); + + return mk_term(Kind::ITE, {signBit, oneExtended, zeroExtended}); +} + +Term BitwuzlaBuilder::writeExpr(Term array, Term index, Term value) { + return mk_term(Kind::ARRAY_STORE, {array, index, value}); +} + +Term BitwuzlaBuilder::readExpr(Term array, Term index) { + return mk_term(Kind::ARRAY_SELECT, {array, index}); +} + +unsigned BitwuzlaBuilder::getBVLength(Term expr) { + if (!expr.sort().is_bv()) { + klee_error("getBVLength() accepts only bitvector, given %s", + expr.sort().str().c_str()); + } + return expr.sort().bv_size(); +} + +Term BitwuzlaBuilder::iteExpr(Term condition, Term whenTrue, Term whenFalse) { + // Handle implicit bitvector/float coercision + Sort whenTrueSort = whenTrue.sort(); + Sort whenFalseSort = whenFalse.sort(); + + if (whenTrueSort.is_bv() && whenFalseSort.is_fp()) { + // Coerce `whenFalse` to be a bitvector + whenFalse = castToBitVector(whenFalse); + } + + if (whenTrueSort.is_fp() && whenFalseSort.is_bv()) { + // Coerce `whenTrue` to be a bitvector + whenTrue = castToBitVector(whenTrue); + } + return mk_term(Kind::ITE, {condition, whenTrue, whenFalse}); +} + +Term BitwuzlaBuilder::bvLtExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_ULT, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvLeExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_ULE, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::sbvLtExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_SLT, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::sbvLeExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_SLE, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::constructAShrByConstant(Term expr, unsigned shift, + Term isSigned) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return exprAsBv; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + // FIXME: Is this really the best way to interact with Bitwuzla? + Term signed_term = + mk_term(Kind::BV_CONCAT, + {bvMinusOne(shift), bvExtract(exprAsBv, width - 1, shift)}); + Term unsigned_term = bvRightShift(exprAsBv, shift); + + return mk_term(Kind::ITE, {isSigned, signed_term, unsigned_term}); + } +} + +Term BitwuzlaBuilder::getInitialArray(const Array *root) { + assert(root); + Term array_expr; + bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); + + if (!hashed) { + // Unique arrays by name, so we make sure the name is unique by + // using the size of the array hash as a counter. + std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); + std::string unique_name = root->getIdentifier() + unique_id; + + auto source = dyn_cast(root->source); + auto value = (source ? source->constantValues.defaultV() : nullptr); + if (source) { + assert(value); + } + + if (source && !isa(root->size)) { + array_expr = buildConstantArray(unique_name.c_str(), root->getDomain(), + root->getRange(), value->getZExtValue(8)); + } else { + array_expr = + buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); + } + + if (source) { + if (auto constSize = dyn_cast(root->size)) { + std::vector array_assertions; + for (size_t i = 0; i < constSize->getZExtValue(); i++) { + auto value = source->constantValues.load(i); + // construct(= (select i root) root->value[i]) to be asserted in + // BitwuzlaSolver.cpp + int width_out; + Term array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_assertions.push_back( + eqExpr(readExpr(array_expr, bvConst32(root->getDomain(), i)), + array_value)); + } + constant_array_assertions[root] = std::move(array_assertions); + } else { + for (auto &[index, value] : source->constantValues.storage()) { + int width_out; + Term array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } + } + } + + _arr_hash.hashArrayExpr(root, array_expr); + } + + return array_expr; +} + +Term BitwuzlaBuilder::getInitialRead(const Array *root, unsigned index) { + return readExpr(getInitialArray(root), bvConst32(32, index)); +} + +Term BitwuzlaBuilder::getArrayForUpdate(const Array *root, + const UpdateNode *un) { + // Iterate over the update nodes, until we find a cached version of the node, + // or no more update nodes remain + Term un_expr; + std::vector update_nodes; + for (; un && !_arr_hash.lookupUpdateNodeExpr(un, un_expr); + un = un->next.get()) { + update_nodes.push_back(un); + } + if (!un) { + un_expr = getInitialArray(root); + } + // `un_expr` now holds an expression for the array - either from cache or by + // virtue of being the initial array expression + + // Create and cache solver expressions based on the update nodes starting from + // the oldest + for (const auto &un : + llvm::make_range(update_nodes.crbegin(), update_nodes.crend())) { + un_expr = + writeExpr(un_expr, construct(un->index, 0), construct(un->value, 0)); + + _arr_hash.hashUpdateNodeExpr(un, un_expr); + } + + return un_expr; +} + +Term BitwuzlaBuilder::construct(ref e, int *width_out) { + if (!BitwuzlaHashConfig::UseConstructHashBitwuzla || isa(e)) { + return constructActual(e, width_out); + } else { + ExprHashMap>::iterator it = constructed.find(e); + if (it != constructed.end()) { + if (width_out) + *width_out = it->second.second; + return it->second.first; + } else { + int width; + if (!width_out) + width_out = &width; + Term res = constructActual(e, width_out); + constructed.insert(std::make_pair(e, std::make_pair(res, *width_out))); + return res; + } + } +} + +void BitwuzlaBuilder::FPCastWidthAssert(int *width_out, char const *msg) { + assert(&(ConstantExpr::widthToFloatSemantics(*width_out)) != + &(llvm::APFloat::Bogus()) && + msg); +} + +/** if *width_out!=1 then result is a bitvector, +otherwise it is a bool */ +Term BitwuzlaBuilder::constructActual(ref e, int *width_out) { + + int width; + if (!width_out) + width_out = &width; + ++stats::queryConstructs; + switch (e->getKind()) { + case Expr::Constant: { + ConstantExpr *CE = cast(e); + *width_out = CE->getWidth(); + + // Coerce to bool if necessary. + if (*width_out == 1) + return CE->isTrue() ? getTrue() : getFalse(); + + Term Res; + if (*width_out <= 32) { + // Fast path. + Res = bvConst32(*width_out, CE->getZExtValue(32)); + } else if (*width_out <= 64) { + // Fast path. + Res = bvConst64(*width_out, CE->getZExtValue()); + } else { + llvm::SmallString<129> CEUValue; + CE->getAPValue().toStringUnsigned(CEUValue); + Res = mk_bv_value(mk_bv_sort(CE->getWidth()), CEUValue.str().str(), 10); + } + // Coerce to float if necesary + if (CE->isFloat()) { + Res = castToFloat(Res); + } + return Res; + } + + // Special + case Expr::NotOptimized: { + NotOptimizedExpr *noe = cast(e); + return construct(noe->src, width_out); + } + + case Expr::Read: { + ReadExpr *re = cast(e); + assert(re && re->updates.root); + *width_out = re->updates.root->getRange(); + return readExpr(getArrayForUpdate(re->updates.root, re->updates.head.get()), + construct(re->index, 0)); + } + + case Expr::Select: { + SelectExpr *se = cast(e); + Term cond = construct(se->cond, 0); + Term tExpr = construct(se->trueExpr, width_out); + Term fExpr = construct(se->falseExpr, width_out); + return iteExpr(cond, tExpr, fExpr); + } + + case Expr::Concat: { + ConcatExpr *ce = cast(e); + unsigned numKids = ce->getNumKids(); + std::vector term_args; + term_args.reserve(numKids); + + for (unsigned i = 0; i < numKids; ++i) { + term_args.push_back(construct(ce->getKid(i), 0)); + } + + *width_out = ce->getWidth(); + return mk_term(Kind::BV_CONCAT, term_args); + } + + case Expr::Extract: { + ExtractExpr *ee = cast(e); + Term src = construct(ee->expr, width_out); + *width_out = ee->getWidth(); + if (*width_out == 1) { + return bvBoolExtract(src, ee->offset); + } else { + return bvExtract(src, ee->offset + *width_out - 1, ee->offset); + } + } + + // Casting + + case Expr::ZExt: { + int srcWidth; + CastExpr *ce = cast(e); + Term src = construct(ce->src, &srcWidth); + *width_out = ce->getWidth(); + if (srcWidth == 1) { + return iteExpr(src, bvOne(*width_out), bvZero(*width_out)); + } else { + assert(*width_out > srcWidth && "Invalid width_out"); + return mk_term(Kind::BV_CONCAT, + {bvZero(*width_out - srcWidth), castToBitVector(src)}); + } + } + + case Expr::SExt: { + int srcWidth; + CastExpr *ce = cast(e); + Term src = construct(ce->src, &srcWidth); + *width_out = ce->getWidth(); + if (srcWidth == 1) { + return iteExpr(src, bvMinusOne(*width_out), bvZero(*width_out)); + } else { + return bvSignExtend(src, *width_out); + } + } + + case Expr::FPExt: { + int srcWidth; + FPExtExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPExt width"); + assert(*width_out >= srcWidth && "Invalid FPExt"); + // Just use any arounding mode here as we are extending + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term( + Kind::FP_TO_FP_FROM_FP, + {getRoundingModeSort(llvm::APFloat::rmNearestTiesToEven), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::FPTrunc: { + int srcWidth; + FPTruncExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPTrunc width"); + assert(*width_out <= srcWidth && "Invalid FPTrunc"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term( + Kind::FP_TO_FP_FROM_FP, + {getRoundingModeSort(llvm::APFloat::rmNearestTiesToEven), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::FPToUI: { + int srcWidth; + FPToUIExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPToUI width"); + return mk_term(Kind::FP_TO_UBV, + {getRoundingModeSort(ce->roundingMode), src}, + {ce->getWidth()}); + } + + case Expr::FPToSI: { + int srcWidth; + FPToSIExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPToSI width"); + return mk_term(Kind::FP_TO_SBV, + {getRoundingModeSort(ce->roundingMode), src}, + {ce->getWidth()}); + } + + case Expr::UIToFP: { + int srcWidth; + UIToFPExpr *ce = cast(e); + Term src = castToBitVector(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid UIToFP width"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term(Kind::FP_TO_FP_FROM_UBV, + {getRoundingModeSort(ce->roundingMode), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::SIToFP: { + int srcWidth; + SIToFPExpr *ce = cast(e); + Term src = castToBitVector(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid SIToFP width"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term(Kind::FP_TO_FP_FROM_SBV, + {getRoundingModeSort(ce->roundingMode), src}, + {out_widths.first, out_widths.second}); + } + + // Arithmetic + case Expr::Add: { + AddExpr *ae = cast(e); + Term left = castToBitVector(construct(ae->left, width_out)); + Term right = castToBitVector(construct(ae->right, width_out)); + assert(*width_out != 1 && "uncanonicalized add"); + Term result = mk_term(Kind::BV_ADD, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::Sub: { + SubExpr *se = cast(e); + Term left = castToBitVector(construct(se->left, width_out)); + Term right = castToBitVector(construct(se->right, width_out)); + assert(*width_out != 1 && "uncanonicalized sub"); + Term result = mk_term(Kind::BV_SUB, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::Mul: { + MulExpr *me = cast(e); + Term right = castToBitVector(construct(me->right, width_out)); + assert(*width_out != 1 && "uncanonicalized mul"); + Term left = castToBitVector(construct(me->left, width_out)); + Term result = mk_term(Kind::BV_MUL, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::UDiv: { + UDivExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized udiv"); + + if (ConstantExpr *CE = dyn_cast(de->right)) { + if (CE->getWidth() <= 64) { + uint64_t divisor = CE->getZExtValue(); + if (bits64::isPowerOfTwo(divisor)) + return bvRightShift(left, bits64::indexOfSingleBit(divisor)); + } + } + + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_UDIV, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::SDiv: { + SDivExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized sdiv"); + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_SDIV, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::URem: { + URemExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized urem"); + + if (ConstantExpr *CE = dyn_cast(de->right)) { + if (CE->getWidth() <= 64) { + uint64_t divisor = CE->getZExtValue(); + + if (bits64::isPowerOfTwo(divisor)) { + int bits = bits64::indexOfSingleBit(divisor); + assert(bits >= 0 && "bit index cannot be negative"); + assert(bits64::indexOfSingleBit(divisor) < INT32_MAX); + + // special case for modding by 1 or else we bvExtract -1:0 + if (bits == 0) { + return bvZero(*width_out); + } else { + assert(*width_out > bits && "invalid width_out"); + return mk_term(Kind::BV_CONCAT, {bvZero(*width_out - bits), + bvExtract(left, bits - 1, 0)}); + } + } + } + } + + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_UREM, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::SRem: { + SRemExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + Term right = castToBitVector(construct(de->right, width_out)); + assert(*width_out != 1 && "uncanonicalized srem"); + Term result = mk_term(Kind::BV_SREM, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + // Bitwise + case Expr::Not: { + NotExpr *ne = cast(e); + Term expr = construct(ne->expr, width_out); + if (*width_out == 1) { + return notExpr(expr); + } else { + return bvNotExpr(expr); + } + } + + case Expr::And: { + AndExpr *ae = cast(e); + Term left = construct(ae->left, width_out); + Term right = construct(ae->right, width_out); + if (*width_out == 1) { + return andExpr(left, right); + } else { + return bvAndExpr(left, right); + } + } + + case Expr::Or: { + OrExpr *oe = cast(e); + Term left = construct(oe->left, width_out); + Term right = construct(oe->right, width_out); + if (*width_out == 1) { + return orExpr(left, right); + } else { + return bvOrExpr(left, right); + } + } + + case Expr::Xor: { + XorExpr *xe = cast(e); + Term left = construct(xe->left, width_out); + Term right = construct(xe->right, width_out); + + if (*width_out == 1) { + // XXX check for most efficient? + return iteExpr(left, Term(notExpr(right)), right); + } else { + return bvXorExpr(left, right); + } + } + + case Expr::Shl: { + ShlExpr *se = cast(e); + Term left = construct(se->left, width_out); + assert(*width_out != 1 && "uncanonicalized shl"); + + if (ConstantExpr *CE = dyn_cast(se->right)) { + return bvLeftShift(left, (unsigned)CE->getLimitedValue()); + } else { + int shiftWidth; + Term amount = construct(se->right, &shiftWidth); + return bvVarLeftShift(left, amount); + } + } + + case Expr::LShr: { + LShrExpr *lse = cast(e); + Term left = construct(lse->left, width_out); + assert(*width_out != 1 && "uncanonicalized lshr"); + + if (ConstantExpr *CE = dyn_cast(lse->right)) { + return bvRightShift(left, (unsigned)CE->getLimitedValue()); + } else { + int shiftWidth; + Term amount = construct(lse->right, &shiftWidth); + return bvVarRightShift(left, amount); + } + } + + case Expr::AShr: { + AShrExpr *ase = cast(e); + Term left = castToBitVector(construct(ase->left, width_out)); + assert(*width_out != 1 && "uncanonicalized ashr"); + + if (ConstantExpr *CE = dyn_cast(ase->right)) { + unsigned shift = (unsigned)CE->getLimitedValue(); + Term signedBool = bvBoolExtract(left, *width_out - 1); + return constructAShrByConstant(left, shift, signedBool); + } else { + int shiftWidth; + Term amount = construct(ase->right, &shiftWidth); + return bvVarArithRightShift(left, amount); + } + } + + // Comparison + + case Expr::Eq: { + EqExpr *ee = cast(e); + Term left = construct(ee->left, width_out); + Term right = construct(ee->right, width_out); + if (*width_out == 1) { + if (ConstantExpr *CE = dyn_cast(ee->left)) { + if (CE->isTrue()) + return right; + return notExpr(right); + } else { + return iffExpr(left, right); + } + } else { + *width_out = 1; + return eqExpr(left, right); + } + } + + case Expr::Ult: { + UltExpr *ue = cast(e); + Term left = construct(ue->left, width_out); + Term right = construct(ue->right, width_out); + assert(*width_out != 1 && "uncanonicalized ult"); + *width_out = 1; + return bvLtExpr(left, right); + } + + case Expr::Ule: { + UleExpr *ue = cast(e); + Term left = construct(ue->left, width_out); + Term right = construct(ue->right, width_out); + assert(*width_out != 1 && "uncanonicalized ule"); + *width_out = 1; + return bvLeExpr(left, right); + } + + case Expr::Slt: { + SltExpr *se = cast(e); + Term left = construct(se->left, width_out); + Term right = construct(se->right, width_out); + assert(*width_out != 1 && "uncanonicalized slt"); + *width_out = 1; + return sbvLtExpr(left, right); + } + + case Expr::Sle: { + SleExpr *se = cast(e); + Term left = construct(se->left, width_out); + Term right = construct(se->right, width_out); + assert(*width_out != 1 && "uncanonicalized sle"); + *width_out = 1; + return sbvLeExpr(left, right); + } + + case Expr::FOEq: { + FOEqExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_EQUAL, {left, right}); + } + + case Expr::FOLt: { + FOLtExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_LT, {left, right}); + } + + case Expr::FOLe: { + FOLeExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_LEQ, {left, right}); + } + + case Expr::FOGt: { + FOGtExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_GT, {left, right}); + } + + case Expr::FOGe: { + FOGeExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_GEQ, {left, right}); + } + + case Expr::IsNaN: { + IsNaNExpr *ine = cast(e); + Term arg = castToFloat(construct(ine->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_NAN, {arg}); + } + + case Expr::IsInfinite: { + IsInfiniteExpr *iie = cast(e); + Term arg = castToFloat(construct(iie->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_INF, {arg}); + } + + case Expr::IsNormal: { + IsNormalExpr *ine = cast(e); + Term arg = castToFloat(construct(ine->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_NORMAL, {arg}); + } + + case Expr::IsSubnormal: { + IsSubnormalExpr *ise = cast(e); + Term arg = castToFloat(construct(ise->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_SUBNORMAL, {arg}); + } + + case Expr::FAdd: { + FAddExpr *fadd = cast(e); + Term left = castToFloat(construct(fadd->left, width_out)); + Term right = castToFloat(construct(fadd->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FAdd"); + return mk_term(Kind::FP_ADD, + {getRoundingModeSort(fadd->roundingMode), left, right}); + } + + case Expr::FSub: { + FSubExpr *fsub = cast(e); + Term left = castToFloat(construct(fsub->left, width_out)); + Term right = castToFloat(construct(fsub->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FSub"); + return mk_term(Kind::FP_SUB, + {getRoundingModeSort(fsub->roundingMode), left, right}); + } + + case Expr::FMul: { + FMulExpr *fmul = cast(e); + Term left = castToFloat(construct(fmul->left, width_out)); + Term right = castToFloat(construct(fmul->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMul"); + return mk_term(Kind::FP_MUL, + {getRoundingModeSort(fmul->roundingMode), left, right}); + } + + case Expr::FDiv: { + FDivExpr *fdiv = cast(e); + Term left = castToFloat(construct(fdiv->left, width_out)); + Term right = castToFloat(construct(fdiv->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FDiv"); + return mk_term(Kind::FP_DIV, + {getRoundingModeSort(fdiv->roundingMode), left, right}); + } + case Expr::FRem: { + FRemExpr *frem = cast(e); + Term left = castToFloat(construct(frem->left, width_out)); + Term right = castToFloat(construct(frem->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FRem"); + return mk_term(Kind::FP_REM, {left, right}); + } + + case Expr::FMax: { + FMaxExpr *fmax = cast(e); + Term left = castToFloat(construct(fmax->left, width_out)); + Term right = castToFloat(construct(fmax->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMax"); + return mk_term(Kind::FP_MAX, {left, right}); + } + + case Expr::FMin: { + FMinExpr *fmin = cast(e); + Term left = castToFloat(construct(fmin->left, width_out)); + Term right = castToFloat(construct(fmin->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMin"); + return mk_term(Kind::FP_MIN, {left, right}); + } + + case Expr::FSqrt: { + FSqrtExpr *fsqrt = cast(e); + Term arg = castToFloat(construct(fsqrt->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FSqrt"); + return mk_term(Kind::FP_SQRT, + {getRoundingModeSort(fsqrt->roundingMode), arg}); + } + case Expr::FRint: { + FRintExpr *frint = cast(e); + Term arg = castToFloat(construct(frint->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FSqrt"); + return mk_term(Kind::FP_RTI, + {getRoundingModeSort(frint->roundingMode), arg}); + } + + case Expr::FAbs: { + FAbsExpr *fabsExpr = cast(e); + Term arg = castToFloat(construct(fabsExpr->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FAbs"); + return mk_term(Kind::FP_ABS, {arg}); + } + + case Expr::FNeg: { + FNegExpr *fnegExpr = cast(e); + Term arg = castToFloat(construct(fnegExpr->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FNeg"); + return mk_term(Kind::FP_NEG, {arg}); + } + +// unused due to canonicalization +#if 0 + case Expr::Ne: +case Expr::Ugt: +case Expr::Uge: +case Expr::Sgt: +case Expr::Sge: +#endif + + default: + assert(0 && "unhandled Expr type"); + return getTrue(); + } +} + +Term BitwuzlaBuilder::fpToIEEEBV(const Term &fp) { + if (!fp.sort().is_fp()) { + klee_error("BitwuzlaBuilder::fpToIEEEBV accepts only floats"); + } + + Term signBit = mk_const(getBvSort(1)); + Term exponentBits = mk_const(getBvSort(fp.sort().fp_exp_size())); + Term significandBits = mk_const(getBvSort(fp.sort().fp_sig_size() - 1)); + + Term floatTerm = + mk_term(Kind::FP_FP, {signBit, exponentBits, significandBits}); + sideConstraints.push_back(mk_term(Kind::EQUAL, {fp, floatTerm})); + + return mk_term(Kind::BV_CONCAT, {signBit, exponentBits, significandBits}); +} + +std::pair +BitwuzlaBuilder::getFloatSortFromBitWidth(unsigned bitWidth) { + switch (bitWidth) { + case Expr::Int16: { + return {5, 11}; + } + case Expr::Int32: { + return {8, 24}; + } + case Expr::Int64: { + return {11, 53}; + } + case Expr::Fl80: { + // Note this is an IEEE754 with a 15 bit exponent + // and 64 bit significand. This is not the same + // as x87 fp80 which has a different binary encoding. + // We can use this Bitwuzla type to get the appropriate + // amount of precision. We just have to be very + // careful which casting between floats and bitvectors. + // + // Note that the number of significand bits includes the "implicit" + // bit (which is not implicit for x87 fp80). + return {15, 64}; + } + case Expr::Int128: { + return {15, 113}; + } + default: + assert( + 0 && + "bitWidth cannot converted to a IEEE-754 binary-* number by Bitwuzla"); + std::abort(); + } +} + +Term BitwuzlaBuilder::castToFloat(const Term &e) { + Sort currentSort = e.sort(); + if (currentSort.is_fp()) { + // Already a float + return e; + } else if (currentSort.is_bv()) { + unsigned bitWidth = currentSort.bv_size(); + switch (bitWidth) { + case Expr::Int16: + case Expr::Int32: + case Expr::Int64: + case Expr::Int128: { + auto out_width = getFloatSortFromBitWidth(bitWidth); + return mk_term(Kind::FP_TO_FP_FROM_BV, {e}, + {out_width.first, out_width.second}); + } + case Expr::Fl80: { + // The bit pattern used by x87 fp80 and what we use in Bitwuzla are + // different + // + // x87 fp80 + // + // Sign Exponent Significand + // [1] [15] [1] [63] + // + // The exponent has bias 16383 and the significand has the integer portion + // as an explicit bit + // + // 79-bit IEEE-754 encoding used in Bitwuzla + // + // Sign Exponent [Significand] + // [1] [15] [63] + // + // Exponent has bias 16383 (2^(15-1) -1) and the significand has + // the integer portion as an implicit bit. + // + // We need to provide the mapping here and also emit a side constraint + // to make sure the explicit bit is appropriately constrained so when + // Bitwuzla generates a model we get the correct bit pattern back. + // + // This assumes Bitwuzla's IEEE semantics, x87 fp80 actually + // has additional semantics due to the explicit bit (See 8.2.2 + // "Unsupported Double Extended-Precision Floating-Point Encodings and + // Pseudo-Denormals" in the Intel 64 and IA-32 Architectures Software + // Developer's Manual) but this encoding means we can't model these + // unsupported values in Bitwuzla. + // + // Note this code must kept in sync with + // `BitwuzlaBuilder::castToBitVector()`. Which performs the inverse + // operation here. + // + // TODO: Experiment with creating a constraint that transforms these + // unsupported bit patterns into a Bitwuzla NaN to approximate the + // behaviour from those values. + + // Note we try very hard here to avoid calling into our functions + // here that do implicit casting so we can never recursively call + // into this function. + Term signBit = mk_term(Kind::BV_EXTRACT, {e}, {79, 79}); + Term exponentBits = mk_term(Kind::BV_EXTRACT, {e}, {78, 64}); + Term significandIntegerBit = mk_term(Kind::BV_EXTRACT, {e}, {63, 63}); + Term significandFractionBits = mk_term(Kind::BV_EXTRACT, {e}, {62, 0}); + + Term ieeeBitPatternAsFloat = mk_term( + Kind::FP_FP, {signBit, exponentBits, significandFractionBits}); + + // Generate side constraint on the significand integer bit. It is not + // used in `ieeeBitPatternAsFloat` so we need to constrain that bit to + // have the correct value so that when Bitwuzla gives a model the bit + // pattern has the right value for x87 fp80. + // + // If the number is a denormal or zero then the implicit integer bit + // is zero otherwise it is one. + Term significandIntegerBitConstrainedValue = + getx87FP80ExplicitSignificandIntegerBit(ieeeBitPatternAsFloat); + Term significandIntegerBitConstraint = + mk_term(Kind::EQUAL, {significandIntegerBit, + significandIntegerBitConstrainedValue}); + + sideConstraints.push_back(significandIntegerBitConstraint); + return ieeeBitPatternAsFloat; + } + default: + llvm_unreachable("Unhandled width when casting bitvector to float"); + } + } else { + llvm_unreachable("Sort cannot be cast to float"); + } +} + +Term BitwuzlaBuilder::castToBitVector(const Term &e) { + Sort currentSort = e.sort(); + if (currentSort.is_bool()) { + return mk_term(Kind::ITE, {e, bvOne(1), bvZero(1)}); + } else if (currentSort.is_bv()) { + // Already a bitvector + return e; + } else if (currentSort.is_fp()) { + // Note this picks a single representation for NaN which means + // `castToBitVector(castToFloat(e))` might not equal `e`. + unsigned exponentBits = currentSort.fp_exp_size(); + unsigned significandBits = + currentSort.fp_sig_size(); // Includes implicit bit + unsigned floatWidth = exponentBits + significandBits; + + switch (floatWidth) { + case Expr::Int16: + case Expr::Int32: + case Expr::Int64: + case Expr::Int128: + return fpToIEEEBV(e); + case 79: { + // This is Expr::Fl80 (64 bit exponent, 15 bit significand) but due to + // the "implicit" bit actually being implicit in x87 fp80 the sum of + // the exponent and significand bitwidth is 79 not 80. + + // Get Bitwuzla's IEEE representation + Term ieeeBits = fpToIEEEBV(e); + + // Construct the x87 fp80 bit representation + Term signBit = mk_term(Kind::BV_EXTRACT, {ieeeBits}, {78, 78}); + Term exponentBits = mk_term(Kind::BV_EXTRACT, {ieeeBits}, {77, 63}); + Term significandIntegerBit = getx87FP80ExplicitSignificandIntegerBit(e); + Term significandFractionBits = + mk_term(Kind::BV_EXTRACT, {ieeeBits}, {62, 0}); + Term x87FP80Bits = mk_term(Kind::BV_CONCAT, + {signBit, exponentBits, significandIntegerBit, + significandFractionBits}); + return x87FP80Bits; + } + default: + llvm_unreachable("Unhandled width when casting float to bitvector"); + } + } else { + llvm_unreachable("Sort cannot be cast to float"); + } +} + +Term BitwuzlaBuilder::getRoundingModeSort(llvm::APFloat::roundingMode rm) { + switch (rm) { + case llvm::APFloat::rmNearestTiesToEven: + return mk_rm_value(RoundingMode::RNE); + case llvm::APFloat::rmTowardPositive: + return mk_rm_value(RoundingMode::RTP); + case llvm::APFloat::rmTowardNegative: + return mk_rm_value(RoundingMode::RTN); + case llvm::APFloat::rmTowardZero: + return mk_rm_value(RoundingMode::RTZ); + case llvm::APFloat::rmNearestTiesToAway: + return mk_rm_value(RoundingMode::RNA); + default: + llvm_unreachable("Unhandled rounding mode"); + } +} + +Term BitwuzlaBuilder::getx87FP80ExplicitSignificandIntegerBit(const Term &e) { +#ifndef NDEBUG + // Check the passed in expression is the right type. + Sort currentSort = e.sort(); + assert(currentSort.is_fp()); + + unsigned exponentBits = currentSort.fp_exp_size(); + unsigned significandBits = currentSort.fp_sig_size(); + assert(exponentBits == 15); + assert(significandBits == 64); +#endif + // If the number is a denormal or zero then the implicit integer bit is zero + // otherwise it is one. Term isDenormal = + Term isDenormal = mk_term(Kind::FP_IS_SUBNORMAL, {e}); + Term isZero = mk_term(Kind::FP_IS_ZERO, {e}); + + // FIXME: Cache these constants somewhere + Sort oneBitBvSort = getBvSort(/*width=*/1); + + Term oneBvOne = mk_bv_value_uint64(oneBitBvSort, 1); + Term zeroBvOne = mk_bv_value_uint64(oneBitBvSort, 0); + + Term significandIntegerBitCondition = orExpr(isDenormal, isZero); + + Term significandIntegerBitConstrainedValue = + mk_term(Kind::ITE, {significandIntegerBitCondition, zeroBvOne, oneBvOne}); + + return significandIntegerBitConstrainedValue; +} +} // namespace klee + +#endif // ENABLE_BITWUZLA diff --git a/lib/Solver/BitwuzlaBuilder.h b/lib/Solver/BitwuzlaBuilder.h new file mode 100644 index 0000000000..9119832f3f --- /dev/null +++ b/lib/Solver/BitwuzlaBuilder.h @@ -0,0 +1,140 @@ +//===-- BitwuzlaBuilder.h --------------------------------------------*- C++ +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef BITWUZLABUILDER_H_ +#define BITWUZLABUILDER_H_ + +#include "klee/Config/config.h" +#include "klee/Expr/ArrayExprHash.h" +#include "klee/Expr/ExprHashMap.h" + +#include +#include + +using namespace bitwuzla; + +namespace klee { + +class BitwuzlaArrayExprHash : public ArrayExprHash { + friend class BitwuzlaBuilder; + +public: + BitwuzlaArrayExprHash(){}; + virtual ~BitwuzlaArrayExprHash(); + void clear(); + void clearUpdates(); +}; + +class BitwuzlaBuilder { +private: + void FPCastWidthAssert(int *width_out, char const *msg); + Term fpToIEEEBV(const Term &); + +protected: + Term bvOne(unsigned width); + Term bvZero(unsigned width); + Term bvMinusOne(unsigned width); + Term bvConst32(unsigned width, uint32_t value); + Term bvConst64(unsigned width, uint64_t value); + Term bvZExtConst(unsigned width, uint64_t value); + Term bvSExtConst(unsigned width, uint64_t value); + Term bvBoolExtract(Term expr, int bit); + Term bvExtract(Term expr, unsigned top, unsigned bottom); + Term eqExpr(Term a, Term b); + + // logical left and right shift (not arithmetic) + Term bvLeftShift(Term expr, unsigned shift); + Term bvRightShift(Term expr, unsigned shift); + Term bvVarLeftShift(Term expr, Term shift); + Term bvVarRightShift(Term expr, Term shift); + Term bvVarArithRightShift(Term expr, Term shift); + + Term notExpr(Term expr); + Term andExpr(Term lhs, Term rhs); + Term orExpr(Term lhs, Term rhs); + Term iffExpr(Term lhs, Term rhs); + + Term bvNotExpr(Term expr); + Term bvAndExpr(Term lhs, Term rhs); + Term bvOrExpr(Term lhs, Term rhs); + Term bvXorExpr(Term lhs, Term rhs); + Term bvSignExtend(Term src, unsigned width); + + // Array operations + Term writeExpr(Term array, Term index, Term value); + Term readExpr(Term array, Term index); + + // ITE-expression constructor + Term iteExpr(Term condition, Term whenTrue, Term whenFalse); + + // Bitvector length + unsigned getBVLength(Term expr); + + // Bitvector comparison + Term bvLtExpr(Term lhs, Term rhs); + Term bvLeExpr(Term lhs, Term rhs); + Term sbvLtExpr(Term lhs, Term rhs); + Term sbvLeExpr(Term lhs, Term rhs); + + Term constructAShrByConstant(Term expr, unsigned shift, Term isSigned); + + Term getInitialArray(const Array *os); + Term getArrayForUpdate(const Array *root, const UpdateNode *un); + + Term constructActual(ref e, int *width_out); + Term construct(ref e, int *width_out); + Term buildArray(const char *name, unsigned indexWidth, unsigned valueWidth); + Term buildConstantArray(const char *name, unsigned indexWidth, + unsigned valueWidth, unsigned value); + + Sort getBoolSort(); + Sort getBvSort(unsigned width); + Sort getArraySort(Sort domainSort, Sort rangeSort); + + std::pair getFloatSortFromBitWidth(unsigned bitWidth); + + // Float casts + Term castToFloat(const Term &e); + Term castToBitVector(const Term &e); + + Term getRoundingModeSort(llvm::APFloat::roundingMode rm); + Term getx87FP80ExplicitSignificandIntegerBit(const Term &e); + + ExprHashMap> constructed; + BitwuzlaArrayExprHash _arr_hash; + bool autoClearConstructCache; + +public: + std::unordered_map> + constant_array_assertions; + // These are additional constraints that are generated during the + // translation to Bitwuzla's constraint language. Clients should assert + // these. + std::vector sideConstraints; + + BitwuzlaBuilder(bool autoClearConstructCache); + ~BitwuzlaBuilder(); + + Term getTrue(); + Term getFalse(); + Term buildFreshBoolConst(); + Term getInitialRead(const Array *os, unsigned index); + + Term construct(ref e) { + Term res = construct(std::move(e), nullptr); + if (autoClearConstructCache) + clearConstructCache(); + return res; + } + void clearConstructCache() { constructed.clear(); } + void clearSideConstraints() { sideConstraints.clear(); } +}; +} // namespace klee + +#endif diff --git a/lib/Solver/BitwuzlaHashConfig.cpp b/lib/Solver/BitwuzlaHashConfig.cpp new file mode 100644 index 0000000000..4ee8cfe429 --- /dev/null +++ b/lib/Solver/BitwuzlaHashConfig.cpp @@ -0,0 +1,20 @@ +//===-- BitwuzlaHashConfig.cpp ---------------------------------------*- C++ +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "BitwuzlaHashConfig.h" +#include + +namespace BitwuzlaHashConfig { +llvm::cl::opt UseConstructHashBitwuzla( + "use-construct-hash-bitwuzla", + llvm::cl::desc( + "Use hash-consing during Bitwuzla query construction (default=true)"), + llvm::cl::init(true), llvm::cl::cat(klee::ExprCat)); +} // namespace BitwuzlaHashConfig diff --git a/lib/Solver/BitwuzlaHashConfig.h b/lib/Solver/BitwuzlaHashConfig.h new file mode 100644 index 0000000000..a4a2d97bb1 --- /dev/null +++ b/lib/Solver/BitwuzlaHashConfig.h @@ -0,0 +1,25 @@ +//===-- BitwuzlaHashConfig.h -----------------------------------------*- C++ +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_BITWUZLAHASHCONFIG_H +#define KLEE_BITWUZLAHASHCONFIG_H + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/CommandLine.h" +DISABLE_WARNING_POP + +#include + +namespace BitwuzlaHashConfig { +extern llvm::cl::opt UseConstructHashBitwuzla; +} // namespace BitwuzlaHashConfig +#endif // KLEE_BITWUZLAHASHCONFIG_H diff --git a/lib/Solver/BitwuzlaSolver.cpp b/lib/Solver/BitwuzlaSolver.cpp new file mode 100644 index 0000000000..8c7263f0d5 --- /dev/null +++ b/lib/Solver/BitwuzlaSolver.cpp @@ -0,0 +1,990 @@ + +//===-- BitwuzlaSolver.cpp ---------------------------------------*-C++-*-====// +// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Config/config.h" + +#ifdef ENABLE_BITWUZLA + +#include "BitwuzlaBuilder.h" +#include "BitwuzlaSolver.h" + +#include "klee/ADT/Incremental.h" +#include "klee/ADT/SparseStorage.h" +#include "klee/Expr/Assignment.h" +#include "klee/Expr/Constraints.h" +#include "klee/Expr/ExprUtil.h" +#include "klee/Solver/Solver.h" +#include "klee/Solver/SolverImpl.h" +#include "klee/Support/ErrorHandling.h" +#include "klee/Support/FileHandling.h" +#include "klee/Support/OptionCategories.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include + +#include "bitwuzla/cpp/bitwuzla.h" + +namespace { +// NOTE: Very useful for debugging Bitwuzla behaviour. These files can be given +// to the Bitwuzla binary to replay all Bitwuzla API calls using its `-log` +// option. + +llvm::cl::opt BitwuzlaValidateModels( + "debug-bitwuzla-validate-models", llvm::cl::init(false), + llvm::cl::desc( + "When generating Bitwuzla models validate these against the query"), + llvm::cl::cat(klee::SolvingCat)); + +llvm::cl::opt BitwuzlaVerbosityLevel( + "debug-bitwuzla-verbosity", llvm::cl::init(0), + llvm::cl::desc("Bitwuzla verbosity level (default=0)"), + llvm::cl::cat(klee::SolvingCat)); +} // namespace + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/ErrorHandling.h" +DISABLE_WARNING_POP + +namespace { +bool interrupted = false; + +void signal_handler(int signum) { interrupted = true; } +} // namespace + +namespace klee { + +class BitwuzlaTerminator : public bitwuzla::Terminator { +private: + uint64_t time_limit_micro; + time::Point start; + + bool _isTimeout = false; + +public: + BitwuzlaTerminator(uint64_t); + bool terminate() override; + + bool isTimeout() const { return _isTimeout; } +}; + +BitwuzlaTerminator::BitwuzlaTerminator(uint64_t time_limit_micro) + : Terminator(), time_limit_micro(time_limit_micro), + start(time::getWallTime()) {} + +bool BitwuzlaTerminator::terminate() { + time::Point end = time::getWallTime(); + if ((end - start).toMicroseconds() >= time_limit_micro) { + _isTimeout = true; + return true; + } + if (interrupted) { + return true; + } + return false; +} + +using ConstraintFrames = inc_vector>; +using ExprIncMap = inc_umap>; +using BitwuzlaASTIncMap = inc_umap; +using ExprIncSet = + inc_uset, klee::util::ExprHash, klee::util::ExprCmp>; +using BitwuzlaASTIncSet = inc_uset; + +extern void dump(const ConstraintFrames &); + +class ConstraintQuery { +private: + // this should be used when only query is needed, se comment below + ref expr; + +public: + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Bitwuzla works in terms of satisfiability so instead we ask the + // negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + // so this `constraints` field contains: Constraints(X) ∧ ¬ query(X) + ConstraintFrames constraints; + + explicit ConstraintQuery() {} + + explicit ConstraintQuery(const ConstraintFrames &frames, const ref &e) + : expr(e), constraints(frames) {} + explicit ConstraintQuery(ConstraintFrames &&frames, ref &&e) + : expr(std::move(e)), constraints(std::move(frames)) {} + + explicit ConstraintQuery(const Query &q, bool incremental) : expr(q.expr) { + if (incremental) { + for (auto &constraint : q.constraints.cs()) { + constraints.v.push_back(constraint); + constraints.push(); + } + } else { + const auto &other = q.constraints.cs(); + constraints.v.reserve(other.size()); + constraints.v.insert(constraints.v.end(), other.begin(), other.end()); + } + if (q.expr->getWidth() == Expr::Bool && !q.expr->isFalse()) + constraints.v.push_back(NotExpr::create(q.expr)); + } + + size_t size() const { return constraints.v.size(); } + + ref getOriginalQueryExpr() const { return expr; } + + ConstraintQuery withFalse() const { + return ConstraintQuery(ConstraintFrames(constraints), Expr::createFalse()); + } + + std::vector gatherArrays() const { + std::vector arrays; + findObjects(constraints.v.begin(), constraints.v.end(), arrays); + return arrays; + } +}; + +enum class ObjectAssignment { + NotNeeded, + NeededForObjectsFromEnv, + NeededForObjectsFromQuery +}; + +struct BitwuzlaSolverEnv { + using arr_vec = std::vector; + inc_vector objects; + arr_vec objectsForGetModel; + ExprIncMap bitwuzla_ast_expr_to_klee_expr; + BitwuzlaASTIncSet expr_to_track; + inc_umap usedArrayBytes; + ExprIncSet symbolicObjects; + + explicit BitwuzlaSolverEnv() = default; + explicit BitwuzlaSolverEnv(const arr_vec &objects); + + void pop(size_t popSize); + void push(); + void clear(); + + const arr_vec *getObjectsForGetModel(ObjectAssignment oa) const; +}; + +BitwuzlaSolverEnv::BitwuzlaSolverEnv(const arr_vec &objects) + : objectsForGetModel(objects) {} + +void BitwuzlaSolverEnv::pop(size_t popSize) { + if (popSize == 0) + return; + objects.pop(popSize); + objectsForGetModel.clear(); + bitwuzla_ast_expr_to_klee_expr.pop(popSize); + expr_to_track.pop(popSize); + usedArrayBytes.pop(popSize); + symbolicObjects.pop(popSize); +} + +void BitwuzlaSolverEnv::push() { + objects.push(); + bitwuzla_ast_expr_to_klee_expr.push(); + expr_to_track.push(); + usedArrayBytes.push(); + symbolicObjects.push(); +} + +void BitwuzlaSolverEnv::clear() { + objects.clear(); + objectsForGetModel.clear(); + bitwuzla_ast_expr_to_klee_expr.clear(); + expr_to_track.clear(); + usedArrayBytes.clear(); + symbolicObjects.clear(); +} + +const BitwuzlaSolverEnv::arr_vec * +BitwuzlaSolverEnv::getObjectsForGetModel(ObjectAssignment oa) const { + switch (oa) { + case ObjectAssignment::NotNeeded: + return nullptr; + case ObjectAssignment::NeededForObjectsFromEnv: + return &objectsForGetModel; + case ObjectAssignment::NeededForObjectsFromQuery: + return &objects.v; + default: + llvm_unreachable("unknown object assignment"); + } +} + +class BitwuzlaSolverImpl : public SolverImpl { +protected: + std::unique_ptr builder; + Options solverParameters; + +private: + time::Span timeout; + SolverImpl::SolverRunStatus runStatusCode; + + bool internalRunSolver(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, + ValidityCore *validityCore, bool &hasSolution); + + SolverImpl::SolverRunStatus handleSolverResponse( + Bitwuzla &theSolver, Result satisfiable, const BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution); + +protected: + BitwuzlaSolverImpl(); + + virtual Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) = 0; + virtual void deinitNativeBitwuzla(Bitwuzla &theSolver) = 0; + virtual void push(Bitwuzla &s) = 0; + + bool computeTruth(const ConstraintQuery &, BitwuzlaSolverEnv &env, + bool &isValid); + bool computeValue(const ConstraintQuery &, BitwuzlaSolverEnv &env, + ref &result); + bool computeInitialValues(const ConstraintQuery &, BitwuzlaSolverEnv &env, + std::vector> &values, + bool &hasSolution); + bool check(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ref &result); + bool computeValidityCore(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ValidityCore &validityCore, bool &isValid); + +public: + char *getConstraintLog(const Query &) final; + SolverImpl::SolverRunStatus getOperationStatusCode() final; + void setCoreSolverTimeout(time::Span _timeout) final { timeout = _timeout; } + void enableUnsatCore() { + solverParameters.set(Option::PRODUCE_UNSAT_CORES, true); + } + void disableUnsatCore() { + solverParameters.set(Option::PRODUCE_UNSAT_CORES, false); + } + + // pass virtual functions to children + using SolverImpl::check; + using SolverImpl::computeInitialValues; + using SolverImpl::computeTruth; + using SolverImpl::computeValidityCore; + using SolverImpl::computeValue; +}; + +void deleteNativeBitwuzla(std::optional &theSolver) { + theSolver.reset(); +} + +BitwuzlaSolverImpl::BitwuzlaSolverImpl() + : runStatusCode(SolverImpl::SOLVER_RUN_STATUS_FAILURE) { + builder = std::unique_ptr(new BitwuzlaBuilder( + /*autoClearConstructCache=*/false)); + assert(builder && "unable to create BitwuzlaBuilder"); + + solverParameters.set(Option::PRODUCE_MODELS, true); + + setCoreSolverTimeout(timeout); + + if (ProduceUnsatCore) { + enableUnsatCore(); + } else { + disableUnsatCore(); + } + + // Set verbosity + if (BitwuzlaVerbosityLevel > 0) { + solverParameters.set(Option::VERBOSITY, BitwuzlaVerbosityLevel); + } + + if (BitwuzlaValidateModels) { + solverParameters.set(Option::DBG_CHECK_MODEL, true); + } +} + +char *BitwuzlaSolverImpl::getConstraintLog(const Query &query) { + std::stringstream outputLog; + + // We use a different builder here because we don't want to interfere + // with the solver's builder because it may change the solver builder's + // cache. + std::unique_ptr tempBuilder(new BitwuzlaBuilder(false)); + ConstantArrayFinder constant_arrays_in_query; + + std::function(const Term &)> constantsIn = + [&constantsIn](const Term &term) { + if (term.is_const()) { + return std::unordered_set{term}; + } + std::unordered_set symbols; + for (const auto &child : term.children()) { + for (const auto &childsSymbol : constantsIn(child)) { + symbols.emplace(childsSymbol); + } + } + return symbols; + }; + + std::function declareLog = + [&outputLog](const Term &term) { + outputLog << "(declare-fun " << term.str(10) << " () " + << term.sort().str() << ")\n"; + }; + std::function assertLog = [&outputLog](const Term &term) { + outputLog << "(assert " << term.str(10) << ")\n"; + }; + + std::vector assertions; + std::unordered_set assertionSymbols; + + for (auto const &constraint : query.constraints.cs()) { + Term constraintTerm = tempBuilder->construct(constraint); + assertions.push_back(std::move(constraintTerm)); + constant_arrays_in_query.visit(constraint); + } + + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Bitwuzla works in terms of satisfiability so instead we ask the + // the negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + assertions.push_back( + mk_term(Kind::NOT, {tempBuilder->construct(query.expr)})); + constant_arrays_in_query.visit(query.expr); + + for (auto const &constant_array : constant_arrays_in_query.results) { + for (auto const &arrayIndexValueExpr : + tempBuilder->constant_array_assertions[constant_array]) { + assertions.push_back(arrayIndexValueExpr); + } + } + + for (const Term &constraintTerm : assertions) { + std::unordered_set constantsInConstraintTerm = + constantsIn(constraintTerm); + assertionSymbols.insert(constantsInConstraintTerm.begin(), + constantsInConstraintTerm.end()); + } + + for (const Term &symbol : assertionSymbols) { + declareLog(symbol); + } + for (const Term &constraint : assertions) { + assertLog(constraint); + } + + outputLog << "(check-sat)\n"; + + // Client is responsible for freeing the returned C-string + return strdup(outputLog.str().c_str()); +} + +bool BitwuzlaSolverImpl::computeTruth(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, bool &isValid) { + bool hasSolution = false; // to remove compiler warning + bool status = internalRunSolver(query, /*env=*/env, + ObjectAssignment::NotNeeded, /*values=*/NULL, + /*validityCore=*/NULL, hasSolution); + isValid = !hasSolution; + return status; +} + +bool BitwuzlaSolverImpl::computeValue(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ref &result) { + std::vector> values; + bool hasSolution; + + // Find the object used in the expression, and compute an assignment + // for them. + findSymbolicObjects(query.getOriginalQueryExpr(), env.objectsForGetModel); + if (!computeInitialValues(query.withFalse(), env, values, hasSolution)) + return false; + assert(hasSolution && "state has invalid constraint set"); + + // Evaluate the expression with the computed assignment. + Assignment a(env.objectsForGetModel, values); + result = a.evaluate(query.getOriginalQueryExpr()); + + return true; +} + +bool BitwuzlaSolverImpl::computeInitialValues( + const ConstraintQuery &query, BitwuzlaSolverEnv &env, + std::vector> &values, bool &hasSolution) { + return internalRunSolver(query, env, + ObjectAssignment::NeededForObjectsFromEnv, &values, + /*validityCore=*/NULL, hasSolution); +} + +bool BitwuzlaSolverImpl::check(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ref &result) { + std::vector> values; + ValidityCore validityCore; + bool hasSolution = false; + bool status = + internalRunSolver(query, env, ObjectAssignment::NeededForObjectsFromQuery, + &values, &validityCore, hasSolution); + if (status) { + result = hasSolution + ? (SolverResponse *)new InvalidResponse(env.objects.v, values) + : (SolverResponse *)new ValidResponse(validityCore); + } + return status; +} + +bool BitwuzlaSolverImpl::computeValidityCore(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ValidityCore &validityCore, + bool &isValid) { + bool hasSolution = false; // to remove compiler warning + bool status = + internalRunSolver(query, /*env=*/env, ObjectAssignment::NotNeeded, + /*values=*/NULL, &validityCore, hasSolution); + isValid = !hasSolution; + return status; +} + +bool BitwuzlaSolverImpl::internalRunSolver( + const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, + ValidityCore *validityCore, bool &hasSolution) { + TimerStatIncrementer t(stats::queryTime); + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_FAILURE; + + std::unordered_set all_constant_arrays_in_query; + BitwuzlaASTIncSet exprs; + + for (size_t i = 0; i < query.constraints.framesSize(); + i++, env.push(), exprs.push()) { + ConstantArrayFinder constant_arrays_in_query; + env.symbolicObjects.insert(query.constraints.begin(i), + query.constraints.end(i)); + // FIXME: findSymbolicObjects template does not support inc_uset::iterator + // findSymbolicObjects(env.symbolicObjects.begin(-1), + // env.symbolicObjects.end(-1), env.objects.v); + std::vector> tmp(env.symbolicObjects.begin(-1), + env.symbolicObjects.end(-1)); + findSymbolicObjects(tmp.begin(), tmp.end(), env.objects.v); + for (auto cs_it = query.constraints.begin(i), + cs_ite = query.constraints.end(i); + cs_it != cs_ite; cs_it++) { + const auto &constraint = *cs_it; + Term bitwuzlaConstraint = builder->construct(constraint); + if (ProduceUnsatCore && validityCore) { + env.bitwuzla_ast_expr_to_klee_expr.insert( + {bitwuzlaConstraint, constraint}); + env.expr_to_track.insert(bitwuzlaConstraint); + } + + exprs.insert(bitwuzlaConstraint); + + constant_arrays_in_query.visit(constraint); + + std::vector> reads; + findReads(constraint, true, reads); + for (const auto &readExpr : reads) { + auto readFromArray = readExpr->updates.root; + assert(readFromArray); + env.usedArrayBytes[readFromArray].insert(readExpr->index); + } + } + + for (auto constant_array : constant_arrays_in_query.results) { + if (all_constant_arrays_in_query.count(constant_array)) + continue; + all_constant_arrays_in_query.insert(constant_array); + const auto &cas = builder->constant_array_assertions[constant_array]; + exprs.insert(cas.begin(), cas.end()); + } + + // Assert an generated side constraints we have to this last so that all + // other constraints have been traversed so we have all the side constraints + // needed. + exprs.insert(builder->sideConstraints.begin(), + builder->sideConstraints.end()); + } + exprs.pop(1); // drop last empty frame + + ++stats::solverQueries; + if (!env.objects.v.empty()) + ++stats::queryCounterexamples; + + // Prepare signal handler and terminator fot bitwuzla + auto timeoutInMicroSeconds = static_cast(timeout.toMicroseconds()); + if (!timeoutInMicroSeconds) + timeoutInMicroSeconds = UINT_MAX; + BitwuzlaTerminator terminator(timeoutInMicroSeconds); + + struct sigaction action, old_action; + action.sa_handler = signal_handler; + action.sa_flags = 0; + sigaction(SIGINT, &action, &old_action); + + Bitwuzla &theSolver = initNativeBitwuzla(query, exprs); + theSolver.configure_terminator(&terminator); + + for (size_t i = 0; i < exprs.framesSize(); i++) { + push(theSolver); + for (auto it = exprs.begin(i), ie = exprs.end(i); it != ie; ++it) { + theSolver.assert_formula(*it); + } + } + + Result satisfiable = theSolver.check_sat(); + theSolver.configure_terminator(nullptr); + runStatusCode = handleSolverResponse(theSolver, satisfiable, env, needObjects, + values, hasSolution); + sigaction(SIGINT, &old_action, nullptr); + + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_FAILURE) { + if (terminator.isTimeout()) { + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; + } + if (interrupted) { + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED; + } + } + + if (ProduceUnsatCore && validityCore && satisfiable == Result::UNSAT) { + const std::vector bitwuzla_unsat_core = theSolver.get_unsat_core(); + const std::unordered_set bitwuzla_term_unsat_core( + bitwuzla_unsat_core.begin(), bitwuzla_unsat_core.end()); + + constraints_ty unsatCore; + for (const auto &bitwuzla_constraint : env.expr_to_track) { + if (bitwuzla_term_unsat_core.count(bitwuzla_constraint)) { + ref constraint = + env.bitwuzla_ast_expr_to_klee_expr[bitwuzla_constraint]; + unsatCore.insert(constraint); + } + } + assert(validityCore && "validityCore cannot be nullptr"); + *validityCore = ValidityCore(unsatCore, query.getOriginalQueryExpr()); + + stats::validQueriesSize += theSolver.get_assertions().size(); + stats::validityCoresSize += bitwuzla_unsat_core.size(); + ++stats::queryValidityCores; + } + + deinitNativeBitwuzla(theSolver); + + // Clear the builder's cache to prevent memory usage exploding. + // By using ``autoClearConstructCache=false`` and clearning now + // we allow Term expressions to be shared from an entire + // ``Query`` rather than only sharing within a single call to + // ``builder->construct()``. + builder->clearConstructCache(); + builder->clearSideConstraints(); + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE || + runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE) { + if (hasSolution) { + ++stats::queriesInvalid; + } else { + ++stats::queriesValid; + } + return true; // success + } + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED) { + raise(SIGINT); + } + return false; // failed +} + +SolverImpl::SolverRunStatus BitwuzlaSolverImpl::handleSolverResponse( + Bitwuzla &theSolver, Result satisfiable, const BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution) { + switch (satisfiable) { + case Result::SAT: { + hasSolution = true; + auto objects = env.getObjectsForGetModel(needObjects); + if (!objects) { + // No assignment is needed + assert(!values); + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; + } + assert(values && "values cannot be nullptr"); + + values->reserve(objects->size()); + for (auto array : *objects) { + SparseStorage data; + + if (env.usedArrayBytes.count(array)) { + std::unordered_set offsetValues; + for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { + Term arrayElementOffsetExpr = + theSolver.get_value(builder->construct(offsetExpr)); + + uint64_t concretizedOffsetValue = + std::stoull(arrayElementOffsetExpr.value(10)); + offsetValues.insert(concretizedOffsetValue); + } + + for (unsigned offset : offsetValues) { + // We can't use Term here so have to do ref counting manually + Term initial_read = builder->getInitialRead(array, offset); + Term initial_read_expr = theSolver.get_value(initial_read); + + uint64_t arrayElementValue = + std::stoull(initial_read_expr.value(10)); + data.store(offset, arrayElementValue); + } + } + + values->emplace_back(std::move(data)); + } + + assert(values->size() == objects->size()); + + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; + } + case Result::UNSAT: + hasSolution = false; + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; + case Result::UNKNOWN: { + return SolverImpl::SOLVER_RUN_STATUS_FAILURE; + } + default: + llvm_unreachable("unhandled Bitwuzla result"); + } +} + +SolverImpl::SolverRunStatus BitwuzlaSolverImpl::getOperationStatusCode() { + return runStatusCode; +} + +class BitwuzlaNonIncSolverImpl final : public BitwuzlaSolverImpl { +private: + std::optional theSolver; + +public: + BitwuzlaNonIncSolverImpl() = default; + + /// implementation of BitwuzlaSolverImpl interface + Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) override { + theSolver.emplace(solverParameters); + return theSolver.value(); + } + + void deinitNativeBitwuzla(Bitwuzla &) override { + deleteNativeBitwuzla(theSolver); + } + + void push(Bitwuzla &s) override {} + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeTruth(ConstraintQuery(query, false), env, + isValid); + } + bool computeValue(const Query &query, ref &result) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeValue(ConstraintQuery(query, false), env, + result); + } + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override { + BitwuzlaSolverEnv env(objects); + return BitwuzlaSolverImpl::computeInitialValues( + ConstraintQuery(query, false), env, values, hasSolution); + } + bool check(const Query &query, ref &result) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::check(ConstraintQuery(query, false), env, + result); + } + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeValidityCore( + ConstraintQuery(query, false), env, validityCore, isValid); + } + void notifyStateTermination(std::uint32_t id) override {} +}; + +BitwuzlaSolver::BitwuzlaSolver() + : Solver(std::make_unique()) {} + +struct ConstraintDistance { + size_t toPopSize = 0; + ConstraintQuery toPush; + + explicit ConstraintDistance() {} + ConstraintDistance(const ConstraintQuery &q) : toPush(q) {} + explicit ConstraintDistance(size_t toPopSize, const ConstraintQuery &q) + : toPopSize(toPopSize), toPush(q) {} + + size_t getDistance() const { return toPopSize + toPush.size(); } + + bool isOnlyPush() const { return toPopSize == 0; } + + void dump() const { + llvm::errs() << "ConstraintDistance: pop: " << toPopSize << "; push:\n"; + klee::dump(toPush.constraints); + } +}; + +class BitwuzlaIncNativeSolver { +private: + std::optional nativeSolver; + Options solverParameters; + /// underlying solver frames + /// saved only for calculating distances from next queries + ConstraintFrames frames; + + void pop(size_t popSize); + +public: + BitwuzlaSolverEnv env; + std::uint32_t stateID = 0; + bool isRecycled = false; + + BitwuzlaIncNativeSolver(Options solverParameters) + : solverParameters(solverParameters) {} + ~BitwuzlaIncNativeSolver(); + + void clear(); + + void distance(const ConstraintQuery &query, ConstraintDistance &delta) const; + + void popPush(ConstraintDistance &delta); + + Bitwuzla &getOrInit(); + + bool isConsistent() const { + return frames.framesSize() == env.objects.framesSize(); + } + + void dump() const { ::klee::dump(frames); } +}; + +void BitwuzlaIncNativeSolver::pop(size_t popSize) { + if (!nativeSolver.has_value() || !popSize) + return; + nativeSolver.value().pop(popSize); +} + +void BitwuzlaIncNativeSolver::popPush(ConstraintDistance &delta) { + env.pop(delta.toPopSize); + pop(delta.toPopSize); + frames.pop(delta.toPopSize); + frames.extend(delta.toPush.constraints); +} + +Bitwuzla &BitwuzlaIncNativeSolver::getOrInit() { + if (!nativeSolver.has_value()) { + nativeSolver.emplace(solverParameters); + } + return nativeSolver.value(); +} + +BitwuzlaIncNativeSolver::~BitwuzlaIncNativeSolver() { + if (nativeSolver.has_value()) { + deleteNativeBitwuzla(nativeSolver); + } +} + +void BitwuzlaIncNativeSolver::clear() { + if (!nativeSolver.has_value()) + return; + env.clear(); + frames.clear(); + nativeSolver.emplace(solverParameters); + isRecycled = false; +} + +void BitwuzlaIncNativeSolver::distance(const ConstraintQuery &query, + ConstraintDistance &delta) const { + auto sit = frames.v.begin(); + auto site = frames.v.end(); + auto qit = query.constraints.v.begin(); + auto qite = query.constraints.v.end(); + auto it = frames.begin(); + auto ite = frames.end(); + size_t intersect = 0; + for (; it != ite && sit != site && qit != qite && *sit == *qit; it++) { + size_t frame_size = *it; + for (size_t i = 0; + i < frame_size && sit != site && qit != qite && *sit == *qit; + i++, sit++, qit++, intersect++) { + } + } + for (; sit != site && qit != qite && *sit == *qit; + sit++, qit++, intersect++) { + } + size_t toPop, extraTakeFromOther; + ConstraintFrames d; + if (sit == site) { // solver frames ended + toPop = 0; + extraTakeFromOther = 0; + } else { + frames.takeBefore(intersect, toPop, extraTakeFromOther); + } + query.constraints.takeAfter(intersect - extraTakeFromOther, d); + ConstraintQuery q(std::move(d), query.getOriginalQueryExpr()); + delta = ConstraintDistance(toPop, std::move(q)); +} + +class BitwuzlaTreeSolverImpl final : public BitwuzlaSolverImpl { +private: + using solvers_ty = std::vector>; + using solvers_it = solvers_ty::iterator; + + const size_t maxSolvers; + std::unique_ptr currentSolver = nullptr; + solvers_ty solvers; + + void findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta); + void setSolver(solvers_it &it, bool recycle = false); + ConstraintQuery prepare(const Query &q); + +public: + BitwuzlaTreeSolverImpl(size_t maxSolvers) : maxSolvers(maxSolvers){}; + + /// implementation of BitwuzlaSolverImpl interface + Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) override { + return currentSolver->getOrInit(); + } + void deinitNativeBitwuzla(Bitwuzla &theSolver) override { + assert(currentSolver->isConsistent()); + solvers.push_back(std::move(currentSolver)); + } + void push(Bitwuzla &s) override { s.push(1); } + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override; + bool computeValue(const Query &query, ref &result) override; + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override; + bool check(const Query &query, ref &result) override; + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override; + + void notifyStateTermination(std::uint32_t id) override; +}; + +void BitwuzlaTreeSolverImpl::setSolver(solvers_it &it, bool recycle) { + assert(it != solvers.end()); + currentSolver = std::move(*it); + solvers.erase(it); + currentSolver->isRecycled = false; + if (recycle) + currentSolver->clear(); +} + +void BitwuzlaTreeSolverImpl::findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta) { + ConstraintDistance min_delta; + auto min_distance = std::numeric_limits::max(); + auto min_it = solvers.end(); + auto free_it = solvers.end(); + for (auto it = solvers.begin(), ite = min_it; it != ite; it++) { + if ((*it)->isRecycled) + free_it = it; + (*it)->distance(query, delta); + if (delta.isOnlyPush()) { + setSolver(it); + return; + } + auto distance = delta.getDistance(); + if (distance < min_distance) { + min_delta = delta; + min_distance = distance; + min_it = it; + } + } + if (solvers.size() < maxSolvers) { + delta = ConstraintDistance(query); + if (delta.getDistance() < min_distance) { + // it is cheaper to create new solver + if (free_it == solvers.end()) + currentSolver = + std::make_unique(solverParameters); + else + setSolver(free_it, /*recycle=*/true); + return; + } + } + assert(min_it != solvers.end()); + delta = min_delta; + setSolver(min_it); +} + +ConstraintQuery BitwuzlaTreeSolverImpl::prepare(const Query &q) { + ConstraintDistance delta; + ConstraintQuery query(q, true); + findSuitableSolver(query, delta); + assert(currentSolver->isConsistent()); + currentSolver->stateID = q.id; + currentSolver->popPush(delta); + return delta.toPush; +} + +bool BitwuzlaTreeSolverImpl::computeTruth(const Query &query, bool &isValid) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeTruth(q, currentSolver->env, isValid); +} + +bool BitwuzlaTreeSolverImpl::computeValue(const Query &query, + ref &result) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeValue(q, currentSolver->env, result); +} + +bool BitwuzlaTreeSolverImpl::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + auto q = prepare(query); + currentSolver->env.objectsForGetModel = objects; + return BitwuzlaSolverImpl::computeInitialValues(q, currentSolver->env, values, + hasSolution); +} + +bool BitwuzlaTreeSolverImpl::check(const Query &query, + ref &result) { + auto q = prepare(query); + return BitwuzlaSolverImpl::check(q, currentSolver->env, result); +} + +bool BitwuzlaTreeSolverImpl::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeValidityCore(q, currentSolver->env, + validityCore, isValid); +} + +void BitwuzlaTreeSolverImpl::notifyStateTermination(std::uint32_t id) { + for (auto &s : solvers) + if (s->stateID == id) + s->isRecycled = true; +} + +BitwuzlaTreeSolver::BitwuzlaTreeSolver(unsigned maxSolvers) + : Solver(std::make_unique(maxSolvers)) {} + +} // namespace klee +#endif // ENABLE_BITWUZLA diff --git a/lib/Solver/BitwuzlaSolver.h b/lib/Solver/BitwuzlaSolver.h new file mode 100644 index 0000000000..613b416c5a --- /dev/null +++ b/lib/Solver/BitwuzlaSolver.h @@ -0,0 +1,22 @@ +#ifndef BITWUZLASOLVER_H_ +#define BITWUZLASOLVER_H_ + +#include "klee/Solver/Solver.h" + +namespace klee { + +/// BitwuzlaSolver - A complete solver based on Bitwuzla +class BitwuzlaSolver : public Solver { +public: + /// BitwuzlaSolver - Construct a new BitwuzlaSolver. + BitwuzlaSolver(); +}; + +class BitwuzlaTreeSolver : public Solver { +public: + BitwuzlaTreeSolver(unsigned maxSolvers); +}; + +} // namespace klee + +#endif diff --git a/lib/Solver/CMakeLists.txt b/lib/Solver/CMakeLists.txt index a1b15052bc..b4523d1594 100644 --- a/lib/Solver/CMakeLists.txt +++ b/lib/Solver/CMakeLists.txt @@ -7,7 +7,11 @@ # #===------------------------------------------------------------------------===# add_library(kleaverSolver + AlphaEquivalenceSolver.cpp AssignmentValidatingSolver.cpp + BitwuzlaBuilder.cpp + BitwuzlaHashConfig.cpp + BitwuzlaSolver.cpp CachingSolver.cpp CexCachingSolver.cpp ConstantDivision.cpp @@ -48,7 +52,6 @@ target_include_directories(kleaverSolver PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INC target_compile_options(kleaverSolver PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(kleaverSolver PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) - install(TARGETS kleaverSolver EXPORT run_klee DESTINATION "${RUN_KLEE_LIB_DEST}" diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index 0bf904a60a..f01d760d32 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -36,12 +36,12 @@ class CachingSolver : public SolverImpl { struct CacheEntry { CacheEntry(const ConstraintSet &c, ref q) - : constraints(c), query(q) {} + : constraints(c.cs()), query(q) {} CacheEntry(const CacheEntry &ce) : constraints(ce.constraints), query(ce.query) {} - ConstraintSet constraints; + constraints_ty constraints; ref query; bool operator==(const CacheEntry &b) const { @@ -53,7 +53,7 @@ class CachingSolver : public SolverImpl { unsigned operator()(const CacheEntry &ce) const { unsigned result = ce.query->hash(); - for (auto const &constraint : ce.constraints.cs()) { + for (auto const &constraint : ce.constraints) { result ^= constraint->hash(); } @@ -187,30 +187,36 @@ bool CachingSolver::computeValidity(const Query &query, return true; case PValidity::MayBeTrue: { ++stats::queryCacheMisses; - if (!solver->impl->computeTruth(query, tmp)) - return false; - if (tmp) { + bool success = solver->impl->computeTruth(query, tmp); + if (success && tmp) { cacheInsert(query, PValidity::MustBeTrue); result = PValidity::MustBeTrue; return true; - } else { + } else if (success && !tmp) { cacheInsert(query, PValidity::TrueOrFalse); result = PValidity::TrueOrFalse; return true; + } else { + cacheInsert(query, PValidity::MayBeTrue); + result = PValidity::MayBeTrue; + return true; } } case PValidity::MayBeFalse: { ++stats::queryCacheMisses; - if (!solver->impl->computeTruth(query.negateExpr(), tmp)) - return false; - if (tmp) { + bool success = solver->impl->computeTruth(query.negateExpr(), tmp); + if (success && tmp) { cacheInsert(query, PValidity::MustBeFalse); result = PValidity::MustBeFalse; return true; - } else { + } else if (success && !tmp) { cacheInsert(query, PValidity::TrueOrFalse); result = PValidity::TrueOrFalse; return true; + } else { + cacheInsert(query, PValidity::MayBeFalse); + result = PValidity::MayBeFalse; + return true; } } default: @@ -267,50 +273,8 @@ bool CachingSolver::computeTruth(const Query &query, bool &isValid) { bool CachingSolver::computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid) { - PartialValidity cachedResult; - bool tmp, cacheHit = cacheLookup(query, cachedResult); - - // a cached result of MayBeTrue forces us to check whether - // a False assignment exists. - if (cacheHit && cachedResult != PValidity::MayBeTrue) { - ValidityCore cachedValidityCore; - cacheHit = validityCoreCacheLookup(query, cachedValidityCore); - if (cacheHit && cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheHits; - validityCore = cachedValidityCore; - } else if (cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheMisses; - if (!solver->impl->computeValidityCore(query, validityCore, tmp)) - return false; - assert(tmp && "Query must be true!"); - validityCoreCacheInsert(query, validityCore); - } else { - ++stats::queryCacheHits; - } - isValid = (cachedResult == PValidity::MustBeTrue); - return true; - } - ++stats::queryCacheMisses; - - // cache miss: query solver - if (!solver->impl->computeValidityCore(query, validityCore, isValid)) - return false; - - if (isValid) { - cachedResult = PValidity::MustBeTrue; - validityCoreCacheInsert(query, validityCore); - } else if (cacheHit) { - // We know a true assignment exists, and query isn't valid, so - // must be TrueOrFalse. - assert(cachedResult == PValidity::MayBeTrue); - cachedResult = PValidity::TrueOrFalse; - } else { - cachedResult = PValidity::MayBeFalse; - } - - cacheInsert(query, cachedResult); - return true; + return solver->impl->computeValidityCore(query, validityCore, isValid); } bool CachingSolver::computeInitialValues( @@ -322,50 +286,8 @@ bool CachingSolver::computeInitialValues( } bool CachingSolver::check(const Query &query, ref &result) { - PartialValidity cachedResult; - bool tmp, cacheHit = cacheLookup(query, cachedResult); - - // a cached result of MayBeTrue forces us to check whether - // a False assignment exists. - if (cacheHit && cachedResult != PValidity::MayBeTrue) { - ValidityCore cachedValidityCore; - cacheHit = validityCoreCacheLookup(query, cachedValidityCore); - if (cacheHit && cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheHits; - result = new ValidResponse(cachedValidityCore); - } else if (cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheMisses; - if (!solver->impl->computeValidityCore(query, cachedValidityCore, tmp)) - return false; - result = new ValidResponse(cachedValidityCore); - assert(tmp && "Query must be true!"); - } else { - ++stats::queryCacheMisses; - if (!solver->impl->check(query, result)) - return false; - } - return true; - } - ++stats::queryCacheMisses; - - // cache miss: query solver - if (!solver->impl->check(query, result)) - return false; - - if (isa(result)) { - cachedResult = PValidity::MustBeTrue; - } else if (cacheHit) { - // We know a true assignment exists, and query isn't valid, so - // must be TrueOrFalse. - assert(cachedResult == PValidity::MayBeTrue); - cachedResult = PValidity::TrueOrFalse; - } else { - cachedResult = PValidity::MayBeFalse; - } - - cacheInsert(query, cachedResult); - return true; + return solver->impl->check(query, result); } SolverImpl::SolverRunStatus CachingSolver::getOperationStatusCode() { diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 92a209e4f9..038af68e2e 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -93,6 +93,7 @@ class CexCachingSolver : public SolverImpl { } bool getResponse(const Query &query, ref &result); + void setResponse(const Query &query, ref &result); public: CexCachingSolver(std::unique_ptr solver) @@ -128,23 +129,13 @@ struct isInvalidResponse { }; struct isValidOrSatisfyingResponse { - KeyType booleanKey; - KeyType nonBooleanKey; - isValidOrSatisfyingResponse(KeyType &_key) { - for (auto i : _key) { - if (i->getWidth() == Expr::Bool) { - booleanKey.insert(i); - } else { - nonBooleanKey.insert(i); - } - } - } + KeyType key; + isValidOrSatisfyingResponse(KeyType &_key) : key(_key) {} bool operator()(ref a) const { return isa(a) || (isa(a) && - cast(a)->satisfies(booleanKey) && - cast(a)->satisfiesNonBoolean(nonBooleanKey)); + cast(a)->satisfiesOrConstant(key)); } }; @@ -186,7 +177,8 @@ bool CexCachingSolver::searchForResponse(KeyType &key, ie = responseTable.end(); it != ie; ++it) { ref a = *it; - if (isa(a) && cast(a)->satisfies(key)) { + if (isa(a) && + cast(a)->satisfiesOrConstant(key)) { result = a; return true; } @@ -218,6 +210,17 @@ bool CexCachingSolver::searchForResponse(KeyType &key, return false; } +KeyType makeKey(const Query &query) { + KeyType key = + KeyType(query.constraints.cs().begin(), query.constraints.cs().end()); + for (ref s : query.constraints.symcretes()) { + key.insert(s->symcretized); + } + ref neg = Expr::createIsZero(query.expr); + key.insert(neg); + return key; +} + /// lookupResponse - Lookup a cached result for the given \arg query. /// /// \param query - The query to lookup. @@ -227,10 +230,7 @@ bool CexCachingSolver::searchForResponse(KeyType &key, /// an unsatisfiable query). \return True if a cached result was found. bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, ref &result) { - key = KeyType(query.constraints.cs().begin(), query.constraints.cs().end()); - for (ref s : query.constraints.symcretes()) { - key.insert(s->symcretized); - } + key = makeKey(query); ref neg = Expr::createIsZero(query.expr); if (ConstantExpr *CE = dyn_cast(neg)) { if (CE->isFalse()) { @@ -238,8 +238,6 @@ bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, ++stats::queryCexCacheHits; return true; } - } else { - key.insert(neg); } bool found = searchForResponse(key, result); @@ -253,8 +251,7 @@ bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, bool CexCachingSolver::getResponse(const Query &query, ref &result) { - KeyType key; - if (lookupResponse(query, key, result)) { + if (lookupResponse(query, result)) { return true; } @@ -262,6 +259,14 @@ bool CexCachingSolver::getResponse(const Query &query, return false; } + setResponse(query, result); + return true; +} + +void CexCachingSolver::setResponse(const Query &query, + ref &result) { + KeyType key = makeKey(query); + if (isa(result)) { // Memorize the result. std::pair res = @@ -270,12 +275,13 @@ bool CexCachingSolver::getResponse(const Query &query, result = *res.first; } - if (DebugCexCacheCheckBinding) - if (!cast(result)->satisfies(key)) { + if (DebugCexCacheCheckBinding) { + if (!cast(result)->satisfiesOrConstant(key, false)) { query.dump(); result->dump(); klee_error("Generated assignment doesn't match query"); } + } } ValidityCore resultCore; @@ -283,15 +289,13 @@ bool CexCachingSolver::getResponse(const Query &query, result->tryGetValidityCore(resultCore); KeyType resultCoreConstarints(resultCore.constraints.begin(), resultCore.constraints.end()); - ref neg = Expr::createIsZero(query.expr); + ref neg = Expr::createIsZero(resultCore.expr); resultCoreConstarints.insert(neg); cache.insert(resultCoreConstarints, result); } if (isa(result) || isa(result)) { cache.insert(key, result); } - - return true; } /// @@ -307,21 +311,19 @@ bool CexCachingSolver::computeValidity(const Query &query, return false; if (cast(q)->isTrue()) { - if (!getResponse(query, a)) - return false; - if (isa(a)) { + bool success = getResponse(query, a); + if (success && isa(a)) { result = PValidity::MustBeTrue; - } else if (isa(a)) { + } else if (success && isa(a)) { result = PValidity::TrueOrFalse; } else { result = PValidity::MayBeTrue; } } else { - if (!getResponse(query.negateExpr(), a)) - return false; - if (isa(a)) { + bool success = getResponse(query.negateExpr(), a); + if (success && isa(a)) { result = PValidity::MustBeFalse; - } else if (isa(a)) { + } else if (success && isa(a)) { result = PValidity::TrueOrFalse; } else { result = PValidity::MayBeFalse; @@ -375,6 +377,12 @@ bool CexCachingSolver::computeValue(const Query &query, ref &result) { assert(isa(result) && "assignment evaluation did not result in constant"); + + if (cast(result)->isTrue()) { + setResponse(query.negateExpr(), a); + } else if (cast(result)->isFalse()) { + setResponse(query, a); + } return true; } @@ -393,10 +401,11 @@ bool CexCachingSolver::computeInitialValues( // FIXME: We should use smarter assignment for result so we don't // need redundant copy. values = std::vector>(objects.size()); + Assignment::bindings_ty aBindings; + a->tryGetInitialValues(aBindings); + for (unsigned i = 0; i < objects.size(); ++i) { const Array *os = objects[i]; - Assignment::bindings_ty aBindings; - a->tryGetInitialValues(aBindings); Assignment::bindings_ty::iterator it = aBindings.find(os); if (it == aBindings.end()) { @@ -404,8 +413,7 @@ bool CexCachingSolver::computeInitialValues( cast(a)->evaluate(os->size); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - values[i] = - SparseStorage(arrayConstantSize->getZExtValue(), 0); + values[i] = SparseStorage(0); } else { values[i] = it->second; } diff --git a/lib/Solver/ConcretizingSolver.cpp b/lib/Solver/ConcretizingSolver.cpp index c2d717ceed..645d1863f4 100644 --- a/lib/Solver/ConcretizingSolver.cpp +++ b/lib/Solver/ConcretizingSolver.cpp @@ -3,6 +3,7 @@ #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Symcrete.h" @@ -378,7 +379,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, sizeSymcrete->addressSymcrete.symcretized, newSize); unsigned char *charAddressIterator = reinterpret_cast(&address); - SparseStorage storage(sizeof(address)); + SparseStorage storage(0); storage.store(0, charAddressIterator, charAddressIterator + sizeof(address)); diff --git a/lib/Solver/ConstructSolverChain.cpp b/lib/Solver/ConstructSolverChain.cpp index f8c9c8d522..c734db9c64 100644 --- a/lib/Solver/ConstructSolverChain.cpp +++ b/lib/Solver/ConstructSolverChain.cpp @@ -34,7 +34,7 @@ std::unique_ptr constructSolverChain( std::unique_ptr coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath, - AddressGenerator *addressGenerator) { + AddressGenerator *addressGenerator, ArrayCache &arrayCache) { Solver *rawCoreSolver = coreSolver.get(); std::unique_ptr solver = std::move(coreSolver); const time::Span minQueryTimeToLog(MinQueryTimeToLog); @@ -67,6 +67,9 @@ std::unique_ptr constructSolverChain( if (UseBranchCache) solver = createCachingSolver(std::move(solver)); + if (UseAlphaEquivalence) + solver = createAlphaEquivalenceSolver(std::move(solver), arrayCache); + if (UseIndependentSolver) solver = createIndependentSolver(std::move(solver)); diff --git a/lib/Solver/CoreSolver.cpp b/lib/Solver/CoreSolver.cpp index ff6f9cf76e..a82dfc6a44 100644 --- a/lib/Solver/CoreSolver.cpp +++ b/lib/Solver/CoreSolver.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "BitwuzlaSolver.h" #include "MetaSMTSolver.h" #include "STPSolver.h" #include "Z3Solver.h" @@ -28,7 +29,7 @@ DISABLE_WARNING_POP namespace klee { std::unique_ptr createCoreSolver(CoreSolverType cst) { - bool isTreeSolver = cst == Z3_TREE_SOLVER; + bool isTreeSolver = (cst == Z3_TREE_SOLVER || cst == BITWUZLA_TREE_SOLVER); if (!isTreeSolver && MaxSolversApproxTreeInc > 0) klee_warning("--%s option is ignored because --%s is not z3-tree", MaxSolversApproxTreeInc.ArgStr.str().c_str(), @@ -74,13 +75,28 @@ std::unique_ptr createCoreSolver(CoreSolverType cst) { if (isTreeSolver) { if (MaxSolversApproxTreeInc > 0) return std::make_unique(type, MaxSolversApproxTreeInc); - klee_warning("--%s is 0, so falling back to non tree-incremental solver", + klee_warning("--%s is 0, so falling back to non tree-incremental solver ", MaxSolversApproxTreeInc.ArgStr.str().c_str()); } return std::make_unique(type); #else klee_message("Not compiled with Z3 support"); return NULL; +#endif + case BITWUZLA_TREE_SOLVER: + case BITWUZLA_SOLVER: +#ifdef ENABLE_BITWUZLA + klee_message("Using Bitwuzla solver backend"); + if (isTreeSolver) { + if (MaxSolversApproxTreeInc > 0) + return std::make_unique(MaxSolversApproxTreeInc); + klee_warning("--%s is 0, so falling back to non tree-incremental solver", + MaxSolversApproxTreeInc.ArgStr.str().c_str()); + } + return std::make_unique(); +#else + klee_message("Not compiled with Bitwuzla support"); + return NULL; #endif case NO_SOLVER: klee_message("Invalid solver"); diff --git a/lib/Solver/FastCexSolver.cpp b/lib/Solver/FastCexSolver.cpp index 3276b3d1be..f4c1b377aa 100644 --- a/lib/Solver/FastCexSolver.cpp +++ b/lib/Solver/FastCexSolver.cpp @@ -389,13 +389,9 @@ class CexRangeEvaluator : public ExprRangeEvaluator { if (array.isConstantArray() && index.isFixed()) { if (ref constantSource = dyn_cast(array.source)) { - if (index.min() < constantSource->constantValues.size()) { - return ValueRange( - constantSource->constantValues[index.min()]->getZExtValue(8)); + if (auto value = constantSource->constantValues.load(index.min())) { + return ValueRange(value->getZExtValue(8)); } - } else if (ref symbolicSizeConstantSource = - dyn_cast(array.source)) { - return ValueRange(symbolicSizeConstantSource->defaultValue); } } return ValueRange(0, 255); @@ -896,10 +892,11 @@ class CexData { if (ref constantSource = dyn_cast(array->source)) { // Verify the range. - propagateExactValues(constantSource->constantValues[index.min()], + if (!isa(array->size)) { + assert(0 && "Unimplemented"); + } + propagateExactValues(constantSource->constantValues.load(index.min()), range); - } else if (isa(array->source)) { - assert(0 && "not implemented"); } else { CexValueData cvd = cod.getExactValues(index.min()); if (range.min() > cvd.min()) { @@ -1195,7 +1192,6 @@ bool FastCexSolver::computeInitialValues( dyn_cast(cd.evaluatePossible(array->size)); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - data.resize(arrayConstantSize->getZExtValue()); for (unsigned i = 0; i < arrayConstantSize->getZExtValue(); i++) { ref read = ReadExpr::create( diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index 67c0309335..56cf4d043c 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -225,7 +225,7 @@ bool IndependentSolver::computeInitialValues( dyn_cast(retMap.evaluate(arr->size)); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - SparseStorage ret(arrayConstantSize->getZExtValue()); + SparseStorage ret(0); values.push_back(ret); } else { values.push_back(retMap.bindings.at(arr)); diff --git a/lib/Solver/MetaSMTBuilder.h b/lib/Solver/MetaSMTBuilder.h index b2418b8f91..6944402788 100644 --- a/lib/Solver/MetaSMTBuilder.h +++ b/lib/Solver/MetaSMTBuilder.h @@ -216,10 +216,11 @@ MetaSMTBuilder::getInitialArray(const Array *root) { bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); if (!hashed) { - if (isa(root->source)) { - llvm::report_fatal_error("MetaSMT does not support constant arrays or " - "quantifiers to instantiate " - "constant array of symbolic size!"); + if (ref constantSource = + dyn_cast(root->source)) { + if (!isa(root->size)) { + assert(0 && "MetaSMT does not support symsize constant arrays"); + } } array_expr = @@ -227,14 +228,14 @@ MetaSMTBuilder::getInitialArray(const Array *root) { if (ref constantSource = dyn_cast(root->source)) { - uint64_t constantSize = cast(root->size)->getZExtValue(); - for (unsigned i = 0, e = constantSize; i != e; ++i) { + auto constantSize = cast(root->size)->getZExtValue(); + for (unsigned i = 0; i < constantSize; ++i) { typename SolverContext::result_type tmp = evaluate( _solver, metaSMT::logic::Array::store( array_expr, construct(ConstantExpr::alloc(i, root->getDomain()), 0), - construct(constantSource->constantValues[i], 0))); + construct(constantSource->constantValues.load(i), 0))); array_expr = tmp; } } @@ -705,6 +706,33 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { ReadExpr *re = cast(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); + + if (auto constantSource = + dyn_cast(re->updates.root->source)) { + if (!isa(re->updates.root->size)) { + ref selectExpr = constantSource->constantValues.defaultV(); + for (const auto &[index, value] : + constantSource->constantValues.storage()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + std::vector update_nodes; + auto un = re->updates.head.get(); + for (; un; un = un->next.get()) { + update_nodes.push_back(un); + } + + for (auto it = update_nodes.rbegin(); it != update_nodes.rend(); ++it) { + selectExpr = + SelectExpr::create(EqExpr::create(re->index, (*it)->index), + (*it)->value, selectExpr); + } + return construct(selectExpr, width_out); + } + } + // FixMe call method of Array res = evaluate(_solver, metaSMT::logic::Array::select( getArrayForUpdate(re->updates.root, diff --git a/lib/Solver/MetaSMTSolver.cpp b/lib/Solver/MetaSMTSolver.cpp index f162013864..55ba6a4b4a 100644 --- a/lib/Solver/MetaSMTSolver.cpp +++ b/lib/Solver/MetaSMTSolver.cpp @@ -261,14 +261,7 @@ SolverImpl::SolverRunStatus MetaSMTSolverImpl::runAndGetCex( typename SolverContext::result_type array_exp = _builder->getInitialArray(array); - size_t constantSize = 0; - if (ref sizeExpr = dyn_cast(array->size)) { - constantSize = sizeExpr->getZExtValue(); - } else { - constantSize = - read_value(_meta_solver, _builder->construct(array->size)); - } - SparseStorage data(constantSize, 0); + SparseStorage data(0); for (unsigned offset : readOffsets.at(array)) { typename SolverContext::result_type elem_exp = evaluate( @@ -415,7 +408,6 @@ MetaSMTSolverImpl::runAndGetCexForked( values = std::vector>(objects.size()); for (unsigned i = 0; i < objects.size(); ++i) { SparseStorage &data = values[i]; - data.resize(shared_memory_sizes_ptr[i]); data.store(0, pos, pos + shared_memory_sizes_ptr[i]); pos += shared_memory_sizes_ptr[i]; } diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp index 3ee8fbe2b7..b766111ed7 100644 --- a/lib/Solver/STPBuilder.cpp +++ b/lib/Solver/STPBuilder.cpp @@ -426,6 +426,14 @@ ExprHandle STPBuilder::constructSDivByConstant(ExprHandle expr_n, ::VCExpr STPBuilder::getInitialArray(const Array *root) { assert(root); + + if (ref constantSource = + dyn_cast(root->source)) { + if (!isa(root->size)) { + assert(0 && "STP does not support symsize constant arrays"); + } + } + ::VCExpr array_expr; bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); @@ -433,13 +441,7 @@ ::VCExpr STPBuilder::getInitialArray(const Array *root) { // STP uniques arrays by name, so we make sure the name is unique by // using the size of the array hash as a counter. std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); - std::string unique_name = root->getName() + unique_id; - - if (isa(root->source)) { - llvm::report_fatal_error( - "STP does not support constant arrays or quantifiers to instantiate " - "constant array of symbolic size!"); - } + std::string unique_name = root->getIdentifier() + unique_id; array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); @@ -450,13 +452,13 @@ ::VCExpr STPBuilder::getInitialArray(const Array *root) { // using assertions, which is much faster, but we need to fix the caching // to work correctly in that case. + auto constSize = cast(root->size)->getZExtValue(); // TODO: usage of `constantValues.size()` seems unconvinient. - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { + for (unsigned i = 0; i < constSize; i++) { ::VCExpr prev = array_expr; array_expr = vc_writeExpr( vc, prev, construct(ConstantExpr::alloc(i, root->getDomain()), 0), - construct(constantSource->constantValues[i], 0)); + construct(constantSource->constantValues.load(i), 0)); vc_DeleteExpr(prev); } } @@ -568,6 +570,33 @@ ExprHandle STPBuilder::constructActual(ref e, int *width_out) { ReadExpr *re = cast(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); + + if (auto constantSource = + dyn_cast(re->updates.root->source)) { + if (!isa(re->updates.root->size)) { + ref selectExpr = constantSource->constantValues.defaultV(); + for (const auto &[index, value] : + constantSource->constantValues.storage()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + std::vector update_nodes; + auto un = re->updates.head.get(); + for (; un; un = un->next.get()) { + update_nodes.push_back(un); + } + + for (auto it = update_nodes.rbegin(); it != update_nodes.rend(); ++it) { + selectExpr = + SelectExpr::create(EqExpr::create(re->index, (*it)->index), + (*it)->value, selectExpr); + } + return construct(selectExpr, width_out); + } + } + return vc_readExpr( vc, getArrayForUpdate(re->updates.root, re->updates.head.get()), construct(re->index, 0)); diff --git a/lib/Solver/STPSolver.cpp b/lib/Solver/STPSolver.cpp index 5927a90038..86679cc898 100644 --- a/lib/Solver/STPSolver.cpp +++ b/lib/Solver/STPSolver.cpp @@ -392,7 +392,7 @@ runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q, values.reserve(objects.size()); for (unsigned idx = 0; idx < objects.size(); ++idx) { uint64_t objectSize = shared_memory_object_sizes[idx]; - values.emplace_back(objectSize, 0); + values.emplace_back(0); values.back().store(0, pos, pos + objectSize); pos += objectSize; } diff --git a/lib/Solver/SolverCmdLine.cpp b/lib/Solver/SolverCmdLine.cpp index 0f51525d53..41f8324e7c 100644 --- a/lib/Solver/SolverCmdLine.cpp +++ b/lib/Solver/SolverCmdLine.cpp @@ -56,6 +56,11 @@ cl::opt UseBranchCache("use-branch-cache", cl::init(true), cl::desc("Use the branch cache (default=true)"), cl::cat(SolvingCat)); +cl::opt + UseAlphaEquivalence("use-alpha-equivalence", cl::init(true), + cl::desc("Use the alpha version builder(default=true)"), + cl::cat(SolvingCat)); + cl::opt UseConcretizingSolver("use-concretizing-solver", cl::init(true), cl::desc("Use concretization manager(default=true)"), @@ -181,15 +186,23 @@ cl::opt MetaSMTBackend( #endif /* ENABLE_METASMT */ // Pick the default core solver based on configuration -#ifdef ENABLE_Z3 +#ifdef ENABLE_BITWUZLA +#define STP_IS_DEFAULT_STR "" +#define METASMT_IS_DEFAULT_STR "" +#define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR " (default)" +#define DEFAULT_CORE_SOLVER BITWUZLA_SOLVER +#elif ENABLE_Z3 #define STP_IS_DEFAULT_STR "" #define METASMT_IS_DEFAULT_STR "" #define Z3_IS_DEFAULT_STR " (default)" +#define BITWUZLA_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER Z3_SOLVER #elif ENABLE_STP #define STP_IS_DEFAULT_STR " (default)" #define METASMT_IS_DEFAULT_STR "" #define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER STP_SOLVER #elif ENABLE_METASMT #define STP_IS_DEFAULT_STR "" @@ -197,6 +210,7 @@ cl::opt MetaSMTBackend( #define Z3_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER METASMT_SOLVER #define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR "" #else #error "Unsupported solver configuration" #endif @@ -204,6 +218,10 @@ cl::opt MetaSMTBackend( cl::opt CoreSolverToUse( "solver-backend", cl::desc("Specifiy the core solver backend to use"), cl::values( + clEnumValN(BITWUZLA_SOLVER, "bitwuzla", + "Bitwuzla" BITWUZLA_IS_DEFAULT_STR), + clEnumValN(BITWUZLA_TREE_SOLVER, "bitwuzla-tree", + "Bitwuzla tree-incremental solver"), clEnumValN(STP_SOLVER, "stp", "STP" STP_IS_DEFAULT_STR), clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT" METASMT_IS_DEFAULT_STR), clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), @@ -219,6 +237,7 @@ cl::opt DebugCrossCheckCoreSolverWith( clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT"), clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), clEnumValN(Z3_SOLVER, "z3", "Z3"), + clEnumValN(BITWUZLA_SOLVER, "bitwuzla", "Bitwuzla"), clEnumValN(NO_SOLVER, "none", "Do not crosscheck (default)")), cl::init(NO_SOLVER), cl::cat(SolvingCat)); @@ -230,11 +249,12 @@ llvm::cl::opt llvm::cl::opt SymbolicAllocationThreshold( "symbolic-allocation-threshold", llvm::cl::desc("Maximum possible sum of sizes for all symbolic allocation " - "before minimazation (default 1Kb)"), + "before minimization (default 1Kb)"), llvm::cl::init(1024), llvm::cl::cat(klee::SolvingCat)); } // namespace klee #undef STP_IS_DEFAULT_STR #undef METASMT_IS_DEFAULT_STR #undef Z3_IS_DEFAULT_STR +#undef BITWUZLA_IS_DEFAULT_STR #undef DEFAULT_CORE_SOLVER diff --git a/lib/Solver/SolverImpl.cpp b/lib/Solver/SolverImpl.cpp index 2768ce3ce9..e1d3ab3513 100644 --- a/lib/Solver/SolverImpl.cpp +++ b/lib/Solver/SolverImpl.cpp @@ -18,27 +18,41 @@ using namespace klee; SolverImpl::~SolverImpl() {} bool SolverImpl::computeValidity(const Query &query, PartialValidity &result) { + bool trueSuccess, falseSuccess; bool isTrue, isFalse; - if (!computeTruth(query, isTrue)) - return false; - if (isTrue) { + trueSuccess = computeTruth(query, isTrue); + if (trueSuccess && isTrue) { result = PValidity::MustBeTrue; } else { - if (!computeTruth(query.negateExpr(), isFalse)) - return false; - result = isFalse ? PValidity::MustBeFalse : PValidity::TrueOrFalse; + falseSuccess = computeTruth(query.negateExpr(), isFalse); + if (falseSuccess && isFalse) { + result = PValidity::MustBeFalse; + } else { + if (trueSuccess && falseSuccess) { + result = PValidity::TrueOrFalse; + } else if (!trueSuccess) { + result = PValidity::MayBeTrue; + } else if (!falseSuccess) { + result = PValidity::MayBeFalse; + } else { + result = PValidity::None; + } + } } - return true; + return result != PValidity::None; } bool SolverImpl::computeValidity(const Query &query, ref &queryResult, ref &negatedQueryResult) { - if (!check(query, queryResult)) - return false; - if (!check(query.negateExpr(), negatedQueryResult)) - return false; - return true; + if (!check(query, queryResult)) { + queryResult = new UnknownResponse(); + } + if (!check(query.negateExpr(), negatedQueryResult)) { + negatedQueryResult = new UnknownResponse(); + } + return !isa(queryResult) || + !isa(negatedQueryResult); } bool SolverImpl::check(const Query &query, ref &result) { diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index e80feae88c..7cc873980c 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -13,6 +13,7 @@ #include "klee/ADT/Bits.h" #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" +#include "klee/Module/KModule.h" #include "klee/Solver/Solver.h" #include "klee/Solver/SolverStats.h" #include "klee/Support/ErrorHandling.h" @@ -252,35 +253,77 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { // using the size of the array hash as a counter. std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); std::string unique_name = root->getIdentifier() + unique_id; - if (ref symbolicSizeConstantSource = - dyn_cast(root->source)) { + + auto source = dyn_cast(root->source); + auto value = (source ? source->constantValues.defaultV() : nullptr); + if (source) { + assert(value); + } + + if (source && !isa(root->size)) { array_expr = buildConstantArray(unique_name.c_str(), root->getDomain(), - root->getRange(), - symbolicSizeConstantSource->defaultValue); + root->getRange(), value->getZExtValue(8)); + } else if (ref mockDeterministicSource = + dyn_cast(root->source)) { + size_t num_args = mockDeterministicSource->args.size(); + std::vector args(num_args); + std::vector argsSort(num_args); + for (size_t i = 0; i < num_args; i++) { + ref kid = mockDeterministicSource->args[i]; + int kidWidth = kid->getWidth(); + Z3ASTHandle argsHandle = construct(kid, &kidWidth); + args[i] = argsHandle; + Z3SortHandle z3SortHandle = + Z3SortHandle(Z3_get_sort(ctx, args[i]), ctx); + argsSort[i] = z3SortHandle; + } + + Z3SortHandle domainSort = getBvSort(root->getDomain()); + Z3SortHandle rangeSort = getBvSort(root->getRange()); + Z3SortHandle retValSort = getArraySort(domainSort, rangeSort); + + Z3FuncDeclHandle func; + func = Z3FuncDeclHandle( + Z3_mk_func_decl( + ctx, + Z3_mk_string_symbol( + ctx, + mockDeterministicSource->function.getName().str().c_str()), + num_args, argsSort.data(), retValSort), + ctx); + array_expr = + Z3ASTHandle(Z3_mk_app(ctx, func, num_args, args.data()), ctx); } else { array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); } - if (root->isConstantArray() && constant_array_assertions.count(root) == 0) { - std::vector array_assertions; - if (ref constantSource = - dyn_cast(root->source)) { - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { + if (source) { + if (auto constSize = dyn_cast(root->size)) { + std::vector array_assertions; + for (size_t i = 0; i < constSize->getZExtValue(); i++) { + auto value = source->constantValues.load(i); // construct(= (select i root) root->value[i]) to be asserted in // Z3Solver.cpp int width_out; - Z3ASTHandle array_value = - construct(constantSource->constantValues[i], &width_out); + Z3ASTHandle array_value = construct(value, &width_out); assert(width_out == (int)root->getRange() && "Value doesn't match root range"); array_assertions.push_back( eqExpr(readExpr(array_expr, bvConst32(root->getDomain(), i)), array_value)); } + constant_array_assertions[root] = std::move(array_assertions); + } else { + for (auto &[index, value] : source->constantValues.storage()) { + int width_out; + Z3ASTHandle array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } } - constant_array_assertions[root] = std::move(array_assertions); } _arr_hash.hashArrayExpr(root, array_expr); diff --git a/lib/Solver/Z3Builder.h b/lib/Solver/Z3Builder.h index 7b407c6e3d..e6d10fed10 100644 --- a/lib/Solver/Z3Builder.h +++ b/lib/Solver/Z3Builder.h @@ -91,6 +91,13 @@ typedef Z3NodeHandle Z3SortHandle; template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); +// Specialize for Z3_func_decl +template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { + return ::Z3_func_decl_to_ast(context, node); +} +typedef Z3NodeHandle Z3FuncDeclHandle; +template <> void Z3NodeHandle::dump() const __attribute__((used)); + // Specialise for Z3_ast template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { return node; diff --git a/lib/Solver/Z3Solver.cpp b/lib/Solver/Z3Solver.cpp index d5f2232a6e..a485ebe83e 100644 --- a/lib/Solver/Z3Solver.cpp +++ b/lib/Solver/Z3Solver.cpp @@ -551,8 +551,8 @@ bool Z3SolverImpl::internalRunSolver( } for (auto constant_array : constant_arrays_in_query.results) { - assert(builder->constant_array_assertions.count(constant_array) == 1 && - "Constant array found in query, but not handled by Z3Builder"); + // assert(builder->constant_array_assertions.count(constant_array) == 1 && + // "Constant array found in query, but not handled by Z3Builder"); if (all_constant_arrays_in_query.count(constant_array)) continue; all_constant_arrays_in_query.insert(constant_array); @@ -701,7 +701,6 @@ SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( Z3_get_numeral_uint64(builder->ctx, arraySizeExpr, &arraySize); assert(success && "Failed to get size"); - data.resize(arraySize); if (env.usedArrayBytes.count(array)) { std::unordered_set offsetValues; for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { @@ -853,7 +852,8 @@ class Z3NonIncSolverImpl final : public Z3SolverImpl { auto arrays = query.gatherArrays(); bool forceTactic = true; for (auto array : arrays) { - if (isa(array->source)) { + if (isa(array->source) && + !isa(array->size)) { forceTactic = false; break; } diff --git a/optional b/optional deleted file mode 160000 index 0723abd03b..0000000000 --- a/optional +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0723abd03b25fb11997fcb6cff6471408fc33072 diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index ada82c0f33..d1c8a17d2f 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -90,12 +90,14 @@ add_subdirectory(Freestanding) add_subdirectory(Intrinsic) add_subdirectory(klee-libc) add_subdirectory(Fortify) +add_subdirectory(Mocks) set(RUNTIME_LIBRARIES RuntimeFreestanding RuntimeIntrinsic RuntimeKLEELibc RuntimeFortify + RuntimeMocks ) if (ENABLE_KLEE_EH_CXX) diff --git a/runtime/Mocks/CMakeLists.txt b/runtime/Mocks/CMakeLists.txt new file mode 100644 index 0000000000..efd6497470 --- /dev/null +++ b/runtime/Mocks/CMakeLists.txt @@ -0,0 +1,19 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +set(LIB_PREFIX "RuntimeMocks") +set(SRC_FILES + models.c + ) + +# Build it +include("${CMAKE_SOURCE_DIR}/cmake/compile_bitcode_library.cmake") +prefix_with_path("${SRC_FILES}" "${CMAKE_CURRENT_SOURCE_DIR}/" runtime_mocks_files) + +add_bitcode_library_targets("${LIB_PREFIX}" "${runtime_mocks_files}" "" "") diff --git a/runtime/Mocks/models.c b/runtime/Mocks/models.c new file mode 100644 index 0000000000..e40b0cfaa0 --- /dev/null +++ b/runtime/Mocks/models.c @@ -0,0 +1,45 @@ +//===-- models.c ----------------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "stddef.h" + +extern void klee_make_symbolic(void *array, size_t nbytes, const char *name); +extern void *malloc(size_t size); +extern void *calloc(size_t num, size_t size); +extern void *realloc(void *ptr, size_t new_size); + +void *__klee_wrapped_malloc(size_t size) { + unsigned char retNull; + klee_make_symbolic(&retNull, sizeof(retNull), "retNullMalloc"); + if (retNull) { + return 0; + } + void *array = malloc(size); + return array; +} + +void *__klee_wrapped_calloc(size_t num, size_t size) { + unsigned char retNull; + klee_make_symbolic(&retNull, sizeof(retNull), "retNullCalloc"); + if (retNull) { + return 0; + } + void *array = calloc(num, size); + return array; +} + +void *__klee_wrapped_realloc(void *ptr, size_t new_size) { + unsigned char retNull; + klee_make_symbolic(&retNull, sizeof(retNull), "retNullRealloc"); + if (retNull) { + return 0; + } + void *array = realloc(ptr, new_size); + return array; +} diff --git a/runtime/POSIX/input_output.c b/runtime/POSIX/input_output.c index afed9e3d0d..14daa68af8 100644 --- a/runtime/POSIX/input_output.c +++ b/runtime/POSIX/input_output.c @@ -2,6 +2,7 @@ #include #include #include +#include /* * Return the (stdio) flags for a given mode. Store the flags @@ -53,8 +54,13 @@ FILE *fopen(const char *file, const char *mode) { if ((f = open(file, oflags)) < 0) return NULL; } +#ifndef __FreeBSD__ fp->_fileno = f; fp->_mode = oflags; +#else + fp->_file = f; + fp->_flags = oflags; +#endif return fp; } @@ -68,7 +74,11 @@ int get_file_descriptor(FILE *stream) { if (stream == stderr) { return 2; } +#ifndef __FreeBSD__ return stream->_fileno; +#else + return stream->_file; +#endif } int fgetc(FILE *stream) { @@ -86,6 +96,7 @@ int fgetc(FILE *stream) { } } +#ifndef __FreeBSD__ int getc(FILE *stream) { if (stream == NULL) { return 0; @@ -100,6 +111,7 @@ int getc(FILE *stream) { return EOF; } } +#endif size_t fread(void *buffer, size_t size, size_t count, FILE *stream) { if (stream == NULL) { @@ -137,7 +149,9 @@ char *fgets(char *s, int n, FILE *stream) { return s; } +#ifndef __FreeBSD__ int getchar(void) { return getc(stdin); } +#endif char *gets(char *s) { char *p = s; @@ -174,6 +188,7 @@ int fputc(int c, FILE *stream) { } } +#ifndef __FreeBSD__ int putc(int c, FILE *stream) { if (stream == NULL) { return 0; @@ -188,6 +203,7 @@ int putc(int c, FILE *stream) { return EOF; } } +#endif size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream) { if (stream == NULL) { @@ -221,7 +237,9 @@ int fputs(const char *str, FILE *stream) { return 1; } +#ifndef __FreeBSD__ int putchar(int c) { return putc(c, stdout); } +#endif int puts(const char *str) { int write_code = fputs(str, stdout); diff --git a/runtime/Runtest/CMakeLists.txt b/runtime/Runtest/CMakeLists.txt index df5f2c23be..33d190a262 100644 --- a/runtime/Runtest/CMakeLists.txt +++ b/runtime/Runtest/CMakeLists.txt @@ -9,6 +9,8 @@ add_library(kleeRuntest SHARED intrinsics.c + # Mocks: + ${CMAKE_SOURCE_DIR}/runtime/Mocks/models.c # HACK: ${CMAKE_SOURCE_DIR}/lib/Basic/KTest.cpp ) diff --git a/runtime/Runtest/intrinsics.c b/runtime/Runtest/intrinsics.c index 34a9e9d2c8..5402908de2 100644 --- a/runtime/Runtest/intrinsics.c +++ b/runtime/Runtest/intrinsics.c @@ -43,7 +43,10 @@ static void report_internal_error(const char *msg, ...) { va_end(ap); fprintf(stderr, "\n"); char *testErrorsNonFatal = getenv("KLEE_RUN_TEST_ERRORS_NON_FATAL"); - if (testErrorsNonFatal) { + if (testErrorsNonFatal && !strcmp(testErrorsNonFatal, "STOP")) { + fprintf(stderr, "KLEE_RUN_TEST_ERROR: Stop execution without an error\n"); + exit(0); + } else if (testErrorsNonFatal && !strcmp(testErrorsNonFatal, "FORCE")) { fprintf(stderr, "KLEE_RUN_TEST_ERROR: Forcing execution to continue\n"); } else { exit(1); @@ -72,8 +75,7 @@ void recursively_allocate(KTestObject *obj, size_t index, void *addr, return; } -void klee_make_symbolic(void *array, size_t nbytes, const char *name) { - +static void klee_make_symbol(void *array, size_t nbytes, const char *name) { if (!name) name = "unnamed"; @@ -154,6 +156,14 @@ void klee_make_symbolic(void *array, size_t nbytes, const char *name) { } } +void klee_make_symbolic(void *array, size_t nbytes, const char *name) { + klee_make_symbol(array, nbytes, name); +} + +void klee_make_mock(void *ret_array, size_t ret_nbytes, const char *fname) { + klee_make_symbol(ret_array, ret_nbytes, fname); +} + void klee_silent_exit(int x) { exit(x); } uintptr_t klee_choose(uintptr_t n) { diff --git a/runtime/klee-fp/CMakeLists.txt b/runtime/klee-fp/CMakeLists.txt index 0314ca9c50..42b2829004 100644 --- a/runtime/klee-fp/CMakeLists.txt +++ b/runtime/klee-fp/CMakeLists.txt @@ -10,18 +10,18 @@ set(LIB_PREFIX "RuntimeFp") set(SRC_FILES ceil.c - klee_copysign.c + copysign.c exp.c fabs.c - klee_fenv.c - klee_floor.c + fenv.c + floor.c fpclassify.c - klee_internal_isinf.ll - klee_rint.c + isinf.ll klee_set_rounding_mode.c - klee_signbit.ll log.c + rint.c round.c + signbit.ll sqrt.c trigonometry.c ) diff --git a/runtime/klee-fp/ceil.c b/runtime/klee-fp/ceil.c index 9d112a16a3..d185cb7cb1 100644 --- a/runtime/klee-fp/ceil.c +++ b/runtime/klee-fp/ceil.c @@ -8,26 +8,26 @@ //===----------------------------------------------------------------------===*/ #include "float.h" -#include "klee_floor.h" -#include "klee_rint.h" +#include "floor.h" +#include "rint.h" float ceilf(float f) { - if (f == klee_internal_rintf(f)) { + if (f == rintf(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floorf(f); + return ((f < 0.0f) ? -1 : 1) + floorf(f); } double ceil(double f) { - if (f == klee_internal_rint(f)) { + if (f == rint(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floor(f); + return ((f < 0.0f) ? -1 : 1) + floor(f); } long double ceill(long double f) { - if (f == klee_internal_rintl(f)) { + if (f == rintl(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floorl(f); + return ((f < 0.0f) ? -1 : 1) + floorl(f); } diff --git a/runtime/klee-fp/klee_copysign.c b/runtime/klee-fp/copysign.c similarity index 97% rename from runtime/klee-fp/klee_copysign.c rename to runtime/klee-fp/copysign.c index ddd72fdc53..7505b51ffb 100644 --- a/runtime/klee-fp/klee_copysign.c +++ b/runtime/klee-fp/copysign.c @@ -1,4 +1,4 @@ -/*===-- klee_copysign.c ---------------------------------------------------===// +/*===-- copysign.c --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_copysign.h" +#include "copysign.h" #include "ansidecl.h" #include "klee/klee.h" diff --git a/runtime/klee-fp/klee_copysign.h b/runtime/klee-fp/copysign.h similarity index 88% rename from runtime/klee-fp/klee_copysign.h rename to runtime/klee-fp/copysign.h index 444e0ab264..4384a216cb 100644 --- a/runtime/klee-fp/klee_copysign.h +++ b/runtime/klee-fp/copysign.h @@ -1,4 +1,4 @@ -/*===-- klee_copysign.h ---------------------------------------------------===// +/*===-- copysign.h --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // diff --git a/runtime/klee-fp/fabs.c b/runtime/klee-fp/fabs.c index c3c4c88a6a..236cc38658 100644 --- a/runtime/klee-fp/fabs.c +++ b/runtime/klee-fp/fabs.c @@ -8,12 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "klee/klee.h" -double klee_internal_fabs(double d) { return klee_abs_double(d); } +double fabs(double d) { return klee_abs_double(d); } -float klee_internal_fabsf(float f) { return klee_abs_float(f); } +float fabsf(float f) { return klee_abs_float(f); } #if defined(__x86_64__) || defined(__i386__) -long double klee_internal_fabsl(long double f) { - return klee_abs_long_double(f); -} +long double fabsl(long double f) { return klee_abs_long_double(f); } #endif diff --git a/runtime/klee-fp/klee_fenv.c b/runtime/klee-fp/fenv.c similarity index 69% rename from runtime/klee-fp/klee_fenv.c rename to runtime/klee-fp/fenv.c index d6b52e3820..c5dda37789 100644 --- a/runtime/klee-fp/klee_fenv.c +++ b/runtime/klee-fp/fenv.c @@ -1,4 +1,4 @@ -/*===-- klee_fenv.c -------------------------------------------------------===// +/*===-- fenv.c ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -6,29 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===*/ -#include "klee_fenv.h" +#include "fenv.h" #include "klee/klee.h" -// Define the constants. Don't include `fenv.h` here to avoid -// polluting the Intrinsic module. -#if defined(__x86_64__) || defined(__i386__) -// These are the constants used by glibc and musl for x86_64 and i386 -enum { - FE_TONEAREST = 0, - FE_DOWNWARD = 0x400, - FE_UPWARD = 0x800, - FE_TOWARDZERO = 0xc00, - - // Our own implementation defined values. - // Do we want this? Although it's allowed by - // the standard it won't be replayable on native - // binaries. -}; -#else -#error Architecture not supported -#endif - -int klee_internal_fegetround(void) { +int fegetround(void) { enum KleeRoundingMode rm = klee_get_rounding_mode(); switch (rm) { case KLEE_FP_RNE: @@ -52,7 +33,7 @@ int klee_internal_fegetround(void) { } } -int klee_internal_fesetround(int rm) { +int fesetround(int rm) { switch (rm) { case FE_TONEAREST: klee_set_rounding_mode(KLEE_FP_RNE); diff --git a/runtime/klee-fp/fenv.h b/runtime/klee-fp/fenv.h new file mode 100644 index 0000000000..a833ac75c1 --- /dev/null +++ b/runtime/klee-fp/fenv.h @@ -0,0 +1,44 @@ +/*===-- klee_fenv.h -------------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===*/ + +#ifndef KLEE_FENV_H +#define KLEE_FENV_H + +#if defined(__x86_64__) || defined(__i386__) +#include +#elif defined(__arm64__) || defined(__arm__) +enum { + FE_TONEAREST = 0x0, + FE_UPWARD = 0x1, + FE_DOWNWARD = 0x2, + FE_TOWARDZERO = 0x3, + + // Our own implementation defined values. + // Do we want this? Although it's allowed by + // the standard it won't be replayable on native + // binaries. +}; +enum { + FE_INVALID = 0x01, + FE_DIVBYZERO = 0x02, + FE_OVERFLOW = 0x04, + FE_UNDERFLOW = 0x08, + FE_INEXACT = 0x10, + FE_DENORMAL = 0x80, + FE_ALL_EXCEPT = FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | + FE_UNDERFLOW | FE_DENORMAL +}; +#else +#error Architecture not supported +#endif + +int fegetround(void); +int fesetround(int rm); + +#endif // KLEE_FENV_H diff --git a/runtime/klee-fp/klee_floor.c b/runtime/klee-fp/floor.c similarity index 79% rename from runtime/klee-fp/klee_floor.c rename to runtime/klee-fp/floor.c index 51a3785fe7..3b79738fe2 100644 --- a/runtime/klee-fp/klee_floor.c +++ b/runtime/klee-fp/floor.c @@ -1,4 +1,5 @@ -/*===-- klee_floor.c ------------------------------------------------------===// +/*===-- floor.c +------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,11 +8,11 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_floor.h" +#include "floor.h" #include "klee/klee.h" #include "math.h" -float klee_floorf(float x) { +float floorf(float x) { int sign = signbit(x); x = klee_abs_float(x); if (klee_rintf(x) > x) { @@ -21,7 +22,7 @@ float klee_floorf(float x) { } } -double klee_floor(double x) { +double floor(double x) { int sign = signbit(x); x = klee_abs_double(x); if (klee_rint(x) > x) { @@ -31,7 +32,7 @@ double klee_floor(double x) { } } -long double klee_floorl(long double x) { +long double floorl(long double x) { int sign = signbit(x); x = klee_abs_long_double(x); if (klee_rintl(x) > x) { diff --git a/runtime/klee-fp/klee_floor.h b/runtime/klee-fp/floor.h similarity index 68% rename from runtime/klee-fp/klee_floor.h rename to runtime/klee-fp/floor.h index 03e1c1c8da..4cdbc93981 100644 --- a/runtime/klee-fp/klee_floor.h +++ b/runtime/klee-fp/floor.h @@ -1,4 +1,4 @@ -/*===-- klee_floor.h ------------------------------------------------------===// +/*===-- floor.h -----------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -10,8 +10,8 @@ #ifndef KLEE_FLOOR_H #define KLEE_FLOOR_H -float klee_floorf(float x); -double klee_floor(double x); -long double klee_floorl(long double x); +float floorf(float x); +double floor(double x); +long double floorl(long double x); #endif // KLEE_FLOOR_H diff --git a/runtime/klee-fp/fpclassify.c b/runtime/klee-fp/fpclassify.c index 06f9d001f9..0e0b1b179d 100644 --- a/runtime/klee-fp/fpclassify.c +++ b/runtime/klee-fp/fpclassify.c @@ -13,16 +13,19 @@ // during linking. // __isnanf -int klee_internal_isnanf(float f) { return klee_is_nan_float(f); } +int __isnanf(float f) { return klee_is_nan_float(f); } +int isnanf(float f) { return __isnanf(f); } // __isnan -int klee_internal_isnan(double d) { return klee_is_nan_double(d); } +int __isnan(double d) { return klee_is_nan_double(d); } +int isnan(double d) { return __isnan(d); } // __isnanl -int klee_internal_isnanl(long double d) { return klee_is_nan_long_double(d); } +int __isnanl(long double d) { return klee_is_nan_long_double(d); } +int isnanl(long double d) { return __isnanl(d); } // __fpclassifyf -int klee_internal_fpclassifyf(float f) { +int __fpclassifyf(float f) { /* * This version acts like a switch case which returns correct * float type from the enum, but itself does not fork @@ -33,38 +36,44 @@ int klee_internal_fpclassifyf(float f) { int x = klee_is_normal_float(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassifyf(float f) { return __fpclassifyf(f); } // __fpclassify -int klee_internal_fpclassify(double f) { +int __fpclassify(double f) { int b = klee_is_infinite_double(f); int c = (f == 0.0f); int d = klee_is_subnormal_double(f); int x = klee_is_normal_double(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassify(double f) { return __fpclassify(f); } // __fpclassifyl #if defined(__x86_64__) || defined(__i386__) -int klee_internal_fpclassifyl(long double f) { +int __fpclassifyl(long double f) { int b = klee_is_infinite_long_double(f); int c = (f == 0.0f); int d = klee_is_subnormal_long_double(f); int x = klee_is_normal_long_double(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassifyl(long double f) { return __fpclassifyl(f); } #endif // __finitef -int klee_internal_finitef(float f) { +int __finitef(float f) { return (!klee_is_nan_float(f)) & (!klee_is_infinite_float(f)); } +int finitef(float f) { return __finitef(f); } // __finite -int klee_internal_finite(double f) { +int __finite(double f) { return (!klee_is_nan_double(f)) & (!klee_is_infinite_double(f)); } +int finite(double f) { return __finite(f); } // __finitel -int klee_internal_finitel(long double f) { +int __finitel(long double f) { return (!klee_is_nan_long_double(f)) & (!klee_is_infinite_long_double(f)); } +int finitel(long double f) { return finitel(f); } diff --git a/runtime/klee-fp/klee_internal_isinf.ll b/runtime/klee-fp/isinf.ll similarity index 78% rename from runtime/klee-fp/klee_internal_isinf.ll rename to runtime/klee-fp/isinf.ll index 8a50b15134..f22bee07ce 100644 --- a/runtime/klee-fp/klee_internal_isinf.ll +++ b/runtime/klee-fp/isinf.ll @@ -1,4 +1,4 @@ -;;===-- klee_internal_isinff.ll --------------------------------------------===;; +;;===-- isinff.ll ---------------------------------------------------------===;; ;; ;; The KLEE Symbolic Virtual Machine ;; @@ -6,8 +6,6 @@ ;; License. See LICENSE.TXT for details. ;; ;;===----------------------------------------------------------------------===;; -;target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -;target triple = "x86_64-unknown-linux-gnu" ;; These are implementations of internal functions found in libm for classifying ;; floating point numbers. They have different names to avoid name collisions @@ -19,7 +17,7 @@ declare zeroext i1 @klee_is_infinite_float(float) #2 declare zeroext i1 @klee_is_infinite_double(double) #2 declare zeroext i1 @klee_is_infinite_long_double(x86_fp80) #2 -define i32 @klee_internal_isinff(float %f) #1 #0 { +define i32 @__isinff(float %f) #1 #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_float(float %f) #3 %cmp = fcmp ogt float %f, 0.000000e+00 @@ -28,7 +26,13 @@ entry: ret i32 %result } -define i32 @klee_internal_isinf(double %d) #1 #0 { +define i32 @isinff(float %f) #1 #0 { +entry: + %result = tail call zeroext i32 @__isinff(float %f) #3 + ret i32 %result +} + +define i32 @__isinf(double %d) #1 #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_double(double %d) #3 %cmp = fcmp ogt double %d, 0.000000e+00 @@ -37,7 +41,13 @@ entry: ret i32 %result } -define i32 @klee_internal_isinfl(x86_fp80 %d) #0 { +define i32 @isinf(double %d) #1 #0 { +entry: + %result = tail call zeroext i32 @__isinf(double %d) #3 + ret i32 %result +} + +define i32 @__isinfl(x86_fp80 %d) #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_long_double(x86_fp80 %d) #3 %cmp = fcmp ogt x86_fp80 %d, 0xK00000000000000000000 @@ -46,6 +56,12 @@ entry: ret i32 %result } +define i32 @isinfl(x86_fp80 %d) #0 { +entry: + %result = tail call zeroext i32 @__isinfl(x86_fp80 %d) #3 + ret i32 %result +} + ; NOTE: Use of optnone and noinline here are important so that the KLEE diff --git a/runtime/klee-fp/klee_fenv.h b/runtime/klee-fp/klee_fenv.h deleted file mode 100644 index af75c5591b..0000000000 --- a/runtime/klee-fp/klee_fenv.h +++ /dev/null @@ -1,17 +0,0 @@ -/*===-- klee_fenv.h -------------------------------------------------------===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===*/ - -#ifndef KLEE_FENV_H -#define KLEE_FENV_H -#include "klee/klee.h" - -int klee_internal_fegetround(void); -int klee_internal_fesetround(int rm); - -#endif // KLEE_FENV_H diff --git a/runtime/klee-fp/log.c b/runtime/klee-fp/log.c index 25b797ace4..62d54db47b 100644 --- a/runtime/klee-fp/log.c +++ b/runtime/klee-fp/log.c @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===*/ #include "fenv.h" -#include "klee_fenv.h" -#include "math.h" + +#include #define LOG_CORNER_CASE(suffix, type, isnan_function) \ int log_corner_case_##suffix(type *x) { \ diff --git a/runtime/klee-fp/klee_rint.c b/runtime/klee-fp/rint.c similarity index 62% rename from runtime/klee-fp/klee_rint.c rename to runtime/klee-fp/rint.c index 9dc7701991..a15096a01c 100644 --- a/runtime/klee-fp/klee_rint.c +++ b/runtime/klee-fp/rint.c @@ -1,4 +1,4 @@ -/*===-- klee_rint.c -------------------------------------------------------===// +/*===-- rint.c ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_rint.h" +#include "rint.h" #include "klee/klee.h" -float klee_internal_rintf(float arg) { return klee_rintf(arg); } +float rintf(float arg) { return klee_rintf(arg); } -double klee_internal_rint(double arg) { return klee_rint(arg); } +double rint(double arg) { return klee_rint(arg); } -long double klee_internal_rintl(long double arg) { return klee_rintl(arg); } +long double rintl(long double arg) { return klee_rintl(arg); } float nearbyintf(float arg) { return klee_rintf(arg); } diff --git a/runtime/klee-fp/klee_rint.h b/runtime/klee-fp/rint.h similarity index 69% rename from runtime/klee-fp/klee_rint.h rename to runtime/klee-fp/rint.h index b1be763080..4fb35f4382 100644 --- a/runtime/klee-fp/klee_rint.h +++ b/runtime/klee-fp/rint.h @@ -1,4 +1,4 @@ -/*===-- klee_rint.h -------------------------------------------------------===// +/*===-- rint.h ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -10,9 +10,9 @@ #ifndef KLEE_RINT_H #define KLEE_RINT_H -float klee_internal_rintf(float arg); -double klee_internal_rint(double arg); -long double klee_internal_rintl(long double arg); +float rintf(float arg); +double rint(double arg); +long double rintl(long double arg); float nearbyintf(float arg); double nearbyint(double arg); long double nearbyintl(long double arg); diff --git a/runtime/klee-fp/round.c b/runtime/klee-fp/round.c index 490cc4849e..d5a6ad9f51 100644 --- a/runtime/klee-fp/round.c +++ b/runtime/klee-fp/round.c @@ -9,6 +9,12 @@ #include "klee/klee.h" +float roundf(float x) { return klee_rintf(x); } + +double round(double x) { return klee_rint(x); } + +long double roundl(long double x) { return klee_rintl(x); } + long lroundf(float x) { return klee_rintf(x); } long lround(double x) { return klee_rint(x); } diff --git a/runtime/klee-fp/klee_signbit.ll b/runtime/klee-fp/signbit.ll similarity index 89% rename from runtime/klee-fp/klee_signbit.ll rename to runtime/klee-fp/signbit.ll index a7c504f856..8ee4768ed9 100644 --- a/runtime/klee-fp/klee_signbit.ll +++ b/runtime/klee-fp/signbit.ll @@ -9,7 +9,7 @@ ;target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ;target triple = "x86_64-unknown-linux-gnu" -define i32 @klee_internal_signbitf(float %f) #1 #0 { +define i32 @__signbitf(float %f) #1 #0 { entry: %0 = bitcast float %f to i32 %1 = icmp slt i32 %0, 0 @@ -17,7 +17,7 @@ entry: ret i32 %2 } -define i32 @klee_internal_signbit(double %d) #1 #0 { +define i32 @__signbit(double %d) #1 #0 { entry: %0 = bitcast double %d to i64 %1 = icmp slt i64 %0, 0 @@ -25,7 +25,7 @@ entry: ret i32 %2 } -define i32 @klee_internal_signbitl(x86_fp80 %d) #0 { +define i32 @__signbitl(x86_fp80 %d) #0 { entry: %0 = bitcast x86_fp80 %d to i80 %1 = icmp slt i80 %0, 0 diff --git a/runtime/klee-fp/sqrt.c b/runtime/klee-fp/sqrt.c index ba1b928340..26fbe2cc9f 100644 --- a/runtime/klee-fp/sqrt.c +++ b/runtime/klee-fp/sqrt.c @@ -8,12 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "klee/klee.h" -double klee_internal_sqrt(double d) { return klee_sqrt_double(d); } +double sqrt(double d) { return klee_sqrt_double(d); } -float klee_internal_sqrtf(float f) { return klee_sqrt_float(f); } +float sqrtf(float f) { return klee_sqrt_float(f); } #if defined(__x86_64__) || defined(__i386__) -long double klee_internal_sqrtl(long double f) { - return klee_sqrt_long_double(f); -} +long double sqrtl(long double f) { return klee_sqrt_long_double(f); } #endif diff --git a/scripts/build/common-functions b/scripts/build/common-functions index c964419f60..d7ae4654c4 100644 --- a/scripts/build/common-functions +++ b/scripts/build/common-functions @@ -8,11 +8,12 @@ function git_clone_or_update() { if [[ ! -e "${destination}/.git" ]]; then git clone $([ "${branch}x" != "x" ] && echo "--depth 1 -b ${branch}" || echo "") "$url" "$destination" else - cd "$destination" + pushd "$destination" git pull if [[ ! -z "$branch" ]]; then git checkout "${branch}" fi + popd fi } @@ -20,12 +21,12 @@ function get_git_hash() { local url="$1" local branch="$2" local commit_id="" - + # List remote git branches and get the commit id of the branch - commit_id="$(git ls-remote -h "$url" |grep "$branch" | cut -d$'\t' -f 1)" - + commit_id="$(git ls-remote -h "$url" | grep "$branch" | cut -d$'\t' -f 1)" + # If that doesn't work use the branch instead of the commit id - if [[ -z "${commit_id}" ]]; then + if [[ -z "${commit_id}" ]]; then echo "${branch}" else echo "${commit_id:0:7}" @@ -33,10 +34,10 @@ function get_git_hash() { } function with_sudo() { - echo "Checking sudo $@" - if [[ $(whoami) != "root" ]]; then - sudo "$@" - else - "$@" - fi -} \ No newline at end of file + echo "Checking sudo $@" + if [[ $(whoami) != "root" ]]; then + sudo "$@" + else + "$@" + fi +} diff --git a/scripts/build/p-bitwuzla-linux-ubuntu.inc b/scripts/build/p-bitwuzla-linux-ubuntu.inc new file mode 100644 index 0000000000..f36ab25d5e --- /dev/null +++ b/scripts/build/p-bitwuzla-linux-ubuntu.inc @@ -0,0 +1,25 @@ +# Build dependencies Bitwuzla +install_build_dependencies_bitwuzla() { + source "${DIR}/common-functions" + with_sudo apt update -y + + dependencies=( + build-essential + + ninja-build + python3 + python3-pip + cmake + git + ) + + #Install essential dependencies + with_sudo apt -y --no-install-recommends install "${dependencies[@]}" + + with_sudo apt-get update -y + with_sudo apt-get -y --no-install-recommends install pkg-config cmake-data m4 + + pip3 install --user meson + base_path="$(python3 -m site --user-base)" + export PATH="$PATH:${base_path}/bin" +} diff --git a/scripts/build/p-bitwuzla-osx.inc b/scripts/build/p-bitwuzla-osx.inc new file mode 100644 index 0000000000..27df98058e --- /dev/null +++ b/scripts/build/p-bitwuzla-osx.inc @@ -0,0 +1,14 @@ +install_build_dependencies_bitwuzla() { + dependencies=( + ninja + python3 + python3-pip + cmake + git + pkg-config + ) + brew install "${dependencies[@]}" + pip3 install --user meson + base_path="$(python3 -m site --user-base)" + export PATH="$PATH:${base_path}/bin" +} diff --git a/scripts/build/p-bitwuzla.inc b/scripts/build/p-bitwuzla.inc new file mode 100644 index 0000000000..fb518ab1f8 --- /dev/null +++ b/scripts/build/p-bitwuzla.inc @@ -0,0 +1,74 @@ +# Build scripts for Bitwuzla +# Variables that any artifact of this package might depend on +setup_build_variables_bitwuzla() { + BITWUZLA_SUFFIX="${SANITIZER_SUFFIX}" + + BITWUZLA_BUILD_PATH="${BASE}/bitwuzla-${BITWUZLA_VERSION}-build${BITWUZLA_SUFFIX}" + BITWUZLA_INSTALL_PATH="${BASE}/bitwuzla-${BITWUZLA_VERSION}-install${BITWUZLA_SUFFIX}" + bitwuzla_url="https://github.com/bitwuzla/bitwuzla.git" + + return 0 +} + +download_bitwuzla() { + source "${DIR}/common-functions" + # Download Bitwuzla + git_clone_or_update "${bitwuzla_url}" "${BASE}/bitwuzla-${BITWUZLA_VERSION}" "${BITWUZLA_VERSION}" +} + +build_bitwuzla() { + pushd "${BASE}/bitwuzla-${BITWUZLA_VERSION}" + + args=(--build-dir "${BITWUZLA_BUILD_PATH}" --prefix "${BITWUZLA_INSTALL_PATH}" --static --no-unit-testing) + + if [[ -n "${SANITIZER_SUFFIX:-}" ]]; then + if [[ "${SANITIZER_BUILD:-}" == "address" ]]; then + args+=("--asan") + fi + if [[ "${SANITIZER_BUILD:-}" == "undefined" ]]; then + args+=("--ubsan") + fi + args+=("--assertions" "debug") + else + args+=("--no-assertions" "release") + fi + + ./configure.py "${args[@]}" + popd + cd "${BITWUZLA_BUILD_PATH}" || return 1 + yes n | ninja install + touch "${BITWUZLA_INSTALL_PATH}/.bitwuzla_installed" +} + +install_bitwuzla() { + return 0 +} + +# Check if the binary artifact is installed +is_installed_bitwuzla() { + ( + setup_build_variables_bitwuzla + [[ -f "${BITWUZLA_INSTALL_PATH}/.bitwuzla_installed" ]] + ) || return 1 +} + +setup_artifact_variables_bitwuzla() { + setup_build_variables_bitwuzla +} + +get_build_artifacts_bitwuzla() { + ( + setup_build_variables_bitwuzla + echo "${BITWUZLA_INSTALL_PATH}" + ) +} + +get_docker_config_id_bitwuzla() { + ( + source "${DIR}/common-functions" + setup_build_variables_bitwuzla + + biwuzla_remote_commit="$(get_git_hash "${bitwuzla_url}" "${BITWUZLA_VERSION}")" + echo "${biwuzla_remote_commit}" + ) +} diff --git a/scripts/build/p-json-linux-ubuntu.inc b/scripts/build/p-json-linux-ubuntu.inc new file mode 100644 index 0000000000..37538f86a1 --- /dev/null +++ b/scripts/build/p-json-linux-ubuntu.inc @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +install_build_dependencies_json() { + source "${DIR}/common-functions" + with_sudo apt update -y + + dependencies=( + ca-certificates + wget + unzip + git + ) + + #Install essential dependencies + with_sudo apt -y --no-install-recommends install "${dependencies[@]}" +} diff --git a/scripts/build/p-json-osx.inc b/scripts/build/p-json-osx.inc new file mode 100644 index 0000000000..4ca06662d8 --- /dev/null +++ b/scripts/build/p-json-osx.inc @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +install_build_dependencies_json() { + # Install essential dependency + # Ignore if already installed + brew install wget || /usr/bin/true +} diff --git a/scripts/build/p-json.inc b/scripts/build/p-json.inc new file mode 100644 index 0000000000..66a1ee6f54 --- /dev/null +++ b/scripts/build/p-json.inc @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +setup_build_variables_json() { + JSON_INSTALL_PATH="${BASE}/json-${JSON_VERSION}" + json_url="https://github.com/nlohmann/json.git" + return 0 +} + +download_json() { + source "${DIR}/common-functions" + # Download json + git_clone_or_update "${json_url}" "${JSON_INSTALL_PATH}" "${JSON_VERSION}" + touch "${JSON_INSTALL_PATH}"/.is_installed +} + +build_json() { + return 0 +} + +install_json() { + return 0 +} + +is_installed_json() { + ( + setup_build_variables_json + [[ -f "${JSON_INSTALL_PATH}"/.is_installed ]] + ) || return 1 +} + +get_build_artifacts_json() { + ( + setup_build_variables_json + echo "${JSON_INSTALL_PATH}" + ) +} + +setup_artifact_variables_json() { + setup_build_variables_json +} + +get_docker_config_id_json() { + ( + setup_build_variables_json + echo "${JSON_VERSION}" + ) +} diff --git a/scripts/build/p-klee-linux-ubuntu.inc b/scripts/build/p-klee-linux-ubuntu.inc index 8bf39a199b..70af8dc110 100644 --- a/scripts/build/p-klee-linux-ubuntu.inc +++ b/scripts/build/p-klee-linux-ubuntu.inc @@ -10,6 +10,9 @@ install_build_dependencies_klee() { python3-setuptools python3-pip python3-wheel + pkg-config + cmake-data + coreutils ) if [[ "${SOLVERS:-}" == "metaSMT" ]]; then diff --git a/scripts/build/p-klee-osx.inc b/scripts/build/p-klee-osx.inc index 0561e28f68..12893fbbb4 100644 --- a/scripts/build/p-klee-osx.inc +++ b/scripts/build/p-klee-osx.inc @@ -9,6 +9,8 @@ install_build_dependencies_klee() { pip3 install --user --upgrade lit tabulate + brew install pkg-config + brew install coreutils # Get path of package location base_path=$(python3 -m site --user-base) export PATH="${base_path}/bin:$PATH" diff --git a/scripts/build/p-klee.inc b/scripts/build/p-klee.inc index 248d3a9bb7..83379129a6 100644 --- a/scripts/build/p-klee.inc +++ b/scripts/build/p-klee.inc @@ -19,6 +19,7 @@ build_klee() { local CMAKE_ARGUMENTS=( "-DLLVM_DIR=${LLVM_INSTALL}" "-DGTEST_SRC_DIR=${GTEST_INSTALL_PATH}" + "-DJSON_SRC_DIR=${JSON_INSTALL_PATH}" "-DENABLE_UNIT_TESTS=TRUE" "-DENABLE_SYSTEM_TESTS=TRUE" "-DENABLE_DOXYGEN=${ENABLE_DOXYGEN}" @@ -67,6 +68,7 @@ fi local KLEE_Z3_CONFIGURE_OPTION=("-DENABLE_SOLVER_Z3=OFF") local KLEE_STP_CONFIGURE_OPTION=("-DENABLE_SOLVER_STP=OFF") local KLEE_METASMT_CONFIGURE_OPTION=("-DENABLE_SOLVER_METASMT=OFF") + local KLEE_BITWUZLA_CONFIGURE_OPTION=("-DENABLE_SOLVER_BITWUZLA=OFF") KLEE_FLOATING_POINT=( "-DENABLE_FLOATING_POINT=FALSE" "-DENABLE_FP_RUNTIME=FALSE" @@ -106,6 +108,18 @@ fi "-DMETASMT_DEFAULT_BACKEND=${METASMT_DEFAULT}" ) ;; + bitwuzla) + KLEE_BITWUZLA_CONFIGURE_OPTION=( + "-DENABLE_SOLVER_BITWUZLA=TRUE" + ) + + CMAKE_PREFIX_PATH+=("${BITWUZLA_INSTALL_PATH}") + KLEE_FLOATING_POINT=( + "-DENABLE_FLOATING_POINT=TRUE" + "-DENABLE_FP_RUNTIME=TRUE" + ) + echo "bitwuzla" + ;; *) echo "Unknown solver ${solver}" exit 1 @@ -116,6 +130,7 @@ fi "${KLEE_Z3_CONFIGURE_OPTION[@]}" "${KLEE_STP_CONFIGURE_OPTION[@]}" "${KLEE_METASMT_CONFIGURE_OPTION[@]}" + "${KLEE_BITWUZLA_CONFIGURE_OPTION[@]}" "${KLEE_FLOATING_POINT[@]}" ) @@ -240,4 +255,4 @@ is_installed_klee() { setup_artifact_variables_klee() { setup_build_variables_klee -} \ No newline at end of file +} diff --git a/scripts/build/v-bitwuzla.inc b/scripts/build/v-bitwuzla.inc new file mode 100644 index 0000000000..752e9e64d8 --- /dev/null +++ b/scripts/build/v-bitwuzla.inc @@ -0,0 +1,10 @@ +# Build information for Bitwuzla solver +required_variables_bitwuzla=( + "BITWUZLA_VERSION" +) + +artifact_dependency_bitwuzla=("sanitizer") + +install_build_dependencies_bitwuzla() { + return 0 +} diff --git a/scripts/build/v-json.inc b/scripts/build/v-json.inc new file mode 100644 index 0000000000..46335d4c62 --- /dev/null +++ b/scripts/build/v-json.inc @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +# Build information for json +required_variables_json=( + "JSON_VERSION" +) + +# Artifacts json depends on +artifact_dependency_json=("") diff --git a/scripts/build/v-klee.inc b/scripts/build/v-klee.inc index 4b0f1085f1..eb5815dc53 100644 --- a/scripts/build/v-klee.inc +++ b/scripts/build/v-klee.inc @@ -16,7 +16,7 @@ required_variables_check_klee() { # On which artifacts does KLEE depend on artifact_dependency_klee(){ - local dependencies=("llvm" "solvers" "gtest" "sqlite" "cmake") + local dependencies=("llvm" "solvers" "gtest" "sqlite" "cmake" "json") if [[ "${OS}" != "osx" ]]; then dependencies+=(uclibc) fi @@ -34,7 +34,7 @@ runtime_artifact_dependency_klee(){ if [[ "${OS}" != "osx" ]]; then echo "uclibc" fi - dependencies+=("llvm" "solvers" "gtest" "sqlite") + dependencies+=("llvm" "solvers" "gtest" "sqlite" "json") [[ "${USE_TCMALLOC:-}" -eq 1 ]] && dependencies+=("tcmalloc") [[ "${USE_LIBCXX:-}" -eq 1 ]] && dependencies+=("libcxx") diff --git a/scripts/build/v-solvers.inc b/scripts/build/v-solvers.inc index 9d6bfdc857..74cdac1f5a 100644 --- a/scripts/build/v-solvers.inc +++ b/scripts/build/v-solvers.inc @@ -15,7 +15,8 @@ required_variables_check_solvers() { [[ "${solver}" == "z3" ]] && continue [[ "${solver}" == "stp" ]] && continue [[ "${solver}" == "metasmt" ]] && continue - + [[ "${solver}" == "bitwuzla" ]] && continue + echo "Unknown solver: \"$solver\"" exit 1 done @@ -51,7 +52,7 @@ setup_variables_solvers() { [[ "${solver}" == "z3" ]] && SELECTED_SOLVERS+=("z3") && continue [[ "${solver}" == "stp" ]] && SELECTED_SOLVERS+=("stp") && continue [[ "${solver}" == "metasmt" ]] && SELECTED_SOLVERS+=("metasmt") && continue - + [[ "${solver}" == "bitwuzla" ]] && SELECTED_SOLVERS+=("bitwuzla") && continue echo "Unknown solver: \"$solver\"" exit 1 done diff --git a/scripts/kleef b/scripts/kleef new file mode 100755 index 0000000000..969b6c4460 --- /dev/null +++ b/scripts/kleef @@ -0,0 +1,463 @@ +#!/usr/bin/env python3 +import argparse +import os +import subprocess +import shutil +import tempfile +import hashlib +from functools import partial +from pathlib import Path + + +def klee_options( + max_memory, + test_output_dir, + source, + hexhash, + max_time, + compiled_file, + is32, + f_err, + f_cov, + write_ktests, +): + if max_time and int(max_time) > 30: + MAX_SOLVER_TIME = 15 + else: + MAX_SOLVER_TIME = 10 + cmd = [ + "--strip-unwanted-calls", # removes llvm.dbg.* instructions, exponentially reduces time on some benchmarks + "--delete-dead-loops=false", # without this optimizer removes some code, which decreases coverage + "--emit-all-errors", # without this we generate only one test for assertion failures, which decreases coverage + "--mock-policy=all", # this helps for some linux benchmarks, which have unused extern globals. without this flag we will not even start on them. + "--external-calls=all", + "--use-forked-solver=false", + # "--solver-backend=stp", + # "--solver-backend=z3-tree", + "--solver-backend=bitwuzla-tree", + "--max-solvers-approx-tree-inc=16", + f"--max-memory={int(max_memory * 0.9)}", # Just use half of the memory in case we have to fork + "--libc=klee", + "--skip-not-lazy-initialized", + f"--output-dir={test_output_dir}", # Output files into specific directory + "--output-source=false", # Do not output assembly.ll - it can be too large + "--output-stats=false", + "--output-istats=false", + # "--istats-write-interval=90s", # Istats file can be large as well + "--write-xml-tests", # Write tests in XML format + f"--write-ktests={write_ktests}", # Write tests in KTest format + f"--xml-metadata-programfile={source.name}", # Provide the name of the original source file + f"--xml-metadata-programhash={hexhash}", # Provide sha256 hash of source file + # "--use-guided-search=none", + "--use-sym-size-alloc=true", + "--cex-cache-validity-cores", + # "--libc=uclibc", + # "--posix-runtime", + "--fp-runtime", + # "--max-sym-array-size=4096", + "--symbolic-allocation-threshold=8192", + "--uninit-memory-test-multiplier=10", + # "--dump-all-states=false", + # "--search=nurs:covnew", + # "--search=nurs:md2u", "--search=random-path", + # "-const-array-opt", + ] + + if is32: + cmd += [ + "--allocate-determ", + f"--allocate-determ-size={min(int(max_memory * 0.6), 3 * 1024)}", + "--allocate-determ-start-address=0x00030000000", + "--x86FP-as-x87FP80", + ] + + if f_err: + cmd += [ + "--optimize=true", + "--use-alpha-equivalence=true", + "--function-call-reproduce=reach_error", + # "--max-cycles=0", + # "--tc-type=bug", + "--dump-states-on-halt=unreached", # Explicitly do not dump states + "--exit-on-error-type=Assert", # Only generate test cases of type assert + # "--dump-test-case-type=Assert", # Only dump test cases of type assert + "--search=dfs", + "--search=bfs", + # "--search=nurs:covnew", "--search=random-path","--search=dfs", "--use-batching-search", + # "--search=distance","--search=random-path","--use-batching-search", + # "--target-assert", # Target + ] + if max_time: + max_time = float(max_time) + if max_time and int(max_time) > 30: + max_time = int(max_time * 0.99) + else: + max_time = int(max_time * 0.9) + cmd += [ + f"--max-time={max_time}", + ] + + if f_cov: + cmd += [ + "--optimize=false", + "--mem-trigger-cof", # Start on the fly tests generation after approaching memory cup + "--use-alpha-equivalence=true", + "--optimize-aggressive=false", + "--track-coverage=all", # Only branches and only instructions are wrong in real life. E.g., ternary operators are sometimes counted as different branches, while we stick to look at them as a single instruction from a single branch + "--use-iterative-deepening-search=max-cycles", + f"--max-solver-time={MAX_SOLVER_TIME}s", + "--max-cycles-before-stuck=15", + # "--tc-type=cov", + "--only-output-states-covering-new", # Don't generate all test cases + "--dump-states-on-halt=all", # Check in case we missed some oncovered instructions + "--search=dfs", + "--search=random-state", + ] + if max_time: + max_time = float(max_time) + if max_time and int(max_time) > 30: + late_time = int(max_time * 0.9) + last_time = int(max_time * 0.97) + else: + late_time = int(max_time * 0.8) + last_time = int(max_time * 0.9) + cmd += [ + "--cover-on-the-fly=true", + f"--delay-cover-on-the-fly={late_time}", + f"--max-time={last_time}", + ] + + cmd += [compiled_file] # Finally add the file to be tested + return cmd + + +def normalize_command(cmd, shell=False): + if shell: + out = cmd + else: + cmd2 = [x.as_posix() if isinstance(x, Path) else x for x in cmd] + out = " ".join(cmd2) + print("Running:", out) + return out + + +def check_call(cmd, shell=False): + normalize_command(cmd, shell) + subprocess.check_call(cmd, shell=shell) + # p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + # p.communicate() + # print(p.returncode) + + +def locateBinaryOrFail(binary, err_mess=""): + output = shutil.which(binary) + if output is not None: + return Path(output) + print(f"Command '{binary}' not found{err_mess}") + exit(1) + + +def tryFind(folder, binary): + output = folder / binary + if output.exists(): + return output + return locateBinaryOrFail(binary) + + +def printNotNone(s): + if s is not None: + print(s.decode("utf-8")) + + +class KLEEF(object): + """ + Wrapper to run KLEEF within BenchExec + Compiles source and executes KLEEF + """ + + def __init__( + self, + source=None, + is32=False, + f_cov=False, + f_err=False, + max_memory=0, + max_time=0, + use_perf=False, + use_valgrind=False, + write_ktests=False, + ): + self.source = Path(source) if source else None + self.is32 = is32 + self.tempdir = None + self.compiled_file = None + self.f_cov = f_cov + self.f_err = f_err + self.max_memory = max_memory / 1024 / 1024 # Convert to MB + self.max_time = max_time + self.use_perf = use_perf + self.use_valgrind = use_valgrind + if write_ktests: + self.write_ktests = "true" + else: + self.write_ktests = "false" + + # This file is inside the bin directory - use the root as base + self.bin_directory = Path(__file__).parent + self.base_directory = self.bin_directory.parent + self.klee_path = self.bin_directory / "klee" + self.compiler_path = tryFind(self.bin_directory, "clang") + self.linker_path = tryFind(self.bin_directory, "llvm-link") + self.library_path = self.base_directory / "libraries" + self.runtime_library_path = self.base_directory / "runtime/lib" + self.test_results_path = Path.cwd() / "test-suite" + self.test_results_path.mkdir(exist_ok=True) + + self.callEnv = os.environ.copy() + self.callEnv["LD_LIBRARY_PATH"] = self.library_path + self.callEnv["KLEE_RUNTIME_LIBRARY_PATH"] = self.runtime_library_path + + def compile(self): + self.tempdir = Path(tempfile.mkdtemp()) + + # Compile file for testing + self.compiled_file = self.tempdir / (self.source.name + ".bc") + + compiler_options = [ + self.compiler_path, + "-O0", + "-Xclang", + "-disable-O0-optnone", + "-fbracket-depth=1024", + "-c", + "-g", + "-emit-llvm", + ] + if self.is32: + compiler_options += ["-m32"] + if self.use_perf: + compiler_options += ["-gdwarf-4"] + cmd = compiler_options + [ + "-Wno-everything", # do not print any error statements - we are not allowed to change the code + "-fno-default-inline", + "-o", + self.compiled_file, + self.source, + ] + check_call(cmd) + + # Compile library + compiled_library = self.tempdir / "library.bc" + include_path = self.base_directory / "include/klee-test-comp.c" + cmd = compiler_options + [ + "-o", + compiled_library, + include_path, + ] + check_call(cmd) + + # Link both together to final + cmd = [ + self.linker_path, + "-o", + self.compiled_file, + compiled_library, + self.compiled_file, + ] + check_call(cmd) + + def isModifyingUlimitPermitted(self): + out = subprocess.run( + "ulimit -s unlimited", + shell=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode + return not out + + def run(self): + test_output_dir = self.test_results_path / self.source.name + test_output_dir = self.test_results_path + # Clean-up from previous runs if needed + shutil.rmtree(test_output_dir, ignore_errors=True) + + # Calculate hashsum of original source file + with open(self.source, mode="rb") as f: + h = hashlib.sha256() + for buf in iter(partial(f.read, 128), b""): + h.update(buf) + + cmd = [self.klee_path] + if self.use_perf: + cmd = ["perf", "record", "-g", "--call-graph", "dwarf"] + cmd + elif self.use_valgrind: + cmd = ["valgrind", "--tool=massif"] + cmd + + # Add common arguments + cmd += klee_options( + self.max_memory, + test_output_dir, + self.source, + h.hexdigest(), + self.max_time, + self.compiled_file, + self.is32, + self.f_err, + self.f_cov, + self.write_ktests, + ) + if self.isModifyingUlimitPermitted(): + cmd = ["ulimit -s unlimited", "&&"] + cmd + cmd = normalize_command(cmd) + + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True, + env=self.callEnv, + ) + s_out, s_err = p.communicate() + if not self.use_perf: + printNotNone(s_out) + printNotNone(s_err) + + if self.use_perf: + cmd = "perf script | c++filt | gprof2dot -f perf -s | dot -Tpdf -o output.pdf" + check_call(cmd, shell=True) + + return test_output_dir + + def version(self): + cmd = [self.klee_path, "--version"] + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=self.callEnv, + ) + s_out, s_err = p.communicate() + printNotNone(s_out) + + +def run(args): + if args.version: + wrapper = KLEEF() + wrapper.version() + exit(0) + + # Validation of arguments + if not args.source or not os.path.isfile(args.source): + print("File does not exist", args.source) + exit(1) + + if args.property_file: + with open(args.property_file, "r") as f: + for line in f: + if "@DECISIONEDGE" in line: + args.coverage_only = True + if "@CALL(reach_error)" in line: + args.error_only = True + # Generate wrapper + time = 0 + if args.max_cputime_soft: # Use soft timeout if available + time = args.max_cputime_soft + elif args.max_cputime_hard: + time = args.max_cputime_hard + elif args.max_walltime: + time = args.max_walltime + elif args.max_time: + time = args.max_time + + is32 = None + if vars(args).get("32"): + is32 = True + if vars(args).get("64"): + if is32: + print("Cannot set --64 and --32 simultanously") + exit(1) + is32 = False + + if is32 is None: + print("No architecture set. Assume 64bit") + is32 = False + optAndUsed = [ + (args.perf, "perf", ["perf", "c++filt", "gprof2dot", "dot"]), + (args.valgrind, "valgrind", ["valgrind"]), + ] + for opt, name, used_by_opt in optAndUsed: + if not opt: + continue + for tool in used_by_opt: + locateBinaryOrFail(tool, err_mess=f", so cannot run with option --{name}") + + if args.perf and args.valgrind: + print("Cannot use perf and valgrind at the same time") + exit(1) + wrapper = KLEEF( + source=args.source, + is32=is32, + f_cov=args.coverage_only, + f_err=args.error_only, + max_memory=args.max_memory, + max_time=time, + use_perf=args.perf, + use_valgrind=args.valgrind, + write_ktests=args.write_ktests, + ) + wrapper.compile() + return wrapper.run() + + +def main(): + # Initialize argparse + parser = argparse.ArgumentParser(description="KLEEF single-file runner") + parser.add_argument( + "source", help="klee-out directory to parse", nargs="?", default=None + ) + parser.add_argument("--version", help="print version of klee", action="store_true") + parser.add_argument("--32", help="Compile 32bit binaries", action="store_true") + parser.add_argument("--64", help="Compile 64bit binaries", action="store_true") + parser.add_argument( + "--error-only", help="Focus on searching errors", action="store_true" + ) + parser.add_argument( + "--perf", help="Measure speed with perf", action="store_true", default=False + ) + parser.add_argument( + "--valgrind", + help="Measure memory with valgrind", + action="store_true", + default=False, + ) + parser.add_argument( + "--coverage-only", help="Focus on coverage", action="store_true" + ) + parser.add_argument( + "--max-memory", help="Maximum memory in byte ", type=int, default=2000 + ) + parser.add_argument("--max-time", help="Maximum time in s", type=int, default=0) + parser.add_argument( + "--max-walltime", help="Maximum walltime in s", type=int, default=0 + ) + parser.add_argument( + "--max-cputime-soft", help="Maximum cputime in s (soft)", type=int, default=0 + ) + parser.add_argument( + "--max-cputime-hard", help="Maximum cputime in s (hard)", type=int, default=0 + ) + parser.add_argument( + "--property-file", + help="Property file for test goal description", + type=str, + default=None, + ) + parser.add_argument( + "--write-ktests", help="Write tests in KTest format", action="store_true" + ) + args = parser.parse_args() + run(args) + + +if __name__ == "__main__": + main() diff --git a/scripts/replay.sh b/scripts/replay.sh new file mode 100755 index 0000000000..8a4a426efb --- /dev/null +++ b/scripts/replay.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# ===-- replay.sh --------------------------------------------------------===## +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +# ===----------------------------------------------------------------------===## + +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + TIMEOUT="timeout" +else + TIMEOUT="gtimeout" +fi +find $1 -name "*.ktest" -type f -exec bash -c 'KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$1 $3 1 $2' bash {} $2 $TIMEOUT \; +exit 0 diff --git a/scripts/run_tests_with_mocks.py b/scripts/run_tests_with_mocks.py new file mode 100755 index 0000000000..ef5db2def6 --- /dev/null +++ b/scripts/run_tests_with_mocks.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 + +# This script builds executable file using initial bitcode file and artifacts produced by KLEE. +# To run the script provide all the arguments you want to pass to clang for building executable. +# +# NOTE: First argument is path to compiler +# NOTE: Pre-last argument should be a path to KLEE output directory which contains redefinitions.txt and externals.ll. +# NOTE: Last argument is path to initial bitcode. +# +# Example: python3 run_tests_with_mocks.py clang -I ~/klee/include/ -L ~/klee/build/lib/ -lkleeRuntest klee-last a.bc +# +# You can read more about replaying test cases here: http://klee.github.io/tutorials/testing-function/ + +import subprocess as sp +import sys +import os + +klee_out_dir = sys.argv[-2] +bitcode = sys.argv[-1] + +filename = os.path.splitext(bitcode)[0] +object_file = f'{filename}.o' +sp.run(f'llc {bitcode} -filetype=obj -o {object_file}', shell=True) +sp.run(f'llvm-objcopy {object_file} --redefine-syms {klee_out_dir}/redefinitions.txt', shell=True) + +externals = f'{klee_out_dir}/externals.o' +sp.run(f'llc {klee_out_dir}/externals.ll -filetype=obj -o {externals}', shell=True) + +compiler = sys.argv[1] +user_args = ' '.join(sys.argv[2:len(sys.argv) - 2]) +command = f'{compiler} {externals} {object_file} {user_args}' +print(command) +sp.run(command, shell=True) diff --git a/test/ArrayOpt/test_nier.c b/test/ArrayOpt/test_nier.c index 154f72d854..55ecac126f 100644 --- a/test/ArrayOpt/test_nier.c +++ b/test/ArrayOpt/test_nier.c @@ -1,5 +1,6 @@ // REQUIRES: not-asan // REQUIRES: not-msan +// REQUIRES: not-darwin // Ignore msan: Generates a large stack trace > 8k but not a stack overflow for larger stacks // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out @@ -18,8 +19,8 @@ // RUN: %klee --write-kqueries --output-dir=%t.klee-out --optimize-array=all %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPT_I // RUN: test -f %t.klee-out/test000001.kquery // RUN: test -f %t.klee-out/test000002.kquery -// RUN: not FileCheck %s -input-file=%t.klee-out/test000001.kquery -check-prefix=CHECK-CONST_ARR // RUN: not FileCheck %s -input-file=%t.klee-out/test000002.kquery -check-prefix=CHECK-CONST_ARR +// RUN: not FileCheck %s -input-file=%t.klee-out/test000001.kquery -check-prefix=CHECK-CONST_ARR // CHECK-OPT_I: KLEE: WARNING: OPT_I: successful // CHECK-OPT_V: KLEE: WARNING: OPT_V: successful diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 17723d865f..c7d14ed87e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,6 +15,7 @@ set(LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}") set(LLVMCC "${LLVMCC} -I${CMAKE_SOURCE_DIR}/include") set(LLVMCXX "${LLVMCXX} -I${CMAKE_SOURCE_DIR}/include") set(NATIVE_CC "${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -I ${CMAKE_SOURCE_DIR}/include") +set(NATIVE_OBJCOPY "${CMAKE_OBJCOPY}") set(NATIVE_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} -I ${CMAKE_SOURCE_DIR}/include") set(TARGET_TRIPLE "${TARGET_TRIPLE}") diff --git a/test/CXX/symex/libc++/can_catch_test.cpp b/test/CXX/symex/libc++/can_catch_test.cpp index c70d14a2aa..7515ef33d8 100644 --- a/test/CXX/symex/libc++/can_catch_test.cpp +++ b/test/CXX/symex/libc++/can_catch_test.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/exception_inheritance.cpp b/test/CXX/symex/libc++/exception_inheritance.cpp index ca207eb4be..e24be60da2 100644 --- a/test/CXX/symex/libc++/exception_inheritance.cpp +++ b/test/CXX/symex/libc++/exception_inheritance.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/landingpad.cpp b/test/CXX/symex/libc++/landingpad.cpp index 13dd6bc47a..6e8b13bcd6 100644 --- a/test/CXX/symex/libc++/landingpad.cpp +++ b/test/CXX/symex/libc++/landingpad.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of // c++ type, constructors and destructors. // Based on: https://gcc.gnu.org/wiki/Dwarf2EHNewbiesHowto diff --git a/test/CXX/symex/libc++/rethrow.cpp b/test/CXX/symex/libc++/rethrow.cpp index 149fe693d5..febdf0b3e9 100644 --- a/test/CXX/symex/libc++/rethrow.cpp +++ b/test/CXX/symex/libc++/rethrow.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/throw_specifiers.cpp b/test/CXX/symex/libc++/throw_specifiers.cpp index 96195cd498..6eae7f3abd 100644 --- a/test/CXX/symex/libc++/throw_specifiers.cpp +++ b/test/CXX/symex/libc++/throw_specifiers.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of // throw specifications on functions // REQUIRES: uclibc diff --git a/test/CXX/symex/libc++/throwing_exception_destructor.cpp b/test/CXX/symex/libc++/throwing_exception_destructor.cpp index 02d7cdb920..f1e0e5d447 100644 --- a/test/CXX/symex/libc++/throwing_exception_destructor.cpp +++ b/test/CXX/symex/libc++/throwing_exception_destructor.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of exception destructors that throw. // REQUIRES: uclibc // REQUIRES: libcxx diff --git a/test/Expr/Evaluate.kquery b/test/Expr/Evaluate.kquery index e6b0d1e1a4..b2fc41d746 100644 --- a/test/Expr/Evaluate.kquery +++ b/test/Expr/Evaluate.kquery @@ -17,7 +17,7 @@ arr12 : (array (w64 8) (makeSymbolic arr1 0)) # RUN: grep "Query 2: VALID" %t.log # Query 2 -constant0 : (array (w64 4) (constant [ 1 2 3 5 ])) +constant0 : (array (w64 4) (constant [1, 2, 3, 5] default: 0)) (query [] (Eq (Add w8 (Read w8 0 constant0) (Read w8 3 constant0)) 6)) diff --git a/test/Expr/print-smt-let.kquery b/test/Expr/print-smt-let.kquery index 871e6e4f29..974112a37c 100644 --- a/test/Expr/print-smt-let.kquery +++ b/test/Expr/print-smt-let.kquery @@ -1069,7 +1069,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1105,7 +1105,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1128,7 +1128,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1141,7 +1141,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1160,7 +1160,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-let.smt2.good b/test/Expr/print-smt-let.smt2.good index d0ce68b168..05ea45d94e 100644 --- a/test/Expr/print-smt-let.smt2.good +++ b/test/Expr/print-smt-let.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31312 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31312 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv1 32) ?B3 ) ) (select constant0 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533360 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic2 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533360 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic1 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533328 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv1 32) ?B3 ) ) (select constant3 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533328 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 ((_ extract 31 0) ?B1 ) ) ) (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv1 32) ?B2 ) ) (select constant4 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 ((_ extract 31 0) ?B1 ) ) ) (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B2 ) ) (select constant2 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv111120 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv1 32) ?B3 ) ) (select constant5 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv111120 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31760 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv1 32) ?B3 ) ) (select constant6 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31760 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B3 ) ) (select constant2 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709532800 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709532800 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Expr/print-smt-named.kquery b/test/Expr/print-smt-named.kquery index 5e0112b2b7..78bbbd4ef1 100644 --- a/test/Expr/print-smt-named.kquery +++ b/test/Expr/print-smt-named.kquery @@ -1068,7 +1068,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1104,7 +1104,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1127,7 +1127,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1140,7 +1140,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1159,7 +1159,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-named.smt2.good b/test/Expr/print-smt-named.smt2.good index 455fbc0dfd..fd7e2061ee 100644 --- a/test/Expr/print-smt-named.smt2.good +++ b/test/Expr/print-smt-named.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31312 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31312 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv1 32) ?B3 ) ) (select constant0 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533360 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic2 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533360 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic1 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533328 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant3 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv1 32) ?B3 ) ) (select constant3 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533328 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) ) (concat (select constant4 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv1 32) ?B2 ) ) (select constant4 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B2 ) ) (select constant2 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv111120 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant5 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv1 32) ?B3 ) ) (select constant5 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv111120 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31760 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant6 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv1 32) ?B3 ) ) (select constant6 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31760 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B3 ) ) (select constant2 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709532800 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709532800 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Expr/print-smt-none.kquery b/test/Expr/print-smt-none.kquery index 90c0bce0e7..9b002c3862 100644 --- a/test/Expr/print-smt-none.kquery +++ b/test/Expr/print-smt-none.kquery @@ -1068,7 +1068,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1104,7 +1104,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1127,7 +1127,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1140,7 +1140,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1159,7 +1159,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-none.smt2.good b/test/Expr/print-smt-none.smt2.good index 3a4d2e0ce6..1fe23264f3 100644 --- a/test/Expr/print-smt-none.smt2.good +++ b/test/Expr/print-smt-none.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant0 ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic2 ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic1 ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant3 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant3 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant3 ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant4 (bvadd (_ bv2 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant4 (bvadd (_ bv1 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (select constant4 ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (select constant2 ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant5 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant5 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant5 ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant6 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant6 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant6 ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant2 ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic0 ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic0 ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Feature/Annotation/AllocSource.c b/test/Feature/Annotation/AllocSource.c new file mode 100644 index 0000000000..3ac9a1918e --- /dev/null +++ b/test/Feature/Annotation/AllocSource.c @@ -0,0 +1,65 @@ +// REQUIRES: z3 +// RUN: %clang -DAllocSource1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE1 + +// RUN: %clang -DAllocSource2 %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE2 + +// RUN: %clang -DAllocSource3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE3 + +// RUN: %clang -DAllocSource4 %s -g -emit-llvm %O0opt -c -o %t4.bc +// RUN: rm -rf %t4.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t4.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t4.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE4 + +#include + +#ifdef AllocSource1 +void maybeAllocSource1(int *a); +#endif +void maybeAllocSource2(int **a); +int *maybeAllocSource3(); +int **maybeAllocSource4(); + +int main() { + int *a = 0; +#ifdef AllocSource1 + // CHECK-ALLOCSOURCE1: not valid annotation + maybeAllocSource1(a); + // CHECK-ALLOCSOURCE1: ASSERTION FAIL + // CHECK-ALLOCSOURCE1: partially completed paths = 1 + // CHECK-ALLOCSOURCE1: generated tests = 1 +#endif + +#ifdef AllocSource2 + maybeAllocSource2(&a); + // CHECK-NOT-ALLOCSOURCE2: memory error + // CHECK-NOT-ALLOCSOURCE2: ASSERTION FAIL + // CHECK-ALLOCSOURCE2: partially completed paths = 0 + // CHECK-ALLOCSOURCE2: generated tests = 1 +#endif + +#ifdef AllocSource3 + a = maybeAllocSource3(); + // CHECK-NOT-ALLOCSOURCE3 : memory error + // CHECK-NOT-ALLOCSOURCE3: Not Allocated + // CHECK-ALLOCSOURCE3: partially completed paths = 0 + // CHECK-ALLOCSOURCE3: generated tests = 1 +#endif + +#ifdef AllocSource4 + a = *maybeAllocSource4(); + // CHECK-NOT-ALLOCSOURCE4: ASSERTION FAIL + // CHECK-ALLOCSOURCE4 : memory error + // CHECK-ALLOCSOURCE4: partially completed paths = {{[1-9][0-9]*}} + // CHECK-ALLOCSOURCE4: generated tests = {{[1-9][0-9]*}} +#endif + + assert(a != 0 && "Not Allocated"); + *a = 42; + + return 0; +} diff --git a/test/Feature/Annotation/AllocSource.json b/test/Feature/Annotation/AllocSource.json new file mode 100644 index 0000000000..a31051c64d --- /dev/null +++ b/test/Feature/Annotation/AllocSource.json @@ -0,0 +1,40 @@ +{ + "maybeAllocSource1": { + "name": "maybeAllocSource1", + "annotation": [ + [], + [ + "AllocSource::1" + ] + ], + "properties": [] + }, + "maybeAllocSource2": { + "name": "maybeAllocSource2", + "annotation": [ + [], + [ + "AllocSource:*:1" + ] + ], + "properties": [] + }, + "maybeAllocSource3": { + "name": "maybeAllocSource3", + "annotation": [ + [ + "AllocSource::1" + ] + ], + "properties": [] + }, + "maybeAllocSource4": { + "name": "maybeAllocSource4", + "annotation": [ + [ + "AllocSource::1" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/BrokenAnnotation.json b/test/Feature/Annotation/BrokenAnnotation.json new file mode 100644 index 0000000000..0b5c90598f --- /dev/null +++ b/test/Feature/Annotation/BrokenAnnotation.json @@ -0,0 +1,11 @@ +{ + "maybeDeref1": { + "name": "maybeDeref1", + "annotation": [ + [], + [ + "Deref" + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/Deref.c b/test/Feature/Annotation/Deref.c new file mode 100644 index 0000000000..7a1048f644 --- /dev/null +++ b/test/Feature/Annotation/Deref.c @@ -0,0 +1,104 @@ +// REQUIRES: z3 +// RUN: %clang -DDeref1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF1 + +// RUN: %clang -DDeref2 %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF2 + +// RUN: %clang -DDeref3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF3 + +// RUN: %clang -DDeref4 %s -g -emit-llvm %O0opt -c -o %t4.bc +// RUN: rm -rf %t4.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t4.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t4.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF4 + +// RUN: %clang -DDeref5 %s -g -emit-llvm %O0opt -c -o %t5.bc +// RUN: rm -rf %t5.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t5.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t5.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF5 + +// RUN: %clang -DDeref6 %s -g -emit-llvm %O0opt -c -o %t6.bc +// RUN: rm -rf %t6.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t6.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t6.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF6 + +// RUN: %clang -DHASVALUE -DDeref1 -DDeref2 -DDeref3 -DDeref4 -DDeref5 -DDeref6 %s -g -emit-llvm %O0opt -c -o %t7.bc +// RUN: rm -rf %t7.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t7.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t7.bc 2>&1 | FileCheck %s -check-prefix=CHECK-NODEREF +// CHECK-NODEREF-NOT: memory error: null pointer exception + +// RUN: %clang -DDeref1 -DDeref2 -DDeref3 -DDeref4 -DDeref5 -DDeref6 %s -g -emit-llvm %O0opt -c -o %t8.bc +// RUN: rm -rf %t8.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t8.klee-out-1 --annotations=%S/EmptyAnnotation.json --external-calls=all --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t8.bc 2>&1 | FileCheck %s -check-prefix=CHECK-EMPTY +// CHECK-EMPTY-NOT: memory error: null pointer exception +// CHECK-EMPTY: partially completed paths = 0 +// CHECK-EMPTY: generated tests = 1 + +void maybeDeref1(int *a); +void maybeDeref2(int **a); +void maybeDeref3(int **a); +void maybeDeref4(int b, int *a); +void maybeDeref5(int *a, int b); +void maybeDeref6(int *a, int *b); + +int main() { + int c = 42; +#ifdef HASVALUE + int *a = &c; + int **b = &a; +#else + int *a = 0; + int **b = 0; +#endif + +#ifdef Deref1 + // CHECK-DEREF1: memory error: null pointer exception + maybeDeref1(a); + // CHECK-DEREF1: memory error: out of bound pointer + maybeDeref1((int *)42); + // CHECK-DEREF1: partially completed paths = 2 + // CHECK-DEREF1: generated tests = 3 +#endif + +#ifdef Deref2 + // CHECK-DEREF2: memory error: null pointer exception + maybeDeref2(b); + maybeDeref2(&a); + // CHECK-DEREF2: partially completed paths = 1 + // CHECK-DEREF2: generated tests = 3 +#endif + +#ifdef Deref3 + // CHECK-DEREF3: memory error: null pointer exception + maybeDeref3(&a); + // CHECK-DEREF3: memory error: null pointer exception + maybeDeref3(b); + // CHECK-DEREF3: partially completed paths = 2 + // CHECK-DEREF3: generated tests = 2 +#endif + +#ifdef Deref4 + // CHECK-DEREF4: memory error: null pointer exception + maybeDeref4(0, a); + // CHECK-DEREF4: partially completed paths = 1 + // CHECK-DEREF4: generated tests = 2 +#endif + +#ifdef Deref5 + // CHECK-DEREF5: memory error: null pointer exception + maybeDeref5(a, 0); + // CHECK-DEREF5: partially completed paths = 1 + // CHECK-DEREF5: generated tests = 2 +#endif + +#ifdef Deref6 + // CHECK-DEREF6: memory error: null pointer exception + maybeDeref6(a, &c); + // CHECK-DEREF6: memory error: null pointer exception + maybeDeref6(&c, a); + // CHECK-DEREF6: partially completed paths = 2 + // CHECK-DEREF6: generated tests = 3 +#endif + return 0; +} diff --git a/test/Feature/Annotation/Deref.json b/test/Feature/Annotation/Deref.json new file mode 100644 index 0000000000..02ce7ecbc3 --- /dev/null +++ b/test/Feature/Annotation/Deref.json @@ -0,0 +1,67 @@ +{ + "maybeDeref1": { + "name": "maybeDeref1", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "maybeDeref2": { + "name": "maybeDeref2", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "maybeDeref3": { + "name": "maybeDeref3", + "annotation": [ + [], + [ + "Deref:*" + ] + ], + "properties": [] + }, + "maybeDeref4": { + "name": "maybeDeref4", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "maybeDeref5": { + "name": "maybeDeref5", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "maybeDeref6": { + "name": "maybeDeref6", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/EmptyAnnotation.json b/test/Feature/Annotation/EmptyAnnotation.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/test/Feature/Annotation/EmptyAnnotation.json @@ -0,0 +1 @@ +{} diff --git a/test/Feature/Annotation/Free.c b/test/Feature/Annotation/Free.c new file mode 100644 index 0000000000..22614bf8f5 --- /dev/null +++ b/test/Feature/Annotation/Free.c @@ -0,0 +1,45 @@ +// REQUIRES: z3 +// RUN: %clang -DFree1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/Free.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-FREE1 + +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/Free.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-FREE2 + +// RUN: %clang -DFree3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/Free.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-FREE3 + +#include + +int *maybeAllocSource1(); +void maybeFree1(int *a); + +int main() { + int *a; +#ifdef Free1 + // CHECK-FREE1: memory error: invalid pointer: free + // CHECK-FREE1: KLEE: done: completed paths = 1 + // CHECK-FREE1: KLEE: done: partially completed paths = 1 + // CHECK-FREE1: KLEE: done: generated tests = 2 + a = malloc(sizeof(int)); + maybeFree1(a); + maybeFree1(a); +#endif + + a = maybeAllocSource1(); + maybeFree1(a); + // CHECK-NOT-FREE2: memory error: invalid pointer: free + // CHECK-FREE2: KLEE: done: completed paths = 1 + // CHECK-FREE2: KLEE: done: partially completed paths = 0 + // CHECK-FREE2: KLEE: done: generated tests = 1 +#ifdef Free3 + // CHECK-FREE3: memory error: invalid pointer: free + // CHECK-FREE3: KLEE: done: completed paths = 0 + // CHECK-FREE3: KLEE: done: partially completed paths = 1 + // CHECK-FREE3: KLEE: done: generated tests = 1 + maybeFree1(a); +#endif + return 0; +} diff --git a/test/Feature/Annotation/Free.json b/test/Feature/Annotation/Free.json new file mode 100644 index 0000000000..d8a9becf9d --- /dev/null +++ b/test/Feature/Annotation/Free.json @@ -0,0 +1,31 @@ +{ + "maybeFree1": { + "name": "maybeFree1", + "annotation": [ + [], + [ + "FreeSink::1" + ] + ], + "properties": [] + }, + "maybeFree2": { + "name": "maybeFree2", + "annotation": [ + [], + [ + "FreeSink:*:1" + ] + ], + "properties": [] + }, + "maybeAllocSource1": { + "name": "maybeAllocSource1", + "annotation": [ + [ + "AllocSource::1" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/General.c b/test/Feature/Annotation/General.c new file mode 100644 index 0000000000..a642919f2b --- /dev/null +++ b/test/Feature/Annotation/General.c @@ -0,0 +1,43 @@ +// REQUIRES: z3 +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/BrokenAnnotation.json --mock-policy=all -emit-all-errors=true %t1.bc 2>%t.stderr.log || echo "Exit status must be 0" +// RUN: FileCheck -check-prefix=CHECK-JSON --input-file=%t.stderr.log %s +// CHECK-JSON: Annotation: Parsing JSON + +// RUN: %clang -DPTRARG %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/General.json --mock-policy=all -emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK + +// RUN: %clang -DPTRRET %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/General.json --mock-policy=all -emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK + +#include + +struct ST { + int a; + int b; +}; + +void ptrArg(struct ST, int **a); +int *ptrRet(); + +int main() { + int *a = 15; +#ifdef PTRARG + struct ST st; + ptrArg(st, &a); +#endif + +#ifdef PTRRET + a = ptrRet(); +#endif + + // CHECK: memory error: null pointer exception + // CHECK: partially completed paths = 1 + // CHECK: generated tests = 2 + *a = 42; + + return 0; +} diff --git a/test/Feature/Annotation/General.json b/test/Feature/Annotation/General.json new file mode 100644 index 0000000000..65cffd2fbf --- /dev/null +++ b/test/Feature/Annotation/General.json @@ -0,0 +1,24 @@ +{ + "ptrArg": { + "name": "ptrArg", + "annotation": [ + [], + [], + [ + "InitNull:*", + "AllocSource:*:1" + ] + ], + "properties": [] + }, + "ptrRet": { + "name": "ptrRet", + "annotation": [ + [ + "MaybeInitNull", + "AllocSource::1" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/InitNull.c b/test/Feature/Annotation/InitNull.c new file mode 100644 index 0000000000..ff7e152c71 --- /dev/null +++ b/test/Feature/Annotation/InitNull.c @@ -0,0 +1,79 @@ +// REQUIRES: z3 +// RUN: %clang -DInitNull1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL1 + +// RUN: %clang -DInitNull2 %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL2 + +// RUN: %clang -DInitNull3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL3 + +// RUN: %clang -DInitNull4 %s -g -emit-llvm %O0opt -c -o %t4.bc +// RUN: rm -rf %t4.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t4.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t4.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL4 + +// RUN: %clang -DInitNull1 -DInitNull2 -DInitNull3 -DInitNull4 %s -g -emit-llvm %O0opt -c -o %t5.bc +// RUN: rm -rf %t5.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t5.klee-out-1 --annotations=%S/InitNullEmpty.json --mock-policy=all -emit-all-errors=true %t5.bc 2>&1 | FileCheck %s -check-prefix=CHECK-EMPTY +// CHECK-EMPTY: ASSERTION FAIL +// CHECK-EMPTY: partially completed paths = {{[1-2]}} + +// RUN: %clang -DMustInitNull5 %s -g -emit-llvm %O0opt -c -o %t6.bc +// RUN: rm -rf %t6.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t6.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t6.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL5 + +#include + +#ifdef InitNull1 +void mustInitNull1(int *a); +#endif +void mustInitNull2(int **a); +int *maybeInitNull1(); +int **maybeInitNull2(); + +int *mustInitNull3(); + +int main() { + int c = 42; + int *a = &c; +#ifdef InitNull1 + // CHECK-INITNULL1: not valid annotation + mustInitNull1(a); + // CHECK-INITNULL1-NOT: A is Null + // CHECK-INITNULL1: partially completed paths = 0 + // CHECK-INITNULL1: generated tests = 1 +#endif + +#ifdef InitNull2 + mustInitNull2(&a); + // CHECK-INITNULL2: ASSERTION FAIL + // CHECK-INITNULL2: partially completed paths = 1 + // CHECK-INITNULL2: generated tests = 2 +#endif + +#ifdef InitNull3 + a = maybeInitNull1(); + // CHECK-INITNULL3: ASSERTION FAIL + // CHECK-INITNULL3: partially completed paths = 1 + // CHECK-INITNULL3: generated tests = 2 +#endif + +#ifdef InitNull4 + a = *maybeInitNull2(); + // CHECK-INITNULL4: ASSERTION FAIL + // CHECK-INITNULL4: partially completed paths = {{[2-3]}} +#endif + +#ifdef MustInitNull5 + a = mustInitNull3(); + // CHECK-INITNULL5: partially completed paths = 0 + // CHECK-INITNULL5: generated tests = 2 +#else + assert(a != 0 && "A is Null"); +#endif + + return 0; +} diff --git a/test/Feature/Annotation/InitNull.json b/test/Feature/Annotation/InitNull.json new file mode 100644 index 0000000000..270c7f01d1 --- /dev/null +++ b/test/Feature/Annotation/InitNull.json @@ -0,0 +1,49 @@ +{ + "mustInitNull1": { + "name": "maybeInitNull1", + "annotation": [ + [], + [ + "InitNull" + ] + ], + "properties": [] + }, + "mustInitNull2": { + "name": "maybeInitNull2", + "annotation": [ + [], + [ + "InitNull:*" + ] + ], + "properties": [] + }, + "maybeInitNull1": { + "name": "maybeInitNull1", + "annotation": [ + [ + "MaybeInitNull" + ] + ], + "properties": [] + }, + "maybeInitNull2": { + "name": "maybeInitNull2", + "annotation": [ + [ + "MaybeInitNull:*" + ] + ], + "properties": [] + }, + "mustInitNull3": { + "name": "mustInitNull3", + "annotation": [ + [ + "InitNull" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/InitNullEmpty.json b/test/Feature/Annotation/InitNullEmpty.json new file mode 100644 index 0000000000..535d0a767b --- /dev/null +++ b/test/Feature/Annotation/InitNullEmpty.json @@ -0,0 +1,32 @@ +{ + "maybeInitNull1": { + "name": "maybeInitNull1", + "annotation": [ + [], + [] + ], + "properties": [] + }, + "maybeInitNull2": { + "name": "maybeInitNull2", + "annotation": [ + [], + [] + ], + "properties": [] + }, + "maybeInitNull3": { + "name": "maybeInitNull3", + "annotation": [ + [] + ], + "properties": [] + }, + "maybeInitNull4": { + "name": "maybeInitNull4", + "annotation": [ + [] + ], + "properties": [] + } +} diff --git a/test/Feature/CoverOnTheFly.c b/test/Feature/CoverOnTheFly.c index 85c0ead78c..73bd550f2c 100644 --- a/test/Feature/CoverOnTheFly.c +++ b/test/Feature/CoverOnTheFly.c @@ -1,12 +1,11 @@ -// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=false +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=none // REQUIRES: not-asan // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --delay-cover-on-the-fly=500 --dump-states-on-halt=false --cover-on-the-fly --search=bfs --use-guided-search=none --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --timer-interval=1ms --delay-cover-on-the-fly=1ms --dump-states-on-halt=none --cover-on-the-fly --search=bfs --use-guided-search=none --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" -#define a (2) int main() { int res = 0; for (;;) { @@ -31,5 +30,4 @@ int main() { } } -// CHECK: KLEE: done: completed paths = 0 -// CHECK: KLEE: done: generated tests = 5 +// CHECK-NOT: KLEE: done: generated tests = 0 diff --git a/test/Feature/DumpStatesOnHalt.c b/test/Feature/DumpStatesOnHalt.c index aca8d7c810..9bda0cb83a 100644 --- a/test/Feature/DumpStatesOnHalt.c +++ b/test/Feature/DumpStatesOnHalt.c @@ -1,6 +1,6 @@ // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-instructions=1 --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --max-instructions=1 --dump-states-on-halt=all %t1.bc 2>&1 | FileCheck %s // RUN: test -f %t.klee-out/test000001.ktest int main(int argc, char **argv) { diff --git a/test/Feature/ExprLogging.c b/test/Feature/ExprLogging.c index 8109647a57..ca8d7a7913 100644 --- a/test/Feature/ExprLogging.c +++ b/test/Feature/ExprLogging.c @@ -1,7 +1,7 @@ // RUN: %clang %s -emit-llvm -g %O0opt -c -o %t1.bc // We disable the cex-cache to eliminate nondeterminism across different solvers, in particular when counting the number of queries in the last two commands // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-cex-cache=false --use-query-log=all:kquery,all:smt2,solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: %klee --output-dir=%t.klee-out --use-cex-cache=false --use-alpha-equivalence=false --use-query-log=all:kquery,all:smt2,solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log // RUN: %kleaver -print-ast %t.klee-out/all-queries.kquery > %t3.log // RUN: %kleaver -print-ast %t3.log > %t4.log // RUN: diff %t3.log %t4.log diff --git a/test/Feature/LazyInitialization/DerefSymbolicPointer.c b/test/Feature/LazyInitialization/DerefSymbolicPointer.c index 27fd4d1d42..b0919d56a3 100644 --- a/test/Feature/LazyInitialization/DerefSymbolicPointer.c +++ b/test/Feature/LazyInitialization/DerefSymbolicPointer.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --write-kqueries --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --write-kqueries --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/ImpossibleAddressForLI.c b/test/Feature/LazyInitialization/ImpossibleAddressForLI.c index abc643eb05..f0d9f25bf6 100644 --- a/test/Feature/LazyInitialization/ImpossibleAddressForLI.c +++ b/test/Feature/LazyInitialization/ImpossibleAddressForLI.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/LazyInitialization.c b/test/Feature/LazyInitialization/LazyInitialization.c index 74356f31b3..31e82a124e 100644 --- a/test/Feature/LazyInitialization/LazyInitialization.c +++ b/test/Feature/LazyInitialization/LazyInitialization.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc > %t.log +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log struct Node { diff --git a/test/Feature/LazyInitialization/LinkedList.c b/test/Feature/LazyInitialization/LinkedList.c index 9431e4ffc3..191ce3103b 100644 --- a/test/Feature/LazyInitialization/LinkedList.c +++ b/test/Feature/LazyInitialization/LinkedList.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --write-kqueries --solver-backend=z3 --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --write-kqueries --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/PointerOffset.c b/test/Feature/LazyInitialization/PointerOffset.c index aaf3694e1c..2d0b7a4321 100644 --- a/test/Feature/LazyInitialization/PointerOffset.c +++ b/test/Feature/LazyInitialization/PointerOffset.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --use-timestamps=false --skip-local=false %t.bc +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --skip-local=false %t.bc // RUN: %ktest-tool %t.klee-out/test*.ktest > %t.log // RUN: FileCheck %s -input-file=%t.log // CHECK: pointers: [(0, 1, 4)] diff --git a/test/Feature/LazyInitialization/SingleInitializationAndAccess.c b/test/Feature/LazyInitialization/SingleInitializationAndAccess.c index 1def3a9876..4c2413aa9e 100644 --- a/test/Feature/LazyInitialization/SingleInitializationAndAccess.c +++ b/test/Feature/LazyInitialization/SingleInitializationAndAccess.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --skip-local=false --use-sym-size-li --min-number-elements-li=1 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --skip-local=false --use-sym-size-li --min-number-elements-li=1 %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/LazyInitialization/TwoObjectsInitialization.c b/test/Feature/LazyInitialization/TwoObjectsInitialization.c index ab67462f3d..957f4bd7da 100644 --- a/test/Feature/LazyInitialization/TwoObjectsInitialization.c +++ b/test/Feature/LazyInitialization/TwoObjectsInitialization.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/MemoryLimit.c b/test/Feature/MemoryLimit.c index 330b2547ea..a24a16993e 100644 --- a/test/Feature/MemoryLimit.c +++ b/test/Feature/MemoryLimit.c @@ -44,7 +44,7 @@ int main() { malloc_failed |= (p == 0); // Ensure we hit the periodic check // Use the pointer to be not optimized out by the compiler - for (j = 0; j < 10000; j++) + for (j = 0; j < 100; j++) x += (long)p; } #endif diff --git a/test/Feature/MockPointersDeterministic.c b/test/Feature/MockPointersDeterministic.c new file mode 100644 index 0000000000..03a2480850 --- /dev/null +++ b/test/Feature/MockPointersDeterministic.c @@ -0,0 +1,24 @@ +// REQUIRES: z3 +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc + +// RUN: rm -rf %t.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t.klee-out-1 --min-number-elements-li=0 --use-sym-size-li --skip-not-lazy-initialized --mock-policy=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 +// CHECK-1: memory error: null pointer exception +// CHECK-1: memory error: out of bound pointer +// CHECK-1: KLEE: done: completed paths = 1 +// CHECK-1: KLEE: done: partially completed paths = 2 +// CHECK-1: KLEE: done: generated tests = 3 + +#include + +extern int *age(); + +int main() { + if (age() != age()) { + assert(0 && "age is deterministic"); + } + if (*age() != *age()) { + assert(0 && "age is deterministic"); + } + return *age(); +} diff --git a/test/Feature/MockStrategies.c b/test/Feature/MockStrategies.c new file mode 100644 index 0000000000..d8998cfe54 --- /dev/null +++ b/test/Feature/MockStrategies.c @@ -0,0 +1,37 @@ +// REQUIRES: z3 +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc + +// RUN: rm -rf %t.klee-out-1 +// RUN: %klee --output-dir=%t.klee-out-1 --external-calls=all %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 +// CHECK-1: failed external call +// CHECK-1: KLEE: done: completed paths = 1 +// CHECK-1: KLEE: done: generated tests = 2 + +// RUN: rm -rf %t.klee-out-2 +// RUN: %klee --output-dir=%t.klee-out-2 --mock-policy=all %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-2 +// CHECK-2: ASSERTION FAIL +// CHECK-2: KLEE: done: completed paths = 2 +// CHECK-2: KLEE: done: generated tests = 3 + +// RUN: rm -rf %t.klee-out-3 +// RUN: not %klee --output-dir=%t.klee-out-3 --solver-backend=stp --mock-policy=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-3 +// CHECK-3: KLEE: ERROR: Deterministic mocks can be generated with Z3 solver only. + +// RUN: rm -rf %t.klee-out-4 +// RUN: %klee --output-dir=%t.klee-out-4 --solver-backend=z3 --mock-policy=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-4 +// CHECK-4: KLEE: done: completed paths = 2 +// CHECK-4: KLEE: done: generated tests = 2 + +#include + +extern int foo(int x, int y); + +int main() { + int a, b; + klee_make_symbolic(&a, sizeof(a), "a"); + klee_make_symbolic(&b, sizeof(b), "b"); + if (a == b && foo(a + b, b) != foo(2 * b, a)) { + assert(0); + } + return 0; +} diff --git a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c index 784c0151e2..87b66e23c7 100644 --- a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c +++ b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c @@ -2,7 +2,8 @@ // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/info %s -// CHECK: KLEE: done: total queries = 1 +// 3 = 2 for entrypoint multiplex + 1 for fork +// CHECK: KLEE: done: total queries = 3 #include "assert.h" #include "klee/klee.h" diff --git a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json index ec8403ab45..b34cb11366 100644 --- a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json +++ b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json @@ -20,7 +20,7 @@ "uri": "/tmp/NotCallingUnreachableBranchesInForkErrorGuided.c" }, "region": { - "startLine": 9, + "startLine": 10, "startColumn": 14 } } @@ -33,7 +33,7 @@ "uri": "/tmp/NotCallingUnreachableBranchesInForkErrorGuided.c" }, "region": { - "startLine": 13, + "startLine": 14, "startColumn": 5 } } @@ -52,7 +52,7 @@ "uri": "/tmp/NotCallingUnreachableBranchesInForkErrorGuided.c" }, "region": { - "startLine": 13, + "startLine": 14, "startColumn": 5 } } @@ -62,4 +62,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/test/Feature/Searchers.c b/test/Feature/Searchers.c index 84abd378d1..aacb09de59 100644 --- a/test/Feature/Searchers.c +++ b/test/Feature/Searchers.c @@ -18,13 +18,13 @@ // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --search=random-path --search=nurs:qc %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=random-state %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=random-state %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=nurs:depth %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=nurs:depth %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=nurs:qc %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=nurs:qc %t2.bc /* this test is basically just for coverage and doesn't really do any correctness check (aside from testing that the various combinations diff --git a/test/Feature/SolverTimeout.c b/test/Feature/SolverTimeout.c index af449cebd0..41049f5b34 100644 --- a/test/Feature/SolverTimeout.c +++ b/test/Feature/SolverTimeout.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-solver-time=1 %t.bc +// RUN: %klee --output-dir=%t.klee-out --max-solver-time=1 %t.bc 2>&1 | FileCheck %s // // Note: This test occasionally fails when using Z3 4.4.1 @@ -11,6 +11,8 @@ int main() { klee_make_symbolic(&x, sizeof(x), "x"); + // CHECK-NOT: Yes + // CHECK: No if (x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x + (x * x % (x + 12)) == y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y % i) printf("Yes\n"); else diff --git a/test/Feature/SymbolicSizes/FirstAndLastElements.c b/test/Feature/SymbolicSizes/FirstAndLastElements.c index da74d0569b..10ba4c5784 100644 --- a/test/Feature/SymbolicSizes/FirstAndLastElements.c +++ b/test/Feature/SymbolicSizes/FirstAndLastElements.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/ImplicitArrayExtension.c b/test/Feature/SymbolicSizes/ImplicitArrayExtension.c index 604d137360..273334c84f 100644 --- a/test/Feature/SymbolicSizes/ImplicitArrayExtension.c +++ b/test/Feature/SymbolicSizes/ImplicitArrayExtension.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c b/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c index 0ca567204c..6b4e09d0ee 100644 --- a/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c +++ b/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c @@ -1,4 +1,3 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s diff --git a/test/Feature/SymbolicSizes/IntArray.c b/test/Feature/SymbolicSizes/IntArray.c index e820df0a04..48ea30e48e 100644 --- a/test/Feature/SymbolicSizes/IntArray.c +++ b/test/Feature/SymbolicSizes/IntArray.c @@ -1,7 +1,8 @@ -// REQUIRES: z3 +// REQUIRES: not-darwin, not-metasmt +// Disabling darwin and metasmt because test has flaky behaviour on CI // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c b/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c index 51ad20892e..be244f9ae0 100644 --- a/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c +++ b/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/LowerOutOfBound.c b/test/Feature/SymbolicSizes/LowerOutOfBound.c index 0a97e5c63a..41064df671 100644 --- a/test/Feature/SymbolicSizes/LowerOutOfBound.c +++ b/test/Feature/SymbolicSizes/LowerOutOfBound.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/MinimizeSize.c b/test/Feature/SymbolicSizes/MinimizeSize.c index 5da9f65c0f..c767ff6a97 100644 --- a/test/Feature/SymbolicSizes/MinimizeSize.c +++ b/test/Feature/SymbolicSizes/MinimizeSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --solver-backend=z3 --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/MultipleAllocations.c b/test/Feature/SymbolicSizes/MultipleAllocations.c index 4ef3193a47..d953192616 100644 --- a/test/Feature/SymbolicSizes/MultipleAllocations.c +++ b/test/Feature/SymbolicSizes/MultipleAllocations.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/NegativeIndexArray.c b/test/Feature/SymbolicSizes/NegativeIndexArray.c index 2d4e0a6368..6f5f7e904e 100644 --- a/test/Feature/SymbolicSizes/NegativeIndexArray.c +++ b/test/Feature/SymbolicSizes/NegativeIndexArray.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include "stdlib.h" diff --git a/test/Feature/SymbolicSizes/NegativeSize.c b/test/Feature/SymbolicSizes/NegativeSize.c index 72c0b9c4c7..c7f59e8b49 100644 --- a/test/Feature/SymbolicSizes/NegativeSize.c +++ b/test/Feature/SymbolicSizes/NegativeSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include @@ -22,7 +21,7 @@ int main() { s1[1] = 10; // n == -2 // CHECK: NegativeSize.c:[[@LINE+1]]: memory error: out of bound pointer s2[2] = 20; // m == 3 - // CHECK: NegativeSize.c:[[@LINE+1]]: ASSERTION FAIL: 0 + // CHECK: NegativeSize.c:[[@LINE+1]]: ASSERTION FAIL assert(0); } } diff --git a/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c b/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c index 7d3bab5940..885cc518dc 100644 --- a/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c +++ b/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/SegmentComparator.c b/test/Feature/SymbolicSizes/SegmentComparator.c index 3a7f16db76..614610b76a 100644 --- a/test/Feature/SymbolicSizes/SegmentComparator.c +++ b/test/Feature/SymbolicSizes/SegmentComparator.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c b/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c index acf086a65f..daa6bec34f 100644 --- a/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c +++ b/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --solver-backend=z3 --use-sym-size-alloc --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c b/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c index dbb2331aac..725dc56785 100644 --- a/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c +++ b/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c b/test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c new file mode 100644 index 0000000000..37383aee60 --- /dev/null +++ b/test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c @@ -0,0 +1,14 @@ +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --symbolic-allocation-threshold=0 %t1.bc 2>&1 | FileCheck %s + +extern int GLOBAL[]; + +int main() { + // CHECK: SymbolicSizeUnsizedGlobal.c:[[@LINE+1]]: memory error: out of bound pointer + GLOBAL[1] = 0; + // CHECK: SymbolicSizeUnsizedGlobal.c:[[@LINE+1]]: memory error: out of bound pointer + GLOBAL[2] = 0; + // CHECK-NOT: SymbolicSizeUnsizedGlobal.c:[[@LINE+1]]: memory error: out of bound pointer + GLOBAL[0] = 0; +} diff --git a/test/Feature/SymbolicSizes/UninitializedMemory.c b/test/Feature/SymbolicSizes/UninitializedMemory.c new file mode 100644 index 0000000000..f0501d3893 --- /dev/null +++ b/test/Feature/SymbolicSizes/UninitializedMemory.c @@ -0,0 +1,24 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + int n; + klee_make_symbolic(&n, sizeof(n), "n"); + + char *s = (char *)malloc(n); + s[2] = 10; + if (s[0] == 0) { + printf("1) 0\n"); + } else { + printf("1) not 0\n"); + } + + // CHECK-DAG: 1) 0 + // CHECK-DAG: 1) not 0 +} diff --git a/test/Feature/SymbolicSizes/VoidStar.c b/test/Feature/SymbolicSizes/VoidStar.c index 48924f7b69..8770065d7a 100644 --- a/test/Feature/SymbolicSizes/VoidStar.c +++ b/test/Feature/SymbolicSizes/VoidStar.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --skip-not-lazy-initialized --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --skip-not-lazy-initialized --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/TwoUninitializedRegions.c b/test/Feature/TwoUninitializedRegions.c new file mode 100644 index 0000000000..a772e4d549 --- /dev/null +++ b/test/Feature/TwoUninitializedRegions.c @@ -0,0 +1,23 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char arr1[3]; + char arr2[3]; + + if (arr1[0] == arr2[0]) { + printf("1) equal\n"); + } else { + printf("1) not equal\n"); + } + + // CHECK-DAG: 1) equal + // CHECK-DAG: 1) not equal +} diff --git a/test/Feature/UninitializedConstantMemory.c b/test/Feature/UninitializedConstantMemory.c new file mode 100644 index 0000000000..ee8eb5cc92 --- /dev/null +++ b/test/Feature/UninitializedConstantMemory.c @@ -0,0 +1,29 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char arr[3]; + + if (arr[0] == 0) { + printf("1) 0\n"); + } else { + printf("1) not 0\n"); + } + + char *zero_arr = (char *)calloc(3, sizeof(char)); + if (zero_arr[1] == 0) { + return 0; + } else { + // CHECK-NOT: ASSERTION FAIL + assert(0); + } + + // CHECK-DAG: 1) 0 + // CHECK-DAG: 1) not 0 +} diff --git a/test/Feature/const_array_opt1.c b/test/Feature/const_array_opt1.c index 7482d48232..a70223e36d 100644 --- a/test/Feature/const_array_opt1.c +++ b/test/Feature/const_array_opt1.c @@ -1,5 +1,6 @@ // REQUIRES: not-msan // REQUIRES: not-ubsan +// REQUIRES: not-bitwuzla // Disabling msan and ubsan because it times out on CI // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out diff --git a/test/Feature/uint128.c b/test/Feature/uint128.c new file mode 100644 index 0000000000..98676474c7 --- /dev/null +++ b/test/Feature/uint128.c @@ -0,0 +1,12 @@ +// REQUIRES: target-x86_64 +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t1.bc 2>&1 | FileCheck %s +// CHECK-NOT: failed external call +#include "klee-test-comp.c" +extern unsigned __int128 __VERIFIER_nondet_uint128(); + +int main() { + __int128 x = __VERIFIER_nondet_uint128(); + return x > 0; +} diff --git a/test/Floats/cast_union_loose.c b/test/Floats/cast_union_loose.c new file mode 100644 index 0000000000..6dbf5c77a9 --- /dev/null +++ b/test/Floats/cast_union_loose.c @@ -0,0 +1,53 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "cast_union_loose.c", 3, "reach_error"); } +/* Example from "Abstract Domains for Bit-Level Machine Integer and + Floating-point Operations" by Miné, published in WING 12. +*/ + +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } + return; +} + +union u { + int i[2]; + double d; +}; + +double cast(int i) { + union u x, y; + x.i[0] = 0x43300000; + y.i[0] = x.i[0]; + x.i[1] = 0x80000000; + y.i[1] = i ^ x.i[1]; + return y.d - x.d; +} + +int main() { + int a; + double r; + + a = __VERIFIER_nondet_int(); + assume_abort_if_not(a >= -10000 && a <= 10000); + + r = cast(a); + __VERIFIER_assert(r >= -10000. && r <= 10000.); + return 0; +} diff --git a/test/Floats/cast_union_loose.yml b/test/Floats/cast_union_loose.yml new file mode 100644 index 0000000000..27094e3abe --- /dev/null +++ b/test/Floats/cast_union_loose.yml @@ -0,0 +1,18 @@ +format_version: '2.0' + +# old file name: cast_union_loose_false-unreach-call_true-termination.c +input_files: 'cast_union_loose.c' + +properties: + - property_file: ../properties/termination.prp + expected_verdict: true + - property_file: ../properties/unreach-call.prp + expected_verdict: false + - property_file: ../properties/coverage-error-call.prp + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Floats/cast_union_tight.c b/test/Floats/cast_union_tight.c new file mode 100644 index 0000000000..a5f5e5fe44 --- /dev/null +++ b/test/Floats/cast_union_tight.c @@ -0,0 +1,46 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "cast_union_tight.c", 3, "reach_error"); } +/* Example from "Abstract Domains for Bit-Level Machine Integer and + Floating-point Operations" by Miné, published in WING 12. +*/ + +extern int __VERIFIER_nondet_int(void); +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } + return; +} + +union u { + int i[2]; + double d; +}; + +double cast(int i) { + union u x, y; + x.i[0] = 0x43300000; + y.i[0] = x.i[0]; + x.i[1] = 0x80000000; + y.i[1] = i ^ x.i[1]; + return y.d - x.d; +} + +int main() { + int a; + double r; + + a = __VERIFIER_nondet_int(); + + r = cast(a); + __VERIFIER_assert(r == a); + return 0; +} diff --git a/test/Floats/cast_union_tight.yml b/test/Floats/cast_union_tight.yml new file mode 100644 index 0000000000..7bea04b7f8 --- /dev/null +++ b/test/Floats/cast_union_tight.yml @@ -0,0 +1,18 @@ +format_version: '2.0' + +# old file name: cast_union_tight_false-unreach-call_true-termination.c +input_files: 'cast_union_tight.c' + +properties: + - property_file: ../properties/termination.prp + expected_verdict: true + - property_file: ../properties/unreach-call.prp + expected_verdict: false + - property_file: ../properties/coverage-error-call.prp + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Floats/copysign.c b/test/Floats/copysign.c index 03f3cb4851..80a5921322 100644 --- a/test/Floats/copysign.c +++ b/test/Floats/copysign.c @@ -16,4 +16,4 @@ int main() { return 2; } } -// CHECK: KLEE: done: completed paths = 4 +// CHECK: KLEE: done: completed paths = {{4|6}} diff --git a/test/Floats/coverage-error-call.prp b/test/Floats/coverage-error-call.prp new file mode 100644 index 0000000000..496ed998fa --- /dev/null +++ b/test/Floats/coverage-error-call.prp @@ -0,0 +1,2 @@ +COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) ) + diff --git a/test/Floats/double_req_bl_0670.c b/test/Floats/double_req_bl_0670.c new file mode 100644 index 0000000000..0ecac476be --- /dev/null +++ b/test/Floats/double_req_bl_0670.c @@ -0,0 +1,279 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "double_req_bl_0670.c", 3, "reach_error"); } +extern double __VERIFIER_nondet_double(); + +typedef int __int32_t; +typedef unsigned int __uint32_t; + +/* A union which permits us to convert between a double and two 32 bit + ints. */ +typedef union { + double value; + struct { + __uint32_t lsw; + __uint32_t msw; + } parts; +} ieee_double_shape_type; + +double fabs_double(double x) { + __uint32_t high; + do { + ieee_double_shape_type gh_u; + gh_u.value = (x); + (high) = gh_u.parts.msw; + } while (0); + do { + ieee_double_shape_type sh_u; + sh_u.value = (x); + sh_u.parts.msw = (high & 0x7fffffff); + (x) = sh_u.value; + } while (0); + return x; +} + +/* + * Preprocessed code for the function libs/newlib/math/s_atan.c + */ + +static const double atanhi_atan[] = { + 4.63647609000806093515e-01, + 7.85398163397448278999e-01, + 9.82793723247329054082e-01, + 1.57079632679489655800e+00, +}; + +static const double atanlo_atan[] = { + 2.26987774529616870924e-17, + 3.06161699786838301793e-17, + 1.39033110312309984516e-17, + 6.12323399573676603587e-17, +}; + +static const double aT_atan[] = { + 3.33333333333329318027e-01, + -1.99999999998764832476e-01, + 1.42857142725034663711e-01, + -1.11111104054623557880e-01, + 9.09088713343650656196e-02, + -7.69187620504482999495e-02, + 6.66107313738753120669e-02, + -5.83357013379057348645e-02, + 4.97687799461593236017e-02, + -3.65315727442169155270e-02, + 1.62858201153657823623e-02, +}; + +static const double one_atan = 1.0, pi_o_4 = 7.8539816339744827900E-01, + pi_o_2 = 1.5707963267948965580E+00, + pi = 3.1415926535897931160E+00, huge_atan = 1.0e300; + +double atan_double(double x) { + double w, s1, s2, z; + __int32_t ix, hx, id; + + do { + ieee_double_shape_type gh_u; + gh_u.value = (x); + (hx) = gh_u.parts.msw; + } while (0); + ix = hx & 0x7fffffff; + if (ix >= 0x44100000) { + __uint32_t low; + do { + ieee_double_shape_type gl_u; + gl_u.value = (x); + (low) = gl_u.parts.lsw; + } while (0); + if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (low != 0))) + return x + x; + if (hx > 0) + return atanhi_atan[3] + atanlo_atan[3]; + else + return -atanhi_atan[3] - atanlo_atan[3]; + } + if (ix < 0x3fdc0000) { + if (ix < 0x3e200000) { + if (huge_atan + x > one_atan) + return x; + } + id = -1; + } else { + x = fabs_double(x); + if (ix < 0x3ff30000) { + if (ix < 0x3fe60000) { + id = 0; + x = (2.0 * x - one_atan) / (2.0 + x); + } else { + id = 1; + x = (x - one_atan) / (x + one_atan); + } + } else { + if (ix < 0x40038000) { + id = 2; + x = (x - 1.5) / (one_atan + 1.5 * x); + } else { + id = 3; + x = -1.0 / x; + } + } + } + + z = x * x; + w = z * z; + + s1 = z * (aT_atan[0] + + w * (aT_atan[2] + + w * (aT_atan[4] + + w * (aT_atan[6] + w * (aT_atan[8] + w * aT_atan[10]))))); + s2 = + w * + (aT_atan[1] + + w * (aT_atan[3] + w * (aT_atan[5] + w * (aT_atan[7] + w * aT_atan[9])))); + if (id < 0) + return x - x * (s1 + s2); + else { + z = atanhi_atan[id] - ((x * (s1 + s2) - atanlo_atan[id]) - x); + return (hx < 0) ? -z : z; + } +} + +/* + * Preprocessed code for the function libs/newlib/math/e_atan2.c (Constants are + * defined in requrements/includes/math_constants_double.h) + */ + +static const double tiny_atan2 = 1.0e-300, zero_atan2 = 0.0, + pi_lo_atan2 = 1.2246467991473531772E-16; + +double __ieee754_atan2(double y, double x) { + double z; + __int32_t k, m, hx, hy, ix, iy; + __uint32_t lx, ly; + + do { + ieee_double_shape_type ew_u; + ew_u.value = (x); + (hx) = ew_u.parts.msw; + (lx) = ew_u.parts.lsw; + } while (0); + ix = hx & 0x7fffffff; + do { + ieee_double_shape_type ew_u; + ew_u.value = (y); + (hy) = ew_u.parts.msw; + (ly) = ew_u.parts.lsw; + } while (0); + iy = hy & 0x7fffffff; + if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || + ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) + return x + y; + if (((hx - 0x3ff00000) | lx) == 0) + return atan_double(y); + m = ((hy >> 31) & 1) | ((hx >> 30) & 2); + + if ((iy | ly) == 0) { + switch (m) { + case 0: + case 1: + return y; + case 2: + return pi + tiny_atan2; + case 3: + return -pi - tiny_atan2; + } + } + + if ((ix | lx) == 0) + return (hy < 0) ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2; + + if (ix == 0x7ff00000) { + if (iy == 0x7ff00000) { + switch (m) { + case 0: + return pi_o_4 + tiny_atan2; + case 1: + return -pi_o_4 - tiny_atan2; + case 2: + return 3.0 * pi_o_4 + tiny_atan2; + case 3: + return -3.0 * pi_o_4 - tiny_atan2; + } + } else { + switch (m) { + case 0: + return zero_atan2; + case 1: + return -zero_atan2; + case 2: + return pi + tiny_atan2; + case 3: + return -pi - tiny_atan2; + } + } + } + + if (iy == 0x7ff00000) + return (hy < 0) ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2; + + k = (iy - ix) >> 20; + if (k > 60) + z = pi_o_2 + 0.5 * pi_lo_atan2; + else if (hx < 0 && k < -60) + z = 0.0; + else + z = atan_double(fabs_double(y / x)); + switch (m) { + case 0: + return z; + case 1: { + __uint32_t zh; + do { + ieee_double_shape_type gh_u; + gh_u.value = (z); + (zh) = gh_u.parts.msw; + } while (0); + do { + ieee_double_shape_type sh_u; + sh_u.value = (z); + sh_u.parts.msw = (zh ^ 0x80000000); + (z) = sh_u.value; + } while (0); + } + return z; + case 2: + return pi - (z - pi_lo_atan2); + default: + return (z - pi_lo_atan2) - pi; + } +} + +// nan check for doubles +int isnan_double(double x) { return x != x; } + +int main() { + + /* REQ-BL-0670: + * The atan2 and atan2f procedures shall return NaN if any argument is NaN. + */ + + double x = __VERIFIER_nondet_double(); + double y = __VERIFIER_nondet_double(); + + if (isnan_double(x) || isnan_double(y)) { + + double res = __ieee754_atan2(y, x); + + // x is NAN, y is any or vice versa, the result shall be NAN + if (!isnan_double(res)) { + { reach_error(); } + return 1; + } + } + + return 0; +} diff --git a/test/Floats/double_req_bl_0670.yml b/test/Floats/double_req_bl_0670.yml new file mode 100644 index 0000000000..dfe3bebd6a --- /dev/null +++ b/test/Floats/double_req_bl_0670.yml @@ -0,0 +1,15 @@ +format_version: '2.0' + +# old file name: double_req_bl_0670_true-unreach-call.c +input_files: 'double_req_bl_0670.c' + +properties: + - property_file: ../properties/unreach-call.prp + expected_verdict: true + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Industry/AssignNull_Scene_BadCase02.c b/test/Industry/AssignNull_Scene_BadCase02.c index ecb898b0b2..e8e25bfbe9 100644 --- a/test/Industry/AssignNull_Scene_BadCase02.c +++ b/test/Industry/AssignNull_Scene_BadCase02.c @@ -49,9 +49,8 @@ void TestBad5(struct STU *pdev, const char *buf, unsigned int count) printf("teacher id is %ud", teacherID); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 2 \ No newline at end of file +// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 2 diff --git a/test/Industry/AssignNull_Scene_BadCase04.c b/test/Industry/AssignNull_Scene_BadCase04.c index 757479e40d..272894d73f 100644 --- a/test/Industry/AssignNull_Scene_BadCase04.c +++ b/test/Industry/AssignNull_Scene_BadCase04.c @@ -50,8 +50,7 @@ int TestBad7(char *arg, unsigned int count) return 1; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --smart-resolve-entry-function --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --smart-resolve-entry-function --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/BadCase01_SecB_ForwardNull.c b/test/Industry/BadCase01_SecB_ForwardNull.c index 38431719b3..80b17cbf9b 100644 --- a/test/Industry/BadCase01_SecB_ForwardNull.c +++ b/test/Industry/BadCase01_SecB_ForwardNull.c @@ -140,9 +140,8 @@ void badbad(char *ptr) } #endif -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -// CHECK: KLEE: WARNING: No targets found in error-guided mode \ No newline at end of file +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc > %t1.log 2>&1 +// RUN: FileCheck -input-file=%t1.log %s +// CHECK: KLEE: WARNING: No paths were given to trace verify diff --git a/test/Industry/CheckNull_Scene_BadCase02.c b/test/Industry/CheckNull_Scene_BadCase02.c index fc27954a53..3f19d9b621 100644 --- a/test/Industry/CheckNull_Scene_BadCase02.c +++ b/test/Industry/CheckNull_Scene_BadCase02.c @@ -41,8 +41,7 @@ void TestBad2() free(errMsg); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/CheckNull_Scene_BadCase04.c b/test/Industry/CheckNull_Scene_BadCase04.c index dba74dd82a..179fd1419d 100644 --- a/test/Industry/CheckNull_Scene_BadCase04.c +++ b/test/Industry/CheckNull_Scene_BadCase04.c @@ -56,8 +56,7 @@ void TestBad12(int cond1, int cond2) } } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c new file mode 100644 index 0000000000..fe61b84c59 --- /dev/null +++ b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -0,0 +1,37 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=all %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %gcov-files-path > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s + +// Branch coverage 100%, the number of branches is 2: +// CHECK-COV: Lines executed:100.00% of 1{{1|2}} +// CHECK-COV-NEXT: Branches executed:100.00% of 2 +// CHECK-COV-NEXT: Taken at least once:100.00% of 2 + +#include "klee-test-comp.c" + +#define alloca(size) __builtin_alloca (size) +extern int __VERIFIER_nondet_int(void); + +int main() { + int *x = alloca(sizeof(int)); + int *y = alloca(sizeof(int)); + int *z = alloca(sizeof(int)); + *x = __VERIFIER_nondet_int(); + *y = __VERIFIER_nondet_int(); + *z = __VERIFIER_nondet_int(); + + while (*x > 0) { + *x = *x + *y; + *y = *z; + *z = -(*z) - 1; + } +} + +// CHECK: generated tests = 3 diff --git a/test/Industry/CoverageBranches/CostasArray-17.c b/test/Industry/CoverageBranches/CostasArray-17.c new file mode 100644 index 0000000000..7fc3bafe93 --- /dev/null +++ b/test/Industry/CoverageBranches/CostasArray-17.c @@ -0,0 +1,1772 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs %t1.bc + +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %gcov-files-path > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs %t1.bc + +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %gcov-files-path > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 2: +// CHECK: Lines executed:{{(0\.7[0-9])|(99\.94)}}% of 1545 +// CHECK-NEXT: Branches executed:100.00% of 2 +// CHECK-NEXT: Taken at least once:100.00% of 2 + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2016 Gilles Audemard +// SPDX-FileCopyrightText: 2020 Dirk Beyer +// SPDX-FileCopyrightText: 2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: MIT + +extern void abort(void) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern void __assert_fail(const char *, const char *, unsigned int, + const char *) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +int __VERIFIER_nondet_int(); + +#ifdef GCOV +extern void __gcov_dump(void); +extern void exit(int exit_code) __attribute__((noreturn)); +#endif + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} + +void reach_error() { __assert_fail("0", "CostasArray-17.c", 5, "reach_error"); } +void assume(int cond) { + if (!cond) + abort_prog(); +} +int main() { + int cond0; + int dummy = 0; + int N; + int var0; + var0 = __VERIFIER_nondet_int(); + assume(var0 >= 1); + assume(var0 <= 17); + int var1; + var1 = __VERIFIER_nondet_int(); + assume(var1 >= 1); + assume(var1 <= 17); + int var2; + var2 = __VERIFIER_nondet_int(); + assume(var2 >= 1); + assume(var2 <= 17); + int var3; + var3 = __VERIFIER_nondet_int(); + assume(var3 >= 1); + assume(var3 <= 17); + int var4; + var4 = __VERIFIER_nondet_int(); + assume(var4 >= 1); + assume(var4 <= 17); + int var5; + var5 = __VERIFIER_nondet_int(); + assume(var5 >= 1); + assume(var5 <= 17); + int var6; + var6 = __VERIFIER_nondet_int(); + assume(var6 >= 1); + assume(var6 <= 17); + int var7; + var7 = __VERIFIER_nondet_int(); + assume(var7 >= 1); + assume(var7 <= 17); + int var8; + var8 = __VERIFIER_nondet_int(); + assume(var8 >= 1); + assume(var8 <= 17); + int var9; + var9 = __VERIFIER_nondet_int(); + assume(var9 >= 1); + assume(var9 <= 17); + int var10; + var10 = __VERIFIER_nondet_int(); + assume(var10 >= 1); + assume(var10 <= 17); + int var11; + var11 = __VERIFIER_nondet_int(); + assume(var11 >= 1); + assume(var11 <= 17); + int var12; + var12 = __VERIFIER_nondet_int(); + assume(var12 >= 1); + assume(var12 <= 17); + int var13; + var13 = __VERIFIER_nondet_int(); + assume(var13 >= 1); + assume(var13 <= 17); + int var14; + var14 = __VERIFIER_nondet_int(); + assume(var14 >= 1); + assume(var14 <= 17); + int var15; + var15 = __VERIFIER_nondet_int(); + assume(var15 >= 1); + assume(var15 <= 17); + int var16; + var16 = __VERIFIER_nondet_int(); + assume(var16 >= 1); + assume(var16 <= 17); + int var17; + var17 = __VERIFIER_nondet_int(); + assume(var17 >= -16); + assume(var17 <= 16); + assume(var17 != 0); + int var18; + var18 = __VERIFIER_nondet_int(); + assume(var18 >= -16); + assume(var18 <= 16); + assume(var18 != 0); + int var19; + var19 = __VERIFIER_nondet_int(); + assume(var19 >= -16); + assume(var19 <= 16); + assume(var19 != 0); + int var20; + var20 = __VERIFIER_nondet_int(); + assume(var20 >= -16); + assume(var20 <= 16); + assume(var20 != 0); + int var21; + var21 = __VERIFIER_nondet_int(); + assume(var21 >= -16); + assume(var21 <= 16); + assume(var21 != 0); + int var22; + var22 = __VERIFIER_nondet_int(); + assume(var22 >= -16); + assume(var22 <= 16); + assume(var22 != 0); + int var23; + var23 = __VERIFIER_nondet_int(); + assume(var23 >= -16); + assume(var23 <= 16); + assume(var23 != 0); + int var24; + var24 = __VERIFIER_nondet_int(); + assume(var24 >= -16); + assume(var24 <= 16); + assume(var24 != 0); + int var25; + var25 = __VERIFIER_nondet_int(); + assume(var25 >= -16); + assume(var25 <= 16); + assume(var25 != 0); + int var26; + var26 = __VERIFIER_nondet_int(); + assume(var26 >= -16); + assume(var26 <= 16); + assume(var26 != 0); + int var27; + var27 = __VERIFIER_nondet_int(); + assume(var27 >= -16); + assume(var27 <= 16); + assume(var27 != 0); + int var28; + var28 = __VERIFIER_nondet_int(); + assume(var28 >= -16); + assume(var28 <= 16); + assume(var28 != 0); + int var29; + var29 = __VERIFIER_nondet_int(); + assume(var29 >= -16); + assume(var29 <= 16); + assume(var29 != 0); + int var30; + var30 = __VERIFIER_nondet_int(); + assume(var30 >= -16); + assume(var30 <= 16); + assume(var30 != 0); + int var31; + var31 = __VERIFIER_nondet_int(); + assume(var31 >= -16); + assume(var31 <= 16); + assume(var31 != 0); + int var32; + var32 = __VERIFIER_nondet_int(); + assume(var32 >= -16); + assume(var32 <= 16); + assume(var32 != 0); + int var33; + var33 = __VERIFIER_nondet_int(); + assume(var33 >= -16); + assume(var33 <= 16); + assume(var33 != 0); + int var34; + var34 = __VERIFIER_nondet_int(); + assume(var34 >= -16); + assume(var34 <= 16); + assume(var34 != 0); + int var35; + var35 = __VERIFIER_nondet_int(); + assume(var35 >= -16); + assume(var35 <= 16); + assume(var35 != 0); + int var36; + var36 = __VERIFIER_nondet_int(); + assume(var36 >= -16); + assume(var36 <= 16); + assume(var36 != 0); + int var37; + var37 = __VERIFIER_nondet_int(); + assume(var37 >= -16); + assume(var37 <= 16); + assume(var37 != 0); + int var38; + var38 = __VERIFIER_nondet_int(); + assume(var38 >= -16); + assume(var38 <= 16); + assume(var38 != 0); + int var39; + var39 = __VERIFIER_nondet_int(); + assume(var39 >= -16); + assume(var39 <= 16); + assume(var39 != 0); + int var40; + var40 = __VERIFIER_nondet_int(); + assume(var40 >= -16); + assume(var40 <= 16); + assume(var40 != 0); + int var41; + var41 = __VERIFIER_nondet_int(); + assume(var41 >= -16); + assume(var41 <= 16); + assume(var41 != 0); + int var42; + var42 = __VERIFIER_nondet_int(); + assume(var42 >= -16); + assume(var42 <= 16); + assume(var42 != 0); + int var43; + var43 = __VERIFIER_nondet_int(); + assume(var43 >= -16); + assume(var43 <= 16); + assume(var43 != 0); + int var44; + var44 = __VERIFIER_nondet_int(); + assume(var44 >= -16); + assume(var44 <= 16); + assume(var44 != 0); + int var45; + var45 = __VERIFIER_nondet_int(); + assume(var45 >= -16); + assume(var45 <= 16); + assume(var45 != 0); + int var46; + var46 = __VERIFIER_nondet_int(); + assume(var46 >= -16); + assume(var46 <= 16); + assume(var46 != 0); + int var47; + var47 = __VERIFIER_nondet_int(); + assume(var47 >= -16); + assume(var47 <= 16); + assume(var47 != 0); + int var48; + var48 = __VERIFIER_nondet_int(); + assume(var48 >= -16); + assume(var48 <= 16); + assume(var48 != 0); + int var49; + var49 = __VERIFIER_nondet_int(); + assume(var49 >= -16); + assume(var49 <= 16); + assume(var49 != 0); + int var50; + var50 = __VERIFIER_nondet_int(); + assume(var50 >= -16); + assume(var50 <= 16); + assume(var50 != 0); + int var51; + var51 = __VERIFIER_nondet_int(); + assume(var51 >= -16); + assume(var51 <= 16); + assume(var51 != 0); + int var52; + var52 = __VERIFIER_nondet_int(); + assume(var52 >= -16); + assume(var52 <= 16); + assume(var52 != 0); + int var53; + var53 = __VERIFIER_nondet_int(); + assume(var53 >= -16); + assume(var53 <= 16); + assume(var53 != 0); + int var54; + var54 = __VERIFIER_nondet_int(); + assume(var54 >= -16); + assume(var54 <= 16); + assume(var54 != 0); + int var55; + var55 = __VERIFIER_nondet_int(); + assume(var55 >= -16); + assume(var55 <= 16); + assume(var55 != 0); + int var56; + var56 = __VERIFIER_nondet_int(); + assume(var56 >= -16); + assume(var56 <= 16); + assume(var56 != 0); + int var57; + var57 = __VERIFIER_nondet_int(); + assume(var57 >= -16); + assume(var57 <= 16); + assume(var57 != 0); + int var58; + var58 = __VERIFIER_nondet_int(); + assume(var58 >= -16); + assume(var58 <= 16); + assume(var58 != 0); + int var59; + var59 = __VERIFIER_nondet_int(); + assume(var59 >= -16); + assume(var59 <= 16); + assume(var59 != 0); + int var60; + var60 = __VERIFIER_nondet_int(); + assume(var60 >= -16); + assume(var60 <= 16); + assume(var60 != 0); + int var61; + var61 = __VERIFIER_nondet_int(); + assume(var61 >= -16); + assume(var61 <= 16); + assume(var61 != 0); + int var62; + var62 = __VERIFIER_nondet_int(); + assume(var62 >= -16); + assume(var62 <= 16); + assume(var62 != 0); + int var63; + var63 = __VERIFIER_nondet_int(); + assume(var63 >= -16); + assume(var63 <= 16); + assume(var63 != 0); + int var64; + var64 = __VERIFIER_nondet_int(); + assume(var64 >= -16); + assume(var64 <= 16); + assume(var64 != 0); + int var65; + var65 = __VERIFIER_nondet_int(); + assume(var65 >= -16); + assume(var65 <= 16); + assume(var65 != 0); + int var66; + var66 = __VERIFIER_nondet_int(); + assume(var66 >= -16); + assume(var66 <= 16); + assume(var66 != 0); + int var67; + var67 = __VERIFIER_nondet_int(); + assume(var67 >= -16); + assume(var67 <= 16); + assume(var67 != 0); + int var68; + var68 = __VERIFIER_nondet_int(); + assume(var68 >= -16); + assume(var68 <= 16); + assume(var68 != 0); + int var69; + var69 = __VERIFIER_nondet_int(); + assume(var69 >= -16); + assume(var69 <= 16); + assume(var69 != 0); + int var70; + var70 = __VERIFIER_nondet_int(); + assume(var70 >= -16); + assume(var70 <= 16); + assume(var70 != 0); + int var71; + var71 = __VERIFIER_nondet_int(); + assume(var71 >= -16); + assume(var71 <= 16); + assume(var71 != 0); + int var72; + var72 = __VERIFIER_nondet_int(); + assume(var72 >= -16); + assume(var72 <= 16); + assume(var72 != 0); + int var73; + var73 = __VERIFIER_nondet_int(); + assume(var73 >= -16); + assume(var73 <= 16); + assume(var73 != 0); + int var74; + var74 = __VERIFIER_nondet_int(); + assume(var74 >= -16); + assume(var74 <= 16); + assume(var74 != 0); + int var75; + var75 = __VERIFIER_nondet_int(); + assume(var75 >= -16); + assume(var75 <= 16); + assume(var75 != 0); + int var76; + var76 = __VERIFIER_nondet_int(); + assume(var76 >= -16); + assume(var76 <= 16); + assume(var76 != 0); + int var77; + var77 = __VERIFIER_nondet_int(); + assume(var77 >= -16); + assume(var77 <= 16); + assume(var77 != 0); + int var78; + var78 = __VERIFIER_nondet_int(); + assume(var78 >= -16); + assume(var78 <= 16); + assume(var78 != 0); + int var79; + var79 = __VERIFIER_nondet_int(); + assume(var79 >= -16); + assume(var79 <= 16); + assume(var79 != 0); + int var80; + var80 = __VERIFIER_nondet_int(); + assume(var80 >= -16); + assume(var80 <= 16); + assume(var80 != 0); + int var81; + var81 = __VERIFIER_nondet_int(); + assume(var81 >= -16); + assume(var81 <= 16); + assume(var81 != 0); + int var82; + var82 = __VERIFIER_nondet_int(); + assume(var82 >= -16); + assume(var82 <= 16); + assume(var82 != 0); + int var83; + var83 = __VERIFIER_nondet_int(); + assume(var83 >= -16); + assume(var83 <= 16); + assume(var83 != 0); + int var84; + var84 = __VERIFIER_nondet_int(); + assume(var84 >= -16); + assume(var84 <= 16); + assume(var84 != 0); + int var85; + var85 = __VERIFIER_nondet_int(); + assume(var85 >= -16); + assume(var85 <= 16); + assume(var85 != 0); + int var86; + var86 = __VERIFIER_nondet_int(); + assume(var86 >= -16); + assume(var86 <= 16); + assume(var86 != 0); + int var87; + var87 = __VERIFIER_nondet_int(); + assume(var87 >= -16); + assume(var87 <= 16); + assume(var87 != 0); + int var88; + var88 = __VERIFIER_nondet_int(); + assume(var88 >= -16); + assume(var88 <= 16); + assume(var88 != 0); + int var89; + var89 = __VERIFIER_nondet_int(); + assume(var89 >= -16); + assume(var89 <= 16); + assume(var89 != 0); + int var90; + var90 = __VERIFIER_nondet_int(); + assume(var90 >= -16); + assume(var90 <= 16); + assume(var90 != 0); + int var91; + var91 = __VERIFIER_nondet_int(); + assume(var91 >= -16); + assume(var91 <= 16); + assume(var91 != 0); + int var92; + var92 = __VERIFIER_nondet_int(); + assume(var92 >= -16); + assume(var92 <= 16); + assume(var92 != 0); + int var93; + var93 = __VERIFIER_nondet_int(); + assume(var93 >= -16); + assume(var93 <= 16); + assume(var93 != 0); + int var94; + var94 = __VERIFIER_nondet_int(); + assume(var94 >= -16); + assume(var94 <= 16); + assume(var94 != 0); + int var95; + var95 = __VERIFIER_nondet_int(); + assume(var95 >= -16); + assume(var95 <= 16); + assume(var95 != 0); + int var96; + var96 = __VERIFIER_nondet_int(); + assume(var96 >= -16); + assume(var96 <= 16); + assume(var96 != 0); + int var97; + var97 = __VERIFIER_nondet_int(); + assume(var97 >= -16); + assume(var97 <= 16); + assume(var97 != 0); + int var98; + var98 = __VERIFIER_nondet_int(); + assume(var98 >= -16); + assume(var98 <= 16); + assume(var98 != 0); + int var99; + var99 = __VERIFIER_nondet_int(); + assume(var99 >= -16); + assume(var99 <= 16); + assume(var99 != 0); + int var100; + var100 = __VERIFIER_nondet_int(); + assume(var100 >= -16); + assume(var100 <= 16); + assume(var100 != 0); + int var101; + var101 = __VERIFIER_nondet_int(); + assume(var101 >= -16); + assume(var101 <= 16); + assume(var101 != 0); + int var102; + var102 = __VERIFIER_nondet_int(); + assume(var102 >= -16); + assume(var102 <= 16); + assume(var102 != 0); + int var103; + var103 = __VERIFIER_nondet_int(); + assume(var103 >= -16); + assume(var103 <= 16); + assume(var103 != 0); + int var104; + var104 = __VERIFIER_nondet_int(); + assume(var104 >= -16); + assume(var104 <= 16); + assume(var104 != 0); + int var105; + var105 = __VERIFIER_nondet_int(); + assume(var105 >= -16); + assume(var105 <= 16); + assume(var105 != 0); + int var106; + var106 = __VERIFIER_nondet_int(); + assume(var106 >= -16); + assume(var106 <= 16); + assume(var106 != 0); + int var107; + var107 = __VERIFIER_nondet_int(); + assume(var107 >= -16); + assume(var107 <= 16); + assume(var107 != 0); + int var108; + var108 = __VERIFIER_nondet_int(); + assume(var108 >= -16); + assume(var108 <= 16); + assume(var108 != 0); + int var109; + var109 = __VERIFIER_nondet_int(); + assume(var109 >= -16); + assume(var109 <= 16); + assume(var109 != 0); + int var110; + var110 = __VERIFIER_nondet_int(); + assume(var110 >= -16); + assume(var110 <= 16); + assume(var110 != 0); + int var111; + var111 = __VERIFIER_nondet_int(); + assume(var111 >= -16); + assume(var111 <= 16); + assume(var111 != 0); + int var112; + var112 = __VERIFIER_nondet_int(); + assume(var112 >= -16); + assume(var112 <= 16); + assume(var112 != 0); + int var113; + var113 = __VERIFIER_nondet_int(); + assume(var113 >= -16); + assume(var113 <= 16); + assume(var113 != 0); + int var114; + var114 = __VERIFIER_nondet_int(); + assume(var114 >= -16); + assume(var114 <= 16); + assume(var114 != 0); + int var115; + var115 = __VERIFIER_nondet_int(); + assume(var115 >= -16); + assume(var115 <= 16); + assume(var115 != 0); + int var116; + var116 = __VERIFIER_nondet_int(); + assume(var116 >= -16); + assume(var116 <= 16); + assume(var116 != 0); + int var117; + var117 = __VERIFIER_nondet_int(); + assume(var117 >= -16); + assume(var117 <= 16); + assume(var117 != 0); + int var118; + var118 = __VERIFIER_nondet_int(); + assume(var118 >= -16); + assume(var118 <= 16); + assume(var118 != 0); + int var119; + var119 = __VERIFIER_nondet_int(); + assume(var119 >= -16); + assume(var119 <= 16); + assume(var119 != 0); + int var120; + var120 = __VERIFIER_nondet_int(); + assume(var120 >= -16); + assume(var120 <= 16); + assume(var120 != 0); + int var121; + var121 = __VERIFIER_nondet_int(); + assume(var121 >= -16); + assume(var121 <= 16); + assume(var121 != 0); + int var122; + var122 = __VERIFIER_nondet_int(); + assume(var122 >= -16); + assume(var122 <= 16); + assume(var122 != 0); + int var123; + var123 = __VERIFIER_nondet_int(); + assume(var123 >= -16); + assume(var123 <= 16); + assume(var123 != 0); + int var124; + var124 = __VERIFIER_nondet_int(); + assume(var124 >= -16); + assume(var124 <= 16); + assume(var124 != 0); + int var125; + var125 = __VERIFIER_nondet_int(); + assume(var125 >= -16); + assume(var125 <= 16); + assume(var125 != 0); + int var126; + var126 = __VERIFIER_nondet_int(); + assume(var126 >= -16); + assume(var126 <= 16); + assume(var126 != 0); + int var127; + var127 = __VERIFIER_nondet_int(); + assume(var127 >= -16); + assume(var127 <= 16); + assume(var127 != 0); + int var128; + var128 = __VERIFIER_nondet_int(); + assume(var128 >= -16); + assume(var128 <= 16); + assume(var128 != 0); + int var129; + var129 = __VERIFIER_nondet_int(); + assume(var129 >= -16); + assume(var129 <= 16); + assume(var129 != 0); + int var130; + var130 = __VERIFIER_nondet_int(); + assume(var130 >= -16); + assume(var130 <= 16); + assume(var130 != 0); + int var131; + var131 = __VERIFIER_nondet_int(); + assume(var131 >= -16); + assume(var131 <= 16); + assume(var131 != 0); + int var132; + var132 = __VERIFIER_nondet_int(); + assume(var132 >= -16); + assume(var132 <= 16); + assume(var132 != 0); + int var133; + var133 = __VERIFIER_nondet_int(); + assume(var133 >= -16); + assume(var133 <= 16); + assume(var133 != 0); + int var134; + var134 = __VERIFIER_nondet_int(); + assume(var134 >= -16); + assume(var134 <= 16); + assume(var134 != 0); + int var135; + var135 = __VERIFIER_nondet_int(); + assume(var135 >= -16); + assume(var135 <= 16); + assume(var135 != 0); + int var136; + var136 = __VERIFIER_nondet_int(); + assume(var136 >= -16); + assume(var136 <= 16); + assume(var136 != 0); + int var137; + var137 = __VERIFIER_nondet_int(); + assume(var137 >= -16); + assume(var137 <= 16); + assume(var137 != 0); + int var138; + var138 = __VERIFIER_nondet_int(); + assume(var138 >= -16); + assume(var138 <= 16); + assume(var138 != 0); + int var139; + var139 = __VERIFIER_nondet_int(); + assume(var139 >= -16); + assume(var139 <= 16); + assume(var139 != 0); + int var140; + var140 = __VERIFIER_nondet_int(); + assume(var140 >= -16); + assume(var140 <= 16); + assume(var140 != 0); + int var141; + var141 = __VERIFIER_nondet_int(); + assume(var141 >= -16); + assume(var141 <= 16); + assume(var141 != 0); + int var142; + var142 = __VERIFIER_nondet_int(); + assume(var142 >= -16); + assume(var142 <= 16); + assume(var142 != 0); + int var143; + var143 = __VERIFIER_nondet_int(); + assume(var143 >= -16); + assume(var143 <= 16); + assume(var143 != 0); + int var144; + var144 = __VERIFIER_nondet_int(); + assume(var144 >= -16); + assume(var144 <= 16); + assume(var144 != 0); + int var145; + var145 = __VERIFIER_nondet_int(); + assume(var145 >= -16); + assume(var145 <= 16); + assume(var145 != 0); + int var146; + var146 = __VERIFIER_nondet_int(); + assume(var146 >= -16); + assume(var146 <= 16); + assume(var146 != 0); + int var147; + var147 = __VERIFIER_nondet_int(); + assume(var147 >= -16); + assume(var147 <= 16); + assume(var147 != 0); + int var148; + var148 = __VERIFIER_nondet_int(); + assume(var148 >= -16); + assume(var148 <= 16); + assume(var148 != 0); + int var149; + var149 = __VERIFIER_nondet_int(); + assume(var149 >= -16); + assume(var149 <= 16); + assume(var149 != 0); + int myvar0 = 1; + assume(var0 != var1); + assume(var0 != var2); + assume(var0 != var3); + assume(var0 != var4); + assume(var0 != var5); + assume(var0 != var6); + assume(var0 != var7); + assume(var0 != var8); + assume(var0 != var9); + assume(var0 != var10); + assume(var0 != var11); + assume(var0 != var12); + assume(var0 != var13); + assume(var0 != var14); + assume(var0 != var15); + assume(var0 != var16); + assume(var1 != var2); + assume(var1 != var3); + assume(var1 != var4); + assume(var1 != var5); + assume(var1 != var6); + assume(var1 != var7); + assume(var1 != var8); + assume(var1 != var9); + assume(var1 != var10); + assume(var1 != var11); + assume(var1 != var12); + assume(var1 != var13); + assume(var1 != var14); + assume(var1 != var15); + assume(var1 != var16); + assume(var2 != var3); + assume(var2 != var4); + assume(var2 != var5); + assume(var2 != var6); + assume(var2 != var7); + assume(var2 != var8); + assume(var2 != var9); + assume(var2 != var10); + assume(var2 != var11); + assume(var2 != var12); + assume(var2 != var13); + assume(var2 != var14); + assume(var2 != var15); + assume(var2 != var16); + assume(var3 != var4); + assume(var3 != var5); + assume(var3 != var6); + assume(var3 != var7); + assume(var3 != var8); + assume(var3 != var9); + assume(var3 != var10); + assume(var3 != var11); + assume(var3 != var12); + assume(var3 != var13); + assume(var3 != var14); + assume(var3 != var15); + assume(var3 != var16); + assume(var4 != var5); + assume(var4 != var6); + assume(var4 != var7); + assume(var4 != var8); + assume(var4 != var9); + assume(var4 != var10); + assume(var4 != var11); + assume(var4 != var12); + assume(var4 != var13); + assume(var4 != var14); + assume(var4 != var15); + assume(var4 != var16); + assume(var5 != var6); + assume(var5 != var7); + assume(var5 != var8); + assume(var5 != var9); + assume(var5 != var10); + assume(var5 != var11); + assume(var5 != var12); + assume(var5 != var13); + assume(var5 != var14); + assume(var5 != var15); + assume(var5 != var16); + assume(var6 != var7); + assume(var6 != var8); + assume(var6 != var9); + assume(var6 != var10); + assume(var6 != var11); + assume(var6 != var12); + assume(var6 != var13); + assume(var6 != var14); + assume(var6 != var15); + assume(var6 != var16); + assume(var7 != var8); + assume(var7 != var9); + assume(var7 != var10); + assume(var7 != var11); + assume(var7 != var12); + assume(var7 != var13); + assume(var7 != var14); + assume(var7 != var15); + assume(var7 != var16); + assume(var8 != var9); + assume(var8 != var10); + assume(var8 != var11); + assume(var8 != var12); + assume(var8 != var13); + assume(var8 != var14); + assume(var8 != var15); + assume(var8 != var16); + assume(var9 != var10); + assume(var9 != var11); + assume(var9 != var12); + assume(var9 != var13); + assume(var9 != var14); + assume(var9 != var15); + assume(var9 != var16); + assume(var10 != var11); + assume(var10 != var12); + assume(var10 != var13); + assume(var10 != var14); + assume(var10 != var15); + assume(var10 != var16); + assume(var11 != var12); + assume(var11 != var13); + assume(var11 != var14); + assume(var11 != var15); + assume(var11 != var16); + assume(var12 != var13); + assume(var12 != var14); + assume(var12 != var15); + assume(var12 != var16); + assume(var13 != var14); + assume(var13 != var15); + assume(var13 != var16); + assume(var14 != var15); + assume(var14 != var16); + assume(var15 != var16); + assume(var17 != var18); + assume(var17 != var19); + assume(var17 != var20); + assume(var17 != var21); + assume(var17 != var22); + assume(var17 != var23); + assume(var17 != var24); + assume(var17 != var25); + assume(var17 != var26); + assume(var17 != var27); + assume(var17 != var28); + assume(var17 != var29); + assume(var17 != var30); + assume(var17 != var31); + assume(var17 != var32); + assume(var18 != var19); + assume(var18 != var20); + assume(var18 != var21); + assume(var18 != var22); + assume(var18 != var23); + assume(var18 != var24); + assume(var18 != var25); + assume(var18 != var26); + assume(var18 != var27); + assume(var18 != var28); + assume(var18 != var29); + assume(var18 != var30); + assume(var18 != var31); + assume(var18 != var32); + assume(var19 != var20); + assume(var19 != var21); + assume(var19 != var22); + assume(var19 != var23); + assume(var19 != var24); + assume(var19 != var25); + assume(var19 != var26); + assume(var19 != var27); + assume(var19 != var28); + assume(var19 != var29); + assume(var19 != var30); + assume(var19 != var31); + assume(var19 != var32); + assume(var20 != var21); + assume(var20 != var22); + assume(var20 != var23); + assume(var20 != var24); + assume(var20 != var25); + assume(var20 != var26); + assume(var20 != var27); + assume(var20 != var28); + assume(var20 != var29); + assume(var20 != var30); + assume(var20 != var31); + assume(var20 != var32); + assume(var21 != var22); + assume(var21 != var23); + assume(var21 != var24); + assume(var21 != var25); + assume(var21 != var26); + assume(var21 != var27); + assume(var21 != var28); + assume(var21 != var29); + assume(var21 != var30); + assume(var21 != var31); + assume(var21 != var32); + assume(var22 != var23); + assume(var22 != var24); + assume(var22 != var25); + assume(var22 != var26); + assume(var22 != var27); + assume(var22 != var28); + assume(var22 != var29); + assume(var22 != var30); + assume(var22 != var31); + assume(var22 != var32); + assume(var23 != var24); + assume(var23 != var25); + assume(var23 != var26); + assume(var23 != var27); + assume(var23 != var28); + assume(var23 != var29); + assume(var23 != var30); + assume(var23 != var31); + assume(var23 != var32); + assume(var24 != var25); + assume(var24 != var26); + assume(var24 != var27); + assume(var24 != var28); + assume(var24 != var29); + assume(var24 != var30); + assume(var24 != var31); + assume(var24 != var32); + assume(var25 != var26); + assume(var25 != var27); + assume(var25 != var28); + assume(var25 != var29); + assume(var25 != var30); + assume(var25 != var31); + assume(var25 != var32); + assume(var26 != var27); + assume(var26 != var28); + assume(var26 != var29); + assume(var26 != var30); + assume(var26 != var31); + assume(var26 != var32); + assume(var27 != var28); + assume(var27 != var29); + assume(var27 != var30); + assume(var27 != var31); + assume(var27 != var32); + assume(var28 != var29); + assume(var28 != var30); + assume(var28 != var31); + assume(var28 != var32); + assume(var29 != var30); + assume(var29 != var31); + assume(var29 != var32); + assume(var30 != var31); + assume(var30 != var32); + assume(var31 != var32); + assume(var33 != var34); + assume(var33 != var35); + assume(var33 != var36); + assume(var33 != var37); + assume(var33 != var38); + assume(var33 != var39); + assume(var33 != var40); + assume(var33 != var41); + assume(var33 != var42); + assume(var33 != var43); + assume(var33 != var44); + assume(var33 != var45); + assume(var33 != var46); + assume(var33 != var47); + assume(var34 != var35); + assume(var34 != var36); + assume(var34 != var37); + assume(var34 != var38); + assume(var34 != var39); + assume(var34 != var40); + assume(var34 != var41); + assume(var34 != var42); + assume(var34 != var43); + assume(var34 != var44); + assume(var34 != var45); + assume(var34 != var46); + assume(var34 != var47); + assume(var35 != var36); + assume(var35 != var37); + assume(var35 != var38); + assume(var35 != var39); + assume(var35 != var40); + assume(var35 != var41); + assume(var35 != var42); + assume(var35 != var43); + assume(var35 != var44); + assume(var35 != var45); + assume(var35 != var46); + assume(var35 != var47); + assume(var36 != var37); + assume(var36 != var38); + assume(var36 != var39); + assume(var36 != var40); + assume(var36 != var41); + assume(var36 != var42); + assume(var36 != var43); + assume(var36 != var44); + assume(var36 != var45); + assume(var36 != var46); + assume(var36 != var47); + assume(var37 != var38); + assume(var37 != var39); + assume(var37 != var40); + assume(var37 != var41); + assume(var37 != var42); + assume(var37 != var43); + assume(var37 != var44); + assume(var37 != var45); + assume(var37 != var46); + assume(var37 != var47); + assume(var38 != var39); + assume(var38 != var40); + assume(var38 != var41); + assume(var38 != var42); + assume(var38 != var43); + assume(var38 != var44); + assume(var38 != var45); + assume(var38 != var46); + assume(var38 != var47); + assume(var39 != var40); + assume(var39 != var41); + assume(var39 != var42); + assume(var39 != var43); + assume(var39 != var44); + assume(var39 != var45); + assume(var39 != var46); + assume(var39 != var47); + assume(var40 != var41); + assume(var40 != var42); + assume(var40 != var43); + assume(var40 != var44); + assume(var40 != var45); + assume(var40 != var46); + assume(var40 != var47); + assume(var41 != var42); + assume(var41 != var43); + assume(var41 != var44); + assume(var41 != var45); + assume(var41 != var46); + assume(var41 != var47); + assume(var42 != var43); + assume(var42 != var44); + assume(var42 != var45); + assume(var42 != var46); + assume(var42 != var47); + assume(var43 != var44); + assume(var43 != var45); + assume(var43 != var46); + assume(var43 != var47); + assume(var44 != var45); + assume(var44 != var46); + assume(var44 != var47); + assume(var45 != var46); + assume(var45 != var47); + assume(var46 != var47); + assume(var48 != var49); + assume(var48 != var50); + assume(var48 != var51); + assume(var48 != var52); + assume(var48 != var53); + assume(var48 != var54); + assume(var48 != var55); + assume(var48 != var56); + assume(var48 != var57); + assume(var48 != var58); + assume(var48 != var59); + assume(var48 != var60); + assume(var48 != var61); + assume(var49 != var50); + assume(var49 != var51); + assume(var49 != var52); + assume(var49 != var53); + assume(var49 != var54); + assume(var49 != var55); + assume(var49 != var56); + assume(var49 != var57); + assume(var49 != var58); + assume(var49 != var59); + assume(var49 != var60); + assume(var49 != var61); + assume(var50 != var51); + assume(var50 != var52); + assume(var50 != var53); + assume(var50 != var54); + assume(var50 != var55); + assume(var50 != var56); + assume(var50 != var57); + assume(var50 != var58); + assume(var50 != var59); + assume(var50 != var60); + assume(var50 != var61); + assume(var51 != var52); + assume(var51 != var53); + assume(var51 != var54); + assume(var51 != var55); + assume(var51 != var56); + assume(var51 != var57); + assume(var51 != var58); + assume(var51 != var59); + assume(var51 != var60); + assume(var51 != var61); + assume(var52 != var53); + assume(var52 != var54); + assume(var52 != var55); + assume(var52 != var56); + assume(var52 != var57); + assume(var52 != var58); + assume(var52 != var59); + assume(var52 != var60); + assume(var52 != var61); + assume(var53 != var54); + assume(var53 != var55); + assume(var53 != var56); + assume(var53 != var57); + assume(var53 != var58); + assume(var53 != var59); + assume(var53 != var60); + assume(var53 != var61); + assume(var54 != var55); + assume(var54 != var56); + assume(var54 != var57); + assume(var54 != var58); + assume(var54 != var59); + assume(var54 != var60); + assume(var54 != var61); + assume(var55 != var56); + assume(var55 != var57); + assume(var55 != var58); + assume(var55 != var59); + assume(var55 != var60); + assume(var55 != var61); + assume(var56 != var57); + assume(var56 != var58); + assume(var56 != var59); + assume(var56 != var60); + assume(var56 != var61); + assume(var57 != var58); + assume(var57 != var59); + assume(var57 != var60); + assume(var57 != var61); + assume(var58 != var59); + assume(var58 != var60); + assume(var58 != var61); + assume(var59 != var60); + assume(var59 != var61); + assume(var60 != var61); + assume(var62 != var63); + assume(var62 != var64); + assume(var62 != var65); + assume(var62 != var66); + assume(var62 != var67); + assume(var62 != var68); + assume(var62 != var69); + assume(var62 != var70); + assume(var62 != var71); + assume(var62 != var72); + assume(var62 != var73); + assume(var62 != var74); + assume(var63 != var64); + assume(var63 != var65); + assume(var63 != var66); + assume(var63 != var67); + assume(var63 != var68); + assume(var63 != var69); + assume(var63 != var70); + assume(var63 != var71); + assume(var63 != var72); + assume(var63 != var73); + assume(var63 != var74); + assume(var64 != var65); + assume(var64 != var66); + assume(var64 != var67); + assume(var64 != var68); + assume(var64 != var69); + assume(var64 != var70); + assume(var64 != var71); + assume(var64 != var72); + assume(var64 != var73); + assume(var64 != var74); + assume(var65 != var66); + assume(var65 != var67); + assume(var65 != var68); + assume(var65 != var69); + assume(var65 != var70); + assume(var65 != var71); + assume(var65 != var72); + assume(var65 != var73); + assume(var65 != var74); + assume(var66 != var67); + assume(var66 != var68); + assume(var66 != var69); + assume(var66 != var70); + assume(var66 != var71); + assume(var66 != var72); + assume(var66 != var73); + assume(var66 != var74); + assume(var67 != var68); + assume(var67 != var69); + assume(var67 != var70); + assume(var67 != var71); + assume(var67 != var72); + assume(var67 != var73); + assume(var67 != var74); + assume(var68 != var69); + assume(var68 != var70); + assume(var68 != var71); + assume(var68 != var72); + assume(var68 != var73); + assume(var68 != var74); + assume(var69 != var70); + assume(var69 != var71); + assume(var69 != var72); + assume(var69 != var73); + assume(var69 != var74); + assume(var70 != var71); + assume(var70 != var72); + assume(var70 != var73); + assume(var70 != var74); + assume(var71 != var72); + assume(var71 != var73); + assume(var71 != var74); + assume(var72 != var73); + assume(var72 != var74); + assume(var73 != var74); + assume(var75 != var76); + assume(var75 != var77); + assume(var75 != var78); + assume(var75 != var79); + assume(var75 != var80); + assume(var75 != var81); + assume(var75 != var82); + assume(var75 != var83); + assume(var75 != var84); + assume(var75 != var85); + assume(var75 != var86); + assume(var76 != var77); + assume(var76 != var78); + assume(var76 != var79); + assume(var76 != var80); + assume(var76 != var81); + assume(var76 != var82); + assume(var76 != var83); + assume(var76 != var84); + assume(var76 != var85); + assume(var76 != var86); + assume(var77 != var78); + assume(var77 != var79); + assume(var77 != var80); + assume(var77 != var81); + assume(var77 != var82); + assume(var77 != var83); + assume(var77 != var84); + assume(var77 != var85); + assume(var77 != var86); + assume(var78 != var79); + assume(var78 != var80); + assume(var78 != var81); + assume(var78 != var82); + assume(var78 != var83); + assume(var78 != var84); + assume(var78 != var85); + assume(var78 != var86); + assume(var79 != var80); + assume(var79 != var81); + assume(var79 != var82); + assume(var79 != var83); + assume(var79 != var84); + assume(var79 != var85); + assume(var79 != var86); + assume(var80 != var81); + assume(var80 != var82); + assume(var80 != var83); + assume(var80 != var84); + assume(var80 != var85); + assume(var80 != var86); + assume(var81 != var82); + assume(var81 != var83); + assume(var81 != var84); + assume(var81 != var85); + assume(var81 != var86); + assume(var82 != var83); + assume(var82 != var84); + assume(var82 != var85); + assume(var82 != var86); + assume(var83 != var84); + assume(var83 != var85); + assume(var83 != var86); + assume(var84 != var85); + assume(var84 != var86); + assume(var85 != var86); + assume(var87 != var88); + assume(var87 != var89); + assume(var87 != var90); + assume(var87 != var91); + assume(var87 != var92); + assume(var87 != var93); + assume(var87 != var94); + assume(var87 != var95); + assume(var87 != var96); + assume(var87 != var97); + assume(var88 != var89); + assume(var88 != var90); + assume(var88 != var91); + assume(var88 != var92); + assume(var88 != var93); + assume(var88 != var94); + assume(var88 != var95); + assume(var88 != var96); + assume(var88 != var97); + assume(var89 != var90); + assume(var89 != var91); + assume(var89 != var92); + assume(var89 != var93); + assume(var89 != var94); + assume(var89 != var95); + assume(var89 != var96); + assume(var89 != var97); + assume(var90 != var91); + assume(var90 != var92); + assume(var90 != var93); + assume(var90 != var94); + assume(var90 != var95); + assume(var90 != var96); + assume(var90 != var97); + assume(var91 != var92); + assume(var91 != var93); + assume(var91 != var94); + assume(var91 != var95); + assume(var91 != var96); + assume(var91 != var97); + assume(var92 != var93); + assume(var92 != var94); + assume(var92 != var95); + assume(var92 != var96); + assume(var92 != var97); + assume(var93 != var94); + assume(var93 != var95); + assume(var93 != var96); + assume(var93 != var97); + assume(var94 != var95); + assume(var94 != var96); + assume(var94 != var97); + assume(var95 != var96); + assume(var95 != var97); + assume(var96 != var97); + assume(var98 != var99); + assume(var98 != var100); + assume(var98 != var101); + assume(var98 != var102); + assume(var98 != var103); + assume(var98 != var104); + assume(var98 != var105); + assume(var98 != var106); + assume(var98 != var107); + assume(var99 != var100); + assume(var99 != var101); + assume(var99 != var102); + assume(var99 != var103); + assume(var99 != var104); + assume(var99 != var105); + assume(var99 != var106); + assume(var99 != var107); + assume(var100 != var101); + assume(var100 != var102); + assume(var100 != var103); + assume(var100 != var104); + assume(var100 != var105); + assume(var100 != var106); + assume(var100 != var107); + assume(var101 != var102); + assume(var101 != var103); + assume(var101 != var104); + assume(var101 != var105); + assume(var101 != var106); + assume(var101 != var107); + assume(var102 != var103); + assume(var102 != var104); + assume(var102 != var105); + assume(var102 != var106); + assume(var102 != var107); + assume(var103 != var104); + assume(var103 != var105); + assume(var103 != var106); + assume(var103 != var107); + assume(var104 != var105); + assume(var104 != var106); + assume(var104 != var107); + assume(var105 != var106); + assume(var105 != var107); + assume(var106 != var107); + assume(var108 != var109); + assume(var108 != var110); + assume(var108 != var111); + assume(var108 != var112); + assume(var108 != var113); + assume(var108 != var114); + assume(var108 != var115); + assume(var108 != var116); + assume(var109 != var110); + assume(var109 != var111); + assume(var109 != var112); + assume(var109 != var113); + assume(var109 != var114); + assume(var109 != var115); + assume(var109 != var116); + assume(var110 != var111); + assume(var110 != var112); + assume(var110 != var113); + assume(var110 != var114); + assume(var110 != var115); + assume(var110 != var116); + assume(var111 != var112); + assume(var111 != var113); + assume(var111 != var114); + assume(var111 != var115); + assume(var111 != var116); + assume(var112 != var113); + assume(var112 != var114); + assume(var112 != var115); + assume(var112 != var116); + assume(var113 != var114); + assume(var113 != var115); + assume(var113 != var116); + assume(var114 != var115); + assume(var114 != var116); + assume(var115 != var116); + assume(var117 != var118); + assume(var117 != var119); + assume(var117 != var120); + assume(var117 != var121); + assume(var117 != var122); + assume(var117 != var123); + assume(var117 != var124); + assume(var118 != var119); + assume(var118 != var120); + assume(var118 != var121); + assume(var118 != var122); + assume(var118 != var123); + assume(var118 != var124); + assume(var119 != var120); + assume(var119 != var121); + assume(var119 != var122); + assume(var119 != var123); + assume(var119 != var124); + assume(var120 != var121); + assume(var120 != var122); + assume(var120 != var123); + assume(var120 != var124); + assume(var121 != var122); + assume(var121 != var123); + assume(var121 != var124); + assume(var122 != var123); + assume(var122 != var124); + assume(var123 != var124); + assume(var125 != var126); + assume(var125 != var127); + assume(var125 != var128); + assume(var125 != var129); + assume(var125 != var130); + assume(var125 != var131); + assume(var126 != var127); + assume(var126 != var128); + assume(var126 != var129); + assume(var126 != var130); + assume(var126 != var131); + assume(var127 != var128); + assume(var127 != var129); + assume(var127 != var130); + assume(var127 != var131); + assume(var128 != var129); + assume(var128 != var130); + assume(var128 != var131); + assume(var129 != var130); + assume(var129 != var131); + assume(var130 != var131); + assume(var132 != var133); + assume(var132 != var134); + assume(var132 != var135); + assume(var132 != var136); + assume(var132 != var137); + assume(var133 != var134); + assume(var133 != var135); + assume(var133 != var136); + assume(var133 != var137); + assume(var134 != var135); + assume(var134 != var136); + assume(var134 != var137); + assume(var135 != var136); + assume(var135 != var137); + assume(var136 != var137); + assume(var138 != var139); + assume(var138 != var140); + assume(var138 != var141); + assume(var138 != var142); + assume(var139 != var140); + assume(var139 != var141); + assume(var139 != var142); + assume(var140 != var141); + assume(var140 != var142); + assume(var141 != var142); + assume(var143 != var144); + assume(var143 != var145); + assume(var143 != var146); + assume(var144 != var145); + assume(var144 != var146); + assume(var145 != var146); + assume(var147 != var148); + assume(var147 != var149); + assume(var148 != var149); + assume(var0 - var1 == var17); + assume(var1 - var2 == var18); + assume(var2 - var3 == var19); + assume(var3 - var4 == var20); + assume(var4 - var5 == var21); + assume(var5 - var6 == var22); + assume(var6 - var7 == var23); + assume(var7 - var8 == var24); + assume(var8 - var9 == var25); + assume(var9 - var10 == var26); + assume(var10 - var11 == var27); + assume(var11 - var12 == var28); + assume(var12 - var13 == var29); + assume(var13 - var14 == var30); + assume(var14 - var15 == var31); + assume(var15 - var16 == var32); + assume(var0 - var2 == var33); + assume(var1 - var3 == var34); + assume(var2 - var4 == var35); + assume(var3 - var5 == var36); + assume(var4 - var6 == var37); + assume(var5 - var7 == var38); + assume(var6 - var8 == var39); + assume(var7 - var9 == var40); + assume(var8 - var10 == var41); + assume(var9 - var11 == var42); + assume(var10 - var12 == var43); + assume(var11 - var13 == var44); + assume(var12 - var14 == var45); + assume(var13 - var15 == var46); + assume(var14 - var16 == var47); + assume(var0 - var3 == var48); + assume(var1 - var4 == var49); + assume(var2 - var5 == var50); + assume(var3 - var6 == var51); + assume(var4 - var7 == var52); + assume(var5 - var8 == var53); + assume(var6 - var9 == var54); + assume(var7 - var10 == var55); + assume(var8 - var11 == var56); + assume(var9 - var12 == var57); + assume(var10 - var13 == var58); + assume(var11 - var14 == var59); + assume(var12 - var15 == var60); + assume(var13 - var16 == var61); + assume(var0 - var4 == var62); + assume(var1 - var5 == var63); + assume(var2 - var6 == var64); + assume(var3 - var7 == var65); + assume(var4 - var8 == var66); + assume(var5 - var9 == var67); + assume(var6 - var10 == var68); + assume(var7 - var11 == var69); + assume(var8 - var12 == var70); + assume(var9 - var13 == var71); + assume(var10 - var14 == var72); + assume(var11 - var15 == var73); + assume(var12 - var16 == var74); + assume(var0 - var5 == var75); + assume(var1 - var6 == var76); + assume(var2 - var7 == var77); + assume(var3 - var8 == var78); + assume(var4 - var9 == var79); + assume(var5 - var10 == var80); + assume(var6 - var11 == var81); + assume(var7 - var12 == var82); + assume(var8 - var13 == var83); + assume(var9 - var14 == var84); + assume(var10 - var15 == var85); + assume(var11 - var16 == var86); + assume(var0 - var6 == var87); + assume(var1 - var7 == var88); + assume(var2 - var8 == var89); + assume(var3 - var9 == var90); + assume(var4 - var10 == var91); + assume(var5 - var11 == var92); + assume(var6 - var12 == var93); + assume(var7 - var13 == var94); + assume(var8 - var14 == var95); + assume(var9 - var15 == var96); + assume(var10 - var16 == var97); + assume(var0 - var7 == var98); + assume(var1 - var8 == var99); + assume(var2 - var9 == var100); + assume(var3 - var10 == var101); + assume(var4 - var11 == var102); + assume(var5 - var12 == var103); + assume(var6 - var13 == var104); + assume(var7 - var14 == var105); + assume(var8 - var15 == var106); + assume(var9 - var16 == var107); + assume(var0 - var8 == var108); + assume(var1 - var9 == var109); + assume(var2 - var10 == var110); + assume(var3 - var11 == var111); + assume(var4 - var12 == var112); + assume(var5 - var13 == var113); + assume(var6 - var14 == var114); + assume(var7 - var15 == var115); + assume(var8 - var16 == var116); + assume(var0 - var9 == var117); + assume(var1 - var10 == var118); + assume(var2 - var11 == var119); + assume(var3 - var12 == var120); + assume(var4 - var13 == var121); + assume(var5 - var14 == var122); + assume(var6 - var15 == var123); + assume(var7 - var16 == var124); + assume(var0 - var10 == var125); + assume(var1 - var11 == var126); + assume(var2 - var12 == var127); + assume(var3 - var13 == var128); + assume(var4 - var14 == var129); + assume(var5 - var15 == var130); + assume(var6 - var16 == var131); + assume(var0 - var11 == var132); + assume(var1 - var12 == var133); + assume(var2 - var13 == var134); + assume(var3 - var14 == var135); + assume(var4 - var15 == var136); + assume(var5 - var16 == var137); + assume(var0 - var12 == var138); + assume(var1 - var13 == var139); + assume(var2 - var14 == var140); + assume(var3 - var15 == var141); + assume(var4 - var16 == var142); + assume(var0 - var13 == var143); + assume(var1 - var14 == var144); + assume(var2 - var15 == var145); + assume(var3 - var16 == var146); + assume(var0 - var14 == var147); + assume(var1 - var15 == var148); + assume(var2 - var16 == var149); + assume((var0 - var15) != (var1 - var16)); + reach_error(); + return 0; /* 0 x[0]1 x[1]2 x[2]3 x[3]4 x[4]5 x[5]6 x[6]7 x[7]8 x[8]9 x[9]10 + x[10]11 x[11]12 x[12]13 x[13]14 x[14]15 x[15]16 x[16]17 y[0]18 + y[1]19 y[2]20 y[3]21 y[4]22 y[5]23 y[6]24 y[7]25 y[8]26 y[9]27 + y[10]28 y[11]29 y[12]30 y[13]31 y[14]32 y[15]33 y[16]34 y[17]35 + y[18]36 y[19]37 y[20]38 y[21]39 y[22]40 y[23]41 y[24]42 y[25]43 + y[26]44 y[27]45 y[28]46 y[29]47 y[30]48 y[31]49 y[32]50 y[33]51 + y[34]52 y[35]53 y[36]54 y[37]55 y[38]56 y[39]57 y[40]58 y[41]59 + y[42]60 y[43]61 y[44]62 y[45]63 y[46]64 y[47]65 y[48]66 y[49]67 + y[50]68 y[51]69 y[52]70 y[53]71 y[54]72 y[55]73 y[56]74 y[57]75 + y[58]76 y[59]77 y[60]78 y[61]79 y[62]80 y[63]81 y[64]82 y[65]83 + y[66]84 y[67]85 y[68]86 y[69]87 y[70]88 y[71]89 y[72]90 y[73]91 + y[74]92 y[75]93 y[76]94 y[77]95 y[78]96 y[79]97 y[80]98 y[81]99 + y[82]100 y[83]101 y[84]102 y[85]103 y[86]104 y[87]105 y[88]106 + y[89]107 y[90]108 y[91]109 y[92]110 y[93]111 y[94]112 y[95]113 + y[96]114 y[97]115 y[98]116 y[99]117 y[100]118 y[101]119 y[102]120 + y[103]121 y[104]122 y[105]123 y[106]124 y[107]125 y[108]126 + y[109]127 y[110]128 y[111]129 y[112]130 y[113]131 y[114]132 + y[115]133 y[116]134 y[117]135 y[118]136 y[119]137 y[120]138 + y[121]139 y[122]140 y[123]141 y[124]142 y[125]143 y[126]144 + y[127]145 y[128]146 y[129]147 y[130]148 y[131]149 y[132] */ +} \ No newline at end of file diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c new file mode 100644 index 0000000000..37524f9b99 --- /dev/null +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -0,0 +1,111 @@ +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-policy=all --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state %t1.bc + +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %gcov-files-path > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// CHECK: Lines executed:{{87\.93|89\.83}}% of 5{{8|9}} +// CHECK-NEXT: Branches executed:100.00% of 1{{8|4}} +// CHECK-NEXT: Taken at least once:{{83\.33|85\.71}}% of 1{{8|4}} + +#include "klee-test-comp.c" +/* extended Euclid's algorithm */ +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +extern void exit( int exit_code ) __attribute__((noreturn)); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: + {reach_error();} + } + return; +} + +int main() { + int x, y; + long long a, b, p, q, r, s; + x = __VERIFIER_nondet_int(); + assume_abort_if_not(x>=0 && x<=10); + y = __VERIFIER_nondet_int(); + assume_abort_if_not(y>=0 && y<=10); + assume_abort_if_not(x >= 1); + assume_abort_if_not(y >= 1); + + a = x; + b = y; + p = 1; + q = 0; + r = 0; + s = 1; + + while (1) { + if (!(b != 0)) + break; + long long c, k; + c = a; + k = 0; + + while (1) { + if (!(c >= b)) + break; + long long d, v; + d = 1; + v = b; + + while (1) { + __VERIFIER_assert(a == y * r + x * p); + __VERIFIER_assert(b == x * q + y * s); + __VERIFIER_assert(a == k * b + c); + __VERIFIER_assert(v == b * d); + + if (!(c >= 2 * v)) + break; + d = 2 * d; + v = 2 * v; + } + c = c - v; + k = k + d; + } + + a = b; + b = c; + long long temp; + temp = p; + p = q; + q = temp - q * k; + temp = r; + r = s; + s = temp - s * k; + } + __VERIFIER_assert(p*x - q*x + r*y - s*y == a); + return 0; +} diff --git a/test/Industry/CoverageBranches/lit.local.cfg b/test/Industry/CoverageBranches/lit.local.cfg new file mode 100644 index 0000000000..95cecce749 --- /dev/null +++ b/test/Industry/CoverageBranches/lit.local.cfg @@ -0,0 +1,8 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +rootConfig = getRoot(config) +if config.have_asan or config.have_ubsan or config.have_msan: + config.unsupported = True diff --git a/test/Industry/CoverageBranches/matrix-2-2.c b/test/Industry/CoverageBranches/matrix-2-2.c new file mode 100644 index 0000000000..879b4560ac --- /dev/null +++ b/test/Industry/CoverageBranches/matrix-2-2.c @@ -0,0 +1,68 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=all --max-cycles=2 --optimize=true --emit-all-errors --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=all --use-sym-size-alloc=true --symbolic-allocation-threshold=8192 %t1.bc 2>&1 + +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %gcov-files-path > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s + +// Branch coverage is greater 80%: +// CHECK-COV: Lines executed:{{(9[0-9]\.[0-9][0-9])|(100\.00)}}% of 2{{4|5}} +// CHECK-COV-NEXT: Branches executed:100.00% of 16 +// CHECK-COV-NEXT: Taken at least once:{{([8-9][0-9]\.[0-9][0-9])|(100\.00)}}% of 16 + +#include "klee-test-comp.c" + +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +extern void exit(int); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#endif +} + +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "matrix-2-2.c", 3, "reach_error"); } + +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: {reach_error();abort();} + } + return; +} +extern unsigned int __VERIFIER_nondet_uint(); +extern int __VERIFIER_nondet_int(); + +int main() +{ + unsigned int N_LIN=__VERIFIER_nondet_uint(); + unsigned int N_COL=__VERIFIER_nondet_uint(); + if (N_LIN >= 4000000000 / sizeof(int) || N_COL >= 4000000000 / sizeof(int)) { + return 0; + } + unsigned int j,k; + int matriz[N_COL][N_LIN], maior; + + maior = __VERIFIER_nondet_int(); + for(j=0;jmaior) + maior = matriz[j][k]; + } + + for(j=0;j %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// CHECK: Lines executed:{{(9[0-9]\.[0-9][0-9])}}% of 41{{(1|5)(3|4)}} +// CHECK-NEXT: Branches executed:{{(9[0-9]\.[0-9][0-9])}}% of {{13404|11628}} +// CHECK-NEXT: Taken at least once:{{([8-9][0-9]\.[0-9][0-9])}}% of {{13404|11628}} + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2012 The RERS Challenge +// SPDX-FileCopyrightText: 2013 Carnegie Mellon University +// SPDX-FileCopyrightText: 2014-2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Attribution-CMU +#include "klee-test-comp.c" + +extern unsigned int __VERIFIER_nondet_uint(); +extern char __VERIFIER_nondet_char(); +extern int __VERIFIER_nondet_int(); +extern long __VERIFIER_nondet_long(); +extern unsigned long __VERIFIER_nondet_ulong(); +extern float __VERIFIER_nondet_float(); +extern void exit(int); +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +extern void exit(int exit_code) __attribute__((noreturn)); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "pals_lcr.3.ufo.UNBOUNDED.pals.c", 3, "reach_error"); } + + +/* Generated by CIL v. 1.6.0 */ +/* print_CIL_Input is true */ + +_Bool __VERIFIER_nondet_bool(void) ; +char __VERIFIER_nondet_char(void) ; +unsigned char __VERIFIER_nondet_uchar(void) ; +void assert(_Bool arg ) ; +void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +typedef char msg_t; +typedef int port_t; +extern void read(port_t p , msg_t m ) ; +extern void write(port_t p , msg_t m ) ; +msg_t nomsg = (msg_t )-1; +unsigned char r1 ; +port_t p1 ; +char p1_old ; +char p1_new ; +char id1 ; +char st1 ; +msg_t send1 ; +_Bool mode1 ; +port_t p2 ; +char p2_old ; +char p2_new ; +char id2 ; +char st2 ; +msg_t send2 ; +_Bool mode2 ; +port_t p3 ; +char p3_old ; +char p3_new ; +char id3 ; +char st3 ; +msg_t send3 ; +_Bool mode3 ; +void node1(void) +{ + msg_t m1 ; + + { + m1 = nomsg; + if (mode1) { + if (r1 == 255) { + r1 = 2; + } + r1 = r1 + 1; + m1 = p3_old; + p3_old = nomsg; + if ((int )m1 != (int )nomsg) { + if ((int )m1 > (int )id1) { + send1 = m1; + } else + if ((int )m1 == (int )id1) { + st1 = (char)1; + } + } + mode1 = (_Bool)0; + } else { + p1_new = send1 != nomsg && p1_new == nomsg ? send1 : p1_new; + mode1 = (_Bool)1; + } + return; +} +} +void node2(void) +{ + msg_t m2 ; + + { + m2 = nomsg; + if (mode2) { + m2 = p1_old; + p1_old = nomsg; + if ((int )m2 != (int )nomsg) { + if ((int )m2 > (int )id2) { + send2 = m2; + } else + if ((int )m2 == (int )id2) { + st2 = (char)1; + } + } + mode2 = (_Bool)0; + } else { + p2_new = send2 != nomsg && p2_new == nomsg ? send2 : p2_new; + mode2 = (_Bool)1; + } + return; +} +} +void node3(void) +{ + msg_t m3 ; + + { + m3 = nomsg; + if (mode3) { + m3 = p2_old; + p2_old = nomsg; + if ((int )m3 != (int )nomsg) { + if ((int )m3 > (int )id3) { + send3 = m3; + } else + if ((int )m3 == (int )id3) { + st3 = (char)1; + } + } + mode3 = (_Bool)0; + } else { + p3_new = send3 != nomsg && p3_new == nomsg ? send3 : p3_new; + mode3 = (_Bool)1; + } + return; +} +} +int init(void) +{ + int tmp ; + + { + if ((int )r1 == 0) { + if ((int )id1 >= 0) { + if ((int )st1 == 0) { + if ((int )send1 == (int )id1) { + if ((int )mode1 == 0) { + if ((int )id2 >= 0) { + if ((int )st2 == 0) { + if ((int )send2 == (int )id2) { + if ((int )mode2 == 0) { + if ((int )id3 >= 0) { + if ((int )st3 == 0) { + if ((int )send3 == (int )id3) { + if ((int )mode3 == 0) { + if ((int )id1 != (int )id2) { + if ((int )id1 != (int )id3) { + if ((int )id2 != (int )id3) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); +} +} +int check(void) +{ + int tmp ; + + { + if (((int )st1 + (int )st2) + (int )st3 <= 1) { + if ((int )r1 >= 3) { + goto _L; + } else + if (((int )st1 + (int )st2) + (int )st3 == 0) { + _L: /* CIL Label */ + if ((int )r1 < 3) { + tmp = 1; + } else + if (((int )st1 + (int )st2) + (int )st3 == 1) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); +} +} +int main1(void) +{ + int c1 ; + int i2 ; + + { + c1 = 0; + r1 = __VERIFIER_nondet_uchar(); + id1 = __VERIFIER_nondet_char(); + st1 = __VERIFIER_nondet_char(); + send1 = __VERIFIER_nondet_char(); + mode1 = __VERIFIER_nondet_bool(); + id2 = __VERIFIER_nondet_char(); + st2 = __VERIFIER_nondet_char(); + send2 = __VERIFIER_nondet_char(); + mode2 = __VERIFIER_nondet_bool(); + id3 = __VERIFIER_nondet_char(); + st3 = __VERIFIER_nondet_char(); + send3 = __VERIFIER_nondet_char(); + mode3 = __VERIFIER_nondet_bool(); + i2 = init(); + assume_abort_if_not(i2); + p1_old = nomsg; + p1_new = nomsg; + p2_old = nomsg; + p2_new = nomsg; + p3_old = nomsg; + p3_new = nomsg; + i2 = 0; + while (1) { + { + node1(); + node2(); + node3(); + p1_old = p1_new; + p1_new = nomsg; + p2_old = p2_new; + p2_new = nomsg; + p3_old = p3_new; + p3_new = nomsg; + c1 = check(); + assert(c1); + } + } +} +return 0; +} +void assert(_Bool arg ) +{ + + + { + if (! arg) { + { + ERROR: {reach_error();abort();} + } + } +} +} + +int calculate_output(int); +int calculate_output2(int); +int calculate_output3(int); +int calculate_output4(int); +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern int __VERIFIER_nondet_int(void); +extern void exit(int); + + // inputs + int inputC = 3; + int inputF = 6; + int inputA = 1; + int inputB = 2; + int inputD = 4; + int inputE = 5; + + + int a17 = -124; + int a5 = 4; + int a24 = 15; + int a2 = 170; + int a7 = 13; + + int calculate_output2(int input); + int calculate_output3(int input); + int calculate_output4(int input); + + int calculate_output(int input) { + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_7: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_35: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_55: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_40: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_48: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_51: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_20: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_37: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_19: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + error_0: {reach_error();abort();} + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_34: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_25: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_50: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_3: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_28: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_39: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_21: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_6: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_38: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_30: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_42: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_10: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_13: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_8: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_52: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_27: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_53: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_54: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_58: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_23: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + globalError: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_57: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_47: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_11: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_17: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_43: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_49: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_32: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==4))){ + error_59: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_26: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_24: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + error_1: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_14: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_33: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_44: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_45: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_41: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_18: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_15: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_29: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_56: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_36: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_12: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_5: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_4: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_46: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_2: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_31: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_22: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_16: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_9: exit(0); + } + + if(((( ((189 < a2) && (281 >= a2)) && ((input == 4) && (((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))))) && (a5==4)) && (a24==14))){ + a17 = (((((a17 % 109)+ -11) - 547674) + -15873) - -563482); + a7 = 12; + + return -1; + } else if(((((a24==13) && (((input == 2) && ((a7==13) || (a7==14))) && (a5==3))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) - -478038) / -5); + a7 = 12; + + return -1; + } else if((((((((a7==12) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14)))) && (input == 1)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = (((a2 - 384978) + -172247) * 1); + a17 = (((a17 * 5) + 542386) * 1); + a7 = 12; + a5 = 7; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4))) && (a5==3)) && (a24==14))){ + a2 = ((((a2 + -131864) * 10)/ 9) - 73578); + a17 = ((((a17 - 0) % 299946)+ -300053) * 1); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 6) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ( 255 < a17 && (a7==12))))) && a2 <= 189 ))){ + a2 = (((((a2 * 9)/ 10) % 45)+ 236) * 1); + a17 = ((((a17 + -100855) - 172157) / 5) + 357533); + a7 = 13; + a24 = 14; + a5 = 3; + + return 23; + } else if((((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12))) && (input == 3)))) && (a5==6))){ + a17 = ((((a17 / 5) % 109)- -2) - 41); + a7 = 12; + + return -1; + } else if(((a5==4) && ( a2 <= 189 && ((((input == 1) && ((a7==13) || (a7==14))) && a17 <= -108 ) && (a24==15))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ((( ((189 < a2) && (281 >= a2)) && ((input == 1) && (a5==4))) && (a7==13)) && 255 < a17 ))){ + a17 = ((((a17 % 71)+ 119) * 1) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 4)))))){ + a2 = (((a2 + 448263) + -951842) * 1); + a17 = (((a17 * 5) / 5) + -274764); + a7 = 14; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((a5==5) && ( a2 <= 189 && ((input == 1) && (a24==15)))) && 255 < a17 ) && (a7==14))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)- -199); + a7 = 13; + a24 = 14; + + return 26; + } else if((( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) || ((a7==12) || (a7==13))) && (input == 1)) && (a24==15)))) && (a5==5))){ + a17 = (((((a17 % 109)+ 16) * 5) % 109)- -2); + a7 = 14; + a24 = 13; + + return -1; + } else if((( a17 <= -108 && (( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 5))) && (a24==13))) && (a5==6))){ + a17 = (((((a17 + 0) - -350799) - -197891) % 71)- -182); + a7 = 14; + a24 = 14; + a5 = 4; + + return -1; + } else if((((a24==13) && ( a17 <= -108 && (((a5==4) && (input == 2)) && ((189 < a2) && (281 >= a2)) ))) && (a7==12))){ + a17 = ((((((a17 - 0) * 9)/ 10) / 5) % 109)- -93); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==3) && ( ((-108 < a17) && (111 >= a17)) && ((a24==13) && (((a7==12) || (a7==13)) && (input == 4))))) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 12; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==4) && ( a2 <= 189 && ((a24==15) && (((a7==13) || (a7==14)) && (input == 5))))))){ + a17 = ((((a17 - 135275) * 10)/ 9) * 3); + a7 = 13; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 6)) && (a5==7)) && (a24==13)))){ + a17 = ((((a17 % 109)+ 2) - 1) - -2); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==5)) || (((a5==4) && ((a24==15) && ((a7==14) && 255 < a17 ))) || ((a5==5) && ((a24==13) && ((a7==12) && a17 <= -108 ))))) && (input == 1)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 - 0) % 109)- -2) + -577173) + 577173); + a7 = 14; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==13) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) )) && (a5==3)) && a17 <= -108 )){ + a2 = (((a2 + -532580) * 1) + -62227); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if((((a5==4) && ((((input == 5) && ((a7==12) || (a7==13))) && (a24==14)) && ((189 < a2) && (281 >= a2)) )) && a17 <= -108 )){ + a2 = (((a2 * 5) / -5) / 5); + a17 = (((((a17 % 109)+ 4) * 5) % 109)+ 1); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && ((a5==3) && (((( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 ))) && (input == 2)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 - 260500) / 5) + -428690); + a17 = ((((a17 % 71)- -184) * 1) - -1); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((((a5==4) && (((input == 1) && (a24==15)) && ((-108 < a17) && (111 >= a17)) )) && a2 <= 189 ) && (a7==12))){ + + a24 = 13; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && (((a5==4) && (((input == 2) && (a24==15)) && (a7==12))) && ((-108 < a17) && (111 >= a17)) ))){ + + a7 = 14; + a24 = 13; + a5 = 5; + + return 26; + } else if(((a24==13) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && (((input == 2) && a2 <= 189 ) && (a7==14)))))){ + + a7 = 13; + a24 = 15; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((((a5==5) && ((input == 3) && (a24==13))) && (a7==14)) && ((111 < a17) && (255 >= a17)) ))){ + a17 = (((a17 * 5) + -131690) - 406420); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((((a5==5) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a7==13)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 / 5) - 248849) * 2); + a17 = ((((a17 / 5) * 5) / 5) - 458249); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && (a24==15))) && (a5==3))){ + a17 = ((((a17 - -260026) + 97662) * 10)/ 9); + a7 = 12; + a24 = 14; + + return -1; + } else if((((a5==7) && ((( ((-108 < a17) && (111 >= a17)) && (input == 1)) && (a7==13)) && a2 <= 189 )) && (a24==14))){ + a17 = ((((a17 % 71)+ 184) - -1) - 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 6))))))){ + a17 = (((a17 - 33426) - 518487) - 34791); + a7 = 13; + a5 = 4; + + return -1; + } else if((( a2 <= 189 && (( 255 < a17 && ((input == 3) && ((a7==13) || (a7==14)))) && (a5==7))) && (a24==15))){ + a17 = ((((a17 - 593212) - -274925) - -137841) + -419796); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==13) && ( ((-108 < a17) && (111 >= a17)) && ((input == 4) && ((a7==12) || (a7==13)))))) && (a5==6))){ + a2 = (((a2 - 356828) + -57766) * 1); + a7 = 14; + + return 26; + } else if(( a17 <= -108 && (((((input == 5) && ((a7==12) || (a7==13))) && (a5==5)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)))){ + a2 = (((a2 - 367280) / 5) + -340709); + a17 = (((((a17 % 299872)+ 300127) * 1) + -276171) + 347263); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((a5==5) && ((input == 6) && (((a24==14) && ((a7==13) && a17 <= -108 )) || (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 )))))))){ + a17 = (((((a17 - 0) % 299946)+ -300053) - -266634) + -266635); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==6) && ((a24==13) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 1)))) && a2 <= 189 )){ + a17 = ((((a17 + -600109) - 2) / 5) - 329060); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==7) && ((((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))) && (input == 4)) && a2 <= 189 )) && (a24==13))){ + a2 = ((((a2 / 5) - 178027) % 45)- -249); + a17 = ((((a17 / 5) - 189029) * 10)/ 9); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && ((a24==15) && ((((input == 6) && ((a7==13) || (a7==14))) && (a5==4)) && ((-108 < a17) && (111 >= a17)) )))){ + a17 = ((((a17 - -591336) + -371053) * -1)/ 10); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 * -5) * 5) - 39358); + a17 = ((((a17 % 109)- -1) + -513301) + 513302); + a7 = 13; + a5 = 5; + + return 26; + } else if((((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 2)) && (a5==4))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 * -5) + -139298) * 10)/ 9); + a17 = (((a17 - 600110) - 0) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((a5==5) && (input == 4)) && a2 <= 189 )) && (a7==14)) && (a24==15))){ + a2 = ((((a2 / 5) + -370165) % 45)- -261); + a17 = (((a17 + 573666) * 1) + -329578); + a7 = 12; + a5 = 4; + + return 21; + } else if(((((((a7==12) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && (a24==13)) && a17 <= -108 )){ + + return 21; + } else if(((a24==15) && ((a5==6) && ((((a7==12) && (input == 6)) && a17 <= -108 ) && a2 <= 189 )))){ + a2 = ((((((a2 * 9)/ 10) + -20706) + -31885) % 45)- -245); + a17 = ((((a17 % 109)- -26) / 5) * 5); + a5 = 3; + + return 23; + } else if((( ((111 < a17) && (255 >= a17)) && ((a24==15) && ((a5==6) && ((a7==12) && (input == 6))))) && a2 <= 189 )){ + a2 = ((((a2 - 0) + 15546) % 45)+ 235); + a17 = (((a17 * 5) - -401693) - -144036); + a5 = 3; + + return 23; + } else if((((((a24==14) && ((input == 4) && ((a7==12) || (a7==13)))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a17 = ((((((a17 % 71)- -223) * 10)/ 9) * 9)/ 10); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a24==13) && (( ((111 < a17) && (255 >= a17)) && (((input == 6) && ((a7==12) || (a7==13))) && (a5==4))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - 188462) * 3) + -6); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==15) && ( a2 <= 189 && ((((a7==12) || (a7==13)) && (input == 6)) && (a5==5)))) && 255 < a17 )){ + a17 = (((a17 + -66404) - -20679) + -554407); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a7==12) && ((a24==15) && ((a5==6) && ((input == 2) && a2 <= 189 )))) && a17 <= -108 )){ + a2 = (((((a2 % 45)+ 235) * 1) - -275959) + -275957); + a17 = (((((a17 % 71)+ 208) / 5) * 10)/ 2); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==6) && ((((a7==12) && ((input == 3) && (a24==13))) && a2 <= 189 ) && a17 <= -108 ))){ + a2 = ((((a2 / 5) + 158559) % 45)+ 204); + a17 = (((((a17 % 109)+ 75) - 24) + 175099) - 175127); + a24 = 15; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((((a24==15) && (input == 6)) && (a5==4)) && (a7==12))))){ + a17 = (((a17 + -497569) + 497379) - -33); + a7 = 14; + a24 = 14; + a5 = 5; + + return 26; + } else if((((a5==6) && (((input == 2) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a24==13))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 10)/ 9) + -424739); + a17 = (((a17 + -600109) * 1) + -3); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((((a7==12) || (a7==13)) && (input == 6)) && a2 <= 189 ))) && 255 < a17 )){ + + a7 = 14; + a5 = 5; + + return 26; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 6) && (a5==4))) && (a24==15)) && ((-108 < a17) && (111 >= a17)) ) && (a7==13))){ + a17 = (((a17 - 534822) - -388608) * 4); + a7 = 14; + a24 = 14; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (((a24==13) && ((a5==4) && (((a7==13) || (a7==14)) && (input == 5)))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(( a17 <= -108 && ((a24==14) && (( a2 <= 189 && ((input == 3) && ((a7==13) || (a7==14)))) && (a5==6))))){ + a2 = ((((a2 / 5) * 4) % 45)+ 236); + a17 = ((((a17 - -556050) % 109)- -1) - 0); + a7 = 12; + a5 = 3; + + return 21; + } else if(( a2 <= 189 && (((a5==4) && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 1)))) && (a24==15)))){ + a17 = ((((a17 + -600240) / 5) * 10)/ 4); + a7 = 14; + a24 = 13; + a5 = 6; + + return 23; + } else if(((a5==7) && (((a24==14) && ((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14)))))) && a2 <= 189 ))){ + a17 = ((((a17 % 299946)+ -300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && (((a7==13) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((-108 < a17) && (111 >= a17)) ))) && (a5==4)))){ + a2 = (((a2 / 5) / -5) * 5); + a7 = 14; + a24 = 13; + + return -1; + } else if(((((a5==5) && (((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )) && (input == 6))) && (a24==13)) && a2 <= 189 )){ + a17 = (((((a17 / 5) + 383422) + -411251) % 71)- -233); + a7 = 14; + a24 = 14; + a5 = 6; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a7==14) && ((a5==5) && (((a24==13) && (input == 6)) && a2 <= 189 ))))){ + a17 = (((a17 * 5) - 61428) + -534582); + a7 = 13; + a24 = 15; + a5 = 6; + + return 21; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 3) && ((a7==13) || (a7==14))) && (a5==6)) && (a24==15))) && a2 <= 189 )){ + a2 = (((((a2 + 39352) / 5) / 5) % 45)+ 234); + a7 = 12; + a24 = 14; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && ((a7==13) && ((a5==3) && (input == 5)))) && ((111 < a17) && (255 >= a17)) ))){ + a2 = (((a2 - 43077) / 5) / 5); + a17 = (((a17 / 5) / 5) - -99709); + a7 = 12; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && (((input == 2) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==6)))))){ + a2 = (((((a2 % 45)- -235) - -2) - 444254) - -444251); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a5==5) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a2 = (((a2 + -159174) - 203606) + -130058); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && (( ((-108 < a17) && (111 >= a17)) && ((a24==14) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a5==5)))){ + a17 = (((a17 + -547450) / 5) + -82633); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 5) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))) && (a24==14)) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -395244) - -867612) + -1020920); + a17 = (((((a17 % 299872)- -256) * 1) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==13) && ((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 5)) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - 325121) * 10)/ 9) * 1); + a17 = (((((a17 % 71)+ 160) / 5) + -586476) - -586646); + a7 = 14; + a24 = 15; + + return 21; + } else if((((((a24==14) && (((a7==13) || (a7==14)) && (input == 4))) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && 255 < a17 )){ + a2 = (((a2 - -513398) * 1) * -1); + a17 = (((a17 + -11058) * 1) + -589131); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14)))))) && a2 <= 189 ))){ + a17 = (((a17 / 5) - -11377) - 448490); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==5) && ( ((-108 < a17) && (111 >= a17)) && (((a7==14) && (input == 5)) && (a24==13)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 10)/ 9) - 571457); + a17 = ((((a17 - -227661) + 18143) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==4) && ((((((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 3)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 % 109)+ 3) + -187035) + 26490) + 160528); + a7 = 13; + + return -1; + } else if(((a7==14) && ((a5==5) && ((( ((-108 < a17) && (111 >= a17)) && (input == 2)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * -5) + -437978) + 281140); + a17 = ((((a17 * 5) / 5) / 5) - 83944); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 1) && (a5==6)) && (a24==13)) && (a7==13))) && 255 < a17 )){ + a17 = (((a17 + -491213) - 108914) + -47); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a5==6) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((((a7==12) || (a7==13)) && (input == 2)) && (a24==13)))))){ + a2 = (((a2 + 391304) * -1) / 5); + a17 = (((a17 - 532893) - 26035) + -34319); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a5==4) && ((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 )) && ((-108 < a17) && (111 >= a17)) ) && (a24==15))){ + a17 = (((((a17 * 5) % 71)- -183) + -26829) + 26828); + a7 = 13; + a24 = 13; + a5 = 5; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && (((((a24==13) && (input == 4)) && (a5==5)) && (a7==14)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * -5) * 5) - 149618); + a17 = (((a17 / 5) * 5) - 544978); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((( a2 <= 189 && ((input == 4) && (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ( a17 <= -108 && (a7==12)))))) && (a5==7))){ + a17 = ((((a17 / 5) - -3819) - 117000) - 285915); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((a24==13) && ( a2 <= 189 && ((a7==14) && ( ((-108 < a17) && (111 >= a17)) && (input == 5))))))){ + a17 = ((((a17 - 51813) - -610607) * -1)/ 10); + a24 = 15; + a5 = 6; + + return 23; + } else if(((((a24==14) && ((input == 2) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )))) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + -132328) + -282019); + a17 = (((a17 + -600110) * 1) - 2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && ((a5==4) && ( a2 <= 189 && ((input == 6) && ((a7==13) || (a7==14)))))) && (a24==15))){ + a17 = ((((((a17 % 109)- -74) * 5) * 5) % 109)- -2); + a7 = 14; + + return 21; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 2)))) && (a24==13))){ + a2 = ((((a2 / -5) + 8939) * 5) - 171471); + a17 = ((((a17 + -514608) + 103914) % 109)+ 2); + a7 = 14; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((a5==3) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))))){ + + a7 = 13; + a24 = 13; + + return -1; + } else if(((((((a24==13) && ((a7==13) && a17 <= -108 )) && (a5==5)) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || ((( a17 <= -108 && (a7==12)) && (a24==13)) && (a5==5)))) && (input == 2)) && a2 <= 189 )){ + a17 = (((((a17 + 0) - 0) / 5) % 71)- -184); + a7 = 13; + a24 = 13; + a5 = 6; + + return 26; + } else if(( a17 <= -108 && ((a24==15) && ( a2 <= 189 && ((((a7==13) || (a7==14)) && (input == 3)) && (a5==4)))))){ + a17 = ((((a17 % 299872)+ 300127) + 133154) / 5); + a7 = 12; + + return 21; + } else if(( a2 <= 189 && ((a24==14) && ((a5==6) && ( ((111 < a17) && (255 >= a17)) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 4))))))){ + a2 = (((((a2 % 45)- -234) * 1) + 447091) + -447090); + a7 = 13; + a5 = 3; + + return 23; + } else if((( 255 < a17 && (((a24==13) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 3))) && (a5==5))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -391458) - 38043) * 1); + a17 = ((((((a17 * 9)/ 10) - 302989) / 5) % 71)+ 184); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a24==15) && ((((input == 4) && (a5==5)) && a17 <= -108 ) && (a7==14))) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -234) * 5) % 45)+ 227); + a17 = ((((((a17 * 9)/ 10) * 1) + -14728) % 109)- -22); + a24 = 14; + a5 = 4; + + return 23; + } else if((((a5==3) && (((( 255 < a17 && (a7==14)) && (a24==14)) || ((a24==15) && ( a17 <= -108 && (a7==12)))) && (input == 6))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 0) % 109)- -1) - 0); + a7 = 12; + a24 = 14; + + return -1; + } else if((((a5==7) && ((a24==15) && (((input == 6) && 255 < a17 ) && (a7==12)))) && a2 <= 189 )){ + a17 = ((((a17 + -312975) + -287141) / 5) + -19782); + a24 = 14; + a5 = 5; + + return -1; + } else if(((a5==4) && ((a24==15) && ((((input == 5) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && a17 <= -108 )))){ + + a7 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) || ((a7==13) && 255 < a17 )) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 * 5) * 5) / -5); + a17 = (((a17 + 0) - 600109) - 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((input == 5) && ((( a17 <= -108 && (a7==12)) && (a24==14)) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14)))))) && (a5==3)))){ + a2 = ((((a2 - 68838) - -367491) + 74473) * -1); + a17 = (((((a17 + 0) / 5) / 5) % 71)- -184); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((( a2 <= 189 && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==14)) && (a5==7))){ + a17 = ((((a17 % 299946)- 300053) * 1) - 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && (((a7==13) && ((input == 2) && (a5==3))) && (a24==14))) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 14; + a24 = 13; + + return -1; + } else if((((a24==13) && (((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))) && 255 < a17 )){ + a2 = (((a2 - 410733) / 5) / 5); + a17 = ((((a17 % 71)+ 113) * 1) + 14); + a7 = 13; + a24 = 15; + + return -1; + } else if(((a5==3) && (((((input == 2) && (a7==12)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && a17 <= -108 ))){ + a2 = ((((a2 - 291109) - 296476) + 724390) + -687165); + return -1; + } else if(( a17 <= -108 && ((((a24==15) && ((a7==12) && (input == 1))) && a2 <= 189 ) && (a5==6)))){ + a2 = (((((a2 * 9)/ 10) - -368757) % 45)- -235); + a17 = ((((((a17 % 299872)- -300127) * 10)/ 9) * 10)/ 9); + a7 = 13; + a24 = 14; + a5 = 3; + + return 23; + } else if(((a24==13) && ((a5==6) && ((((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && a2 <= 189 )))){ + a2 = ((((((a2 - 0) % 45)+ 235) / 5) * 51)/ 10); + a17 = ((((a17 / 5) / 5) / 5) - 297755); + a7 = 12; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && (((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) || ( 255 < a17 && (a7==13))) && (input == 5))) && (a5==3)))){ + a17 = (((((a17 - 157643) / 5) * 5) % 71)- -182); + a7 = 14; + + return 21; + } else if(((a5==3) && ((((input == 3) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * -5) * 5) * 5); + a17 = ((((a17 % 299946)+ -300053) * 1) - 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==15) && (( a2 <= 189 && (((a5==6) && (input == 4)) && a17 <= -108 )) && (a7==12)))){ + a2 = ((((a2 % 45)+ 235) - 1) - 0); + a17 = ((((((a17 * 9)/ 10) % 109)- -104) + 237666) - 237686); + a5 = 3; + + return 21; + } else if((((((( a17 <= -108 && (a7==13)) && (a24==14)) || ((((a7==14) && 255 < a17 ) && (a24==13)) || (( a17 <= -108 && (a7==12)) && (a24==14)))) && (input == 3)) && (a5==5)) && a2 <= 189 )){ + a17 = ((((a17 % 299872)- -300127) - 0) + 1); + a7 = 12; + a24 = 15; + a5 = 7; + + return 23; + } else if(((( a2 <= 189 && (((a24==13) && (input == 2)) && (a5==5))) && (a7==14)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 + -462656) * 10)/ 9) + 160772); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((((input == 4) && ((a7==12) || (a7==13))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==6))){ + + a7 = 12; + a24 = 15; + a5 = 5; + + return -1; + } else if(( a2 <= 189 && (((a24==15) && ((a5==7) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 6)))) && ((111 < a17) && (255 >= a17)) ))){ + a17 = ((((a17 * 5) - 15195) % 109)+ 56); + a7 = 14; + a24 = 14; + + return -1; + } else if((((((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))) && (a24==13)) && (a5==6)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 * 9)/ 10) + -528924) % 109)+ 1); + a7 = 14; + a5 = 3; + + return -1; + } else if((((a5==7) && ((input == 2) && ((((a7==14) && 255 < a17 ) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14))))) && a2 <= 189 )){ + a17 = (((((a17 % 299946)+ -300053) + 96027) - 5279) - 90748); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 1) && ((a7==12) || (a7==13))) && (a5==5)) && (a24==14))) && a17 <= -108 )){ + a2 = ((((a2 - 167702) / 5) - -475488) * -1); + a17 = (((((a17 % 109)+ 25) - -194163) + 403579) - 597709); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a7==12) && (((a5==6) && (( a2 <= 189 && (input == 4)) && a17 <= -108 )) && (a24==13)))){ + a2 = (((((a2 - 0) * 9)/ 10) % 45)- -234); + a24 = 15; + a5 = 5; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 1)) && (a24==14)) && (a5==5)))){ + a2 = (((a2 * 5) * 5) - 477470); + a17 = ((((a17 % 299946)+ -300053) + 309977) - 309978); + a7 = 12; + a5 = 7; + + return -1; + } else if(((a5==6) && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5)))))){ + a2 = (((a2 / -5) - 543395) - 31512); + a17 = (((a17 - 374709) - 89040) - 22731); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((( a17 <= -108 && (a7==12)) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 6))) && (a5==6))){ + a2 = ((((a2 % 45)- -236) - 2) * 1); + a17 = ((((((a17 * 9)/ 10) % 299872)+ 300127) - 202607) - -202608); + a7 = 13; + a24 = 15; + a5 = 3; + + return 23; + } else if(( 255 < a17 && ((((a24==13) && (((a7==13) || (a7==14)) && (input == 4))) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + + return -1; + } else if(((a24==13) && ((( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && ((111 < a17) && (255 >= a17)) ) && (a5==5)))){ + a2 = (((a2 * -5) + -99498) * 5); + a17 = (((a17 + 560485) + 34614) * 1); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && (((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) || ((a7==13) && 255 < a17 )) && (input == 4)) && (a5==3)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 / -5) + -562394) - 36545); + a17 = ((((a17 - 600109) - 2) + 90959) + -90958); + a7 = 12; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 4)) && (a24==15)) && ((111 < a17) && (255 >= a17)) ) && (a5==7)))){ + + a7 = 14; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((((a5==5) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 5))) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)))){ + a2 = ((((a2 - -285304) + -146058) % 45)- -236); + a17 = ((((a17 / 5) - 378389) - 189972) + 981500); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if((((((input == 3) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && a2 <= 189 ) && (a5==6)) && (a24==13))){ + a2 = ((((a2 + 0) % 45)+ 235) + 1); + a17 = (((a17 * 5) - -515114) - 13294); + a7 = 13; + + return 26; + } else if(( a2 <= 189 && (( a17 <= -108 && ((a24==15) && ((input == 2) && ((a7==12) || (a7==13))))) && (a5==5)))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==12) && ((a24==15) && ((a5==4) && ( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (input == 5))))))){ + a17 = ((((a17 * 10)/ -9) + -170917) * 3); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==15) && ( 255 < a17 && ((input == 4) && a2 <= 189 ))) && (a7==12)) && (a5==7))){ + a17 = ((((a17 % 71)+ 179) - 53) - -56); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && (((input == 1) && ((a7==13) || (a7==14))) && ((189 < a2) && (281 >= a2)) ))))){ + a2 = ((((a2 + -164688) * 10)/ 9) + -309761); + a17 = (((a17 * 5) + -186431) * 3); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 6)) && (a24==14))))){ + a17 = ((((a17 - -337472) * 10)/ 9) + 150308); + a7 = 12; + a5 = 4; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==14)) && (a5==3))){ + a17 = (((((a17 / 5) + 139884) - -176184) * -1)/ 10); + a7 = 13; + + return 23; + } else if((((a5==6) && (( 255 < a17 && ((input == 2) && ((a7==12) || (a7==13)))) && (a24==15))) && a2 <= 189 )){ + a17 = (((((a17 % 109)+ 1) + 493840) - 420141) + -73780); + a7 = 12; + a24 = 14; + a5 = 4; + + return -1; + } else if(((((((input == 6) && ((189 < a2) && (281 >= a2)) ) && 255 < a17 ) && (a24==15)) && (a5==4)) && (a7==13))){ + a2 = (((a2 * -5) + 126647) * -4); + a24 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 1) && ((a7==12) || (a7==13))) && (a24==15)) && (a5==5)) && a2 <= 189 ) && 255 < a17 )){ + a2 = (((((a2 % 45)- -235) - 1) / 5) - -212); + a17 = ((((((a17 % 71)+ 132) - 10) * 5) % 71)+ 135); + a7 = 14; + a24 = 13; + + return 23; + } else if(((a7==13) && ( ((-108 < a17) && (111 >= a17)) && ((((a24==14) && (input == 2)) && a2 <= 189 ) && (a5==7))))){ + a17 = ((((a17 - 453039) * 10)/ 9) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && ( ((-108 < a17) && (111 >= a17)) && ((((a24==15) && (input == 5)) && (a7==13)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) / 5) / -5); + a17 = (((a17 - 279125) - 101385) * 1); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a5==6) && (((input == 5) && (((a7==12) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))))) && (a24==13))) && a2 <= 189 )){ + a2 = (((((a2 - 0) + 194300) * 1) % 45)+ 235); + a17 = ((((a17 - 508865) * 10)/ 9) + -4999); + a7 = 14; + + return 23; + } else if(((( a2 <= 189 && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 6))) && (a24==14)) && (a5==7))){ + a17 = ((((a17 * 9)/ 10) + 13957) - -35746); + a7 = 12; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==13)) && (a5==5)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 - 216) - 479578) - 45364) + 524988); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((( a2 <= 189 && (((input == 6) && ((a7==12) || (a7==13))) && (a5==5))) && (a24==15)) && a17 <= -108 )){ + a2 = (((((a2 % 45)- -235) + -1) - 553229) - -553229); + a17 = (((a17 / 5) - -167109) / 5); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if(( a2 <= 189 && ((input == 1) && ((((a5==4) && (( 255 < a17 && (a7==14)) && (a24==15))) || ((a5==5) && (((a7==12) && a17 <= -108 ) && (a24==13)))) || ((a5==5) && (( a17 <= -108 && (a7==13)) && (a24==13))))))){ + a17 = ((((a17 - 0) % 299946)- 300053) + -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a24==15) && ((input == 5) && (a5==4))) && ((189 < a2) && (281 >= a2)) ) && 255 < a17 ) && (a7==13))){ + a2 = (((a2 / 5) / 5) - 136738); + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((a7==13) || (a7==14))) && (a24==15)))) && (a5==5))){ + a17 = (((a17 / 5) + 572999) + 22824); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==5) && ((a24==14) && ((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 ))))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 109)+ 2) / 5) + -88); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && (((((input == 6) && ((a7==13) || (a7==14))) && (a5==7)) && 255 < a17 ) && (a24==15)))){ + a17 = ((((a17 % 109)- 61) / 5) / 5); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a24==13) && ((a5==7) && (((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (input == 5)) && a2 <= 189 )))){ + a2 = ((((((a2 % 45)+ 234) * 1) / 5) * 51)/ 10); + a17 = ((((a17 / 5) * 4) % 109)- -2); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(((( a2 <= 189 && ((input == 3) && ((( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )))) && (a5==7)) && (a24==13))){ + a17 = ((((a17 % 299946)+ -300053) * 1) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==6) && ( a2 <= 189 && ((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))))))) && (a24==13))){ + a2 = (((((a2 + 0) % 45)+ 234) - 472412) + 472412); + a17 = ((((a17 + 0) % 71)- -182) + 3); + a7 = 12; + a24 = 15; + a5 = 5; + + return 23; + } else if(((((a24==15) && (((input == 2) && ((a7==12) || (a7==13))) && (a5==5))) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 )){ + a17 = (((((a17 / 5) + -238456) - -765474) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==15) && ((((input == 4) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && (a5==5))) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 * 5) * 5) + -325620); + a17 = (((a17 + 366270) + 10197) + 134633); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==13) && ((a5==4) && (((((a7==13) || (a7==14)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && ((-108 < a17) && (111 >= a17)) )))){ + + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==6) && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a7==14) && (input == 1))))) && a17 <= -108 )){ + a17 = ((((((a17 % 71)- -247) + 5) / 5) * 32)/ 10); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((a5==5) && ((input == 4) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))) && ((189 < a2) && (281 >= a2)) ) && (a24==14))){ + a2 = (((a2 * 5) - 562071) * 1); + a17 = (((((a17 - -128476) + 315707) + -905468) * -1)/ 10); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 ) && (a5==7)) && (a24==15)))){ + a17 = (((((a17 - 271153) + 418092) / 5) * -1)/ 10); + a7 = 14; + + return -1; + } else if(((a24==13) && ((((((a7==12) || (a7==13)) && (input == 4)) && 255 < a17 ) && a2 <= 189 ) && (a5==5)))){ + a17 = (((((a17 % 109)+ 3) * 5) % 109)- -2); + a7 = 14; + a24 = 15; + a5 = 7; + + return 23; + } else if((((a5==4) && ((a24==14) && ((input == 3) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) - 516770) - 71238); + a17 = ((((a17 - 0) % 299872)+ 300127) + 1); + a7 = 12; + a5 = 7; + + return -1; + } else if((( 255 < a17 && (((a24==15) && ((input == 2) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==3))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 507108) + -40186) * 1); + a17 = ((((a17 % 71)- -168) + 373224) + -373250); + a7 = 14; + a24 = 14; + + return -1; + } else if(((((a7==14) && (((input == 3) && (a24==15)) && a2 <= 189 )) && 255 < a17 ) && (a5==5))){ + a2 = (((((a2 % 45)- -236) / 5) / 5) + 268); + a7 = 12; + a24 = 14; + + return 21; + } else if(((a5==5) && ( a2 <= 189 && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 1)) && (a24==15))))){ + a17 = ((((a17 - 99808) / 5) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && (((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a2 = (((a2 - -222045) / 5) + -435548); + a17 = (((((a17 * 5) % 71)- -183) + 531003) + -531001); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a24==14) && ( ((189 < a2) && (281 >= a2)) && (((input == 3) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==5))))){ + a2 = (((a2 - 537051) + -19713) - 17151); + a17 = (((((a17 % 299872)+ 300127) + -161234) - 361454) + 522690); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && ((((a7==13) || (a7==14)) && (input == 4)) && (a5==6)))) && (a24==15))){ + a17 = (((a17 - 438310) / 5) + -185271); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==13) && ((a5==4) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 252975) * 2) - -454453); + a17 = (((((((a17 * 9)/ 10) % 71)+ 176) / 5) * 39)/ 10); + a7 = 13; + a24 = 15; + + return 21; + } else if(( 255 < a17 && ((( ((189 < a2) && (281 >= a2)) && ((a7==13) && (input == 5))) && (a24==13)) && (a5==6)))){ + + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && (((input == 3) && ((a7==12) || (a7==13))) && a17 <= -108 ))) && (a5==5))){ + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 109)- -107); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a5==5) && ( a2 <= 189 && ((a24==13) && ((input == 4) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) ))))))){ + a17 = ((((a17 + 0) % 299946)- 300053) + -1); + a7 = 12; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((a24==14) && ( ((111 < a17) && (255 >= a17)) && ((a5==6) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13))))))))){ + a17 = ((((a17 - -144076) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (( a17 <= -108 && ((((a7==13) || (a7==14)) && (input == 6)) && (a24==13))) && (a5==3)))){ + a2 = (((a2 - 324660) + 36683) * 2); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && (((a7==14) && ((a24==13) && (input == 2))) && (a5==6))))){ + a2 = (((a2 - -379518) + 60031) + -652869); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==4) && (((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) && (input == 3)) && ((189 < a2) && (281 >= a2)) )) && (a24==15))){ + a17 = (((a17 - 0) + -600109) - 1); + a7 = 14; + a24 = 14; + + return -1; + } else if((((((a24==15) && (((a7==12) || (a7==13)) && (input == 4))) && 255 < a17 ) && a2 <= 189 ) && (a5==5))){ + a2 = (((((a2 % 45)- -235) - -264986) / 5) - 52838); + a17 = (((((a17 % 109)+ 3) + -92) - -39346) - 39285); + a7 = 14; + a24 = 13; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((a5==4) && ((input == 2) && ((a7==13) || (a7==14)))) && (a24==13))))){ + a17 = ((((a17 - 8964) * 10)/ 9) / 5); + a7 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==5) && ((a24==15) && (((input == 1) && ((a7==14) || ((a7==12) || (a7==13)))) && 255 < a17 ))))){ + a17 = (((((a17 + -204208) + -294222) / 5) % 109)- -2); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a24==15) && (( a2 <= 189 && ((input == 1) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))))) && (a5==7)))){ + a17 = ((((a17 + 445460) + -108723) % 109)+ 2); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a5==6) && ( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a7==14) && (input == 6))))))){ + a17 = ((((((a17 * 9)/ 10) + -8929) / 5) % 109)- -99); + a5 = 5; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && (a24==13)))){ + + a7 = 12; + + return -1; + } else if(((a24==13) && ((a5==3) && (((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 6)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 * 5) - -456899) * 1) * -1); + a17 = ((((a17 % 109)+ 2) - -1) + -2); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==5) && ( a2 <= 189 && ( ((-108 < a17) && (111 >= a17)) && ((((a7==12) || (a7==13)) && (input == 6)) && (a24==15)))))){ + a17 = (((((a17 - 533399) + 268098) + 539288) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((( ((189 < a2) && (281 >= a2)) && ((a24==13) && (input == 3))) && ((-108 < a17) && (111 >= a17)) ) && (a7==13)))){ + a2 = ((((a2 + 15012) - -575888) * 1) * -1); + a17 = ((((a17 - -31776) - -471905) / 5) - 154264); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 6))) && (a24==15)))){ + a17 = ((((a17 - 600111) + 328854) * 1) + -328853); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==7) && (((input == 4) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && a2 <= 189 )) && (a24==14))){ + a17 = ((((a17 % 71)- -117) + 189902) - 189835); + a7 = 13; + + return -1; + } else if(((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((a5==5) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13))))) && 255 < a17 )))){ + a2 = ((((a2 - 330313) * 10)/ 9) - 15295); + a17 = (((((a17 / 5) - 422861) + 205502) % 109)- -66); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && (( ((-108 < a17) && (111 >= a17)) && ((input == 4) && ((a7==13) || (a7==14)))) && (a5==4))))){ + a17 = (((a17 + -505795) * 1) * 1); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (( 255 < a17 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 2))) && (a5==6))) && (a24==14))){ + a17 = (((a17 - 600255) + -1) - 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==14) && (((input == 4) && (a7==13)) && ((-108 < a17) && (111 >= a17)) )) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 574876) / 5) - 126841); + a17 = ((((a17 % 71)- -182) - 0) - 0); + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && (a24==14))))){ + a2 = (((a2 / -5) - -106688) - 700155); + a17 = ((((a17 - -444995) * 1) % 71)- -142); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if((( a2 <= 189 && ( 255 < a17 && ((a24==15) && ((input == 3) && (a7==12))))) && (a5==7))){ + a17 = ((((a17 + -443894) / 5) / 5) + -460355); + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((input == 5) && (a24==13)) && (a7==12)))) && a2 <= 189 )){ + a17 = ((((a17 + -406871) - 29414) + 509500) - 209883); + a7 = 13; + a5 = 7; + + return 23; + } else if(((a5==5) && ( ((111 < a17) && (255 >= a17)) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = ((((a17 + -386404) - -386194) - -24721) - 24655); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((((a5==4) && (((a7==13) || (a7==14)) && (input == 4))) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)))){ + a17 = ((((a17 % 71)+ 184) - -1) - 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((a5==5) && ((a24==13) && ( a17 <= -108 && (a7==13)))) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || ((a5==5) && (((a7==12) && a17 <= -108 ) && (a24==13))))) && (input == 3)))){ + a2 = (((a2 * 5) + -496396) - -43586); + a17 = ((((a17 + 0) % 71)- -183) - -1); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a5==6)) && (a24==13))){ + a17 = (((((a17 % 71)- -184) - 1) + -591569) + 591570); + a7 = 14; + a5 = 4; + + return -1; + } else if((((((input == 1) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && (a24==14)) && (a5==7)) && a2 <= 189 )){ + a17 = ((((a17 / 5) - -456210) - 346519) + -109681); + a7 = 13; + + return -1; + } else if(((a7==13) && ((a24==15) && (((a5==6) && ((input == 2) && a17 <= -108 )) && a2 <= 189 )))){ + a17 = (((((a17 % 71)- -191) + 37) + 557078) + -557055); + a7 = 12; + a24 = 13; + a5 = 7; + + return 26; + } else if(((a5==7) && (((a24==14) && ((input == 5) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))))) && a2 <= 189 ))){ + a17 = (((((a17 + -437926) * 1) / 5) % 71)+ 182); + a7 = 14; + + return 26; + } else if(((a7==13) && ((a24==13) && ((((input == 3) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 ) && (a5==5))))){ + a17 = ((((a17 * 23)/ 10) - -95194) + 367978); + a5 = 7; + + return 23; + } else if(((a24==13) && ((a7==13) && ( ((-108 < a17) && (111 >= a17)) && (((input == 2) && (a5==5)) && ((189 < a2) && (281 >= a2)) ))))){ + a2 = (((a2 * 5) + -75316) * 5); + a17 = ((((a17 / 5) * 5) * 5) - 551159); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==7) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 6)) && a2 <= 189 )))){ + a17 = (((a17 + 497335) - 362468) / 5); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a7==14) && ((a5==3) && ( ((111 < a17) && (255 >= a17)) && (((input == 4) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))))){ + + a7 = 12; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((a5==7) && ((a24==13) && (((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )) && (input == 2)))))){ + a2 = ((((a2 % 45)+ 235) - -164895) - 164893); + a17 = (((((a17 * 9)/ 10) % 109)- -2) / 5); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && ((a24==14) && (((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==5)))))){ + a2 = ((((a2 / 5) / 5) % 45)- -235); + a17 = (((a17 * 5) - -230268) / 5); + a7 = 14; + a24 = 13; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((input == 5) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )))) && (a24==15)))){ + a17 = (((((a17 % 71)+ 146) - -107220) - 259531) + 152347); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((a24==14) && (( a2 <= 189 && ((input == 4) && (a5==5))) && (a7==14))))){ + a17 = ((((a17 * 10)/ -9) * 5) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((a5==6) && (input == 5)) && (a24==15))) && (a7==12)) && a2 <= 189 )){ + a2 = ((((a2 % 45)+ 234) * 1) + 1); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==5) && ((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && (input == 3))) && (a7==12)) && (a24==13)))){ + a17 = ((((a17 * 10)/ -9) * 5) + -240506); + a5 = 3; + + return -1; + } else if(((((((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 2)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = ((((a2 / -5) + -417573) * 10)/ 9); + a17 = ((((a17 - 128270) + -400314) + 6367) + -77894); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((((a5==4) && (input == 4)) && (a7==13)) && (a24==15))))){ + a2 = ((((a2 + -199858) * 10)/ 9) + -50269); + a17 = (((((a17 + -143986) * 1) / 5) % 71)- -183); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && ((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) || ((a7==13) && 255 < a17 ))))))){ + a2 = (((a2 * 5) / 5) - 103911); + a17 = (((a17 - 600110) * 1) - 2); + a7 = 12; + a24 = 13; + + return -1; + } else if(((( a2 <= 189 && ((input == 6) && ((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))))) && (a5==7)) && (a24==13))){ + a17 = ((((a17 % 299946)+ -300053) - 2) - 0); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((input == 2) && (((((a24==15) && ((a7==14) && 255 < a17 )) && (a5==4)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5))) || (((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==5)))))){ + a2 = (((a2 / -5) / 5) - 528849); + a17 = ((((a17 - 0) / 5) - 300593) + 687900); + a7 = 14; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((input == 4) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )))))) && (a24==15))){ + a2 = (((a2 + -76921) + -80615) - 172398); + a17 = (((((a17 - 0) % 299946)+ -300053) - -542550) - 542551); + a7 = 12; + a24 = 13; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((a24==13) && (input == 5)) && (a7==13)))) && (a5==5))){ + a2 = (((a2 / 5) - 555637) + -17770); + a17 = (((((a17 - -266183) * 10)/ 9) * 10)/ 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==3) && ((a24==15) && (((input == 1) && (a7==13)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = ((((a17 / 5) + 156) + 305089) + -305059); + a7 = 14; + a24 = 13; + + return -1; + } else if(( 255 < a17 && ((a24==14) && (( a2 <= 189 && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==5))))){ + a2 = ((((((a2 % 45)- -235) * 1) * 5) % 45)+ 226); + a17 = (((a17 - 600142) + 457437) + -457541); + a7 = 12; + a24 = 13; + a5 = 4; + + return 21; + } else if((((a7==12) && (((a5==4) && ((input == 3) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )) && (a24==15))){ + + a24 = 14; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ((input == 4) && (((((a24==15) && ((a7==14) && 255 < a17 )) && (a5==6)) || ((a5==7) && ((a24==13) && ( a17 <= -108 && (a7==12))))) || ((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==7)))))){ + a2 = ((((a2 % 45)+ 234) * 1) * 1); + a17 = ((((a17 % 109)- -2) - -1) / 5); + a7 = 14; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a5==4) && ((a24==14) && ( ((189 < a2) && (281 >= a2)) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 5))))))){ + a2 = (((a2 * -5) + 490210) + -622035); + a17 = (((((a17 / 5) + -253338) - -303884) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ((a24==15) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = (((((a17 / 5) * 5) - 517057) % 71)- -222); + a7 = 13; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ( a17 <= -108 && ((a5==5) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13))))))) && (a24==15))){ + a2 = (((a2 - 51957) - 201016) + -229661); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 4) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==5)) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14))){ + a17 = ((((a17 + -583681) / 5) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((a7==12) || (a7==13)))) && a17 <= -108 ) && (a5==4)) && (a24==14))){ + a2 = ((((a2 * -5) / 5) - -461012) * -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((((((a7==13) && 255 < a17 ) && (a24==14)) || (((a7==14) && 255 < a17 ) && (a24==14))) || ((a24==15) && ((a7==12) && a17 <= -108 ))) && (input == 2))) && (a5==7))){ + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12))) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)) && (a5==4))){ + a2 = (((a2 + -56097) + -204457) / 5); + a17 = ((((a17 - 0) - 600111) / 5) + -466402); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a24==15) && (((((input == 1) && (a5==3)) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) ) && (a7==14)))){ + a2 = (((a2 + -198382) * 3) - 2631); + a17 = ((((a17 / 5) * 10)/ -2) + -174727); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==14) && ((a5==7) && (((input == 5) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && a2 <= 189 )))){ + a17 = ((((a17 - 587947) / 5) / 5) + 23535); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if((((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((a7==13) && ((a5==4) && (input == 4))))) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 * 5) / 5) + -257179); + a17 = (((((a17 % 71)- -184) + 43333) / 5) + -8544); + a7 = 12; + a5 = 5; + + return -1; + } else if((((((a24==14) && (((a7==12) || (a7==13)) && (input == 2))) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a5==5))){ + a2 = (((((a2 % 45)+ 234) * 5) % 45)+ 193); + a17 = ((((a17 - -121418) * 10)/ -9) + -75458); + a7 = 12; + a24 = 15; + a5 = 3; + + return 23; + } else if(( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==13) && (((a7==13) || (a7==14)) && (input == 1))))))){ + a2 = (((a2 + -566056) + -17565) - 7708); + a17 = ((((((a17 - -545152) % 109)- -2) * 5) % 109)- -2); + a7 = 13; + a24 = 15; + a5 = 4; + + return 21; + } else if(((a7==12) && (((( a2 <= 189 && (input == 2)) && ((111 < a17) && (255 >= a17)) ) && (a5==4)) && (a24==15)))){ + a17 = ((((((a17 - -393608) * 10)/ 9) - 738081) * -1)/ 10); + a7 = 13; + a24 = 14; + a5 = 5; + + return 23; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 1) && ((a7==13) || (a7==14))) && a2 <= 189 ) && (a5==4))) && (a24==15))){ + a17 = (((a17 - -93652) / 5) * 5); + a7 = 14; + a24 = 13; + a5 = 5; + + return 23; + } + return calculate_output2(input); + } + + int calculate_output2(int input) { + + + if(((a5==7) && (((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 4)) && a2 <= 189 ) && (a24==13)))){ + a17 = (((a17 + -223220) - 376890) - 0); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==13) && (((a5==3) && (((a7==13) || (a7==14)) && (input == 3))) && ((189 < a2) && (281 >= a2)) )) && a17 <= -108 )){ + a2 = (((a2 * 5) - 572766) - 10840); + a17 = (((((a17 + 0) % 299872)+ 300127) * 10)/ 9); + a7 = 12; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a17 <= -108 && (((input == 5) && ((a7==12) || (a7==13))) && a2 <= 189 ))) && (a24==15))){ + a2 = ((((a2 % 45)- -234) * 1) + 0); + a17 = (((((a17 % 299872)- -300127) - -85883) - 234462) - -340820); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(((a5==7) && ((( ((111 < a17) && (255 >= a17)) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && (a24==15)) && a2 <= 189 ))){ + a17 = (((a17 - 554057) - 32150) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((input == 4) && (((a24==14) && ((a7==12) && a17 <= -108 )) || ((( 255 < a17 && (a7==13)) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13)))))) && (a5==6))){ + a17 = (((a17 / 5) - 146392) - 201110); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 2))) && (a5==4)) && (a24==14))){ + a2 = ((((a2 + -438465) * 10)/ 9) + -61750); + a17 = (((a17 - -547585) - -40543) + -650123); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && (((a24==14) && ((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 2))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * 5) - 588386) - 700); + a17 = ((((a17 % 299946)- 300053) / 5) - 223475); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((input == 1) && (a5==5)) && (a7==12)))))){ + a17 = (((a17 - -556781) - -32123) - -2336); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((((a7==12) && (input == 1)) && (a24==13)) && a17 <= -108 )))){ + + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==3) && (((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + -105771) / 5) * 5); + a17 = ((((a17 / 5) + 192183) * -1)/ 10); + a7 = 12; + + return -1; + } else if(((((((a24==13) && (input == 6)) && (a7==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 - 160975) / 5) * 5); + a17 = (((a17 + -217141) + 302270) - 56859); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a24==13) && ((((input == 3) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (a5==7)) && a2 <= 189 ))){ + a17 = (((((a17 * 5) - 221071) / 5) % 71)- -220); + a7 = 12; + a5 = 5; + + return 21; + } else if((((( a2 <= 189 && ((input == 4) && (a24==13))) && ((111 < a17) && (255 >= a17)) ) && (a7==12)) && (a5==5))){ + a17 = (((a17 + -543666) - 48044) - 4253); + a5 = 3; + + return -1; + } else if(((a5==6) && ( ((189 < a2) && (281 >= a2)) && (((((a7==12) || (a7==13)) && (input == 3)) && (a24==13)) && ((-108 < a17) && (111 >= a17)) )))){ + a17 = (((a17 + -479754) * 1) - 60677); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a24==15) && (input == 5)) && (a7==13)))))){ + a17 = ((((a17 - 89845) % 71)- -187) * 1); + a24 = 13; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && (a24==13))) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = (((a2 / 5) * 5) + -133618); + a17 = ((((a17 - 64840) - 296199) * 10)/ 9); + a7 = 12; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((a7==12) && (input == 6)) && ((-108 < a17) && (111 >= a17)) )) && (a24==15)) && (a5==5))){ + a2 = (((a2 + -519111) - -90859) / 5); + a17 = (((a17 / 5) + -553032) + 553176); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==4) && ((a24==15) && ( ((-108 < a17) && (111 >= a17)) && (((input == 3) && a2 <= 189 ) && (a7==12)))))){ + a17 = (((((a17 / 5) + 521700) - 934556) * -1)/ 10); + a7 = 14; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==14) && ((input == 6) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))))){ + a2 = (((a2 / 5) * -5) * 5); + a17 = ((((a17 * 5) % 71)+ 182) + 1); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if((((((((a7==13) || (a7==14)) && (input == 4)) && a17 <= -108 ) && (a24==15)) && (a5==4)) && a2 <= 189 )){ + a17 = ((((((a17 + 343527) % 71)+ 183) * 5) % 71)- -165); + a7 = 13; + + return 21; + } else if((( a17 <= -108 && ((a5==6) && ( a2 <= 189 && ((a24==15) && (input == 3))))) && (a7==13))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 3) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a5==5)) && (a24==14)))){ + a2 = (((a2 + -81628) * 5) - 151837); + a17 = (((a17 + -600110) - 0) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && (((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)))){ + a17 = (((((a17 - 0) + -206889) + 16806) % 109)- -2); + a7 = 13; + a5 = 4; + + return -1; + } else if((((((a24==14) && (((a7==12) || (a7==13)) && (input == 3))) && (a5==4)) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 217302) + -351806) / 5); + a17 = ((((((a17 % 71)- -205) * 9)/ 10) * 10)/ 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && ((input == 6) && (((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==5)) || ((((a24==15) && ( 255 < a17 && (a7==14))) && (a5==4)) || (((a24==13) && ( a17 <= -108 && (a7==12))) && (a5==5))))))){ + a17 = ((((a17 + 0) % 299946)+ -300053) - 2); + a7 = 14; + a24 = 14; + a5 = 6; + + return 26; + } else if(((((input == 6) && ((( 255 < a17 && (a7==14)) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14)))) && (a5==7)) && a2 <= 189 )){ + a17 = (((((a17 + 0) - 0) + 0) % 299946)+ -300053); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((((input == 2) && ((a7==13) || (a7==14))) && (a5==4)) && ((111 < a17) && (255 >= a17)) )))){ + a17 = (((a17 - 112842) + -369240) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((a24==15) && (input == 3)) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )) && (a7==12))){ + a17 = (((a17 + 316175) * 1) + 233255); + a24 = 14; + a5 = 4; + + return -1; + } else if((((a5==7) && ((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 6)))) && a2 <= 189 )){ + a17 = (((a17 + -600109) + -1) + -2); + a7 = 12; + a5 = 3; + + return -1; + } else if((((( a17 <= -108 && ((input == 6) && (a5==5))) && (a7==14)) && (a24==15)) && a2 <= 189 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((input == 1) && ((a7==12) || (a7==13)))) && (a24==13))))){ + + a7 = 12; + + return 23; + } else if((((((input == 4) && (( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12)))) && (a24==13)) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 + -427791) / 5) / 5) % 71)+ 182); + a7 = 13; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 + -120881) * 4) * 1); + a17 = (((((a17 % 109)- -2) + -127431) - 362706) + 490136); + a7 = 12; + a5 = 5; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 2) && ((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==3))) && (a24==15))){ + a2 = (((a2 * 5) * -5) - 245970); + a17 = (((((a17 % 299946)+ -300053) + -1) + 161315) - 161314); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && ((input == 6) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))) && (a5==4)))){ + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 3) && (a7==12))) && (a24==13)) && a17 <= -108 ) && (a5==3))){ + a2 = (((a2 + 430380) * 1) / -5); + a17 = (((((a17 * 9)/ 10) % 109)+ 42) - 25); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((((a7==13) && 255 < a17 ) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13))) || ((a24==14) && ((a7==12) && a17 <= -108 ))) && (input == 3))))){ + a2 = (((a2 - -54478) + -529752) + -118732); + a17 = (((a17 / 5) / 5) + -531417); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==13) && ((a5==7) && ((a7==13) && ( a2 <= 189 && ( 255 < a17 && (input == 2))))))){ + a17 = (((a17 - 0) + -600254) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((((((a7==12) || (a7==13)) && (input == 5)) && (a24==15)) && 255 < a17 ) && a2 <= 189 ) && (a5==5))){ + a2 = (((((a2 - -169038) + -8583) + -45242) % 45)+ 234); + a7 = 13; + a24 = 13; + + return 23; + } else if(((a24==15) && ((a5==6) && ( a2 <= 189 && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)))))){ + a17 = ((((a17 % 299946)+ -300053) * 1) - 2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a7==12) && (((input == 2) && ((111 < a17) && (255 >= a17)) ) && (a5==6))) && a2 <= 189 ) && (a24==15))){ + a2 = (((((a2 % 45)- -236) / 5) - -550201) + -549992); + a7 = 14; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && (((a5==4) && (((input == 3) && ((a7==13) || (a7==14))) && ((111 < a17) && (255 >= a17)) )) && (a24==15)))){ + + a7 = 14; + a5 = 5; + + return 23; + } else if(((a7==14) && (((( a2 <= 189 && (input == 2)) && (a24==14)) && (a5==5)) && ((111 < a17) && (255 >= a17)) ))){ + a2 = (((((a2 % 45)- -235) - -1) + 81498) - 81497); + a17 = (((((a17 * 10)/ 4) / 5) * 10)/ 2); + a7 = 12; + a24 = 15; + a5 = 3; + + return 21; + } else if(((a24==13) && ( 255 < a17 && (((a5==5) && (((a7==12) || (a7==13)) && (input == 5))) && a2 <= 189 )))){ + a17 = ((((a17 % 109)+ -14) + -65) - 16); + a7 = 12; + a24 = 15; + a5 = 7; + + return 26; + } else if(( a2 <= 189 && (( ((-108 < a17) && (111 >= a17)) && (((a5==5) && (input == 4)) && (a24==13))) && (a7==14)))){ + a17 = (((((a17 - 567803) % 71)+ 187) - 424769) - -424798); + a24 = 15; + a5 = 6; + + return 23; + } else if(( a2 <= 189 && (((((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==6)))){ + a2 = (((((a2 - -148382) + 15537) - 69273) % 45)+ 235); + a17 = (((a17 - 250975) * 2) - -374533); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && (((a24==14) && (((input == 1) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 )) && (a5==6)))){ + a2 = (((((((a2 * 9)/ 10) % 45)- -234) / 5) * 51)/ 10); + a7 = 13; + a5 = 3; + + return 23; + } else if(( 255 < a17 && (((a5==5) && (((input == 1) && ((a7==12) || (a7==13))) && a2 <= 189 )) && (a24==13)))){ + a17 = ((((a17 / 5) * 10)/ -4) - 18616); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a5==6) && (((((a24==14) && ((a7==12) && a17 <= -108 )) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 3)) && a2 <= 189 ))){ + a2 = (((((a2 * 9)/ 10) % 45)+ 234) + 0); + a17 = (((((a17 * 9)/ 10) % 299946)+ -300053) - 0); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ( a17 <= -108 && ((input == 1) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)))){ + a17 = (((((a17 * 9)/ 10) - -39396) % 109)- -1); + a7 = 12; + a24 = 14; + + return -1; + } else if(((((((a7==12) && (input == 4)) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)) && a2 <= 189 ) && (a24==15))){ + a17 = (((a17 * 5) / 5) - 8323); + a24 = 13; + a5 = 3; + + return -1; + } else if(((( a2 <= 189 && ((a5==6) && ((input == 5) && a17 <= -108 ))) && (a24==13)) && (a7==12))){ + + a5 = 3; + + return -1; + } else if(((((a5==5) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((((a17 % 71)+ 183) * 5) * 5) % 71)- -147); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==12) && a17 <= -108 ) && (a24==14)) || ((( 255 < a17 && (a7==13)) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 1))))){ + a2 = ((((a2 * -5) + 512688) / 5) + -671267); + a17 = (((((a17 % 299946)+ -300053) + -2) - -209672) - 209671); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14)))) && (input == 1)))) && (a24==15))){ + a17 = ((((((a17 * 9)/ 10) % 71)- -182) - -14398) + -14397); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==3) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 4)) && (a24==15))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - 440571) * 10)/ 9) * 1); + a17 = (((a17 / 5) + 199) + -13); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && (((a5==6) && ( a2 <= 189 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5)))) && 255 < a17 ))){ + + a7 = 12; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==5) && ((a24==15) && ((((a7==12) || (a7==13)) && (input == 1)) && a2 <= 189 ))))){ + a17 = ((((a17 - 548709) + 66483) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 4) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (a5==6)) && ((189 < a2) && (281 >= a2)) ) && (a24==13))){ + a17 = ((((a17 * 5) - 44693) % 109)+ 15); + a7 = 14; + a5 = 5; + + return -1; + } else if((((a24==13) && (( ((189 < a2) && (281 >= a2)) && ( a17 <= -108 && (input == 5))) && (a7==12))) && (a5==3))){ + a2 = (((a2 + -572725) + 175794) * 1); + a17 = ((((a17 / 5) % 109)- -105) / 5); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((( a17 <= -108 && (input == 1)) && (a7==14)) && a2 <= 189 ) && (a24==14)) && (a5==5))){ + a2 = ((((a2 / 5) % 45)+ 235) - 1); + a17 = (((((a17 % 109)- -95) - 397967) + 16520) + 381429); + a24 = 13; + a5 = 3; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((a5==6) && (( a2 <= 189 && (input == 4)) && (a24==15)))))){ + a17 = ((((a17 - -175358) * 10)/ -9) * 3); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 5) && a2 <= 189 ) && (a5==5)) && (a24==15)) && (a7==14)) && a17 <= -108 )){ + a2 = (((((a2 + 0) - -533443) / 5) % 45)- -235); + a17 = ((((a17 % 109)+ 56) + 32) - 64); + a7 = 13; + a24 = 14; + a5 = 4; + + return 23; + } else if(((a5==6) && ((a24==14) && ((((input == 4) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )))){ + a2 = ((((a2 % 45)+ 236) * 1) - 2); + a17 = ((((a17 - -285478) - -176297) % 71)+ 120); + a7 = 14; + a5 = 3; + + return 23; + } else if((((a5==3) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 3)) && (a24==15))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) * 5) * 5); + a17 = (((a17 / 5) + 443474) - -14231); + a7 = 13; + a24 = 14; + + return -1; + } else if(((a5==4) && ((a7==12) && ( ((-108 < a17) && (111 >= a17)) && ((a24==15) && ((input == 2) && ((189 < a2) && (281 >= a2)) )))))){ + a2 = ((((a2 - -382813) + -765612) - -535577) * -3); + a17 = ((((a17 - 191016) * 10)/ 9) * 2); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==6)) || ((a5==7) && (( a17 <= -108 && (a7==12)) && (a24==13)))) || ((a5==7) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 2)) && a2 <= 189 )){ + a17 = ((((a17 % 299946)- 300053) * 1) + -1); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if((((a5==3) && ((( ((111 < a17) && (255 >= a17)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ) && (a7==14))) && (a24==15))){ + a2 = ((((a2 - 503628) * 10)/ 9) * 1); + a17 = (((a17 - 141047) * 4) - 9786); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a24==14) && ( a2 <= 189 && ((input == 6) && ((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && (a5==7))){ + a17 = (((((a17 % 109)+ 1) * 5) % 109)- -1); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==7) && (((a24==15) && (((input == 5) && ((a7==13) || (a7==14))) && a2 <= 189 )) && 255 < a17 ))){ + a17 = (((((a17 % 71)+ 138) + 39) - 439359) + 439313); + a7 = 13; + a24 = 14; + + return -1; + } else if(((a5==4) && ((a24==13) && ((((input == 2) && ((a7==12) || (a7==13))) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) )))){ + a2 = (((a2 * 5) - -555151) * -1); + a17 = (((((a17 / 5) - 449993) + 603017) * -1)/ 10); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==6) && ( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && (((a7==13) || (a7==14)) && (input == 2))))) && (a24==15))){ + a2 = ((((((a2 % 45)+ 235) + 1) * 5) % 45)+ 219); + a17 = ((((a17 % 71)+ 184) + 1) + -1); + a7 = 14; + a24 = 13; + a5 = 3; + + return 21; + } else if((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((input == 2) && (a5==5))))) && (a24==13))){ + a17 = (((a17 - 199) + -6) + -5); + a7 = 14; + a5 = 7; + + return 21; + } else if(((a7==13) && (((((input == 4) && (a5==7)) && (a24==14)) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ))){ + a17 = (((a17 - 357382) + -119715) * 1); + a7 = 14; + + return -1; + } else if(((a24==14) && ((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))))))){ + a2 = (((a2 - -271816) / 5) * -5); + a17 = ((((a17 - -250279) + 97462) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 3) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )))) && a2 <= 189 ) && (a5==6)) && (a24==13))){ + a17 = (((((a17 % 299946)- 300053) / 5) / 5) + -264660); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a7==12) && ((a5==5) && ((((input == 1) && (a24==13)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) )))){ + a17 = (((((a17 * -1)/ 10) + 161751) + -250598) + 88873); + a5 = 7; + + return 23; + } else if((((a24==13) && ((((input == 1) && (a5==5)) && ((-108 < a17) && (111 >= a17)) ) && (a7==14))) && a2 <= 189 )){ + a17 = ((((((a17 % 71)- -182) - 0) * 5) % 71)- -178); + a7 = 12; + a24 = 15; + a5 = 6; + + return 26; + } else if((((a5==3) && ( a17 <= -108 && (((a24==13) && (input == 4)) && ((189 < a2) && (281 >= a2)) ))) && (a7==12))){ + a2 = (((a2 * -5) * 5) / 5); + a24 = 14; + a5 = 5; + + return 23; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 4)))) && (a24==14))){ + a17 = (((((a17 % 109)+ 2) - 348657) + -227996) - -576653); + a7 = 14; + + return -1; + } else if(((a24==14) && ((a5==4) && (( ((-108 < a17) && (111 >= a17)) && ((input == 3) && (a7==13))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 / -5) - -389340) * -1); + a17 = (((((a17 + 69965) + -188133) + -248443) * -1)/ 10); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a7==13) && ((a24==15) && ( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==4) && (input == 3))))))){ + a2 = (((a2 * -5) - 523034) * 1); + a17 = ((((((a17 % 71)+ 184) + 138561) * 4) % 71)+ 151); + a24 = 13; + a5 = 7; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (((((a7==13) || (a7==14)) && (input == 2)) && (a5==6)) && (a24==15))))){ + a2 = ((((((a2 - 0) % 45)+ 236) * 5) % 45)+ 213); + a17 = (((a17 - -31328) * 5) * 3); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==7) && ( a2 <= 189 && ((a24==13) && ((input == 3) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))))))){ + a17 = ((((((a17 % 109)- 13) * 5) + -231249) % 109)- -55); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==6) && ( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 5))))))){ + a17 = (((((a17 % 71)+ 184) * 1) / 5) + 111); + a7 = 12; + a24 = 13; + a5 = 7; + + return 23; + } else if(((a5==5) && ( ((-108 < a17) && (111 >= a17)) && ((((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a24==14)) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -234) * 1) + -304708) - -304710); + a7 = 13; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==14) && ((((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==6)) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -236) - -1) / 5) + 208); + a17 = (((((a17 + -583311) / 5) * 5) % 71)- -225); + a7 = 14; + a24 = 15; + a5 = 3; + + return 23; + } else if(((a24==14) && ((a5==4) && (((((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) * 5) - 372070); + a17 = ((((a17 % 71)+ 123) - -13742) + -13696); + a7 = 14; + a24 = 15; + + return 21; + } else if((((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((input == 1) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))))) && (a24==15))){ + a2 = ((((a2 - 67499) * 5) * 10)/ 9); + a17 = ((((((a17 % 71)+ 183) * 5) * 5) % 71)- -126); + a7 = 12; + a5 = 5; + + return 21; + } else if(((((a24==13) && ((input == 1) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 0) % 109)+ 2) + 1); + a7 = 13; + a5 = 3; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 6) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))))) && a2 <= 189 ))){ + a2 = ((((a2 / 5) - -545601) % 45)+ 203); + a17 = ((((a17 % 109)- -2) + 1) + -2); + a7 = 13; + + return 23; + } else if(((a5==4) && ((((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))))) && ((189 < a2) && (281 >= a2)) ) && (a24==13)))){ + a17 = (((((a17 % 71)- -182) - -29808) + -229764) + 199957); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==5) && ((( ((189 < a2) && (281 >= a2)) && (input == 6)) && (a24==13)) && ((-108 < a17) && (111 >= a17)) )) && (a7==13))){ + a2 = ((((a2 - -93069) / 5) * 5) - 656223); + a17 = (((a17 + -400644) - 189700) - 2801); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a7==14) && (((input == 1) && a2 <= 189 ) && (a5==5))) && (a24==15)) && a17 <= -108 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((input == 4) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)))) && (a7==13))){ + + return 26; + } else if(((((((input == 5) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && (a24==15)) && (a5==5)) && 255 < a17 )){ + a2 = (((a2 + -1933) * 5) + -538505); + a7 = 13; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((((a5==3) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 % 71)+ 182) + -10) + 11); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a5==6) && (((((input == 5) && (a7==12)) && (a24==15)) && a2 <= 189 ) && a17 <= -108 ))){ + a2 = ((((a2 % 45)- -235) + 1) + -2); + a7 = 13; + a24 = 14; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && (((input == 5) && (((a24==13) && ( 255 < a17 && (a7==14))) || (( a17 <= -108 && (a7==12)) && (a24==14)))) && (a5==7)))){ + a17 = (((((a17 % 109)- -2) + 1) - -372693) - 372693); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((a24==14) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3))) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 * 5) + -72167) * 5); + a17 = ((((a17 + -186071) + -206980) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((((((a24==13) && ((input == 6) && ((a7==12) || (a7==13)))) && 255 < a17 ) && (a5==5)) && a2 <= 189 )){ + a17 = (((a17 + -600164) * 1) + -53); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==13) && ( 255 < a17 && (((a7==13) && ((input == 4) && (a5==7))) && a2 <= 189 )))){ + a17 = (((((a17 - 0) - 0) + 0) % 71)- -150); + a5 = 5; + + return -1; + } else if(( a2 <= 189 && ((((a24==15) && (((a7==13) || (a7==14)) && (input == 2))) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)))){ + a17 = (((a17 - 164414) - 174884) + -159208); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((a24==14) && (((a7==12) || (a7==13)) && (input == 1))) && a17 <= -108 )) && (a5==4))){ + a2 = (((a2 / 5) * 5) / -5); + a7 = 12; + a24 = 15; + a5 = 5; + + return -1; + } else if((((a24==15) && ( 255 < a17 && ((a5==7) && (((a7==13) || (a7==14)) && (input == 2))))) && a2 <= 189 )){ + a17 = (((a17 - 600173) / 5) * 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && (( 255 < a17 && ( a2 <= 189 && ((input == 3) && ((a7==12) || (a7==13))))) && (a24==15)))){ + + a7 = 13; + a5 = 5; + + return 23; + } else if((( a17 <= -108 && ((a24==15) && ( a2 <= 189 && ((a5==6) && (input == 3))))) && (a7==12))){ + a17 = ((((a17 % 109)- -35) - 26) / 5); + a5 = 4; + + return 21; + } else if(((a24==15) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 4)))))){ + a17 = ((((a17 - 384201) % 109)+ 1) + 2); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && ((a5==6) && ((a24==13) && ((input == 6) && (a7==12))))) && a2 <= 189 )){ + a2 = ((((((a2 * 9)/ 10) * 1) - -556567) % 45)+ 231); + a17 = ((((a17 % 109)+ 37) + 6) - 19); + a7 = 13; + a24 = 15; + a5 = 5; + + return 23; + } else if(((a5==3) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 3)) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a17 = (((((a17 % 109)+ 3) + -50) - -516936) + -516973); + a7 = 12; + a24 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (( ((-108 < a17) && (111 >= a17)) && (((a7==12) || (a7==13)) && (input == 6))) && (a5==3))) && (a24==13))){ + a2 = (((a2 + -109630) - 123244) - 219626); + a17 = ((((a17 + -100817) * 5) * 10)/ 9); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==13) && ((a5==5) && ( ((-108 < a17) && (111 >= a17)) && (((input == 1) && (a7==14)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = (((a17 + 526530) + 65040) + 5305); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && (( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))))))){ + a2 = (((a2 * 5) / 5) / -5); + a17 = (((a17 - 0) - 600110) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (( a17 <= -108 && ((input == 2) && (a7==12))) && (a5==6))) && (a24==13))){ + + a5 = 3; + + return -1; + } else if(((((a24==15) && ( a2 <= 189 && ((input == 2) && ((a7==12) || (a7==13))))) && 255 < a17 ) && (a5==5))){ + a17 = ((((a17 + 0) / 5) * 4) + -576078); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && ((((input == 2) && (((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && a2 <= 189 ) && (a24==13)))){ + a17 = (((((a17 + -600111) + -1) * 9)/ 10) + -11291); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((input == 4) && (((((a7==13) && 255 < a17 ) && (a24==14)) || (( 255 < a17 && (a7==14)) && (a24==14))) || ((a24==15) && ((a7==12) && a17 <= -108 ))))))){ + a17 = (((((a17 * 9)/ 10) % 71)- -184) - 2); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if((((a24==14) && ( a2 <= 189 && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 3)))) && (a5==7))){ + a17 = ((((a17 % 109)+ 1) - -2) - 1); + a7 = 12; + + return -1; + } else if((((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) && (input == 2)) && a2 <= 189 ) && (a24==14)) && (a5==7))){ + a17 = (((a17 - 600111) - 1) - 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==5) && (( a2 <= 189 && ((input == 3) && (a7==14))) && a17 <= -108 )))){ + a2 = ((((a2 % 45)+ 236) - -1) * 1); + a24 = 13; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && ((a5==7) && ((a24==13) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 5)))))){ + a17 = ((((((a17 % 71)+ 166) * 9)/ 10) * 9)/ 10); + a7 = 13; + + return -1; + } else if((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && (((input == 1) && (a7==13)) && (a24==13)))) && (a5==5))){ + + a5 = 7; + + return 26; + } else if((((a24==13) && ((a5==5) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))) && 255 < a17 )){ + + a7 = 13; + + return 23; + } else if(( a2 <= 189 && ((a24==13) && ((a5==5) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (input == 5)))))){ + a17 = ((((a17 * 9)/ 10) - 5211) + 549653); + a7 = 13; + a24 = 14; + a5 = 6; + + return 26; + } else if((( ((111 < a17) && (255 >= a17)) && ((a5==5) && ((a7==14) && ((input == 6) && (a24==13))))) && a2 <= 189 )){ + a17 = ((((a17 + 372015) + -372184) + 315921) + -315903); + a24 = 14; + a5 = 7; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a5==4) && ((input == 3) && ((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))))))){ + a2 = (((a2 * 5) - 399704) * 1); + a17 = (((((a17 % 299946)- 300053) + -1) - -345280) - 345280); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))) && (a5==5))){ + a2 = ((((a2 * -5) * 5) - -579500) * -1); + a17 = (((a17 / 5) - 391832) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (input == 2)) && (a5==3))))){ + a2 = (((a2 + -106788) * 5) * 1); + a17 = ((((a17 + 74148) + 98517) % 109)- 1); + a7 = 13; + a24 = 13; + a5 = 4; + + return -1; + } else if((((a5==5) && ((((input == 3) && ((-108 < a17) && (111 >= a17)) ) && (a7==14)) && (a24==13))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) - 597366) + -852); + a17 = (((a17 - 484669) + -100380) - 5769); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a5==7) && (((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (a24==13))) && a2 <= 189 )){ + a17 = ((((a17 % 109)- -2) / 5) / 5); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(((a5==6) && ((a24==14) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && 255 < a17 ) && a2 <= 189 )))){ + a2 = ((((a2 - -292946) + -155034) % 45)+ 234); + a17 = (((((a17 % 109)+ -95) - -473885) * 1) - 473817); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if(((a24==14) && (((a5==5) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 3)))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 + -251055) % 71)+ 183) + 492006) + -492005); + a7 = 12; + + return -1; + } else if((( 255 < a17 && ((((input == 2) && (a7==14)) && a2 <= 189 ) && (a5==5))) && (a24==15))){ + a17 = ((((a17 / 5) * 4) * -6)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && (((a7==13) && ( 255 < a17 && ((a24==15) && (input == 3)))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 % 109)- 46) - 573448) + 573425); + a24 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((a5==3) && ((input == 3) && (a24==15))) && (a7==14))) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 - 230215) / 5) + -123947); + a17 = ((((a17 / 5) * 10)/ -2) * 5); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((( ((111 < a17) && (255 >= a17)) && ((input == 4) && ((a7==12) || (a7==13)))) && (a5==4)) && (a24==13)))){ + a2 = ((((a2 * -5) * 10)/ 9) * 5); + a17 = (((a17 * 5) * 5) / 5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((( 255 < a17 && ( a2 <= 189 && ((input == 4) && ((a7==12) || (a7==13))))) && (a5==4)) && (a24==15))){ + a17 = ((((((a17 % 71)+ 177) * 9)/ 10) + -198267) + 198271); + a7 = 12; + a24 = 13; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((input == 3) && (((a5==7) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==6)) || ((a5==7) && ((a24==13) && ( a17 <= -108 && (a7==12))))))))){ + a2 = (((((a2 % 45)+ 235) - -2) - 281898) - -281896); + a17 = (((((a17 * 9)/ 10) % 299946)- 300053) - 2); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((((a5==6) && ((((a7==13) || (a7==14)) && (input == 1)) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 ) && (a24==15))){ + a2 = ((((a2 + 0) % 45)- -235) + -1); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if((((a5==6) && (((a24==14) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 4))) && 255 < a17 )) && a2 <= 189 )){ + a2 = (((((a2 - 0) % 45)+ 236) + 67568) - 67569); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if((((((a24==15) && ((input == 3) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 ) && (a5==6)) && (a7==12))){ + + return 23; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 2))))) && (a5==4))){ + a2 = (((a2 - 517350) / 5) + -227328); + a17 = ((((a17 * 9)/ 10) + -544188) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==5) && (((a7==12) || (a7==13)) && (input == 1))) && (a24==14)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((((a2 % 45)- -236) * 5) % 45)- -234); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a24==14) && (( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 1)) && (a5==4))) && 255 < a17 ))){ + a17 = ((((((a17 % 71)+ 148) * 9)/ 10) * 9)/ 10); + a7 = 14; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )))) && (a5==4)) && (a24==13)))){ + a2 = (((a2 - 478599) * 1) * 1); + a17 = ((((a17 / 5) / 5) / 5) + -495670); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 3) && ((a7==12) || (a7==13))) && (a24==13)) && (a5==3))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + -578339) + -2272); + a17 = ((((a17 % 71)+ 183) + 2) - 1); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a5==7) && (((input == 5) && ((((a24==14) && ( 255 < a17 && (a7==13))) || ((a24==14) && ((a7==14) && 255 < a17 ))) || (( a17 <= -108 && (a7==12)) && (a24==15)))) && a2 <= 189 ))){ + a17 = (((((a17 * 9)/ 10) % 109)- -2) + -1); + a7 = 14; + a24 = 14; + + return -1; + } else if(((a5==4) && ( a17 <= -108 && ((((input == 3) && (a24==13)) && (a7==12)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 + -508787) / 5) * 10)/ 9); + a17 = (((((a17 + 0) % 71)+ 254) * 9)/ 10); + a24 = 15; + + return -1; + } else if((( a17 <= -108 && (((a5==6) && ((input == 5) && ((a7==13) || (a7==14)))) && (a24==14))) && a2 <= 189 )){ + a2 = ((((((a2 % 45)+ 236) - 1) / 5) * 51)/ 10); + a17 = ((((a17 % 109)- -32) + -26) - -40); + a7 = 14; + a5 = 3; + + return 23; + } else if((((a24==13) && (((input == 3) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && ((189 < a2) && (281 >= a2)) )) && (a5==3))){ + a17 = (((((a17 % 109)+ 1) + 536699) + 4168) - 540865); + a7 = 13; + + return -1; + } else if((((a24==13) && ((((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ( 255 < a17 && (a7==12))) && (input == 1)) && ((189 < a2) && (281 >= a2)) )) && (a5==3))){ + a2 = (((a2 * 5) / -5) - 131726); + a17 = (((((a17 / 5) / 5) - 197914) % 109)+ 43); + a7 = 13; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a24==13) && ( a17 <= -108 && (((a5==6) && (((a7==12) || (a7==13)) && (input == 2))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + 123909) - 483346) - 41719); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==3) && ((a24==14) && ((input == 5) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - -143250) / -5) * 10)/ 9); + a17 = ((((a17 % 71)+ 183) / 5) + 104); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (((a7==12) && ( ((189 < a2) && (281 >= a2)) && ((a24==15) && (input == 2)))) && (a5==5)))){ + a2 = (((a2 + -139817) - 311967) / 5); + a17 = (((a17 - 584030) / 5) / 5); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==6) && (((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 4)) && a2 <= 189 )))){ + a2 = (((((a2 * 9)/ 10) % 45)- -236) + -2); + a17 = ((((a17 % 71)+ 183) + 2) + -3); + a7 = 14; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==15) && ((a5==4) && ((((a7==13) || (a7==14)) && (input == 3)) && a2 <= 189 ))))){ + a17 = ((((a17 + -240122) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 5; + + return 26; + } else if(( a2 <= 189 && ((a5==6) && ( a17 <= -108 && ((a24==14) && (((a7==13) || (a7==14)) && (input == 6))))))){ + a2 = (((((a2 % 45)- -236) - -1) - -152243) - 152245); + a7 = 12; + a5 = 3; + + return 26; + } else if(((a5==6) && (((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 4))) && a2 <= 189 ))){ + a2 = (((((a2 % 45)+ 236) - -249333) - 625277) - -375944); + a17 = ((((((a17 % 109)- -1) - 100) * 5) % 109)+ 2); + a7 = 13; + a5 = 4; + + return 26; + } else if((((((( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 2)) && (a5==6)) && a2 <= 189 ) && (a24==13))){ + a2 = (((((a2 % 45)- -234) + -442292) - -617405) - 175110); + a17 = ((((((a17 * 9)/ 10) % 71)- -115) / 5) - -197); + a7 = 13; + a24 = 14; + a5 = 3; + + return 21; + } else if((( a2 <= 189 && ((((a7==14) && (input == 4)) && (a5==5)) && (a24==14))) && a17 <= -108 )){ + a2 = ((((a2 % 45)+ 235) - 1) + 2); + a17 = ((((a17 % 109)+ 8) - 7) - -91); + a7 = 13; + a24 = 13; + a5 = 3; + + return 26; + } else if((( a2 <= 189 && ((a24==14) && ((input == 4) && (((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && (a5==7))){ + a17 = ((((a17 - 363253) / 5) + -406812) + 479520); + a7 = 13; + + return -1; + } else if((( a2 <= 189 && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && (a24==14)) && (a5==5))) && 255 < a17 )){ + a17 = (((((a17 * 9)/ 10) / 5) * 10)/ -4); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==7) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && a2 <= 189 ) && (a24==15)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 / 5) + -515705) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( a17 <= -108 && ((a5==5) && ((input == 2) && (a24==14)))) && (a7==14)) && a2 <= 189 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ( ((-108 < a17) && (111 >= a17)) && ((a5==6) && ((((a7==14) || ((a7==12) || (a7==13))) && (input == 3)) && (a24==14)))))){ + a2 = (((((a2 + 0) / 5) * 4) % 45)+ 234); + a7 = 12; + a5 = 3; + + return 26; + } else if((((a24==15) && ((((input == 2) && a2 <= 189 ) && (a7==12)) && (a5==7))) && 255 < a17 )){ + a17 = ((((a17 - 570713) - 29535) / 5) - 458064); + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==5) && (((input == 3) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && a2 <= 189 )) && (a24==15))){ + a2 = ((((((a2 * 9)/ 10) * 1) - 13827) % 45)+ 249); + a17 = ((((a17 % 109)+ 1) - -2) + -2); + a7 = 14; + a5 = 4; + + return 26; + } else if((((a24==15) && ( a2 <= 189 && ((input == 4) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))))) && (a5==5))){ + a2 = (((((a2 % 45)- -235) - 195114) - 258356) - -453470); + a17 = (((((a17 + 155793) % 109)- 63) + 567392) - 567346); + a7 = 13; + a5 = 4; + + return 23; + } else if((((a24==14) && ((a5==4) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - -528091) - 699874) + 649609) + -972756); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( 255 < a17 && ((a24==15) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ))) && (a5==3))){ + a2 = (((a2 / -5) - 163348) + 56585); + a7 = 14; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==15) && ((input == 5) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))))))))){ + a2 = (((a2 / -5) + -568912) + -5609); + a17 = (((((a17 % 71)+ 184) + -1) / 5) - -182); + a7 = 12; + a5 = 4; + + return 23; + } else if(((a24==13) && ((((input == 1) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - 161488) * 3) + 590787) + -671028); + a17 = ((((a17 - 600109) + 22162) + -18521) - 3641); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==6) && (((a24==14) && (((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 )) && 255 < a17 ))){ + + a7 = 14; + + return 26; + } else if((((((input == 6) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 - 579407) - 8118) * 1); + a17 = (((((a17 % 109)+ 3) + -458073) + 848155) + -390111); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==4)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5))) || ((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==5))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 299872)- -300127) - -1) + 0); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && ((( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (input == 5))) && (a24==13)) && (a7==13)))){ + a17 = (((a17 + -452489) * 1) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((a5==7) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 4)))) && (a24==13))){ + a17 = ((((a17 % 109)- -1) / 5) / 5); + a7 = 12; + a24 = 15; + a5 = 4; + + return 21; + } else if((((a24==13) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && (a5==5))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / 5) + -341809) * 10)/ 9); + a17 = (((((a17 % 299872)- -300127) - 515739) + 17318) - -498422); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((((a24==15) && ((((a7==13) || (a7==14)) && (input == 3)) && a2 <= 189 )) && (a5==7)) && ((-108 < a17) && (111 >= a17)) )){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((a7==12) && (( a2 <= 189 && (((input == 5) && (a5==4)) && (a24==15))) && ((-108 < a17) && (111 >= a17)) ))){ + a17 = (((a17 - 277016) * 2) + -6397); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && (((((a24==15) && ( a17 <= -108 && (a7==12))) || (((a24==14) && ((a7==13) && 255 < a17 )) || ((a24==14) && ( 255 < a17 && (a7==14))))) && (input == 1)) && a2 <= 189 ))){ + a17 = ((((a17 % 299872)- -300127) + 1) + 0); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && (((a5==5) && ((a24==15) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13)))))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && (((((a24==14) && ( a17 <= -108 && (a7==13))) || (((a24==13) && ((a7==14) && 255 < a17 )) || ((a24==14) && ((a7==12) && a17 <= -108 )))) && (input == 4)) && a2 <= 189 ))){ + a17 = ((((a17 + 0) - 0) / 5) + -383300); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (input == 5)) && (a24==15)) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 219315) + -185024) / 5); + a17 = ((((a17 + -245709) % 71)- -191) * 1); + a7 = 13; + a24 = 13; + + return -1; + } else if((((a5==6) && ((a24==13) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 2)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) / 5) + -556465); + a17 = (((a17 / 5) + -548457) + -1247); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && (((((input == 5) && (a5==7)) && a2 <= 189 ) && 255 < a17 ) && (a7==12)))){ + a17 = ((((((a17 * 9)/ 10) * 1) - 509339) % 71)+ 183); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==7) && (((input == 2) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && a2 <= 189 )) && (a24==13))){ + a2 = ((((((a2 % 45)+ 236) * 5) - -150446) % 45)- -205); + a17 = ((((a17 + -490890) / 5) + -314798) + 884206); + a7 = 14; + a24 = 14; + a5 = 3; + + return 23; + } else if((( 255 < a17 && (( a2 <= 189 && ((a24==15) && (input == 6))) && (a5==5))) && (a7==14))){ + a2 = (((((a2 * 9)/ 10) % 45)- -234) + 2); + a17 = (((((a17 / 5) + 157023) - 304246) % 109)+ 90); + a7 = 13; + a24 = 14; + + return 23; + } else if(((((a5==6) && (((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 2))) && a2 <= 189 ) && (a24==13))){ + a17 = ((((a17 % 299946)- 300053) * 1) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==6) && ((((input == 2) && ((a7==14) || ((a7==12) || (a7==13)))) && a2 <= 189 ) && (a24==14))))){ + a2 = (((((a2 + 0) * 9)/ 10) % 45)- -236); + a17 = ((((a17 + -217095) - -761433) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 4; + + return 21; + } else if(( a2 <= 189 && (((a7==14) && (((input == 1) && ((111 < a17) && (255 >= a17)) ) && (a5==5))) && (a24==14)))){ + a2 = ((((a2 % 45)- -234) - 10732) - -10732); + a24 = 15; + a5 = 3; + + return 26; + } else if(( a17 <= -108 && ((( ((189 < a2) && (281 >= a2)) && ((a5==3) && (input == 1))) && (a7==12)) && (a24==13)))){ + a2 = (((a2 + -187375) * 3) - -239890); + a17 = ((((((a17 % 71)- -216) * 9)/ 10) * 10)/ 9); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if(((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 1)) && (a5==5)) && (a24==14)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 309533) % 299872)- -300127) * 1); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 4)) && (a24==13))) && (a5==3))){ + a2 = (((a2 / 5) / 5) + -113113); + a17 = ((((a17 + -152498) - 120570) * 10)/ 9); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((((( 255 < a17 && (a7==13)) && (a24==13)) || (( 255 < a17 && (a7==14)) && (a24==13))) || (((a7==12) && a17 <= -108 ) && (a24==14))) && (input == 4))))){ + a2 = (((a2 + -277502) * 2) - 40398); + a17 = ((((a17 + 0) / 5) + 23146) - 484422); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==13) && ((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 ))))))){ + a2 = (((a2 / 5) / -5) - 183721); + a17 = ((((a17 % 109)+ -83) + -12) + 78); + a7 = 13; + a24 = 14; + a5 = 5; + + return 26; + } else if((((((input == 3) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a24==13)) && (a5==6)) && a2 <= 189 )){ + a2 = ((((a2 + 0) % 45)- -234) * 1); + a17 = (((((a17 * 9)/ 10) * 1) % 71)- -138); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a5==4) && (((input == 5) && ((a7==12) || (a7==13))) && ((111 < a17) && (255 >= a17)) ))))){ + + a7 = 13; + + return -1; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((input == 4) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))))) && (a24==13)))){ + a2 = (((a2 * 5) * 5) + -590870); + a17 = ((((a17 + 439473) + -202777) % 299946)+ -300053); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && (( 255 < a17 && ((a5==5) && ((input == 3) && (((a7==12) || (a7==13)) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - -345840) * 1) * -1); + a17 = ((((a17 % 109)- 50) - 15) / 5); + a7 = 13; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==7))) && (a24==15)))){ + a17 = ((((a17 / 5) + -289356) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ((a24==13) && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14)))) && (input == 6)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = (((((a17 % 299872)- -300127) / 5) / 5) - -212547); + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && ((a24==15) && ((((a7==13) || (a7==14)) && (input == 6)) && (a5==6)))))){ + a2 = ((((a2 % 45)+ 234) / 5) - -178); + a7 = 14; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && (((((a24==15) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && (a7==13)))){ + a2 = (((a2 + -185317) * 3) * 1); + a17 = (((a17 - -209383) / 5) + -402688); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==4) && ((a24==13) && ((input == 4) && a17 <= -108 ))) && (a7==12)) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 + -340540) + -216382) - -1035898) * -1); + a17 = ((((a17 % 299872)- -300127) - 43079) + 207436); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && (((input == 1) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (a24==14))))){ + a2 = (((a2 * 5) * 5) - 195095); + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 109)+ 2); + a7 = 13; + a5 = 5; + + return 26; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((((a7==12) || (a7==13)) && (input == 4)) && a17 <= -108 )) && (a24==14)))){ + + a7 = 12; + + return -1; + } else if(( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((a5==4) && ((a24==15) && (input == 4))))))){ + a17 = ((((a17 * 5) * 5) * 10)/ -9); + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (( ((-108 < a17) && (111 >= a17)) && ((a7==13) && ((input == 6) && (a5==3)))) && (a24==15)))){ + a2 = (((a2 + 505188) / 5) - 263894); + a17 = (((((a17 % 71)- -182) + 569253) * 1) + -569250); + a7 = 12; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((input == 6) && ((((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==6)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==7))) || (((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==7)))))){ + a2 = (((((a2 % 45)- -236) + -2) / 5) - -177); + a17 = ((((a17 % 299872)- -300127) / 5) - -33046); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if(((( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((a7==13) || (a7==14))) && (a24==14))) && 255 < a17 ) && (a5==4))){ + + a7 = 12; + a24 = 13; + + return -1; + } else if(((a5==6) && ((a24==15) && (((a7==13) && ((input == 6) && a17 <= -108 )) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -235) + 573332) * 1) + -573331); + a17 = ((((a17 % 109)- -40) - 575414) + 575451); + a7 = 14; + a24 = 13; + a5 = 4; + + return 23; + } else if(((a24==15) && ((a5==4) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 4)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) + -205527) + -261072); + a17 = ((((a17 * 5) + 376065) % 71)+ 172); + a7 = 12; + a5 = 5; + + return 21; + } else if((( a2 <= 189 && ((((( 255 < a17 && (a7==13)) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13))) || ((a24==14) && ( a17 <= -108 && (a7==12)))) && (input == 1))) && (a5==6))){ + a2 = ((((a2 % 45)- -235) / 5) * 5); + a17 = (((((a17 * 9)/ 10) % 299946)- 300053) - 1); + a7 = 12; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a7==14) && ((a24==15) && ((((input == 6) && ((111 < a17) && (255 >= a17)) ) && ((189 < a2) && (281 >= a2)) ) && (a5==3))))){ + a17 = (((a17 + -508114) * 1) - 7160); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==5) && (( a2 <= 189 && ((input == 5) && (a7==14))) && 255 < a17 )) && (a24==15))){ + a2 = ((((a2 - 0) / 5) % 45)- -236); + a17 = (((a17 - 600247) * 1) * 1); + a7 = 12; + a24 = 14; + + return 21; + } else if(((((a24==13) && ((input == 6) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))) && ((189 < a2) && (281 >= a2)) ) && (a5==6))){ + a17 = (((((a17 / 5) - -11) * 5) % 109)+ 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((input == 3) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - 251250) * 10)/ 9) + -123956); + a17 = ((((a17 + -55926) + -49743) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==13) && ((a5==6) && ((((input == 2) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13))))){ + a2 = ((((a2 + -73789) * 10)/ 9) - 475570); + a17 = (((a17 + -600188) - 1) + -26); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((((((a7==13) || (a7==14)) && (input == 4)) && a2 <= 189 ) && (a24==15)) && (a5==4)))){ + + a7 = 13; + a5 = 5; + + return 21; + } + return calculate_output3(input); + } + + int calculate_output3(int input) { + + + if(( a2 <= 189 && ((a24==15) && ((a7==14) && ((a5==5) && ( a17 <= -108 && (input == 2))))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==13) || (a7==14)))))) && (a5==5))){ + a2 = (((a2 / 5) * -5) / 5); + a17 = ((((a17 + 77227) + 218385) - 579561) - -466982); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a2 <= 189 && ((a7==14) && ((a24==13) && (input == 4))))) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 + -361852) * 1) / 5) - -72429); + a7 = 13; + a24 = 14; + a5 = 7; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((a7==13) && ((a5==3) && (input == 3))) && (a24==15)) && ((-108 < a17) && (111 >= a17)) ))){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))) && (input == 1)) && a2 <= 189 ) && (a5==7)) && (a24==13))){ + a2 = ((((a2 - -278577) * 1) % 45)- -234); + a17 = ((((a17 / 5) % 109)- -2) - 1); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==13) && (((a5==3) && ((input == 2) && ((a7==12) || (a7==13)))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + 542429) / -5) + -452431); + a17 = (((((a17 + -62715) % 71)- -200) * 9)/ 10); + a7 = 14; + + return -1; + } else if(((((a5==5) && ((((a7==12) || (a7==13)) && (input == 5)) && (a24==14))) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + a17 = ((((a17 * 5) / 5) * 10)/ -9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 1)) && (a5==4)))))){ + a2 = ((((a2 + -345206) - -753451) / 5) * -5); + a17 = ((((a17 % 109)- 98) - 8) + 96); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(( 255 < a17 && (((a24==14) && ((a5==5) && ((input == 1) && ((a7==13) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * 5) + 150678) + -312416); + a17 = (((((a17 + 0) + 0) / 5) % 71)+ 147); + a7 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==5))){ + a2 = (((a2 + -439935) * 1) * 1); + a17 = (((a17 - 581561) + -18563) - 36); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((input == 2) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && (a5==7))) && (a24==14))){ + a17 = (((a17 - 547158) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && ((a24==14) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) || ( 255 < a17 && (a7==13)))))))){ + a2 = (((a2 * -5) * 5) - 267645); + a17 = ((((((a17 * 9)/ 10) % 71)+ 146) - 7467) - -7498); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if((((a5==5) && (( a2 <= 189 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==14))) && 255 < a17 )){ + a17 = (((a17 + -600255) + -1) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==6) && (( ((189 < a2) && (281 >= a2)) && ((input == 5) && (a7==14))) && a17 <= -108 )) && (a24==13))){ + a17 = ((((((a17 % 109)- -39) * 5) - 208544) % 109)+ 56); + a5 = 3; + + return -1; + } else if(((a7==14) && ( ((189 < a2) && (281 >= a2)) && ((( a17 <= -108 && (input == 3)) && (a24==13)) && (a5==6))))){ + a2 = (((a2 + -369894) + -119659) - 59892); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a7==14) && (((a5==5) && ((input == 1) && (a24==13))) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )){ + a17 = (((((a17 * 10)/ -9) - -538584) * 1) - 852442); + a7 = 12; + a24 = 15; + a5 = 7; + + return 23; + } else if((( a2 <= 189 && ((((input == 3) && ((a7==12) || (a7==13))) && (a5==6)) && 255 < a17 )) && (a24==15))){ + a2 = ((((a2 - 0) % 45)+ 235) + 1); + a17 = ((((a17 - 0) % 109)- 13) - -1); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if((((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 2)))) && (a5==4))){ + a2 = (((a2 * 5) / -5) * 5); + a17 = (((a17 + -600110) * 1) + -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((((a24==14) && ( 255 < a17 && (a7==14))) || ((a24==15) && ( a17 <= -108 && (a7==12)))) && (input == 5)) && (a5==3)))){ + a2 = (((a2 * -5) - 176348) - 175983); + a17 = ((((a17 % 71)- -182) + 3) - 3); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && 255 < a17 ) && a2 <= 189 ) && (a24==14)) && (a5==5))){ + a2 = (((((a2 + 252809) % 45)+ 234) - -188524) + -188523); + a17 = ((((((a17 / 5) % 109)+ 1) * 5) % 109)+ 3); + a7 = 14; + a24 = 13; + a5 = 4; + + return 21; + } else if(( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && ((a7==13) && ((input == 3) && (a5==7))))))){ + a17 = (((a17 - 479950) * 1) / 5); + a7 = 12; + + return -1; + } else if((((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (input == 1)) && a2 <= 189 ) && (a5==5)) && (a24==13))){ + a17 = ((((a17 - -331363) % 109)- -1) + 0); + a7 = 12; + a24 = 14; + a5 = 6; + + return 21; + } else if((( 255 < a17 && (( ((189 < a2) && (281 >= a2)) && ((input == 4) && (((a7==12) || (a7==13)) || (a7==14)))) && (a24==15))) && (a5==3))){ + a2 = ((((a2 * 5) / 5) - -456557) * -1); + a17 = (((a17 / 5) * 4) + -534343); + a7 = 13; + a24 = 13; + + return -1; + } else if((((a24==15) && (((input == 2) && (( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && a2 <= 189 )) && (a5==6))){ + a17 = ((((a17 % 299946)- 300053) / 5) + -177770); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && (((a24==15) && (((input == 4) && ((a7==13) || (a7==14))) && (a5==7))) && 255 < a17 ))){ + + a7 = 13; + a24 = 13; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((( 255 < a17 && (a7==14)) && (a24==14)) || ((a24==15) && ( a17 <= -108 && (a7==12)))))))){ + a17 = (((((a17 % 299872)+ 300127) + 0) + -528429) + 528430); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a24==14) && ((a5==4) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 1)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -412962) - 162289) + -93); + a17 = ((((a17 + 200708) / 5) - -224575) + -264525); + a7 = 13; + a24 = 15; + + return 21; + } else if(( 255 < a17 && ((a5==4) && ((((a7==13) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))))){ + a2 = ((((a2 + 17174) - -390384) * 1) * -1); + a17 = (((a17 + -200385) - 399757) + -108); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==5) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 / 5) / 5) * 5); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((a5==6) && (((input == 1) && ((a7==13) || (a7==14))) && ((-108 < a17) && (111 >= a17)) ))))){ + a2 = ((((a2 % 45)- -236) + 1) - 2); + a17 = ((((a17 * 5) % 71)- -183) + -1); + a7 = 14; + a24 = 14; + a5 = 3; + + return 21; + } else if((((a24==13) && (((input == 5) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && a2 <= 189 )) && (a5==6))){ + a2 = ((((a2 % 45)+ 235) - 1) + 1); + a17 = ((((a17 - 0) % 299872)- -300127) * 1); + a7 = 13; + a24 = 15; + a5 = 5; + + return 26; + } else if((((((a24==14) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 1))) && a2 <= 189 ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = ((((a2 % 45)+ 234) + 293810) + -293808); + a7 = 12; + a5 = 3; + + return 23; + } else if(((((((a24==15) && (input == 1)) && (a5==4)) && (a7==12)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + + a7 = 14; + a24 = 14; + a5 = 5; + + return 23; + } else if(((a5==5) && ( ((-108 < a17) && (111 >= a17)) && ((((input == 5) && ((a7==12) || (a7==13))) && a2 <= 189 ) && (a24==15))))){ + a2 = (((((a2 % 45)+ 236) - 49315) / 5) + 10068); + a17 = (((a17 + -103117) / 5) - 439137); + a7 = 13; + a5 = 4; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a5==4) && ( ((111 < a17) && (255 >= a17)) && ((input == 3) && ((a7==12) || (a7==13)))))))){ + a2 = ((((a2 * -5) - 314138) - -565933) + -292419); + a17 = (((a17 + -173172) + -177178) * 1); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if((((a5==3) && (((( a17 <= -108 && (a7==12)) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 2))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -532738) + -47238) * 1); + a17 = (((((a17 + 0) * 9)/ 10) % 71)- -182); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((a5==6) && ((a24==13) && (((input == 4) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && a2 <= 189 )))){ + a17 = ((((a17 - -565469) + -60299) / 5) - 520148); + a7 = 12; + a5 = 3; + + return -1; + } else if((((( 255 < a17 && ((input == 3) && (a7==13))) && (a24==13)) && (a5==6)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) - 310362) - 118239); + a17 = ((((a17 + -527475) + -43049) / 5) + -159294); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==14) && ((a5==4) && ((input == 1) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((((a2 * -5) * 10)/ 9) - -320944) * -1); + a17 = (((((a17 * 9)/ 10) + 31872) % 71)+ 182); + a7 = 13; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ( a17 <= -108 && (((a7==13) && (input == 4)) && (a5==6)))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 5) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==14)) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) - 436847) + -130272); + a17 = (((a17 / 5) - 469094) - -33679); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==4) && ( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==13) || (a7==14)))))) && (a24==14))){ + a17 = (((((a17 / 5) * 4) - -51204) % 71)+ 129); + a7 = 14; + + return -1; + } else if((((( a2 <= 189 && ((a7==12) && (input == 1))) && (a5==7)) && 255 < a17 ) && (a24==15))){ + a17 = ((((a17 - 204408) - -50146) % 109)- -2); + a7 = 14; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ((a5==5) && ( a17 <= -108 && ((a7==14) && (input == 3))))))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)+ 204); + a17 = (((((a17 + 0) * 9)/ 10) % 109)+ 90); + a7 = 12; + a24 = 14; + a5 = 4; + + return 26; + } else if(((((a5==6) && ((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 5))) && (a24==15)) && a2 <= 189 )){ + a17 = ((((a17 % 71)+ 184) - 1) - 1); + a7 = 12; + a24 = 13; + a5 = 7; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((( 255 < a17 && (a7==13)) || (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && (input == 1)))) && (a5==3))){ + a17 = (((((a17 * 9)/ 10) % 109)- -2) + 1); + a7 = 12; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((a7==14) && (((input == 2) && ((111 < a17) && (255 >= a17)) ) && (a5==5)))))){ + a17 = ((((a17 - 501351) * 10)/ 9) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==13) && (((((input == 5) && (a5==7)) && (a24==14)) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 ))){ + a17 = (((a17 + -506871) + -84379) / 5); + a7 = 12; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (a5==3)) && (a24==13)))){ + a2 = (((a2 / 5) * 5) - 539865); + a17 = (((a17 + -583438) - 9976) - 606); + a7 = 12; + + return -1; + } else if((((( ((111 < a17) && (255 >= a17)) && ((input == 5) && a2 <= 189 )) && (a7==14)) && (a5==5)) && (a24==14))){ + a17 = ((((a17 / 5) + 148886) * 10)/ -9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && (((( 255 < a17 && (input == 1)) && (a24==13)) && a2 <= 189 ) && (a7==13)))){ + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (( ((189 < a2) && (281 >= a2)) && (input == 4)) && (a7==13))) && (a24==14)) && (a5==3))){ + a17 = ((((a17 / 5) - 84) * 10)/ 9); + a7 = 12; + + return -1; + } else if((((((a24==15) && ((input == 6) && ((111 < a17) && (255 >= a17)) )) && (a5==5)) && (a7==14)) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -234) + 3) - 467950) - -467949); + a17 = ((((a17 * 23)/ 10) - -254710) + 246366); + a5 = 4; + + return 21; + } else if(((((((a5==4) && ((a24==15) && ((a7==14) && 255 < a17 ))) || ((( a17 <= -108 && (a7==12)) && (a24==13)) && (a5==5))) || ((a5==5) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 4)) && a2 <= 189 )){ + a17 = ((((a17 + 0) + 0) % 299946)+ -300053); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((( ((111 < a17) && (255 >= a17)) && (input == 6)) && (a7==13)) && a2 <= 189 ) && (a24==13)) && (a5==5))){ + a17 = (((a17 * 5) + 157598) / 5); + a7 = 14; + a5 = 7; + + return 21; + } else if(( a2 <= 189 && ((a5==7) && (((( 255 < a17 && (a7==14)) && (a24==13)) || ((a24==14) && ( a17 <= -108 && (a7==12)))) && (input == 3))))){ + a17 = ((((a17 + 0) + 0) % 299872)+ 300127); + a7 = 13; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a5==6) && (((((a7==12) && a17 <= -108 ) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || (( 255 < a17 && (a7==14)) && (a24==13)))) && (input == 2))))){ + a2 = (((((a2 + 453687) % 45)- -236) - -350177) + -350178); + a17 = (((((a17 % 71)+ 182) + 0) - -438904) - 438902); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(( ((111 < a17) && (255 >= a17)) && ((a7==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 3)) && (a24==14)) && (a5==3))))){ + a2 = (((a2 / 5) / -5) * 5); + a17 = (((a17 * 5) - -273749) - 586768); + a7 = 14; + + return -1; + } else if(((a5==7) && (( a2 <= 189 && ((input == 3) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))) && (a24==14)))){ + a17 = (((((a17 - 515132) / 5) + 523785) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==5) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 2))) && ((189 < a2) && (281 >= a2)) ) && (a24==13))){ + a2 = (((a2 * 5) + 144469) + -189230); + a17 = (((((a17 + 0) % 299946)- 300053) / 5) + -445482); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a5==5) && (( ((189 < a2) && (281 >= a2)) && (input == 4)) && ((-108 < a17) && (111 >= a17)) )) && (a24==15)) && (a7==12))){ + a2 = (((a2 * 5) / -5) * 5); + a17 = ((((((a17 * 5) % 71)+ 184) * 5) % 71)- -152); + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && (a24==15))))) && (a7==13))){ + a17 = (((a17 - -116942) * 5) * 1); + a24 = 13; + + return -1; + } else if(((a5==5) && ((a24==13) && ( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && ((a7==13) && (input == 4))))))){ + a17 = (((a17 * 5) - 554850) + -19327); + a24 = 14; + a5 = 7; + + return 23; + } else if((( ((-108 < a17) && (111 >= a17)) && (((((a7==13) || (a7==14)) && (input == 4)) && (a24==15)) && a2 <= 189 )) && (a5==7))){ + a17 = (((a17 / 5) + -465987) + -123095); + a7 = 12; + + return -1; + } else if((((((a24==13) && (((a7==13) || (a7==14)) && (input == 3))) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 71)+ 183) - 106273) - -106273); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==13) && ( ((-108 < a17) && (111 >= a17)) && (((a7==12) || (a7==13)) && (input == 5)))) && (a5==3)))){ + a2 = ((((a2 * -5) * 5) + 590510) - 671065); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ((a5==5) && (((input == 6) && (a24==14)) && (a7==14)))) && a2 <= 189 )){ + a17 = ((((a17 * 5) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((( a17 <= -108 && (a7==12)) && (a24==15)) || ((( 255 < a17 && (a7==13)) && (a24==14)) || ((a24==14) && ( 255 < a17 && (a7==14))))) && (input == 6)) && a2 <= 189 ) && (a5==7))){ + a17 = (((a17 / 5) - 232817) * 1); + a7 = 12; + a24 = 15; + + return -1; + } else if((( a2 <= 189 && (((input == 6) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==6))) && (a24==15))){ + a17 = (((((a17 % 299946)+ -300053) + 0) / 5) + -24082); + a7 = 14; + + return 23; + } else if((((a24==14) && (((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 1)) && (a5==7))) && a2 <= 189 )){ + a17 = (((((a17 % 299872)- -256) * 1) / 5) - -44806); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a24==14) && ((( a2 <= 189 && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==6)) && 255 < a17 ))){ + a2 = ((((((a2 / 5) % 45)+ 235) / 5) * 51)/ 10); + a17 = ((((((a17 / 5) % 109)+ 2) * 5) % 109)+ -3); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((( a2 <= 189 && ((a5==6) && (((a7==13) || (a7==14)) && (input == 4)))) && ((-108 < a17) && (111 >= a17)) ) && (a24==15))){ + a2 = ((((a2 + 216043) % 45)+ 236) - -1); + a17 = (((((a17 - 429059) + 308928) * 4) % 71)- -208); + a7 = 14; + a5 = 3; + + return 21; + } else if((((((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==6))){ + a17 = (((a17 + -54487) - 92979) - 379120); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (( ((189 < a2) && (281 >= a2)) && ((a5==6) && (((a7==12) || (a7==13)) && (input == 1)))) && (a24==13)))){ + a2 = (((a2 - 455132) - 98197) + -25953); + a17 = (((a17 + 255777) * 2) + -670603); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==14) && ((a5==3) && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -585771) + -2935) * 1); + a17 = (((((a17 * 9)/ 10) / 5) % 109)- -1); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && (((a24==15) && ( a2 <= 189 && (((a7==12) || (a7==13)) && (input == 4)))) && ((-108 < a17) && (111 >= a17)) ))){ + a2 = ((((((a2 - 0) + 0) * 9)/ 10) % 45)- -234); + a17 = ((((a17 % 71)- -184) - 1) + 1); + a7 = 14; + a24 = 14; + a5 = 4; + + return 21; + } else if((((a5==5) && (((input == 6) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==14))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((((a17 * 9)/ 10) / 5) - 287459) % 109)- -2); + a7 = 12; + a5 = 4; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((a7==14) && (input == 2))))) && (a5==3))){ + + return 26; + } else if(((( a2 <= 189 && ((a24==13) && ((input == 3) && ((-108 < a17) && (111 >= a17)) ))) && (a5==5)) && (a7==14))){ + a17 = ((((a17 / 5) * 5) / 5) - -181132); + a7 = 13; + a24 = 15; + a5 = 6; + + return 23; + } else if(( a2 <= 189 && ((((((a7==13) || (a7==14)) && (input == 2)) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==7)))){ + a17 = (((a17 - 261314) + 71142) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( 255 < a17 && (((a24==13) && ((input == 2) && ((a7==13) || (a7==14)))) && (a5==4))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) + -450773) - 107216); + a17 = ((((((a17 % 71)+ 158) - 39) / 5) * 49)/ 10); + a7 = 14; + a24 = 14; + + return -1; + } else if(((( a2 <= 189 && (((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 4))) && (a5==7)) && (a24==14))){ + a17 = (((((a17 * 9)/ 10) % 109)- -1) + 0); + a7 = 14; + a24 = 15; + a5 = 4; + + return 21; + } else if(((((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 4)))) && (a24==15)) && a17 <= -108 )){ + a17 = (((((a17 % 71)- -182) + 0) / 5) - -96); + a7 = 13; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((a5==6) && (((((a7==12) || (a7==13)) && (input == 5)) && (a24==15)) && 255 < a17 )))){ + a2 = ((((a2 % 45)- -236) + 127994) - 127995); + a17 = (((((a17 - 156755) * 1) * 1) % 109)- -2); + a7 = 13; + a5 = 3; + + return 21; + } else if(((a24==13) && (((a5==6) && ((input == 3) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 / 5) * 5) + -36231) * -1)/ 10); + a7 = 14; + a5 = 4; + + return -1; + } else if(((((((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && (a24==15)) && a2 <= 189 ) && (a5==7))){ + a17 = (((((a17 + 0) / 5) + 400868) % 109)+ -80); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a24==15) && ((((input == 3) && ((a7==12) || (a7==13))) && 255 < a17 ) && (a5==5))) && a2 <= 189 )){ + a17 = (((a17 - 600131) - 103) + -13); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==5) && (((input == 5) && (((a7==12) && ((111 < a17) && (255 >= a17)) ) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 + 363060) - 21984) + -307797) * -5); + a17 = ((((a17 / 5) / 5) - -385642) - 385582); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((a24==15) && ((input == 4) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))))))){ + a17 = ((((a17 - 0) % 299872)- -300127) + 1); + a7 = 13; + a24 = 14; + + return -1; + } else if((((((a5==5) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((a5==4) && (( 255 < a17 && (a7==14)) && (a24==15))) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5)))) && (input == 3)) && a2 <= 189 )){ + a17 = (((a17 / 5) - -222886) * 1); + a7 = 14; + a24 = 13; + a5 = 6; + + return 26; + } else if((((a5==6) && ((((input == 1) && ((a7==13) || (a7==14))) && a2 <= 189 ) && (a24==14))) && a17 <= -108 )){ + a2 = ((((((a2 % 45)+ 235) + -1) * 5) % 45)- -223); + a17 = ((((a17 % 109)+ 16) + -191467) - -191547); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((input == 1) && (a24==14)) && (a7==13)))) && (a5==4))){ + a2 = (((a2 * 5) * 5) - 342077); + a17 = ((((a17 * 5) / 5) % 71)+ 184); + a24 = 15; + + return 21; + } else if(((a5==5) && ( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (((a7==12) || (a7==13)) && (input == 4))) && (a24==14))))){ + a2 = ((((a2 + 110417) % 45)- -236) * 1); + a17 = ((((a17 * 5) * 10)/ -9) - 228824); + a7 = 13; + a24 = 15; + a5 = 3; + + return 21; + } else if((((a24==13) && ( a2 <= 189 && ((input == 1) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))))) && (a5==6))){ + a2 = (((((a2 % 45)+ 234) / 5) - -431906) + -431702); + a17 = (((((a17 + -434179) % 109)+ 30) + 138172) + -138140); + a7 = 14; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && (( a2 <= 189 && (((a24==13) && (input == 5)) && (a5==5))) && (a7==14)))){ + a17 = (((a17 + 592041) * 1) - -2226); + a7 = 12; + a24 = 14; + a5 = 7; + + return 26; + } else if(((((a24==13) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5))) && (a5==7)) && a2 <= 189 )){ + a17 = (((((a17 % 71)+ 182) / 5) * 51)/ 10); + a7 = 12; + a5 = 5; + + return 21; + } else if((((a24==15) && (((a5==4) && ( ((-108 < a17) && (111 >= a17)) && (input == 5))) && (a7==12))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / 5) / -5) * 5); + a17 = (((a17 - -517716) / 5) * 5); + a7 = 13; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==5) && ((a24==13) && ( a2 <= 189 && ((input == 3) && (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))))))){ + a17 = ((((a17 % 299946)+ -300053) - 1) - 1); + a7 = 12; + a24 = 15; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((((a5==7) && (((a7==13) && a17 <= -108 ) && (a24==13))) || (((a5==6) && ((a24==15) && ( 255 < a17 && (a7==14)))) || ((a5==7) && ((a24==13) && ((a7==12) && a17 <= -108 ))))) && (input == 5)))){ + a2 = ((((a2 - -71451) % 45)- -236) + -1); + a17 = (((((a17 * 9)/ 10) % 109)- -2) + -1); + a7 = 13; + a24 = 15; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((( 255 < a17 && (a7==14)) && (a24==14)) || (( a17 <= -108 && (a7==12)) && (a24==15))) && (input == 2)) && (a5==3)))){ + a2 = (((a2 * 5) - 448501) * 1); + a17 = (((((a17 % 71)- -182) / 5) / 5) + 165); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if((((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 3)) && a2 <= 189 ) && (a5==7)) && (a24==14))){ + a17 = ((((a17 % 299872)+ 256) - -48274) + 28236); + a7 = 12; + a24 = 13; + + return -1; + } else if((((( 255 < a17 && ((input == 4) && ((a7==14) || ((a7==12) || (a7==13))))) && (a5==5)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((a17 - 0) - 595306) - 4802); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((((input == 5) && (a24==13)) && (a5==4)) && (a7==12)) && a17 <= -108 ))){ + a2 = (((a2 / -5) / 5) - 315470); + a5 = 3; + + return -1; + } else if(((a24==15) && ((((input == 4) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==6)) && a2 <= 189 ))){ + a17 = ((((a17 - -17630) - 6795) % 109)- -1); + a7 = 12; + + return 26; + } else if((((((((a7==12) || (a7==13)) && (input == 2)) && (a24==15)) && 255 < a17 ) && a2 <= 189 ) && (a5==4))){ + a17 = (((a17 + 0) - 600231) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && ((a5==5) && ((a24==14) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = ((((a17 + 0) % 71)- -167) + 11); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && (a7==13)))) && ((-108 < a17) && (111 >= a17)) ))){ + + return 23; + } else if((( a17 <= -108 && ((((input == 6) && ((a7==12) || (a7==13))) && (a5==5)) && ((189 < a2) && (281 >= a2)) )) && (a24==14))){ + a17 = ((((a17 / 5) % 109)- -109) / 5); + a7 = 13; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)) && (a24==13)) && (a5==5)))){ + a2 = (((a2 / -5) * 5) - 263640); + a17 = ((((a17 * 9)/ 10) + -31880) - 20940); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==15) && ( a2 <= 189 && (((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 2)))) && (a5==5))){ + a17 = (((a17 + 26382) - 539571) - 38393); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a17 <= -108 && ((a5==6) && ((((a7==12) && (input == 1)) && (a24==13)) && a2 <= 189 )))){ + + a5 = 3; + + return -1; + } else if(((a5==3) && (((((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 6)) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 - 0) % 109)- -2) - -1); + a7 = 12; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 2) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && (a5==4))){ + a2 = ((((a2 / -5) + 523985) * 1) + -866052); + a17 = (((((a17 % 109)+ 2) + -1) - -574310) + -574309); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a24==15) && (((a7==12) && ((a5==6) && (input == 1))) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )){ + a2 = ((((a2 + 0) + 6154) % 45)- -236); + a17 = (((a17 / 5) / 5) + -109); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if((((( a17 <= -108 && (((a7==12) || (a7==13)) && (input == 3))) && ((189 < a2) && (281 >= a2)) ) && (a5==6)) && (a24==13))){ + a17 = ((((a17 * 9)/ 10) * 1) - -571423); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if((((a24==15) && ((a7==14) && (((input == 4) && 255 < a17 ) && (a5==5)))) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -235) * 1) / 5) - -166); + a17 = ((((a17 * 9)/ 10) / 5) + -557397); + a24 = 14; + + return 23; + } else if((((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)) && (a5==4))){ + a2 = ((((a2 - -6843) - 234103) - -260659) + -346865); + a17 = (((((a17 % 71)+ 182) - -2) - -415451) - 415452); + a7 = 13; + a24 = 15; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((a5==5) && ((a24==15) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (input == 5)))))){ + a2 = ((((((a2 % 45)- -235) - -220353) * 2) % 45)- -192); + a17 = (((((a17 % 109)- -1) - 487372) / 5) + 97389); + a7 = 12; + a5 = 4; + + return 26; + } else if((((a7==13) && ((((input == 4) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )) && (a24==13))){ + + a24 = 14; + a5 = 4; + + return -1; + } else if((((a7==13) && ((((input == 3) && a2 <= 189 ) && (a24==13)) && 255 < a17 )) && (a5==7))){ + a17 = (((((a17 % 71)- -147) * 5) % 71)- -157); + a5 = 5; + + return 26; + } else if(((( 255 < a17 && ((a5==5) && ((input == 4) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -324872) - 111167) - 140231); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==7) && (((input == 3) && ((((a7==12) && a17 <= -108 ) && (a24==15)) || ((((a7==13) && 255 < a17 ) && (a24==14)) || (((a7==14) && 255 < a17 ) && (a24==14))))) && a2 <= 189 ))){ + a17 = ((((a17 % 299872)+ 300127) + 0) - -1); + a7 = 14; + a24 = 14; + + return 23; + } else if(( a2 <= 189 && (((((( 255 < a17 && (a7==14)) && (a24==13)) || ((a24==14) && ( a17 <= -108 && (a7==12)))) || ((a24==14) && ((a7==13) && a17 <= -108 ))) && (input == 1)) && (a5==5)))){ + a17 = ((((a17 % 299872)+ 300127) - 0) - 0); + a7 = 13; + a24 = 15; + a5 = 7; + + return 23; + } else if(((((a5==7) && ((((a7==13) || (a7==14)) && (input == 1)) && a2 <= 189 )) && (a24==15)) && 255 < a17 )){ + + a7 = 13; + a24 = 14; + + return -1; + } else if((((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 3)) && (a24==13)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 - 228436) / 5) * 5); + a17 = ((((a17 * 9)/ 10) - -37438) - 617865); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 4)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==5))){ + a2 = (((a2 * -5) + -362469) + 206807); + a17 = (((((a17 / 5) / 5) / 5) % 71)+ 183); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==14) && (((a5==5) && ( 255 < a17 && ((input == 4) && ((a7==13) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + + return 26; + } else if((( a2 <= 189 && ((((a24==14) && ( a17 <= -108 && (a7==13))) || (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 )))) && (input == 5))) && (a5==5))){ + a2 = ((((a2 / 5) % 45)- -235) + 1); + a17 = (((a17 / 5) - 256291) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return 26; + } else if(((a24==15) && (( a17 <= -108 && ((a5==6) && ((a7==13) && (input == 1)))) && a2 <= 189 ))){ + a2 = (((((a2 / 5) * 4) / 5) % 45)- -234); + a17 = ((((a17 - -120776) / 5) % 109)- -2); + a24 = 13; + a5 = 4; + + return 21; + } else if((((a5==4) && (( a2 <= 189 && ((input == 6) && ((a7==13) || (a7==14)))) && (a24==15))) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((((a17 * -1)/ 10) * 10)/ 9) + -47); + a7 = 13; + a5 = 5; + + return 21; + } else if(((a5==6) && ((a24==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 4)) && 255 < a17 ) && (a7==13))))){ + a2 = (((a2 / -5) * 5) + -60399); + a17 = ((((a17 / 5) % 109)+ -92) / 5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if((((((a5==5) && ((input == 3) && ((a7==12) || (a7==13)))) && a2 <= 189 ) && (a24==14)) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((((a2 + 399174) % 45)+ 234) - 119189) + 119189); + a17 = (((a17 + -440715) / 5) + 88187); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a24==13) && ( a17 <= -108 && (((a5==6) && (((a7==12) || (a7==13)) && (input == 1))) && ((189 < a2) && (281 >= a2)) )))){ + a17 = ((((a17 + 0) + 354212) % 109)+ 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && (((a5==4) && (((a7==13) || (a7==14)) && (input == 1))) && a2 <= 189 )) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((a17 * 5) - 379915) - -55808); + a7 = 14; + a5 = 5; + + return 23; + } else if(((a5==4) && ( a2 <= 189 && (((((a7==13) || (a7==14)) && (input == 5)) && a17 <= -108 ) && (a24==15))))){ + a17 = ((((((a17 % 71)- -187) * 5) * 5) % 71)- -127); + a7 = 12; + + return 23; + } else if((((a5==4) && (( 255 < a17 && ((input == 6) && ((a7==13) || (a7==14)))) && ((189 < a2) && (281 >= a2)) )) && (a24==13))){ + a17 = ((((a17 / 5) + -588303) % 71)+ 218); + a7 = 12; + + return -1; + } else if(( a2 <= 189 && ((input == 1) && (((a5==7) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==6)) || ((a5==7) && ((a24==13) && ((a7==12) && a17 <= -108 )))))))){ + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 299946)- 300053); + a7 = 12; + a24 = 13; + a5 = 7; + + return 21; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((a24==14) && ((a7==14) && 255 < a17 )) || (( a17 <= -108 && (a7==12)) && (a24==15))) && (input == 3))))){ + a2 = (((a2 + -143123) + -98171) * 2); + a17 = (((((a17 % 71)- -184) * 5) % 71)+ 132); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==4) && (((a7==12) && (input == 3)) && (a24==15)))))){ + a2 = (((a2 * -5) * 5) - 163900); + a17 = (((a17 - 263174) * 2) / 5); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4)) && (a24==14))))){ + a2 = (((a2 / -5) / 5) + -193140); + a17 = ((((a17 % 299946)- 300053) - 2) + 0); + a7 = 12; + a5 = 7; + + return -1; + } else if((((input == 6) && ((((a5==4) && ((a24==15) && ( 255 < a17 && (a7==14)))) || (((a24==13) && ((a7==12) && a17 <= -108 )) && (a5==5))) || (((a24==13) && ((a7==13) && a17 <= -108 )) && (a5==5)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 5) * 10)/ 9); + a17 = (((((a17 % 299872)+ 300127) + 0) - 193833) - -193835); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 2))))) && (a5==5))){ + a2 = (((a2 / 5) * -5) - 445381); + a17 = (((a17 - 533326) - 24751) + -42172); + a7 = 12; + a24 = 13; + a5 = 4; + + return -1; + } else if(((( a2 <= 189 && ((((a7==12) || (a7==13)) && (input == 2)) && 255 < a17 )) && (a24==13)) && (a5==5))){ + a17 = ((((a17 * 9)/ 10) - 571338) / 5); + a7 = 12; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((((input == 6) && (((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && (a24==15)) && (a5==5)))){ + a17 = (((a17 * 5) + -240915) + -308966); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 5) && (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (a24==14))) && (a5==4))){ + a2 = (((a2 - 446402) + -60965) * 1); + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==14) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3)) && ((189 < a2) && (281 >= a2)) )) && (a5==5))){ + a2 = (((a2 - 299989) - 282684) + -11091); + a17 = ((((a17 + -13195) * 10)/ 9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((a24==15) && (input == 1)) && (a5==5)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 ) && (a7==14))){ + a2 = (((((a2 % 45)+ 234) + 93283) + 429518) + -522800); + a17 = ((((a17 - 192) - 1) + 44565) - 44563); + a7 = 13; + a24 = 13; + + return 23; + } else if(( ((111 < a17) && (255 >= a17)) && ((((a5==5) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 4))) && ((189 < a2) && (281 >= a2)) ) && (a24==13)))){ + a2 = (((a2 * 5) - 529848) + -4150); + a17 = (((a17 / 5) / 5) - 39); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if(((( a17 <= -108 && ((a24==14) && ((input == 4) && ((a7==13) || (a7==14))))) && a2 <= 189 ) && (a5==6))){ + + a7 = 13; + a24 = 13; + a5 = 5; + + return 26; + } else if((( a2 <= 189 && ((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((a7==12) || (a7==13)) && (input == 6))))) && (a24==14))){ + a2 = ((((a2 % 45)+ 234) * 5) / 5); + a7 = 14; + a5 = 3; + + return 21; + } else if(((a24==15) && ( a2 <= 189 && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14)))) && (input == 2)) && (a5==7))))){ + a17 = ((((a17 % 299946)+ -300053) + -2) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || (((a24==13) && ((a7==12) && a17 <= -108 )) && (a5==5))) || ((((a7==13) && a17 <= -108 ) && (a24==13)) && (a5==5)))))){ + a2 = (((a2 - -563886) * -1) + 466041); + a17 = ((((a17 % 109)- -2) + 1) - 1); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && (((((a7==14) || ((a7==12) || (a7==13))) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))) && (a5==5))){ + a2 = (((a2 / -5) - 416146) / 5); + a17 = (((a17 - 462537) + -101249) + 137036); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && ((input == 4) && ((a7==13) || (a7==14)))))))){ + a17 = ((((a17 + 115929) / 5) + -404240) + 381192); + a7 = 14; + a24 = 13; + + return -1; + } else if((((a24==15) && ((a5==6) && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 4))))) && a2 <= 189 )){ + a17 = (((((a17 + -82645) / 5) / 5) % 109)+ 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(((a24==13) && (( a17 <= -108 && (((input == 4) && ((a7==13) || (a7==14))) && ((189 < a2) && (281 >= a2)) )) && (a5==3)))){ + a2 = (((a2 * -5) + -23430) * 5); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((a7==12) && ((a24==15) && ((input == 1) && (a5==4))))))){ + a2 = ((((a2 - 86020) + -319001) - -534468) - 217545); + a17 = (((a17 - -503276) + 60279) / 5); + a7 = 13; + a5 = 7; + + return -1; + } else if(((((a5==5) && ( a2 <= 189 && ((input == 4) && ((a7==12) || (a7==13))))) && (a24==15)) && a17 <= -108 )){ + a2 = ((((a2 % 45)- -236) - 1) * 1); + a7 = 13; + a24 = 14; + a5 = 4; + + return 26; + } else if(((((a5==3) && ((input == 6) && (((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))))) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 + -429873) % 299872)+ 300127) - 39771) - -39773); + a7 = 12; + + return 23; + } else if((((((((a7==12) || (a7==13)) && (input == 1)) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && ((189 < a2) && (281 >= a2)) ) && (a5==3))){ + + a7 = 13; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 6) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && (a5==4))))){ + a2 = (((a2 * 5) * 5) - 126327); + a17 = (((a17 + -140957) * 4) - -269430); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && ((a24==15) && (input == 4))) && (a7==12)) && (a5==4)))){ + a2 = (((a2 - 514328) - 2041) - -399856); + a7 = 14; + a5 = 7; + + return -1; + } else if((((a5==3) && ((a24==13) && ((input == 3) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 307516) - 193341) * 1); + a17 = (((((a17 % 71)+ 181) - -293974) / 5) + -58626); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 ))) && (input == 1))))){ + a17 = (((((a17 % 71)+ 183) - 1) - -531843) - 531841); + a7 = 13; + a24 = 13; + a5 = 5; + + return -1; + } else if((((((a24==13) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 1))) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && 255 < a17 )){ + a2 = ((((a2 + -443081) * 10)/ 9) * 1); + a17 = ((((((a17 % 71)- -174) * 5) * 5) % 71)- -133); + a7 = 13; + a5 = 7; + + return -1; + } else if((((((input == 1) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 ))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = ((((a2 + -122718) * 10)/ 9) - -74204); + a17 = ((((a17 % 109)- -2) + -34) + 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a5==4) && ((((a24==15) && ((input == 2) && (((a7==12) || (a7==13)) || (a7==14)))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - -117222) - 186157) - -508770) - 673504); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==7) && ((((a7==13) || (a7==14)) && (input == 1)) && (a24==15))) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )){ + a17 = ((((((a17 % 71)- -183) * 1) * 5) % 71)- -154); + a7 = 12; + a24 = 14; + + return -1; + } else if(((((((( 255 < a17 && (a7==13)) && (a24==13)) || (( 255 < a17 && (a7==14)) && (a24==13))) || (((a7==12) && a17 <= -108 ) && (a24==14))) && (input == 6)) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 596397) + -1500) + -536); + a17 = (((((a17 * 9)/ 10) % 109)+ 2) + -1); + a7 = 13; + a24 = 14; + a5 = 5; + + return 26; + } else if(((a24==13) && (( ((-108 < a17) && (111 >= a17)) && ((a5==6) && ((input == 5) && ((a7==12) || (a7==13))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 + -92113) - 295718) + -53625); + a17 = (((a17 / 5) / 5) - 76916); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((input == 5) && ((a7==13) || (a7==14))))) && a2 <= 189 ) && (a5==6))){ + a2 = ((((a2 % 45)- -236) - -1) + -3); + a17 = ((((a17 + -62237) % 71)+ 199) + -15); + a7 = 13; + a5 = 3; + + return 26; + } else if(( a17 <= -108 && (((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 6)))) && (a5==6)))){ + a17 = (((((a17 % 71)- -223) * 5) % 71)- -154); + a7 = 13; + a24 = 14; + a5 = 5; + + return -1; + } else if(((((((input == 2) && ((a7==12) || (a7==13))) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && (a24==14)) && a17 <= -108 )){ + a2 = ((((a2 - 55102) - -372533) - 62328) * -2); + a17 = (((((a17 * 9)/ 10) * 1) / 5) + 203115); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && (((a5==3) && ((a7==12) && (input == 6))) && ((189 < a2) && (281 >= a2)) )) && (a24==13))){ + a2 = (((a2 / -5) / 5) * 5); + a17 = ((((((a17 % 71)- -247) + 8) * 5) % 71)+ 139); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && (( 255 < a17 && ((((a7==12) || (a7==13)) && (input == 5)) && (a5==4))) && (a24==15)))){ + a17 = (((a17 + -600167) * 1) + -74); + a7 = 12; + a24 = 13; + a5 = 6; + + return 21; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==3) && ((a24==14) && (((input == 1) && ((189 < a2) && (281 >= a2)) ) && (a7==13)))))){ + a2 = (((a2 + 97520) - -476171) + -703390); + a17 = (((a17 - 192516) + 192347) + 14); + a7 = 14; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==15) && ( a17 <= -108 && ((input == 6) && (((a7==12) || (a7==13)) || (a7==14))))) && (a5==4)))){ + a2 = (((a2 / 5) - -274462) - 512632); + a17 = (((((a17 % 71)- -206) - -20) - 351411) + 351407); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a2 <= 189 && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 3))))) && (a24==13))){ + a17 = (((((a17 % 71)+ 123) - 11) + 84970) + -84956); + a7 = 14; + a24 = 15; + a5 = 7; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && (( ((111 < a17) && (255 >= a17)) && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==5))))){ + a17 = ((((a17 * 5) % 109)- 71) - -9); + a7 = 13; + a24 = 14; + + return -1; + } else if((((((((a7==13) || (a7==14)) && (input == 6)) && (a5==5)) && 255 < a17 ) && (a24==14)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - -501110) / -5) + -432351); + a17 = (((((a17 % 71)+ 148) + -248919) + -89135) - -338038); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((( 255 < a17 && ((a7==13) && ((a24==13) && (input == 5)))) && (a5==7)) && a2 <= 189 )){ + + return -1; + } else if(((((a5==5) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 4)) && a2 <= 189 )) && (a24==14)) && 255 < a17 )){ + a17 = (((a17 + -600231) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((-108 < a17) && (111 >= a17)) && (((input == 6) && (a7==13)) && a2 <= 189 )) && (a24==14)) && (a5==7))){ + + return 21; + } else if(( 255 < a17 && ((a5==6) && ( a2 <= 189 && ((a24==15) && (((a7==12) || (a7==13)) && (input == 1))))))){ + a17 = ((((a17 % 109)- 52) - 44) + -3); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((((((a7==14) || ((a7==12) || (a7==13))) && (input == 1)) && (a5==6)) && (a24==14)) && a2 <= 189 ))){ + a17 = ((((a17 / 5) + 148) * 9)/ 10); + a7 = 12; + a24 = 13; + a5 = 7; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==6) && ((a24==13) && ((input == 1) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))))))){ + a17 = ((((((a17 + 0) % 109)- 20) * 5) % 109)+ 1); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 6)) && (a24==13)))) && (a5==4))){ + a17 = (((((a17 - 297061) - -413246) * 5) % 71)- -126); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - -381050) + -586556) - 318711); + a17 = (((a17 * 5) * 5) - 315241); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((((((a7==13) && a17 <= -108 ) && (a24==14)) || ((( 255 < a17 && (a7==14)) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14)))) && (input == 2)) && a2 <= 189 ))){ + a17 = ((((a17 % 299946)+ -300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((111 < a17) && (255 >= a17)) && ((input == 3) && (a7==14))) && (a24==14)) && a2 <= 189 ) && (a5==5))){ + a2 = ((((a2 % 45)- -235) + -1) - 0); + a17 = (((((a17 / 5) * 10)/ 9) * 10)/ 9); + a24 = 15; + a5 = 3; + + return 23; + } else if(( a2 <= 189 && ((a24==14) && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))) && (input == 1)) && (a5==7))))){ + a17 = ((((a17 / 5) * 4) % 109)+ 2); + a7 = 13; + a24 = 15; + a5 = 4; + + return 21; + } else if((( a17 <= -108 && (((((a7==12) || (a7==13)) && (input == 3)) && a2 <= 189 ) && (a5==5))) && (a24==15))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((a24==15) && (input == 3)) && (a5==5)) && (a7==14)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + a2 = ((((a2 % 45)- -236) * 1) - 1); + a17 = ((((a17 - 477741) * 10)/ 9) + -8957); + a24 = 13; + + return 23; + } else if(((((((input == 6) && ((a7==13) || (a7==14))) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==6))){ + + a7 = 12; + a24 = 13; + a5 = 7; + + return 21; + } else if(((( ((189 < a2) && (281 >= a2)) && ((( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))) && (input == 6))) && (a5==6)) && (a24==13))){ + a2 = (((a2 / 5) - 67976) + -37056); + a17 = ((((a17 % 109)+ -50) + 36) / 5); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a5==4) && ((input == 3) && ((a7==13) || (a7==14)))))))){ + a2 = (((a2 + -368535) + -129446) * 1); + a17 = (((((a17 * 9)/ 10) * 1) / 5) - 289303); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a24==14) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 6))))) && a17 <= -108 )){ + a2 = (((a2 / 5) + -164157) * 3); + a7 = 13; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ((a5==7) && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)))))){ + a17 = (((((a17 % 109)- -2) + -1) + 462727) + -462726); + a7 = 14; + a24 = 14; + + return -1; + } else if(((((a5==3) && ((input == 2) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && ((189 < a2) && (281 >= a2)) ) && (a24==14))){ + a17 = ((((a17 % 109)- -2) + -1) - -2); + a7 = 14; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==14) && 255 < a17 ) && (a24==14)) || ((a24==15) && ((a7==12) && a17 <= -108 ))) && (input == 1))))){ + a17 = (((((a17 / 5) % 71)- -184) / 5) + 143); + a7 = 13; + a24 = 14; + + return -1; + } else if(((( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (input == 5)) && (a24==15))) && (a5==5)) && (a7==14))){ + a2 = ((((((a2 - 0) * 9)/ 10) - 15643) % 45)+ 276); + a17 = (((a17 / 5) / 5) - -310668); + a7 = 13; + a5 = 4; + + return 23; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==5)))) && a17 <= -108 )){ + a2 = ((((a2 + 140796) / 5) / 5) * -5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 5) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))))) && (a24==13)) && (a5==4)))){ + a17 = (((a17 / 5) / 5) + -194917); + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((a5==4) && ( a17 <= -108 && ((input == 2) && ((a7==13) || (a7==14)))))) && (a24==15))){ + a17 = ((((a17 % 109)- -85) + -84) - 0); + a7 = 12; + + return 21; + } else if(((a5==6) && (( 255 < a17 && ((((a7==12) || (a7==13)) && (input == 6)) && a2 <= 189 )) && (a24==15)))){ + a2 = (((((a2 % 45)- -235) / 5) / 5) + 244); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a5==3) && (((a24==13) && ((( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 5))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - -580869) + -652808) * 5); + a17 = ((((a17 % 109)- -3) + -41) + 9); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(((((a24==15) && ((((a7==12) || (a7==13)) && (input == 1)) && a17 <= -108 )) && (a5==5)) && a2 <= 189 )){ + a2 = (((((a2 * 9)/ 10) + -16953) % 45)+ 272); + a17 = ((((((a17 % 71)+ 236) * 5) + 502892) % 71)+ 132); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(((((a24==13) && ((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + 409580) + -457191); + a17 = (((a17 - -196150) + 128540) - -116144); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==15) && ((a5==4) && ((( ((-108 < a17) && (111 >= a17)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a7==13))))){ + + return -1; + } else if((((((((a7==12) || (a7==13)) && (input == 3)) && (a5==5)) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 ) && (a24==15))){ + a2 = ((((a2 % 45)+ 234) - -448340) + -448339); + a17 = (((a17 * 5) / 5) - -211113); + a7 = 13; + a24 = 14; + a5 = 4; + + return 26; + } else if((((a24==13) && (((((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )) && (a5==6))){ + a2 = (((a2 / 5) / 5) * -5); + a17 = (((((a17 % 299872)+ 256) + 239410) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==5) && ((a24==14) && ( a2 <= 189 && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && 255 < a17 ))))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)- -195); + a17 = (((a17 - 600134) * 1) - 48); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(( a2 <= 189 && ((a24==15) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 1)) && (a5==6))))){ + a17 = (((((a17 * 9)/ 10) * 1) / 5) - 216856); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==6) && (((input == 5) && (( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && a2 <= 189 )))){ + a17 = ((((a17 % 109)- -1) - 83) - -75); + a7 = 12; + a24 = 15; + a5 = 4; + + return 26; + } else if((((a5==7) && (((input == 1) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && a2 <= 189 )) && (a24==13))){ + a17 = (((((a17 - 274936) + 211306) * 1) % 71)+ 182); + a7 = 13; + a5 = 5; + + return -1; + } else if(((a5==6) && ((a24==13) && (((((a7==12) || (a7==13)) && (input == 6)) && ((-108 < a17) && (111 >= a17)) ) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + -87407) - -312987) - 526695); + a17 = (((a17 + 556571) * 1) * 1); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((( a2 <= 189 && ((a5==6) && ((((a7==13) || (a7==14)) && (input == 2)) && (a24==14)))) && a17 <= -108 )){ + + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(((a24==15) && (((a7==12) && (((input == 6) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )) && (a5==4)))){ + a17 = (((((a17 % 71)+ 182) + 0) + -506914) - -506916); + a24 = 13; + a5 = 5; + + return 21; + } else if(((( a17 <= -108 && (((a5==5) && (input == 5)) && a2 <= 189 )) && (a7==14)) && (a24==14))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((( a17 <= -108 && (a7==12)) && (a24==14)) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ((a7==14) && 255 < a17 )))) && (input == 5))) && (a5==6))){ + a2 = (((((a2 % 45)+ 234) / 5) / 5) + 253); + a17 = ((((a17 % 299872)+ 300127) + 0) + 0); + a7 = 13; + a24 = 14; + a5 = 3; + + return 26; + } + return calculate_output4(input); + } + + int calculate_output4(int input) { + + + if((( ((-108 < a17) && (111 >= a17)) && ((((input == 6) && ((a7==13) || (a7==14))) && (a24==15)) && a2 <= 189 )) && (a5==7))){ + + a7 = 13; + + return -1; + } else if(((((((input == 6) && a2 <= 189 ) && (a24==13)) && (a7==12)) && (a5==5)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 - -162890) - -143056) * 10)/ -9); + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==5)))) && a17 <= -108 )){ + a17 = (((((a17 + 326777) + 251227) - 58119) % 109)+ 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==14) && ((a7==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 5)) && ((-108 < a17) && (111 >= a17)) ) && (a5==4))))){ + + return 23; + } else if(( a2 <= 189 && ((((((a7==13) || (a7==14)) && (input == 3)) && (a24==15)) && (a5==6)) && ((111 < a17) && (255 >= a17)) ))){ + + a7 = 14; + + return 21; + } else if(((a7==13) && ( a17 <= -108 && ( a2 <= 189 && (((input == 5) && (a24==15)) && (a5==6)))))){ + + return 23; + } else if(((a24==14) && (((a5==5) && (( a2 <= 189 && (input == 6)) && a17 <= -108 )) && (a7==14)))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((a5==5) && ( a17 <= -108 && ((input == 4) && (((a7==12) || (a7==13)) || (a7==14)))))))){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((((((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && (a5==7)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15))){ + + a7 = 12; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((((((a24==15) && ( 255 < a17 && (a7==14))) && (a5==4)) || ((a5==5) && (( a17 <= -108 && (a7==12)) && (a24==13)))) || ((a5==5) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 5)))){ + a17 = ((((a17 % 299946)- 300053) + -1) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && (((a5==6) && (((input == 6) && (a24==13)) && ((189 < a2) && (281 >= a2)) )) && (a7==13)))){ + a2 = (((a2 + -559930) - -930633) - 537732); + a17 = (((a17 - 600136) * 1) - 66); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((a24==15) && ((input == 2) && ((a7==13) || (a7==14)))) && (a5==5))))){ + a2 = ((((a2 * -5) * 10)/ 9) * 5); + a17 = (((a17 - 416379) / 5) * 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((input == 3) && (((a7==12) || (a7==13)) || (a7==14))))) && a17 <= -108 ) && (a5==4))){ + a2 = (((a2 / 5) + -106387) + -147146); + a17 = ((((a17 % 299872)- -300127) - -270865) + 27768); + a7 = 12; + a5 = 7; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((a5==5) && ((a24==15) && (input == 5)))) && (a7==12)) && ((-108 < a17) && (111 >= a17)) )){ + a17 = (((a17 - -533048) + 40396) * 1); + a7 = 13; + a24 = 13; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 6) && (a24==15)) && (a5==4)) && (a7==12))) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 * -5) * 5) * 5); + a17 = (((a17 - 418037) * 1) - -234835); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 4) && (a24==13)) && (a5==6)) && a17 <= -108 ) && (a7==14)) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==5) && ( a2 <= 189 && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (input == 2)))))){ + a17 = ((((a17 - -453354) % 299946)+ -300053) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))) && (input == 5)) && (a5==7))))){ + a17 = ((((a17 - 0) % 299872)+ 300127) * 1); + a7 = 13; + a24 = 13; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((a7==13) && (((input == 6) && (a5==3)) && ((111 < a17) && (255 >= a17)) ))))){ + + return 26; + } else if(( 255 < a17 && ((a24==13) && (((a7==13) && ((input == 6) && a2 <= 189 )) && (a5==7))))){ + a17 = (((((a17 % 109)+ 3) - 249216) * 2) - -498320); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a24==14) && ( ((111 < a17) && (255 >= a17)) && (((a5==6) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13))))) && a2 <= 189 )))){ + a2 = (((((a2 % 45)+ 234) * 5) % 45)- -233); + a17 = ((((((a17 * 10)/ -9) + 137075) * 4) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==4) && ((a24==14) && ((input == 5) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))))){ + a2 = (((a2 / -5) + -474783) / 5); + a17 = (((a17 - 32453) * 5) / 5); + a7 = 14; + a24 = 15; + a5 = 5; + + return 23; + } else if(( 255 < a17 && ((a24==15) && ((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 2))))))){ + a2 = (((a2 + -107856) - 174986) / 5); + a17 = (((a17 - 83582) + -516569) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==5) && (((a24==13) && (input == 2)) && a2 <= 189 )) && (a7==13)) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((a17 - 3949) * 5) * 5); + a7 = 12; + a5 = 3; + + return -1; + } + return -2; + } + +int main2() +{ + // default output + int output = -1; + + // main i/o-loop + while(1) + { + // read input + int input; + input = __VERIFIER_nondet_int(); + if ((input != 1) && (input != 2) && (input != 3) && (input != 4) && (input != 5) && (input != 6)) return -2; + + // operate eca engine + output = calculate_output(input); + } +}int main() +{ + if(__VERIFIER_nondet_int()) + main1(); + else + main2(); +} diff --git a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c new file mode 100644 index 0000000000..4b2d6b79fc --- /dev/null +++ b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c @@ -0,0 +1,261 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// REQUIRES: target-x86_64 +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --64 --write-ktests %s 2>&1 | FileCheck %s +// CHECK: KLEE: WARNING: 100.00% Reachable Reachable + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2020 Aman Goel +// SPDX-FileCopyrightText: 2022 The SV-Benchmarks Community +// +// SPDX-License-Identifier: GPL-3.0-or-later + +// This C program is converted from Btor2 by Btor2C version bfcfb8b +// with arguments: { architecture=64, lazy_modulo=true, use_memmove=false, unroll_inner_loops=false, shortest_type=true, diff_type=true, decimal_constant=true, zero_init=false, sra_extend_sign=true } +// Comments from the original Btor2 file: +// ; source: https://github.com/aman-goel/avr/tree/92362931700b66684418a991d018c9fbdbebc06f/tests +// ; BTOR description generated by Yosys 0.9+431 (git sha1 4a3b5437, clang 4.0.1-6 -fPIC -Os) for module main. +extern void abort(void); +void reach_error() {} +extern unsigned char __VERIFIER_nondet_uchar(); +extern unsigned short __VERIFIER_nondet_ushort(); +extern unsigned int __VERIFIER_nondet_uint(); +extern unsigned long __VERIFIER_nondet_ulong(); +extern unsigned __int128 __VERIFIER_nondet_uint128(); +void __VERIFIER_assert(int cond) { if (!(cond)) { ERROR: { reach_error(); abort(); } } } +void assume_abort_if_not(int cond) { if (!cond) { abort(); } } +int main() { + // Defining sorts ... + typedef unsigned char SORT_1; // BV with 1 bits + const SORT_1 mask_SORT_1 = (SORT_1)-1 >> (sizeof(SORT_1) * 8 - 1); + const SORT_1 msb_SORT_1 = (SORT_1)1 << (1 - 1); + typedef unsigned long SORT_5; // BV with 64 bits + const SORT_5 mask_SORT_5 = (SORT_5)-1 >> (sizeof(SORT_5) * 8 - 64); + const SORT_5 msb_SORT_5 = (SORT_5)1 << (64 - 1); + typedef unsigned short SORT_8; // BV with 10 bits + const SORT_8 mask_SORT_8 = (SORT_8)-1 >> (sizeof(SORT_8) * 8 - 10); + const SORT_8 msb_SORT_8 = (SORT_8)1 << (10 - 1); + typedef unsigned __int128 SORT_14; // BV with 128 bits + const SORT_14 mask_SORT_14 = (SORT_14)-1 >> (sizeof(SORT_14) * 8 - 128); + const SORT_14 msb_SORT_14 = (SORT_14)1 << (128 - 1); + typedef unsigned int SORT_57; // BV with 32 bits + const SORT_57 mask_SORT_57 = (SORT_57)-1 >> (sizeof(SORT_57) * 8 - 32); + const SORT_57 msb_SORT_57 = (SORT_57)1 << (32 - 1); + // Initializing constants ... + const SORT_1 var_10 = 0; + const SORT_14 var_15 = 0; + const SORT_1 var_24 = 1; + const SORT_5 var_28 = 0; + const SORT_8 var_35 = 0; + const SORT_57 var_58 = 1; + const SORT_57 var_62 = 1000; + const SORT_5 var_64 = 9223372036854775807; + const SORT_5 var_67 = 12245771; + // Collecting input declarations ... + SORT_1 input_2; + SORT_1 input_3; + SORT_1 input_4; + SORT_5 input_6; + SORT_5 input_7; + SORT_8 input_9; + // Collecting state declarations ... + SORT_1 state_11 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_14 state_16 = __VERIFIER_nondet_uint128() & mask_SORT_14; + SORT_14 state_18 = __VERIFIER_nondet_uint128() & mask_SORT_14; + SORT_5 state_29 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_5 state_31 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_8 state_36 = __VERIFIER_nondet_ushort() & mask_SORT_8; + SORT_1 state_38 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_40 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_5 state_42 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_5 state_44 = __VERIFIER_nondet_ulong() & mask_SORT_5; + // Initializing states ... + SORT_1 init_12_arg_1 = var_10; + state_11 = init_12_arg_1; + SORT_14 init_17_arg_1 = var_15; + state_16 = init_17_arg_1; + SORT_14 init_19_arg_1 = var_15; + state_18 = init_19_arg_1; + SORT_5 init_30_arg_1 = var_28; + state_29 = init_30_arg_1; + SORT_5 init_32_arg_1 = var_28; + state_31 = init_32_arg_1; + SORT_8 init_37_arg_1 = var_35; + state_36 = init_37_arg_1; + SORT_1 init_39_arg_1 = var_24; + state_38 = init_39_arg_1; + SORT_1 init_41_arg_1 = var_24; + state_40 = init_41_arg_1; + SORT_5 init_43_arg_1 = var_28; + state_42 = init_43_arg_1; + SORT_5 init_45_arg_1 = var_28; + state_44 = init_45_arg_1; + for (;;) { + // Getting external input values ... + input_2 = __VERIFIER_nondet_uchar(); + input_3 = __VERIFIER_nondet_uchar(); + input_3 = input_3 & mask_SORT_1; + input_4 = __VERIFIER_nondet_uchar(); + input_4 = input_4 & mask_SORT_1; + input_6 = __VERIFIER_nondet_ulong(); + input_6 = input_6 & mask_SORT_5; + input_7 = __VERIFIER_nondet_ulong(); + input_7 = input_7 & mask_SORT_5; + input_9 = __VERIFIER_nondet_ushort(); + // Assuming invariants ... + // Asserting properties ... + SORT_1 var_13_arg_0 = state_11; + SORT_1 var_13 = ~var_13_arg_0; + SORT_14 var_20_arg_0 = state_16; + SORT_14 var_20_arg_1 = state_18; + SORT_1 var_20 = var_20_arg_0 == var_20_arg_1; + SORT_1 var_21_arg_0 = var_13; + SORT_1 var_21_arg_1 = var_20; + SORT_1 var_21 = var_21_arg_0 | var_21_arg_1; + SORT_1 var_25_arg_0 = var_21; + SORT_1 var_25 = ~var_25_arg_0; + SORT_1 var_26_arg_0 = var_24; + SORT_1 var_26_arg_1 = var_25; + SORT_1 var_26 = var_26_arg_0 & var_26_arg_1; + var_26 = var_26 & mask_SORT_1; + SORT_1 bad_27_arg_0 = var_26; + __VERIFIER_assert(!(bad_27_arg_0)); + // Computing next states ... + SORT_1 next_51_arg_1 = var_24; + SORT_1 var_33_arg_0 = state_11; + SORT_1 var_33 = ~var_33_arg_0; + var_33 = var_33 & mask_SORT_1; + SORT_5 var_52_arg_0 = state_29; + var_52_arg_0 = var_52_arg_0 & mask_SORT_5; + SORT_14 var_52 = var_52_arg_0; + SORT_5 var_53_arg_0 = state_31; + var_53_arg_0 = var_53_arg_0 & mask_SORT_5; + SORT_14 var_53 = var_53_arg_0; + SORT_14 var_54_arg_0 = var_52; + SORT_14 var_54_arg_1 = var_53; + SORT_14 var_54 = var_54_arg_0 * var_54_arg_1; + SORT_1 var_55_arg_0 = var_33; + SORT_14 var_55_arg_1 = var_15; + SORT_14 var_55_arg_2 = var_54; + SORT_14 var_55 = var_55_arg_0 ? var_55_arg_1 : var_55_arg_2; + var_55 = var_55 & mask_SORT_14; + SORT_14 next_56_arg_1 = var_55; + SORT_1 var_71_arg_0 = state_38; + SORT_1 var_71_arg_1 = state_40; + SORT_1 var_71 = var_71_arg_0 | var_71_arg_1; + var_71 = var_71 & mask_SORT_1; + SORT_8 var_61_arg_0 = state_36; + var_61_arg_0 = var_61_arg_0 & mask_SORT_8; + SORT_57 var_61 = var_61_arg_0; + SORT_57 var_63_arg_0 = var_61; + SORT_57 var_63_arg_1 = var_62; + SORT_1 var_63 = var_63_arg_0 > var_63_arg_1; + SORT_5 var_65_arg_0 = input_6; + SORT_5 var_65_arg_1 = var_64; + SORT_1 var_65 = var_65_arg_0 == var_65_arg_1; + SORT_1 var_66_arg_0 = var_63; + SORT_1 var_66_arg_1 = var_65; + SORT_1 var_66 = var_66_arg_0 & var_66_arg_1; + SORT_5 var_68_arg_0 = input_7; + SORT_5 var_68_arg_1 = var_67; + SORT_1 var_68 = var_68_arg_0 == var_68_arg_1; + SORT_1 var_69_arg_0 = var_66; + SORT_1 var_69_arg_1 = var_68; + SORT_1 var_69 = var_69_arg_0 & var_69_arg_1; + var_69 = var_69 & mask_SORT_1; + SORT_5 var_46_arg_0 = state_42; + var_46_arg_0 = var_46_arg_0 & mask_SORT_5; + SORT_14 var_46 = var_46_arg_0; + SORT_5 var_47_arg_0 = state_44; + var_47_arg_0 = var_47_arg_0 & mask_SORT_5; + SORT_14 var_47 = var_47_arg_0; + SORT_14 var_48_arg_0 = var_46; + SORT_14 var_48_arg_1 = var_47; + SORT_14 var_48 = var_48_arg_0 * var_48_arg_1; + SORT_57 var_59_arg_0 = var_58; + var_59_arg_0 = var_59_arg_0 & mask_SORT_57; + SORT_14 var_59 = var_59_arg_0; + SORT_14 var_60_arg_0 = var_48; + SORT_14 var_60_arg_1 = var_59; + SORT_14 var_60 = var_60_arg_0 + var_60_arg_1; + SORT_1 var_70_arg_0 = var_69; + SORT_14 var_70_arg_1 = var_60; + SORT_14 var_70_arg_2 = var_48; + SORT_14 var_70 = var_70_arg_0 ? var_70_arg_1 : var_70_arg_2; + SORT_1 var_72_arg_0 = var_71; + SORT_14 var_72_arg_1 = var_70; + SORT_14 var_72_arg_2 = state_18; + SORT_14 var_72 = var_72_arg_0 ? var_72_arg_1 : var_72_arg_2; + SORT_1 var_73_arg_0 = var_33; + SORT_14 var_73_arg_1 = var_15; + SORT_14 var_73_arg_2 = var_72; + SORT_14 var_73 = var_73_arg_0 ? var_73_arg_1 : var_73_arg_2; + var_73 = var_73 & mask_SORT_14; + SORT_14 next_74_arg_1 = var_73; + SORT_1 var_75_arg_0 = input_3; + SORT_5 var_75_arg_1 = input_6; + SORT_5 var_75_arg_2 = state_29; + SORT_5 var_75 = var_75_arg_0 ? var_75_arg_1 : var_75_arg_2; + SORT_1 var_76_arg_0 = var_33; + SORT_5 var_76_arg_1 = var_28; + SORT_5 var_76_arg_2 = var_75; + SORT_5 var_76 = var_76_arg_0 ? var_76_arg_1 : var_76_arg_2; + SORT_5 next_77_arg_1 = var_76; + SORT_1 var_78_arg_0 = input_4; + SORT_5 var_78_arg_1 = input_7; + SORT_5 var_78_arg_2 = state_31; + SORT_5 var_78 = var_78_arg_0 ? var_78_arg_1 : var_78_arg_2; + SORT_1 var_79_arg_0 = var_33; + SORT_5 var_79_arg_1 = var_28; + SORT_5 var_79_arg_2 = var_78; + SORT_5 var_79 = var_79_arg_0 ? var_79_arg_1 : var_79_arg_2; + SORT_5 next_80_arg_1 = var_79; + SORT_1 var_81_arg_0 = var_33; + SORT_8 var_81_arg_1 = input_9; + SORT_8 var_81_arg_2 = state_36; + SORT_8 var_81 = var_81_arg_0 ? var_81_arg_1 : var_81_arg_2; + SORT_8 next_82_arg_1 = var_81; + SORT_1 var_83_arg_0 = var_33; + SORT_1 var_83_arg_1 = var_24; + SORT_1 var_83_arg_2 = input_3; + SORT_1 var_83 = var_83_arg_0 ? var_83_arg_1 : var_83_arg_2; + SORT_1 next_84_arg_1 = var_83; + SORT_1 var_85_arg_0 = var_33; + SORT_1 var_85_arg_1 = var_24; + SORT_1 var_85_arg_2 = input_4; + SORT_1 var_85 = var_85_arg_0 ? var_85_arg_1 : var_85_arg_2; + SORT_1 next_86_arg_1 = var_85; + SORT_1 var_87_arg_0 = input_3; + SORT_5 var_87_arg_1 = input_6; + SORT_5 var_87_arg_2 = state_42; + SORT_5 var_87 = var_87_arg_0 ? var_87_arg_1 : var_87_arg_2; + SORT_1 var_88_arg_0 = var_33; + SORT_5 var_88_arg_1 = var_28; + SORT_5 var_88_arg_2 = var_87; + SORT_5 var_88 = var_88_arg_0 ? var_88_arg_1 : var_88_arg_2; + SORT_5 next_89_arg_1 = var_88; + SORT_1 var_90_arg_0 = input_4; + SORT_5 var_90_arg_1 = input_7; + SORT_5 var_90_arg_2 = state_44; + SORT_5 var_90 = var_90_arg_0 ? var_90_arg_1 : var_90_arg_2; + SORT_1 var_91_arg_0 = var_33; + SORT_5 var_91_arg_1 = var_28; + SORT_5 var_91_arg_2 = var_90; + SORT_5 var_91 = var_91_arg_0 ? var_91_arg_1 : var_91_arg_2; + SORT_5 next_92_arg_1 = var_91; + // Assigning next states ... + state_11 = next_51_arg_1; + state_16 = next_56_arg_1; + state_18 = next_74_arg_1; + state_29 = next_77_arg_1; + state_31 = next_80_arg_1; + state_36 = next_82_arg_1; + state_38 = next_84_arg_1; + state_40 = next_86_arg_1; + state_42 = next_89_arg_1; + state_44 = next_92_arg_1; + } + return 0; +} diff --git a/test/Industry/CoverageErrorCall/coverage-error-call.prp b/test/Industry/CoverageErrorCall/coverage-error-call.prp new file mode 100644 index 0000000000..496ed998fa --- /dev/null +++ b/test/Industry/CoverageErrorCall/coverage-error-call.prp @@ -0,0 +1,2 @@ +COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) ) + diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c b/test/Industry/FN_SecB_ForwardNull_filed.c index fad10a2644..e4d507692e 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c +++ b/test/Industry/FN_SecB_ForwardNull_filed.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. * @description 空指针解引用 验收失败 @@ -44,8 +39,13 @@ void WB_BadCase_Field(UINT32 inputNum1, UINT32 inputNum2) void WB_BadCase_field2(DataInfo *data) { data->dataBuff = NULL; - *data->dataBuff = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Negative at: {{.*}}test/Industry/FN_SecB_ForwardNull_filed.c:47 19 + *data->dataBuff = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Negative at: {{.*}}test/Industry/FN_SecB_ForwardNull_filed.c:42 19 char *ptr = NULL; *ptr = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c.json b/test/Industry/FN_SecB_ForwardNull_filed.c.json index b54baa91f9..ec0f7d3101 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c.json +++ b/test/Industry/FN_SecB_ForwardNull_filed.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 49, + "startLine": 44, "startColumn": null } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 50, + "startLine": 45, "startColumn": null } } @@ -52,7 +52,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 50, + "startLine": 45, "startColumn": null } } diff --git a/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c b/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c index 4b77bd1b66..58a19a6d5c 100644 --- a/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c +++ b/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c @@ -53,10 +53,9 @@ void call_func(int num) ResourceLeak_bad01(num); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --write-kqueries --max-cycles-before-stuck=0 --use-guided-search=error --check-out-of-memory --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --write-kqueries --max-cycles-before-stuck=0 --use-guided-search=error --annotations=%annotations --mock-policy=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s // CHECK: KLEE: WARNING: 100.00% Reachable Reachable at trace 1 diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c b/test/Industry/NullReturn_BadCase_WhiteBox01.c index 8ee8261adb..0f0ab116e2 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. * @@ -68,3 +63,8 @@ void NullReturn_BadCase_WhiteBox01(UINT8 index, SchedHarqStru *harqInfo) SendMsg(index, usrId, resultInfo); // (3) } } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c.json b/test/Industry/NullReturn_BadCase_WhiteBox01.c.json index 3372239023..42a4b510f1 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c.json +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 45, + "startLine": 40, "startColumn": 9 } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 66, + "startLine": 61, "startColumn": 34 } } @@ -46,7 +46,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 68, + "startLine": 63, "startColumn": 9 } } @@ -59,7 +59,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 56, + "startLine": 51, "startColumn": 30 } } @@ -78,7 +78,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 56, + "startLine": 51, "startColumn": 30 } } @@ -98,7 +98,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 45, + "startLine": 40, "startColumn": 9 } } @@ -111,7 +111,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 66, + "startLine": 61, "startColumn": 34 } } @@ -124,7 +124,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 68, + "startLine": 63, "startColumn": 9 } } @@ -137,7 +137,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 54, + "startLine": 49, "startColumn": 30 } } @@ -156,7 +156,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 54, + "startLine": 49, "startColumn": 30 } } diff --git a/test/Industry/NullReturn_Scene_BadCase01.c b/test/Industry/NullReturn_Scene_BadCase01.c index cfab0db844..b31fb67f34 100644 --- a/test/Industry/NullReturn_Scene_BadCase01.c +++ b/test/Industry/NullReturn_Scene_BadCase01.c @@ -39,8 +39,7 @@ void TestBad1() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --external-calls=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --external-calls=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/NullReturn_Scene_BadCase02.c b/test/Industry/NullReturn_Scene_BadCase02.c index 7042eb01b1..c3a9099c04 100644 --- a/test/Industry/NullReturn_Scene_BadCase02.c +++ b/test/Industry/NullReturn_Scene_BadCase02.c @@ -38,8 +38,7 @@ void TestBad2() printf("The second is %d", info->tm_sec); // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --mock-external-calls --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --extern-calls-can-return-null --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --annotations=%annotations --mock-policy=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/NullReturn_Scene_BadCase03.c b/test/Industry/NullReturn_Scene_BadCase03.c index f24ef754b6..30d8a0d007 100644 --- a/test/Industry/NullReturn_Scene_BadCase03.c +++ b/test/Industry/NullReturn_Scene_BadCase03.c @@ -40,8 +40,7 @@ void TestBad3() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/NullReturn_Scene_BadCase04.c b/test/Industry/NullReturn_Scene_BadCase04.c index d7054e5af2..f2fca4e757 100644 --- a/test/Industry/NullReturn_Scene_BadCase04.c +++ b/test/Industry/NullReturn_Scene_BadCase04.c @@ -44,9 +44,8 @@ void TestBad4() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --mock-external-calls --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --annotations=%annotations --mock-policy=all --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -// CHEK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 \ No newline at end of file +// CHEK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 diff --git a/test/Industry/NullReturn_Scene_BadCase06.c b/test/Industry/NullReturn_Scene_BadCase06.c index 8ad07ac540..8fbac9c0d7 100644 --- a/test/Industry/NullReturn_Scene_BadCase06.c +++ b/test/Industry/NullReturn_Scene_BadCase06.c @@ -52,10 +52,9 @@ void TestBad6(unsigned int count) free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s // CHECK-DAG: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 diff --git a/test/Industry/NullReturn_Scene_BadCase08.cpp b/test/Industry/NullReturn_Scene_BadCase08.cpp index 07870565a0..d066fdc474 100644 --- a/test/Industry/NullReturn_Scene_BadCase08.cpp +++ b/test/Industry/NullReturn_Scene_BadCase08.cpp @@ -37,9 +37,8 @@ void TestBad9() printf("the current integer is: %d", *p); // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clangxx %s -emit-llvm %O0opt -c -g -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --write-kqueries --use-guided-search=error --location-accuracy --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --write-kqueries --use-guided-search=error --location-accuracy --annotations=%annotations --mock-policy=failed --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 2 \ No newline at end of file diff --git a/test/Industry/SecB_ForwardNull.c b/test/Industry/SecB_ForwardNull.c index ef5866afbc..522e1e6fe4 100644 --- a/test/Industry/SecB_ForwardNull.c +++ b/test/Industry/SecB_ForwardNull.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. * @description 空指针解引用 验收失败 @@ -133,3 +128,8 @@ void badbad(char *ptr) ptr = NULL; *ptr = 'a'; // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/SecB_ForwardNull.c.json b/test/Industry/SecB_ForwardNull.c.json index d26344534b..ee8294c266 100644 --- a/test/Industry/SecB_ForwardNull.c.json +++ b/test/Industry/SecB_ForwardNull.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 133, + "startLine": 128, "startColumn": null } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 134, + "startLine": 129, "startColumn": null } } @@ -52,7 +52,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 134, + "startLine": 129, "startColumn": null } } diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase01.c b/test/Industry/UseAfterFree/Double_Free_BadCase01.c index cece04e8a7..34420ba6ee 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase01.c @@ -16,8 +16,8 @@ * @author xwx356597;x00407107 * */ + #include -#include //@scene 指针释放后未置空导致双重释放 void DoubleFreeBad01() @@ -36,8 +36,7 @@ void DoubleFreeBad01() free(p); // CHECK: KLEE: WARNING: 100.00% DoubleFree True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase02.c b/test/Industry/UseAfterFree/Double_Free_BadCase02.c index e6e93818d8..f048ea3234 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase02.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase02.c @@ -16,8 +16,8 @@ * @author xwx356597;x00407107 * */ + #include -#include //@scene 指针释放后未置空,有条件地再再次释放导致双重释放 void DoubleFreeBad02(int flag) @@ -39,8 +39,7 @@ void DoubleFreeBad02(int flag) } } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp index 6c15434bf4..9a6d3fdb5b 100644 --- a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp +++ b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp @@ -17,7 +17,6 @@ * */ -#include #include #include @@ -34,6 +33,7 @@ typedef struct { int a; char *pname; }Data; + //全局变量 分支结束前要重新赋值 char *MSG = (char*)malloc(1000); @@ -75,10 +75,9 @@ int main() return 0; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s // CHECK: KLEE: WARNING: 100.00% UseAfterFree False Positive at trace 1 diff --git a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c index 9c171549e9..a8e08c302b 100644 --- a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c @@ -33,8 +33,7 @@ void UseAfterFree() return; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/ZeroDeref_Scene_BadCase02.c b/test/Industry/ZeroDeref_Scene_BadCase02.c index 0e65b66155..31ac93948c 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase02.c +++ b/test/Industry/ZeroDeref_Scene_BadCase02.c @@ -38,8 +38,7 @@ void TestBad9() memcpy(pDest, p, BUFFERSIZE); // CHECK-DAG: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/ZeroDeref_Scene_BadCase05.c b/test/Industry/ZeroDeref_Scene_BadCase05.c index d094cea77b..f531cf719c 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase05.c +++ b/test/Industry/ZeroDeref_Scene_BadCase05.c @@ -62,10 +62,9 @@ void TestBad18(struct STU *stu) HelpBadTest1(NULL); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --mock-external-calls --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --annotations=%annotations --mock-policy=all --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 2 -// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 \ No newline at end of file +// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c new file mode 100644 index 0000000000..aa563ed00a --- /dev/null +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -0,0 +1,112 @@ +// REQUIRES: not-darwin, not-san +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-policy=all --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state %t1.bc + +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %gcov-files-path > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 1: +// CHECK: Lines executed:{{(8[0-9]\.[0-9][0-9])}}% of 5{{8|9}} +// CHECK-NEXT: Branches executed:100.00% of 1{{8|4}} +// CHECK-NEXT: Taken at least once:{{(8[0-9]\.[0-9][0-9])}}% of 1{{8|4}} + +#include "klee-test-comp.c" +/* extended Euclid's algorithm */ +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: + {reach_error();} + } + return; +} + +int main() { + int x, y; + long long a, b, p, q, r, s; + x = __VERIFIER_nondet_int(); + assume_abort_if_not(x>=0 && x<=10); + y = __VERIFIER_nondet_int(); + assume_abort_if_not(y>=0 && y<=10); + assume_abort_if_not(x >= 1); + assume_abort_if_not(y >= 1); + + a = x; + b = y; + p = 1; + q = 0; + r = 0; + s = 1; + + while (1) { + if (!(b != 0)) + break; + long long c, k; + c = a; + k = 0; + + while (1) { + if (!(c >= b)) + break; + long long d, v; + d = 1; + v = b; + + while (1) { + __VERIFIER_assert(a == y * r + x * p); + __VERIFIER_assert(b == x * q + y * s); + __VERIFIER_assert(a == k * b + c); + __VERIFIER_assert(v == b * d); + + if (!(c >= 2 * v)) + break; + d = 2 * d; + v = 2 * v; + } + c = c - v; + k = k + d; + } + + a = b; + b = c; + long long temp; + temp = p; + p = q; + q = temp - q * k; + temp = r; + r = s; + s = temp - s * k; + } + __VERIFIER_assert(p*x - q*x + r*y - s*y == a); + return 0; +} diff --git a/test/Industry/fn_reverse_null.c b/test/Industry/fn_reverse_null.c index 0e02ebc842..630ac76e28 100644 --- a/test/Industry/fn_reverse_null.c +++ b/test/Industry/fn_reverse_null.c @@ -53,8 +53,7 @@ void TestErr4(TreeNode *head) return; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --external-calls=all --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --external-calls=all --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/fp_forward_null_address.c b/test/Industry/fp_forward_null_address.c index f39297d2a4..b875cce44d 100644 --- a/test/Industry/fp_forward_null_address.c +++ b/test/Industry/fp_forward_null_address.c @@ -22,8 +22,7 @@ void foo() int v = *p; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-cycles-before-stuck=150 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --max-cycles-before-stuck=150 --use-guided-search=error --annotations=%annotations --mock-policy=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/fp_null_returns_self_define.c b/test/Industry/fp_null_returns_self_define.c index 2ed62cfb68..6329a45238 100644 --- a/test/Industry/fp_null_returns_self_define.c +++ b/test/Industry/fp_null_returns_self_define.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s #include diff --git a/test/Industry/fp_null_returns_self_define2.c b/test/Industry/fp_null_returns_self_define2.c index f737f18cc5..551e7aed67 100644 --- a/test/Industry/fp_null_returns_self_define2.c +++ b/test/Industry/fp_null_returns_self_define2.c @@ -26,8 +26,7 @@ void TEST_NullReturns004(unsigned short index) sink(value); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/if2.c b/test/Industry/if2.c index d52edf529f..b6ef8b0982 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -8,11 +8,10 @@ int main(int x) { return *p; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-stepped-instructions=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-instructions=45 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-NONE // CHECK-NONE: KLEE: WARNING: 50.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out/messages.txt %s -check-prefix=CHECK-DISTANCE -// CHECK-DISTANCE: KLEE: (0, 1, 1) for Target 1: error in function main (lines 8 to 8) +// CHECK-DISTANCE: KLEE: (0, 1, 0) for Target 1: error in function main (lines 8 to 8) diff --git a/test/Industry/ll_create_rec-alloca-2.c b/test/Industry/ll_create_rec-alloca-2.c new file mode 100644 index 0000000000..27b037bf35 --- /dev/null +++ b/test/Industry/ll_create_rec-alloca-2.c @@ -0,0 +1,57 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --delete-dead-loops=false --cex-cache-validity-cores --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs --search=random-path %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -check-prefix=CHECK-BRANCH -input-file=%t.stats %s + +// Branch coverage 100%, and instruction coverage may vary: +// CHECK-BRANCH: ICov(%),BCov(%) +// CHECK-BRANCH-NEXT: {{([1-9][0-9]\.[0-9][0-9])}},100.00 + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=blocks --delete-dead-loops=false --cex-cache-validity-cores --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs --search=random-path %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -check-prefix=CHECK-BLOCK -input-file=%t.stats %s + +// Branch coverage 100%, and instruction 100%: +// CHECK-BLOCK: ICov(%),BCov(%) +// CHECK-BLOCK-NEXT: 100.00,100.00 + + +#include "klee-test-comp.c" + +/* + * Date: 30/09/2015 + * Created by: + * Ton Chanh Le (chanhle@comp.nus.edu.sg) and + * Duc Muoi Tran (muoitranduc@gmail.com) + */ + +extern int __VERIFIER_nondet_int(); + +typedef struct node { + int val; + struct node* next; +} node_t; + +// Create a new linked list with length n when n >= 0 +// or non-terminating when n < 0 +node_t* new_ll(int n) +{ + if (n == 0) + return 0; + node_t* head = malloc(sizeof(node_t)); + head->val = n; + head->next = new_ll(n-1); + return head; +} + +int main () +{ + int n = __VERIFIER_nondet_int(); + if (n < 0) { + return 0; + } + node_t* head = new_ll(n); + return 0; +} diff --git a/test/Industry/test.c b/test/Industry/test.c index 9d84770da0..500ab31738 100644 --- a/test/Industry/test.c +++ b/test/Industry/test.c @@ -19,11 +19,10 @@ void TestBad8(int len) buf[0] = 'a'; // CHECK-NUM: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } // CHECK-UID: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 8389b1896658d867c9e15267acfe8c32 -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-NUM // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.sarif %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.sarif %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-UID diff --git a/test/Industry/while_true.c b/test/Industry/while_true.c index a2eebdcc0a..ffbf90e30b 100644 --- a/test/Industry/while_true.c +++ b/test/Industry/while_true.c @@ -8,17 +8,16 @@ int main() { return *p; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out-1 -// RUN: %klee --output-dir=%t.klee-out-1 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=10 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out-1 --use-guided-search=error --mock-policy=failed --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out-1/warnings.txt %s -check-prefix=CHECK-NONE // CHECK-NONE: KLEE: WARNING: 0.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out-1/messages.txt %s -check-prefix=CHECK-REACH-1 // CHECK-REACH-1: (0, 1, 4) for Target 1: error in function main (lines 8 to 8) // RUN: rm -rf %t.klee-out-2 -// RUN: %klee --output-dir=%t.klee-out-2 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=50000 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out-2 --use-guided-search=error --mock-policy=failed --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=4980 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out-2/warnings.txt %s -check-prefix=CHECK-ALL // CHECK-ALL: KLEE: WARNING: 99.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out-2/messages.txt %s -check-prefix=CHECK-REACH-2 diff --git a/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c index 7a6d4ff09c..8314734367 100644 --- a/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c +++ b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c @@ -1,7 +1,8 @@ -// REQUIRES: z3 +// REQUIRES: not-msan +// Disabling msan because it times out on CI // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3 -max-memory=6008 --optimize=true --skip-not-lazy-initialized -output-source=true --output-stats=false --output-istats=false --write-xml-tests --write-ktests=false --xml-metadata-programfile=wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c --xml-metadata-programhash=a18daeacf63b42ad6e1cb490555b7cdecd71ad6e58b167ed0f5626c03bc3d772 --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error --dump-states-on-halt=false -exit-on-error-type=Assert --search=dfs --search=random-path -max-time=20 %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false -max-memory=6008 --optimize=true --skip-not-lazy-initialized -output-source=true --output-stats=false --output-istats=false --write-xml-tests --write-ktests=false --xml-metadata-programfile=wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c --xml-metadata-programhash=a18daeacf63b42ad6e1cb490555b7cdecd71ad6e58b167ed0f5626c03bc3d772 --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error --dump-states-on-halt=all -exit-on-error-type=Assert --search=dfs --search=random-path -max-time=20 %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s // RUN: test -f %t.klee-out/test000001.xml // RUN: not test -f %t.klee-out/test000001.ktest diff --git a/test/InteractiveMode/interactive_mode.c b/test/InteractiveMode/interactive_mode.c deleted file mode 100644 index 1adb5e01f2..0000000000 --- a/test/InteractiveMode/interactive_mode.c +++ /dev/null @@ -1,92 +0,0 @@ -// REQUIRES: not-ubsan -// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc -// RUN: rm -rf %t.klee-out %t.entrypoints -// RUN: echo sign_sum >> %t.entrypoints -// RUN: echo comparison >> %t.entrypoints -// RUN: echo segment_intersection >> %t.entrypoints -// RUN: echo main >> %t.entrypoints -// RUN: %klee --output-dir=%t.klee-out --entry-point=main --interactive --entrypoints-file=%t.entrypoints %t.bc - -// RUN: test -f %t.klee-out/sign_sum/test000001.ktest -// RUN: test -f %t.klee-out/sign_sum/test000002.ktest -// RUN: test -f %t.klee-out/sign_sum/test000003.ktest -// RUN: not test -f %t.klee-out/sign_sum/test000004.ktest - -// RUN: test -f %t.klee-out/comparison/test000001.ktest -// RUN: test -f %t.klee-out/comparison/test000002.ktest -// RUN: not test -f %t.klee-out/comparison/test000003.ktest - -// RUN: test -f %t.klee-out/segment_intersection/test000001.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000002.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000003.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000004.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000005.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000006.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000007.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000008.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000009.ktest -// RUN: not test -f %t.klee-out/segment_intersection/test000010.ktest - -// RUN: test -f %t.klee-out/main/test000001.ktest -// RUN: not test -f %t.klee-out/main/test000002.ktest - -#include "klee/klee.h" -#include - -int sign_sum() { - int x, y; - klee_make_symbolic(&x, sizeof(int), "x"); - klee_make_symbolic(&y, sizeof(int), "y"); - - int c = 0; - if (x + y > 0) { - c = 1; - } else if (x + y < 0) { - c = -1; - } else { - c = 0; - } - return 0; -} - -int comparison() { - int x, y; - klee_make_symbolic(&x, sizeof(int), "x"); - klee_make_symbolic(&y, sizeof(int), "y"); - - if (x < y) { - return 1; - } else { - return 0; - } -} - -int segment_intersection() { - int l, r, A, B; - klee_make_symbolic(&l, sizeof(int), "l"); - klee_make_symbolic(&r, sizeof(int), "r"); - klee_make_symbolic(&A, sizeof(int), "A"); - klee_make_symbolic(&B, sizeof(int), "B"); - - if (l > r || A > B) { - return -1; - } - - if (l > B || r < A) { - return 0; - } - - if (A <= l && r <= B) { - return r - l; - } - - if (l <= A && B <= r) { - return B - A; - } - - return (r <= B ? r : B) - (l >= A ? l : A); -} - -int main() { - return 0; -} diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_assume.c b/test/Replay/libkleeruntest/replay_invalid_klee_assume.c index 89584d6a29..b83cce79e6 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_assume.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_assume.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_choose.c b/test/Replay/libkleeruntest/replay_invalid_klee_choose.c index 32cd136489..9f114d74d9 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_choose.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_choose.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_range.c b/test/Replay/libkleeruntest/replay_invalid_klee_range.c index f342a56aca..7cb016dd28 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_range.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_range.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_num_objects.c b/test/Replay/libkleeruntest/replay_invalid_num_objects.c index ca5615ccc0..8bc5d08d1b 100644 --- a/test/Replay/libkleeruntest/replay_invalid_num_objects.c +++ b/test/Replay/libkleeruntest/replay_invalid_num_objects.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_object_names.c b/test/Replay/libkleeruntest/replay_invalid_object_names.c index 88e81e1bd8..4111da54d5 100644 --- a/test/Replay/libkleeruntest/replay_invalid_object_names.c +++ b/test/Replay/libkleeruntest/replay_invalid_object_names.c @@ -12,7 +12,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_object_size.c b/test/Replay/libkleeruntest/replay_invalid_object_size.c index 4de37bbf7a..6a1e50e28f 100644 --- a/test/Replay/libkleeruntest/replay_invalid_object_size.c +++ b/test/Replay/libkleeruntest/replay_invalid_object_size.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include #include diff --git a/test/Replay/libkleeruntest/replay_mocks.c b/test/Replay/libkleeruntest/replay_mocks.c new file mode 100644 index 0000000000..615bea931b --- /dev/null +++ b/test/Replay/libkleeruntest/replay_mocks.c @@ -0,0 +1,27 @@ +// REQUIRES: geq-llvm-11.0 +// REQUIRES: not-darwin +// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --mock-policy=all %t.bc + +// RUN: %llc %t.bc -filetype=obj -o %t.o +// RUN: %llc %t.klee-out/externals.ll -filetype=obj -o %t_externals.o +// RUN: %objcopy --redefine-syms %t.klee-out/redefinitions.txt %t.o +// RUN: %cc -no-pie %t_externals.o %t.o %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner +// RUN: test -f %t.klee-out/test000001.ktest +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner + +// RUN: %runmocks %cc -no-pie %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner2 %t.klee-out %t.bc +// RUN: test -f %t.klee-out/test000001.ktest +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner2 + +extern int variable; + +extern int foo(int); + +int main() { + int a; + klee_make_symbolic(&a, sizeof(a), "a"); + a = variable + foo(a); + return 0; +} diff --git a/test/Solver/2016-04-12-array-parsing-bug.kquery b/test/Solver/2016-04-12-array-parsing-bug.kquery index 044144ba6a..2fe11893e5 100644 --- a/test/Solver/2016-04-12-array-parsing-bug.kquery +++ b/test/Solver/2016-04-12-array-parsing-bug.kquery @@ -5,8 +5,8 @@ makeSymbolic0 : (array (w64 8) (makeSymbolic A_data 0)) makeSymbolic1 : (array (w64 144) (makeSymbolic A_data_stat 0)) makeSymbolic2 : (array (w64 3) (makeSymbolic arg0 0)) makeSymbolic3 : (array (w64 3) (makeSymbolic arg1 0)) -constant4 : (array (w64 768) (constant [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 3 32 2 32 2 32 2 32 2 32 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 96 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 213 8 213 8 213 8 213 8 213 8 213 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 4 192 4 192 4 192 4 192 4 192 4 192 8 214 8 214 8 214 8 214 8 214 8 214 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 4 192 4 192 4 192 4 192 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0])) -constant5 : (array (w64 277) (constant [0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 24 2 2 25 2 2 2 2 2 2 2 2 2 2 23 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21])) +constant4 : (array (w64 768) (constant [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 3 32 2 32 2 32 2 32 2 32 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 96 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 213 8 213 8 213 8 213 8 213 8 213 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 4 192 4 192 4 192 4 192 4 192 4 192 8 214 8 214 8 214 8 214 8 214 8 214 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 4 192 4 192 4 192 4 192 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] default: 0)) +constant5 : (array (w64 277) (constant [0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 24 2 2 25 2 2 2 2 2 2 2 2 2 2 23 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21] default: 0)) makeSymbolic6 : (array (w64 4) (makeSymbolic model_version 0)) makeSymbolic7 : (array (w64 4) (makeSymbolic n_args 0)) makeSymbolic8 : (array (w64 4) (makeSymbolic n_args_1 0)) diff --git a/test/Solver/AlphaEquivalenceCheck.c b/test/Solver/AlphaEquivalenceCheck.c new file mode 100644 index 0000000000..160fdee515 --- /dev/null +++ b/test/Solver/AlphaEquivalenceCheck.c @@ -0,0 +1,19 @@ +// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out +// RUN: %klee --output-dir=%t1.klee-out --use-alpha-equivalence=false --use-cex-cache=true --use-query-log=solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: rm -rf %t2.klee-out +// RUN: %klee --output-dir=%t2.klee-out --use-alpha-equivalence=true --use-cex-cache=true --use-query-log=solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: grep "^; Query" %t1.klee-out/solver-queries.smt2 | wc -l | grep -q 2 +// RUN: grep "^; Query" %t2.klee-out/solver-queries.smt2 | wc -l | grep -q 1 + +#include "klee/klee.h" + +int main(int argc, char **argv) { + int a, b, c, d; + klee_make_symbolic(&a, sizeof(a), "a"); + klee_make_symbolic(&b, sizeof(b), "b"); + klee_make_symbolic(&c, sizeof(c), "c"); + klee_make_symbolic(&d, sizeof(d), "d"); + klee_assume(a + b == 0); + klee_assume(c + d == 0); +} diff --git a/test/Solver/CallComputeValue.c b/test/Solver/CallComputeValue.c index 3e0dbe408f..36ca85cf1e 100644 --- a/test/Solver/CallComputeValue.c +++ b/test/Solver/CallComputeValue.c @@ -1,7 +1,7 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-lazy-initialization=only %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" @@ -17,5 +17,5 @@ int main() { return 2; } -// CHECK: KLEE: done: completed paths = 17 +// CHECK: KLEE: done: completed paths = {{3|5}} // CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CexCacheCheckBinding.c b/test/Solver/CexCacheCheckBinding.c new file mode 100644 index 0000000000..4743ef1027 --- /dev/null +++ b/test/Solver/CexCacheCheckBinding.c @@ -0,0 +1,8 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --debug-cex-cache-check-binding --search=bfs --use-guided-search=none --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c b/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c new file mode 100644 index 0000000000..f0e1dfc757 --- /dev/null +++ b/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c @@ -0,0 +1,11 @@ +// REQUIRES: bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=bitwuzla --debug-bitwuzla-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=dfs --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=bitwuzla --debug-bitwuzla-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckCoreZ3Bitwuzla.c b/test/Solver/CrosscheckCoreZ3Bitwuzla.c new file mode 100644 index 0000000000..f50a0dd2fc --- /dev/null +++ b/test/Solver/CrosscheckCoreZ3Bitwuzla.c @@ -0,0 +1,10 @@ +// REQUIRES: z3 +// REQUIRES: bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-forked-solver=false --debug-crosscheck-core-solver=bitwuzla --use-guided-search=none %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/DummySolver.c b/test/Solver/DummySolver.c index 9242396854..54d94b5b2c 100644 --- a/test/Solver/DummySolver.c +++ b/test/Solver/DummySolver.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=dummy --use-guided-search=none %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=dummy --use-guided-search=none --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" diff --git a/test/Solver/NoBitwuzla.c b/test/Solver/NoBitwuzla.c new file mode 100644 index 0000000000..a4a915a9d6 --- /dev/null +++ b/test/Solver/NoBitwuzla.c @@ -0,0 +1,10 @@ +// REQUIRES: not-bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: not %klee --output-dir=%t.klee-out --solver-backend=bitwuzla %t1.bc 2>&1 | FileCheck %s +// CHECK: Not compiled with Bitwuzla support +// CHECK: ERROR: Failed to create core solver + +int main(int argc, char **argv) { + return 0; +} diff --git a/test/Solver/Z3ConstantArray.c b/test/Solver/Z3ConstantArray.c index e0452e3106..419c67d124 100644 --- a/test/Solver/Z3ConstantArray.c +++ b/test/Solver/Z3ConstantArray.c @@ -9,14 +9,14 @@ #include "klee/klee.h" int main(int argc, char **argv) { - // CHECK-DAG: (assert (= (select constant11 #x00000000) #x67)) - // CHECK-DAG: (assert (= (select constant11 #x00000001) #x79)) - // CHECK-DAG: (assert (= (select constant11 #x00000002) #x7a)) - // CHECK-DAG: (assert (= (select constant11 #x00000003) #x00)) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv0 32) ) (_ bv103 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv1 32) ) (_ bv121 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv2 32) ) (_ bv122 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) + // CHECK-DAG: (assert (= (select constant01 #x00000000) #x67)) + // CHECK-DAG: (assert (= (select constant01 #x00000001) #x79)) + // CHECK-DAG: (assert (= (select constant01 #x00000002) #x7a)) + // CHECK-DAG: (assert (= (select constant01 #x00000003) #x00)) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv0 32) ) (_ bv103 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv1 32) ) (_ bv121 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv2 32) ) (_ bv122 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) char c[4] = {'g', 'y', 'z', '\0'}; unsigned i; klee_make_symbolic(&i, sizeof i, "i"); diff --git a/test/Solver/Z3LargeConstantArray.kquery b/test/Solver/Z3LargeConstantArray.kquery index d3ccf51e4a..898edd9e22 100644 --- a/test/Solver/Z3LargeConstantArray.kquery +++ b/test/Solver/Z3LargeConstantArray.kquery @@ -1,7 +1,7 @@ # REQUIRES: z3 # RUN: %kleaver --solver-backend=z3 -max-solver-time=20 -debug-z3-dump-queries=%t.smt2 %s &> /dev/null # RUN: grep '(assert (= (select constant0' %t.smt2 -c | grep 3770 -constant0 : (array (w64 3770) (constant [32 0 0 0 192 193 124 5 0 0 0 0 64 242 107 41 0 0 0 0 48 235 107 41 0 0 0 0 0 0 0 0 0 0 0 0 144 0 0 0 14 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 144 33 0 0 65 42 0 0 5 0 0 0 0 0 0 0 7 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 83 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 75 204 147 90 0 0 0 0 55 110 115 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 121 0 0 0 100 101 102 105 110 101 40 96 98 39 44 32 96 117 39 41 10 100 101 102 105 110 101 40 96 104 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 105 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 121 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 65 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 110 39 44 32 50 41 10 100 101 102 105 110 101 40 96 80 39 44 32 50 41 10 0 10 0 10 0 10 128 2 0 0 3 0 0 0 0 0 0 0 200 67 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 249 77 23 3 0 0 0 0 160 42 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 64 13 129 41 0 0 0 0 56 217 22 3 0 0 0 0 96 168 132 41 0 0 0 0 255 255 255 255 255 255 255 255 33 4 0 0 0 0 0 0 48 24 129 41 0 0 0 0 80 43 125 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 255 255 255 255 255 255 255 176 23 129 41 0 0 0 0 252 255 255 255 255 255 255 255 16 14 129 41 0 0 0 0 252 255 255 255 255 255 255 255 32 227 132 41 0 0 0 0 252 255 255 255 255 255 255 255 208 251 132 41 0 0 0 0 252 255 255 255 255 255 255 255 144 16 129 41 0 0 0 0 252 255 255 255 255 255 255 255 192 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 96 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 176 26 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 27 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 51 124 41 0 0 0 0 252 255 255 255 255 255 255 255 48 59 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 68 0 0 0 105 110 116 101 114 110 97 108 32 101 114 114 111 114 32 100 101 116 101 99 116 101 100 59 32 112 108 101 97 115 101 32 114 101 112 111 114 116 32 116 104 105 115 32 98 117 103 32 116 111 32 60 98 117 103 45 109 52 64 103 110 117 46 111 114 103 62 0 19 0 0 0 83 101 103 109 101 110 116 97 116 105 111 110 32 102 97 117 108 116 0 8 0 0 0 65 98 111 114 116 101 100 0 20 0 0 0 73 108 108 101 103 97 108 32 105 110 115 116 114 117 99 116 105 111 110 0 25 0 0 0 70 108 111 97 116 105 110 103 32 112 111 105 110 116 32 101 120 99 101 112 116 105 111 110 0 10 0 0 0 66 117 115 32 101 114 114 111 114 0 2 0 0 0 96 0 2 0 0 0 39 0 2 0 0 0 35 0 2 0 0 0 10 0 40 0 0 0 32 136 117 41 0 0 0 0 24 107 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 0 0 20 25 100 59 116 43 0 0 2 27 100 59 116 43 0 0 223 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 189 22 100 59 116 43 0 0 181 25 100 59 116 43 0 0 140 30 100 59 116 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 24 100 59 116 43 0 0 228 29 100 59 116 43 0 0 242 22 100 59 116 43 0 0 5 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 1 29 100 59 116 43 0 0 167 24 100 59 116 43 0 0 148 23 100 59 116 43 0 0 134 22 100 59 116 43 0 0 114 27 100 59 116 43 0 0 219 21 100 59 116 43 0 0 96 23 100 59 116 43 0 0 0 0 0 0 0 0 0 0 236 25 100 59 116 43 0 0 0 0 0 0 0 0 0 0 60 29 100 59 116 43 0 0 126 25 100 59 116 43 0 0 37 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 28 30 100 59 116 43 0 0 41 23 100 59 116 43 0 0 116 29 100 59 116 43 0 0 81 22 100 59 116 43 0 0 148 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 224 27 100 59 116 43 0 0 74 25 100 59 116 43 0 0 84 30 100 59 116 43 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 22 100 59 116 43 0 0 2 0 0 0 0 48 0 0 248 158 196 4 0 0 0 0 10 0 0 0 99 104 97 110 103 101 99 111 109 0 40 0 0 0 204 23 100 59 116 43 0 0 0 0 128 48 0 0 0 0 65 22 100 59 116 43 0 0 2 0 0 0 170 133 41 0 248 160 196 4 0 0 0 0 12 0 0 0 99 104 97 110 103 101 113 117 111 116 101 0 40 0 0 0 172 29 100 59 116 43 0 0 8 0 0 0 0 0 0 0 125 22 100 59 116 43 0 0 2 0 0 0 0 0 0 38 200 163 196 4 0 0 0 0 5 0 0 0 100 101 99 114 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 80 120 0 0 0 0 178 22 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 166 196 4 0 0 0 0 7 0 0 0 100 101 102 105 110 101 0 40 0 0 0 25 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 233 22 100 59 116 43 0 0 2 0 0 0 17 148 64 0 88 170 196 4 0 0 0 0 5 0 0 0 100 101 102 110 0 40 0 0 0 112 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 30 23 100 59 116 43 0 0 2 0 0 0 160 0 32 7 56 172 196 4 0 0 0 0 7 0 0 0 100 105 118 101 114 116 0 40 0 0 0 81 28 100 59 116 43 0 0 0 0 0 0 0 0 0 0 85 23 100 59 116 43 0 0 2 0 0 0 0 0 0 48 40 173 196 4 0 0 0 0 7 0 0 0 100 105 118 110 117 109 0 40 0 0 0 93 26 100 59 116 43 0 0 0 154 4 0 0 0 0 0 140 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 174 196 4 0 0 0 0 4 0 0 0 100 110 108 0 40 0 0 0 59 27 100 59 116 43 0 0 0 121 34 0 0 0 0 0 192 23 100 59 116 43 0 0 2 0 0 0 160 176 133 41 8 175 196 4 0 0 0 0 8 0 0 0 100 117 109 112 100 101 102 0 40 0 0 0 138 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 248 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 236 197 4 0 0 0 0 9 0 0 0 101 114 114 112 114 105 110 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 64 0 0 0 0 49 24 100 59 116 43 0 0 2 0 0 0 1 0 0 0 24 242 197 4 0 0 0 0 5 0 0 0 101 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 102 24 100 59 116 43 0 0 2 0 0 0 0 0 73 1 152 243 197 4 0 0 0 0 6 0 0 0 105 102 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 156 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 244 197 4 0 0 0 0 7 0 0 0 105 102 101 108 115 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 203 0 0 0 0 0 0 211 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 245 197 4 0 0 0 0 8 0 0 0 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 11 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 246 197 4 0 0 0 0 5 0 0 0 105 110 99 114 0 40 0 0 0 195 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 64 25 100 59 116 43 0 0 2 0 0 0 96 176 133 41 88 247 197 4 0 0 0 0 6 0 0 0 105 110 100 101 120 0 40 0 0 0 204 26 100 59 116 43 0 0 8 0 0 0 0 0 0 0 118 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 249 197 4 0 0 0 0 4 0 0 0 108 101 110 0 40 0 0 0 0 0 0 0 0 0 0 0 0 52 33 0 0 0 0 0 170 25 100 59 116 43 0 0 2 0 0 0 9 63 116 43 88 250 197 4 0 0 0 0 7 0 0 0 109 52 101 120 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 225 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 72 251 197 4 0 0 0 0 7 0 0 0 109 52 119 114 97 112 0 40 0 0 0 169 27 100 59 116 43 0 0 8 0 0 0 0 0 0 0 24 26 100 59 116 43 0 0 2 0 0 0 20 0 0 30 88 118 196 4 0 0 0 0 9 0 0 0 109 97 107 101 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 81 26 100 59 116 43 0 0 2 0 0 0 8 0 0 0 40 121 196 4 0 0 0 0 8 0 0 0 109 107 115 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 137 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 168 7 198 4 0 0 0 0 7 0 0 0 112 111 112 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 0 64 0 0 0 0 192 26 100 59 116 43 0 0 2 0 0 0 192 122 127 41 152 8 198 4 0 0 0 0 8 0 0 0 112 117 115 104 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 248 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 120 10 198 4 0 0 0 0 6 0 0 0 115 104 105 102 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 46 27 100 59 116 43 0 0 2 0 0 0 0 0 52 0 104 11 198 4 0 0 0 0 9 0 0 0 115 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 103 27 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 12 198 4 0 0 0 0 7 0 0 0 115 117 98 115 116 114 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 158 27 100 59 116 43 0 0 2 0 0 0 0 0 64 11 72 13 198 4 0 0 0 0 7 0 0 0 115 121 115 99 109 100 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 27 100 59 116 43 0 0 2 0 0 0 0 0 0 48 56 14 198 4 0 0 0 0 7 0 0 0 115 121 115 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 12 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 40 15 198 4 0 0 0 0 9 0 0 0 116 114 97 99 101 111 102 102 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 8 234 197 4 0 0 0 0 8 0 0 0 116 114 97 99 101 111 110 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 125 28 100 59 116 43 0 0 2 0 0 0 0 0 0 192 248 234 197 4 0 0 0 0 9 0 0 0 116 114 97 110 115 108 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 182 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 200 22 198 4 0 0 0 0 9 0 0 0 117 110 100 101 102 105 110 101 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 239 28 100 59 116 43 0 0 2 0 0 0 0 112 8 0 184 23 198 4 0 0 0 0 9 0 0 0 117 110 100 105 118 101 114 116 0 1 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 99 8 0 0 0 0 0 45 29 100 59 116 43 0 0 1 0 0 0 0 0 0 224 252 28 100 59 116 43 0 0 5 0 0 0 117 110 105 120 0 2 0 0 0 117 0 40 0 0 0 0 0 0 0 0 0 0 0 0 255 95 52 0 0 0 0 104 29 100 59 116 43 0 0 1 0 0 0 240 43 134 41 54 29 100 59 116 43 0 0 2 0 0 0 98 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 29 100 59 116 43 0 0 1 0 0 0 87 0 0 0 110 29 100 59 116 43 0 0 2 0 0 0 104 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 216 29 100 59 116 43 0 0 1 0 0 0 3 24 0 128 166 29 100 59 116 43 0 0 2 0 0 0 105 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 30 100 59 116 43 0 0 1 0 0 0 64 236 0 0 222 29 100 59 116 43 0 0 2 0 0 0 121 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 30 100 59 116 43 0 0 1 0 0 0 48 0 0 0 22 30 100 59 116 43 0 0 2 0 0 0 65 0 2 0 0 0 50 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 30 100 59 116 43 0 0 1 0 0 0 48 120 134 41 78 30 100 59 116 43 0 0 2 0 0 0 110 0 2 0 0 0 50 0 40 0 0 0 21 22 100 59 116 43 0 0 0 0 0 0 0 0 0 0 184 30 100 59 116 43 0 0 1 0 0 0 0 0 0 0 134 30 100 59 116 43 0 0 2 0 0 0 80 0])) +constant0 : (array (w64 3770) (constant [32 0 0 0 192 193 124 5 0 0 0 0 64 242 107 41 0 0 0 0 48 235 107 41 0 0 0 0 0 0 0 0 0 0 0 0 144 0 0 0 14 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 144 33 0 0 65 42 0 0 5 0 0 0 0 0 0 0 7 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 83 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 75 204 147 90 0 0 0 0 55 110 115 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 121 0 0 0 100 101 102 105 110 101 40 96 98 39 44 32 96 117 39 41 10 100 101 102 105 110 101 40 96 104 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 105 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 121 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 65 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 110 39 44 32 50 41 10 100 101 102 105 110 101 40 96 80 39 44 32 50 41 10 0 10 0 10 0 10 128 2 0 0 3 0 0 0 0 0 0 0 200 67 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 249 77 23 3 0 0 0 0 160 42 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 64 13 129 41 0 0 0 0 56 217 22 3 0 0 0 0 96 168 132 41 0 0 0 0 255 255 255 255 255 255 255 255 33 4 0 0 0 0 0 0 48 24 129 41 0 0 0 0 80 43 125 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 255 255 255 255 255 255 255 176 23 129 41 0 0 0 0 252 255 255 255 255 255 255 255 16 14 129 41 0 0 0 0 252 255 255 255 255 255 255 255 32 227 132 41 0 0 0 0 252 255 255 255 255 255 255 255 208 251 132 41 0 0 0 0 252 255 255 255 255 255 255 255 144 16 129 41 0 0 0 0 252 255 255 255 255 255 255 255 192 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 96 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 176 26 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 27 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 51 124 41 0 0 0 0 252 255 255 255 255 255 255 255 48 59 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 68 0 0 0 105 110 116 101 114 110 97 108 32 101 114 114 111 114 32 100 101 116 101 99 116 101 100 59 32 112 108 101 97 115 101 32 114 101 112 111 114 116 32 116 104 105 115 32 98 117 103 32 116 111 32 60 98 117 103 45 109 52 64 103 110 117 46 111 114 103 62 0 19 0 0 0 83 101 103 109 101 110 116 97 116 105 111 110 32 102 97 117 108 116 0 8 0 0 0 65 98 111 114 116 101 100 0 20 0 0 0 73 108 108 101 103 97 108 32 105 110 115 116 114 117 99 116 105 111 110 0 25 0 0 0 70 108 111 97 116 105 110 103 32 112 111 105 110 116 32 101 120 99 101 112 116 105 111 110 0 10 0 0 0 66 117 115 32 101 114 114 111 114 0 2 0 0 0 96 0 2 0 0 0 39 0 2 0 0 0 35 0 2 0 0 0 10 0 40 0 0 0 32 136 117 41 0 0 0 0 24 107 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 0 0 20 25 100 59 116 43 0 0 2 27 100 59 116 43 0 0 223 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 189 22 100 59 116 43 0 0 181 25 100 59 116 43 0 0 140 30 100 59 116 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 24 100 59 116 43 0 0 228 29 100 59 116 43 0 0 242 22 100 59 116 43 0 0 5 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 1 29 100 59 116 43 0 0 167 24 100 59 116 43 0 0 148 23 100 59 116 43 0 0 134 22 100 59 116 43 0 0 114 27 100 59 116 43 0 0 219 21 100 59 116 43 0 0 96 23 100 59 116 43 0 0 0 0 0 0 0 0 0 0 236 25 100 59 116 43 0 0 0 0 0 0 0 0 0 0 60 29 100 59 116 43 0 0 126 25 100 59 116 43 0 0 37 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 28 30 100 59 116 43 0 0 41 23 100 59 116 43 0 0 116 29 100 59 116 43 0 0 81 22 100 59 116 43 0 0 148 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 224 27 100 59 116 43 0 0 74 25 100 59 116 43 0 0 84 30 100 59 116 43 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 22 100 59 116 43 0 0 2 0 0 0 0 48 0 0 248 158 196 4 0 0 0 0 10 0 0 0 99 104 97 110 103 101 99 111 109 0 40 0 0 0 204 23 100 59 116 43 0 0 0 0 128 48 0 0 0 0 65 22 100 59 116 43 0 0 2 0 0 0 170 133 41 0 248 160 196 4 0 0 0 0 12 0 0 0 99 104 97 110 103 101 113 117 111 116 101 0 40 0 0 0 172 29 100 59 116 43 0 0 8 0 0 0 0 0 0 0 125 22 100 59 116 43 0 0 2 0 0 0 0 0 0 38 200 163 196 4 0 0 0 0 5 0 0 0 100 101 99 114 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 80 120 0 0 0 0 178 22 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 166 196 4 0 0 0 0 7 0 0 0 100 101 102 105 110 101 0 40 0 0 0 25 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 233 22 100 59 116 43 0 0 2 0 0 0 17 148 64 0 88 170 196 4 0 0 0 0 5 0 0 0 100 101 102 110 0 40 0 0 0 112 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 30 23 100 59 116 43 0 0 2 0 0 0 160 0 32 7 56 172 196 4 0 0 0 0 7 0 0 0 100 105 118 101 114 116 0 40 0 0 0 81 28 100 59 116 43 0 0 0 0 0 0 0 0 0 0 85 23 100 59 116 43 0 0 2 0 0 0 0 0 0 48 40 173 196 4 0 0 0 0 7 0 0 0 100 105 118 110 117 109 0 40 0 0 0 93 26 100 59 116 43 0 0 0 154 4 0 0 0 0 0 140 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 174 196 4 0 0 0 0 4 0 0 0 100 110 108 0 40 0 0 0 59 27 100 59 116 43 0 0 0 121 34 0 0 0 0 0 192 23 100 59 116 43 0 0 2 0 0 0 160 176 133 41 8 175 196 4 0 0 0 0 8 0 0 0 100 117 109 112 100 101 102 0 40 0 0 0 138 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 248 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 236 197 4 0 0 0 0 9 0 0 0 101 114 114 112 114 105 110 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 64 0 0 0 0 49 24 100 59 116 43 0 0 2 0 0 0 1 0 0 0 24 242 197 4 0 0 0 0 5 0 0 0 101 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 102 24 100 59 116 43 0 0 2 0 0 0 0 0 73 1 152 243 197 4 0 0 0 0 6 0 0 0 105 102 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 156 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 244 197 4 0 0 0 0 7 0 0 0 105 102 101 108 115 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 203 0 0 0 0 0 0 211 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 245 197 4 0 0 0 0 8 0 0 0 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 11 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 246 197 4 0 0 0 0 5 0 0 0 105 110 99 114 0 40 0 0 0 195 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 64 25 100 59 116 43 0 0 2 0 0 0 96 176 133 41 88 247 197 4 0 0 0 0 6 0 0 0 105 110 100 101 120 0 40 0 0 0 204 26 100 59 116 43 0 0 8 0 0 0 0 0 0 0 118 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 249 197 4 0 0 0 0 4 0 0 0 108 101 110 0 40 0 0 0 0 0 0 0 0 0 0 0 0 52 33 0 0 0 0 0 170 25 100 59 116 43 0 0 2 0 0 0 9 63 116 43 88 250 197 4 0 0 0 0 7 0 0 0 109 52 101 120 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 225 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 72 251 197 4 0 0 0 0 7 0 0 0 109 52 119 114 97 112 0 40 0 0 0 169 27 100 59 116 43 0 0 8 0 0 0 0 0 0 0 24 26 100 59 116 43 0 0 2 0 0 0 20 0 0 30 88 118 196 4 0 0 0 0 9 0 0 0 109 97 107 101 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 81 26 100 59 116 43 0 0 2 0 0 0 8 0 0 0 40 121 196 4 0 0 0 0 8 0 0 0 109 107 115 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 137 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 168 7 198 4 0 0 0 0 7 0 0 0 112 111 112 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 0 64 0 0 0 0 192 26 100 59 116 43 0 0 2 0 0 0 192 122 127 41 152 8 198 4 0 0 0 0 8 0 0 0 112 117 115 104 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 248 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 120 10 198 4 0 0 0 0 6 0 0 0 115 104 105 102 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 46 27 100 59 116 43 0 0 2 0 0 0 0 0 52 0 104 11 198 4 0 0 0 0 9 0 0 0 115 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 103 27 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 12 198 4 0 0 0 0 7 0 0 0 115 117 98 115 116 114 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 158 27 100 59 116 43 0 0 2 0 0 0 0 0 64 11 72 13 198 4 0 0 0 0 7 0 0 0 115 121 115 99 109 100 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 27 100 59 116 43 0 0 2 0 0 0 0 0 0 48 56 14 198 4 0 0 0 0 7 0 0 0 115 121 115 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 12 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 40 15 198 4 0 0 0 0 9 0 0 0 116 114 97 99 101 111 102 102 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 8 234 197 4 0 0 0 0 8 0 0 0 116 114 97 99 101 111 110 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 125 28 100 59 116 43 0 0 2 0 0 0 0 0 0 192 248 234 197 4 0 0 0 0 9 0 0 0 116 114 97 110 115 108 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 182 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 200 22 198 4 0 0 0 0 9 0 0 0 117 110 100 101 102 105 110 101 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 239 28 100 59 116 43 0 0 2 0 0 0 0 112 8 0 184 23 198 4 0 0 0 0 9 0 0 0 117 110 100 105 118 101 114 116 0 1 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 99 8 0 0 0 0 0 45 29 100 59 116 43 0 0 1 0 0 0 0 0 0 224 252 28 100 59 116 43 0 0 5 0 0 0 117 110 105 120 0 2 0 0 0 117 0 40 0 0 0 0 0 0 0 0 0 0 0 0 255 95 52 0 0 0 0 104 29 100 59 116 43 0 0 1 0 0 0 240 43 134 41 54 29 100 59 116 43 0 0 2 0 0 0 98 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 29 100 59 116 43 0 0 1 0 0 0 87 0 0 0 110 29 100 59 116 43 0 0 2 0 0 0 104 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 216 29 100 59 116 43 0 0 1 0 0 0 3 24 0 128 166 29 100 59 116 43 0 0 2 0 0 0 105 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 30 100 59 116 43 0 0 1 0 0 0 64 236 0 0 222 29 100 59 116 43 0 0 2 0 0 0 121 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 30 100 59 116 43 0 0 1 0 0 0 48 0 0 0 22 30 100 59 116 43 0 0 2 0 0 0 65 0 2 0 0 0 50 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 30 100 59 116 43 0 0 1 0 0 0 48 120 134 41 78 30 100 59 116 43 0 0 2 0 0 0 110 0 2 0 0 0 50 0 40 0 0 0 21 22 100 59 116 43 0 0 0 0 0 0 0 0 0 0 184 30 100 59 116 43 0 0 1 0 0 0 0 0 0 0 134 30 100 59 116 43 0 0 2 0 0 0 80 0] default: 0)) makeSymbolic1 : (array (w64 121) (makeSymbolic stdin 0)) diff --git a/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c index 4dd74f1d3c..fb8ace55c5 100644 --- a/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c +++ b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c @@ -1,7 +1,7 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3-tree --max-solvers-approx-tree-inc=16 -max-memory=6008 --optimize --skip-not-lazy-initialized -output-source=false --output-stats=false --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error -dump-states-on-halt=true -exit-on-error-type=Assert --search=dfs -max-instructions=6000 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3-tree --max-solvers-approx-tree-inc=16 --optimize-aggressive=false --track-coverage=branches -max-memory=6008 --optimize --skip-not-lazy-initialized -output-source=false --output-stats=false --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error -dump-states-on-halt=all -exit-on-error-type=Assert --search=dfs -max-instructions=6000 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s // CHECK-VERDICT: KLEE: done: total instructions = 6000 #include "klee-test-comp.c" diff --git a/test/Solver/sina2f.c b/test/Solver/sina2f.c new file mode 100644 index 0000000000..c732bf2ddb --- /dev/null +++ b/test/Solver/sina2f.c @@ -0,0 +1,67 @@ +// REQUIRES: bitwuzla +// REQUIRES: not-asan +// REQUIRES: not-msan +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-policy=all --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s +#include "klee-test-comp.c" + +/* + * Benchmarks contributed by Divyesh Unadkat[1,2], Supratik Chakraborty[1], Ashutosh Gupta[1] + * [1] Indian Institute of Technology Bombay, Mumbai + * [2] TCS Innovation labs, Pune + * + */ + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "sina2f.c", 10, "reach_error"); } +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } +} +extern int __VERIFIER_nondet_int(void); +void *malloc(unsigned int size); + +int N; + +int main() { + N = __VERIFIER_nondet_int(); + if (N <= 0) + return 1; + assume_abort_if_not(N <= 2147483647 / sizeof(int)); + + int i; + long long sum[1]; + long long *a = malloc(sizeof(long long) * N); + + sum[0] = 1; + for (i = 0; i < N; i++) { + a[i] = 1; + } + + for (i = 0; i < N; i++) { + sum[0] = sum[0] + a[i]; + } + + for (i = 0; i < N; i++) { + a[i] = a[i] + sum[0]; + } + + for (i = 0; i < N; i++) { + __VERIFIER_assert(a[i] == N); + } + return 1; +} + +// CHECK: KLEE: done diff --git a/test/lit.cfg b/test/lit.cfg index 75978e47b7..79f071b5c0 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -90,17 +90,27 @@ if config.test_exec_root is None: # Add substitutions from lit.site.cfg -subs = [ 'clangxx', 'clang', 'cc', 'cxx', 'O0opt', 'c_prefixes_8', 'c_prefixes_10', 'cpp_prefixes_10' ] +subs = [ 'clangxx', 'clang', 'cc', 'objcopy', 'cxx', 'O0opt', 'c_prefixes_8', 'c_prefixes_10', 'cpp_prefixes_10' ] for name in subs: value = getattr(config, name, None) if value == None: lit_config.fatal('{0} is not set'.format(name)) config.substitutions.append( ('%' + name, value)) +config.substitutions.append( + ('%runmocks', os.path.join(klee_src_root, 'scripts/run_tests_with_mocks.py')) +) + # Add a substitution for lli. config.substitutions.append( ('%lli', os.path.join(llvm_tools_dir, 'lli')) ) + +# Add a substitution for llc. +config.substitutions.append( + ('%llc', os.path.join(llvm_tools_dir, 'llc')) +) + # Add a substitution for llvm-as config.substitutions.append( ('%llvmas', os.path.join(llvm_tools_dir, 'llvm-as')) @@ -113,6 +123,15 @@ config.substitutions.append( config.substitutions.append( ('%llvmlink', os.path.join(llvm_tools_dir, 'llvm-link')) ) +# Add a substitution for llvm-link +config.substitutions.append( + ('%llvmcov', os.path.join(llvm_tools_dir, 'llvm-cov')) +) + +# Add a substitution for llvm-objcopy +config.substitutions.append( + ('%llvmobjcopy', os.path.join(llvm_tools_dir, 'llvm-objcopy')) +) # Add a substition for libkleeruntest config.substitutions.append( @@ -162,9 +181,26 @@ config.substitutions.append( ('%gentmp', os.path.join(klee_src_root, 'scripts/genTempFiles.sh')) ) +config.substitutions.append( + ('%replay', os.path.join(klee_src_root, 'scripts/replay.sh')) +) + +config.substitutions.append( + ('%annotations', os.path.join(klee_src_root, 'configs/annotations.json')) +) + config.substitutions.append( ('%libcxx_include', getattr(config, 'libcxx_include_dir', None))) +if config.target_triple.find("darwin") != -1: + config.substitutions.append( + ('%gcov-files-path', '%basename_t') + ) +else: + config.substitutions.append( + ('%gcov-files-path', '%t_runner-%basename_t') + ) + # Add feature for the LLVM version in use, so it can be tested in REQUIRES and # XFAIL checks. We also add "not-XXX" variants, for the same reason. known_llvm_versions = { "9.0", "10.0", "11.0", "11.1", "12.0", "13.0", "14.0" } @@ -198,6 +234,14 @@ if config.enable_z3: config.available_features.add('z3') else: config.available_features.add('not-z3') +if config.enable_metasmt: + config.available_features.add('metasmt') +else: + config.available_features.add('not-metasmt') +if config.enable_bitwuzla: + config.available_features.add('bitwuzla') +else: + config.available_features.add('not-bitwuzla') # Zlib config.available_features.add('zlib' if config.enable_zlib else 'not-zlib') @@ -244,6 +288,7 @@ else: # m32 support config.available_features.add('{}target-x86'.format('' if config.target_triple.find("i386") != -1 else 'not-')) +config.available_features.add('{}target-x86_64'.format('' if config.target_triple.find("x86_64") != -1 else 'not-')) config.available_features.add('{}32bit-support'.format('' if config.have_32bit_support else 'not-')) @@ -251,3 +296,8 @@ config.available_features.add('{}32bit-support'.format('' if config.have_32bit_s config.available_features.add('{}asan'.format('' if config.have_asan else 'not-')) config.available_features.add('{}ubsan'.format('' if config.have_ubsan else 'not-')) config.available_features.add('{}msan'.format('' if config.have_msan else 'not-')) + +if config.have_asan or config.have_ubsan or config.have_msan: + config.available_features.add('san') +else: + config.available_features.add('not-san') diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 15bc4a20a5..17ad995b8d 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -35,6 +35,7 @@ config.clang = "@LLVMCC@" config.clangxx = "@LLVMCXX@" config.cc = "@NATIVE_CC@" +config.objcopy = "@NATIVE_OBJCOPY@" config.cxx = "@NATIVE_CXX@" # NOTE: any changes to compiler flags also have to be applied to @@ -51,6 +52,8 @@ config.enable_eh_cxx = True if @SUPPORT_KLEE_EH_CXX@ == 1 else False config.have_selinux = True if @HAVE_SELINUX@ == 1 else False config.enable_stp = True if @ENABLE_STP@ == 1 else False config.enable_z3 = True if @ENABLE_Z3@ == 1 else False +config.enable_metasmt = True if @ENABLE_METASMT@ == 1 else False +config.enable_bitwuzla = True if @ENABLE_BITWUZLA@ == 1 else False config.enable_zlib = True if @HAVE_ZLIB_H@ == 1 else False config.have_asan = True if @IS_ASAN_BUILD@ == 1 else False config.have_ubsan = True if @IS_UBSAN_BUILD@ == 1 else False diff --git a/test/regression/2020-02-24-count-paths-nodump.c b/test/regression/2020-02-24-count-paths-nodump.c index c066886c20..83af8e919b 100644 --- a/test/regression/2020-02-24-count-paths-nodump.c +++ b/test/regression/2020-02-24-count-paths-nodump.c @@ -1,8 +1,8 @@ -// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=false +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=none // REQUIRES: not-asan // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee -dump-states-on-halt=false -max-instructions=1 -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +// RUN: %klee -dump-states-on-halt=none -max-instructions=1 -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s int main(int argc, char **argv) { // just do something diff --git a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c index ec58f72187..6befbf686c 100644 --- a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c +++ b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c @@ -1,19 +1,12 @@ -// REQUIRES: not-darwin, z3 +// REQUIRES: not-darwin // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --solver-backend=z3 --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log - -// RUN: test -f %t.klee-out/test000006.ktest +// RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log // RUN: %cc %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000002.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000003.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000004.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000005.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000006.ktest %t_runner >> %t_runner.log - +// RUN: rm -f %t_runner.log +// RUN: %replay %t.klee-out %t_runner > %t_runner.log // RUN: FileCheck -input-file=%t_runner.log %s #include diff --git a/test/regression/2023-03-27-lib-function.c b/test/regression/2023-03-27-lib-function.c index 4754267431..90df4b41a4 100644 --- a/test/regression/2023-03-27-lib-function.c +++ b/test/regression/2023-03-27-lib-function.c @@ -11,6 +11,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #ifdef INET_NTOP const char *inet_ntop(int af, const void *restrict src, char *restrict dst, socklen_t size) { @@ -22,8 +26,8 @@ const char *inet_ntop(int af, const void *restrict src, int main(int argc, char **argv) { inet_ntop(0, 0, 0, 0); - // CHECK_INTERNAL-NOT: calling external: inet_ntop - // CHECK_EXTERNAL: calling external: inet_ntop + // CHECK_INTERNAL-NOT: calling external: {{inet_ntop|__inet_ntop}} + // CHECK_EXTERNAL: calling external: {{inet_ntop|__inet_ntop}} #ifdef INET_PTON struct in_addr inaddr; inet_pton(AF_INET, "10.1.0.29", &inaddr); diff --git a/test/regression/2023-08-28-invalid-pointer-dereference.c b/test/regression/2023-08-28-invalid-pointer-dereference.c new file mode 100644 index 0000000000..cdd8388e71 --- /dev/null +++ b/test/regression/2023-08-28-invalid-pointer-dereference.c @@ -0,0 +1,22 @@ +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --use-sym-size-alloc --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#pragma clang attribute push(__attribute__((optnone)), apply_to = function) + +int main() { + int length1 = klee_int("len"); + int length2 = klee_int("len"); + if (length1 < 1) { + length1 = 1; + } + if (length2 < 1) { + length2 = 1; + } + char *nondetString1 = (char *)__builtin_alloca(length1 * sizeof(char)); + char *nondetString2 = (char *)__builtin_alloca(length2 * sizeof(char)); + nondetString1[length1 - 1] = '\0'; + // CHECK-NOT: memory error: out of bound pointer + nondetString2[length2 - 1] = '\0'; +} +#pragma clang attribute pop diff --git a/test/regression/2023-10-02-test-from-mocked-global.c b/test/regression/2023-10-02-test-from-mocked-global.c new file mode 100644 index 0000000000..c89bc74ec9 --- /dev/null +++ b/test/regression/2023-10-02-test-from-mocked-global.c @@ -0,0 +1,16 @@ +// Darwin does not support section attribute: `argument to 'section' attribute is not valid for this target: mach-o section specifier requires a segment whose length is between 1 and 16 characters` +// REQUIRES: not-darwin +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --mock-policy=all --write-xml-tests --output-dir=%t.klee-out %t1.bc +// RUN: FileCheck --input-file %t.klee-out/test000001.xml %s + +extern void *__crc_mc44s803_attach __attribute__((__weak__)); +static unsigned long const __kcrctab_mc44s803_attach __attribute__((__used__, __unused__, + __section__("___kcrctab+mc44s803_attach"))) = (unsigned long const)((unsigned long)(&__crc_mc44s803_attach)); + +int main() { + return 0; +} + +// CHECK: @external___crc_mc44s803_attach diff --git a/test/regression/2023-10-04-email_spec0_product16.cil.c b/test/regression/2023-10-04-email_spec0_product16.cil.c new file mode 100644 index 0000000000..291d48229c --- /dev/null +++ b/test/regression/2023-10-04-email_spec0_product16.cil.c @@ -0,0 +1,2793 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --optimize-aggressive=false --track-coverage=branches --max-memory=6008 --optimize --skip-not-lazy-initialized --istats-write-interval=90s --exit-on-error-type=Assert --search=dfs --max-time=10s %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +// RUN find %t.klee-out -type f -name "*.assert.err" | sed 's/assert\.err/ktest/' | xargs %ktest-tool | FileCheck -check-prefix=CHECK-TEST %s +// CHECK-TEST-NOT: object 20 + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2011-2013 Alexander von Rhein, University of Passau +// SPDX-FileCopyrightText: 2011-2021 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +// CHECK: email_spec0_product16.cil.c:[[@LINE+1]]: ASSERTION FAIL: 0 +void reach_error() { __assert_fail("0", "email_spec0_product16.cil.c", 3, "reach_error"); } + +extern int __VERIFIER_nondet_int(void); +/* Generated by CIL v. 1.3.7 */ +/* print_CIL_Input is true */ + +struct JoinPoint { + void **(*fp)(struct JoinPoint *); + void **args; + int argsCount; + char const **argsType; + void *(*arg)(int, struct JoinPoint *); + char const *(*argType)(int, struct JoinPoint *); + void **retValue; + char const *retType; + char const *funcName; + char const *targetName; + char const *fileName; + char const *kind; + void *excep_return; +}; +struct __UTAC__CFLOW_FUNC { + int (*func)(int, int); + int val; + struct __UTAC__CFLOW_FUNC *next; +}; +struct __UTAC__EXCEPTION { + void *jumpbuf; + unsigned long long prtValue; + int pops; + struct __UTAC__CFLOW_FUNC *cflowfuncs; +}; +typedef unsigned int size_t; +struct __ACC__ERR { + void *v; + struct __ACC__ERR *next; +}; +#pragma merger(0, "featureselect.i", "") +int __SELECTED_FEATURE_Base; +int __SELECTED_FEATURE_Keys; +int __SELECTED_FEATURE_Encrypt; +int __SELECTED_FEATURE_AutoResponder; +int __SELECTED_FEATURE_AddressBook; +int __SELECTED_FEATURE_Sign; +int __SELECTED_FEATURE_Forward; +int __SELECTED_FEATURE_Verify; +int __SELECTED_FEATURE_Decrypt; +int __GUIDSL_ROOT_PRODUCTION; +int __GUIDSL_NON_TERMINAL_main; +int select_one(void); +void select_features(void); +void select_helpers(void); +int valid_product(void); +int select_one(void) { + int retValue_acc; + int choice = __VERIFIER_nondet_int(); + + { + retValue_acc = choice; + return (retValue_acc); + return (retValue_acc); + } +} +void select_features(void) { + + { + return; + } +} +void select_helpers(void) { + + { + return; + } +} +int valid_product(void) { + int retValue_acc; + + { + retValue_acc = 1; + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "Test.i", "") +extern int printf(char const *__restrict __format, ...); +extern int puts(char const *__s); +void setClientPrivateKey(int handle, int value); +int createClientKeyringEntry(int handle); +int getClientKeyringUser(int handle, int index); +void setClientKeyringUser(int handle, int index, int value); +int getClientKeyringPublicKey(int handle, int index); +void setClientKeyringPublicKey(int handle, int index, int value); +void setClientForwardReceiver(int handle, int value); +void setClientId(int handle, int value); +int is_queue_empty(void); +int get_queued_client(void); +int get_queued_email(void); +void outgoing(int client, int msg); +void sendEmail(int sender, int receiver); +void generateKeyPair(int client, int seed); +int bob; +int rjh; +int chuck; +void setup_bob(int bob___0); +void setup_rjh(int rjh___0); +void setup_chuck(int chuck___0); +void bobToRjh(void); +void rjhToBob(void); +void test(void); +void setup(void); +int main(void); +void bobKeyAdd(void); +void bobKeyAddChuck(void); +void rjhKeyAdd(void); +void rjhKeyAddChuck(void); +void chuckKeyAdd(void); +void bobKeyChange(void); +void rjhKeyChange(void); +void rjhDeletePrivateKey(void); +void chuckKeyAddRjh(void); +void rjhEnableForwarding(void); +void setup_bob__wrappee__Base(int bob___0) { + + { + { + setClientId(bob___0, bob___0); + } + return; + } +} +void setup_bob(int bob___0) { + + { + { + setup_bob__wrappee__Base(bob___0); + setClientPrivateKey(bob___0, 123); + } + return; + } +} +void setup_rjh__wrappee__Base(int rjh___0) { + + { + { + setClientId(rjh___0, rjh___0); + } + return; + } +} +void setup_rjh(int rjh___0) { + + { + { + setup_rjh__wrappee__Base(rjh___0); + setClientPrivateKey(rjh___0, 456); + } + return; + } +} +void setup_chuck__wrappee__Base(int chuck___0) { + + { + { + setClientId(chuck___0, chuck___0); + } + return; + } +} +void setup_chuck(int chuck___0) { + + { + { + setup_chuck__wrappee__Base(chuck___0); + setClientPrivateKey(chuck___0, 789); + } + return; + } +} +void bobToRjh(void) { + int tmp; + int tmp___0; + int tmp___1; + + { + { + puts("Please enter a subject and a message body.\n"); + sendEmail(bob, rjh); + tmp___1 = is_queue_empty(); + } + if (tmp___1) { + + } else { + { + tmp = get_queued_email(); + tmp___0 = get_queued_client(); + outgoing(tmp___0, tmp); + } + } + return; + } +} +void rjhToBob(void) { + + { + { + puts("Please enter a subject and a message body.\n"); + sendEmail(rjh, bob); + } + return; + } +} +void setup(void) { + char const *__restrict __cil_tmp1; + char const *__restrict __cil_tmp2; + char const *__restrict __cil_tmp3; + + { + { + bob = 1; + setup_bob(bob); + __cil_tmp1 = (char const *__restrict)"bob: %d\n"; + printf(__cil_tmp1, bob); + rjh = 2; + setup_rjh(rjh); + __cil_tmp2 = (char const *__restrict)"rjh: %d\n"; + printf(__cil_tmp2, rjh); + chuck = 3; + setup_chuck(chuck); + __cil_tmp3 = (char const *__restrict)"chuck: %d\n"; + printf(__cil_tmp3, chuck); + } + return; + } +} +int main(void) { + int retValue_acc; + int tmp; + + { + { + select_helpers(); + select_features(); + tmp = valid_product(); + } + if (tmp) { + { + setup(); + test(); + } + } else { + } + return (retValue_acc); + } +} +void bobKeyAdd(void) { + int tmp; + int tmp___0; + char const *__restrict __cil_tmp3; + char const *__restrict __cil_tmp4; + + { + { + createClientKeyringEntry(bob); + setClientKeyringUser(bob, 0, 2); + setClientKeyringPublicKey(bob, 0, 456); + puts("bob added rjhs key"); + tmp = getClientKeyringUser(bob, 0); + __cil_tmp3 = (char const *__restrict)"%d\n"; + printf(__cil_tmp3, tmp); + tmp___0 = getClientKeyringPublicKey(bob, 0); + __cil_tmp4 = (char const *__restrict)"%d\n"; + printf(__cil_tmp4, tmp___0); + } + return; + } +} +void rjhKeyAdd(void) { + + { + { + createClientKeyringEntry(rjh); + setClientKeyringUser(rjh, 0, 1); + setClientKeyringPublicKey(rjh, 0, 123); + } + return; + } +} +void rjhKeyAddChuck(void) { + + { + { + createClientKeyringEntry(rjh); + setClientKeyringUser(rjh, 0, 3); + setClientKeyringPublicKey(rjh, 0, 789); + } + return; + } +} +void bobKeyAddChuck(void) { + + { + { + createClientKeyringEntry(bob); + setClientKeyringUser(bob, 1, 3); + setClientKeyringPublicKey(bob, 1, 789); + } + return; + } +} +void chuckKeyAdd(void) { + + { + { + createClientKeyringEntry(chuck); + setClientKeyringUser(chuck, 0, 1); + setClientKeyringPublicKey(chuck, 0, 123); + } + return; + } +} +void chuckKeyAddRjh(void) { + + { + { + createClientKeyringEntry(chuck); + setClientKeyringUser(chuck, 0, 2); + setClientKeyringPublicKey(chuck, 0, 456); + } + return; + } +} +void rjhDeletePrivateKey(void) { + + { + { + setClientPrivateKey(rjh, 0); + } + return; + } +} +void bobKeyChange(void) { + + { + { + generateKeyPair(bob, 777); + } + return; + } +} +void rjhKeyChange(void) { + + { + { + generateKeyPair(rjh, 666); + } + return; + } +} +void rjhEnableForwarding(void) { + + { + { + setClientForwardReceiver(rjh, chuck); + } + return; + } +} +#pragma merger(0, "wsllib_check.i", "") +void __automaton_fail(void) { + + { + ERROR : { + reach_error(); + abort(); + } + return; + } +} +#pragma merger(0, "Email.i", "") +int getEmailId(int handle); +int getEmailFrom(int handle); +void setEmailFrom(int handle, int value); +int getEmailTo(int handle); +void setEmailTo(int handle, int value); +int isEncrypted(int handle); +int getEmailEncryptionKey(int handle); +void printMail(int msg); +int isReadable(int msg); +int createEmail(int from, int to); +int cloneEmail(int msg); +void printMail__wrappee__Keys(int msg) { + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + char const *__restrict __cil_tmp6; + char const *__restrict __cil_tmp7; + char const *__restrict __cil_tmp8; + char const *__restrict __cil_tmp9; + + { + { + tmp = getEmailId(msg); + __cil_tmp6 = (char const *__restrict)"ID:\n %i\n"; + printf(__cil_tmp6, tmp); + tmp___0 = getEmailFrom(msg); + __cil_tmp7 = (char const *__restrict)"FROM:\n %i\n"; + printf(__cil_tmp7, tmp___0); + tmp___1 = getEmailTo(msg); + __cil_tmp8 = (char const *__restrict)"TO:\n %i\n"; + printf(__cil_tmp8, tmp___1); + tmp___2 = isReadable(msg); + __cil_tmp9 = (char const *__restrict)"IS_READABLE\n %i\n"; + printf(__cil_tmp9, tmp___2); + } + return; + } +} +void printMail(int msg) { + int tmp; + int tmp___0; + char const *__restrict __cil_tmp4; + char const *__restrict __cil_tmp5; + + { + { + printMail__wrappee__Keys(msg); + tmp = isEncrypted(msg); + __cil_tmp4 = (char const *__restrict)"ENCRYPTED\n %d\n"; + printf(__cil_tmp4, tmp); + tmp___0 = getEmailEncryptionKey(msg); + __cil_tmp5 = (char const *__restrict)"ENCRYPTION KEY\n %d\n"; + printf(__cil_tmp5, tmp___0); + } + return; + } +} +int isReadable__wrappee__Keys(int msg) { + int retValue_acc; + + { + retValue_acc = 1; + return (retValue_acc); + return (retValue_acc); + } +} +int isReadable(int msg) { + int retValue_acc; + int tmp; + + { + { + tmp = isEncrypted(msg); + } + if (tmp) { + retValue_acc = 0; + return (retValue_acc); + } else { + { + retValue_acc = isReadable__wrappee__Keys(msg); + } + return (retValue_acc); + } + return (retValue_acc); + } +} +int cloneEmail(int msg) { + int retValue_acc; + + { + retValue_acc = msg; + return (retValue_acc); + return (retValue_acc); + } +} +int createEmail(int from, int to) { + int retValue_acc; + int msg; + + { + { + msg = 1; + setEmailFrom(msg, from); + setEmailTo(msg, to); + retValue_acc = msg; + } + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "scenario.i", "") +void test(void) { + int op1; + int op2; + int op3; + int op4; + int op5; + int op6; + int op7; + int op8; + int op9; + int op10; + int op11; + int splverifierCounter; + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + int tmp___3; + int tmp___4; + int tmp___5; + int tmp___6; + int tmp___7; + int tmp___8; + int tmp___9; + + { + op1 = 0; + op2 = 0; + op3 = 0; + op4 = 0; + op5 = 0; + op6 = 0; + op7 = 0; + op8 = 0; + op9 = 0; + op10 = 0; + op11 = 0; + splverifierCounter = 0; + { + while (1) { + while_0_continue: /* CIL Label */; + if (splverifierCounter < 4) { + + } else { + goto while_0_break; + } + splverifierCounter = splverifierCounter + 1; + if (!op1) { + { + tmp___9 = __VERIFIER_nondet_int(); + } + if (tmp___9) { + { + bobKeyAdd(); + op1 = 1; + } + } else { + goto _L___8; + } + } else { + _L___8: /* CIL Label */ + if (!op2) { + { + tmp___8 = __VERIFIER_nondet_int(); + } + if (tmp___8) { + op2 = 1; + } else { + goto _L___7; + } + } else { + _L___7: /* CIL Label */ + if (!op3) { + { + tmp___7 = __VERIFIER_nondet_int(); + } + if (tmp___7) { + { + rjhDeletePrivateKey(); + op3 = 1; + } + } else { + goto _L___6; + } + } else { + _L___6: /* CIL Label */ + if (!op4) { + { + tmp___6 = __VERIFIER_nondet_int(); + } + if (tmp___6) { + { + rjhKeyAdd(); + op4 = 1; + } + } else { + goto _L___5; + } + } else { + _L___5: /* CIL Label */ + if (!op5) { + { + tmp___5 = __VERIFIER_nondet_int(); + } + if (tmp___5) { + { + chuckKeyAddRjh(); + op5 = 1; + } + } else { + goto _L___4; + } + } else { + _L___4: /* CIL Label */ + if (!op6) { + { + tmp___4 = __VERIFIER_nondet_int(); + } + if (tmp___4) { + { + rjhEnableForwarding(); + op6 = 1; + } + } else { + goto _L___3; + } + } else { + _L___3: /* CIL Label */ + if (!op7) { + { + tmp___3 = __VERIFIER_nondet_int(); + } + if (tmp___3) { + { + rjhKeyChange(); + op7 = 1; + } + } else { + goto _L___2; + } + } else { + _L___2: /* CIL Label */ + if (!op8) { + { + tmp___2 = __VERIFIER_nondet_int(); + } + if (tmp___2) { + op8 = 1; + } else { + goto _L___1; + } + } else { + _L___1: /* CIL Label */ + if (!op9) { + { + tmp___1 = __VERIFIER_nondet_int(); + } + if (tmp___1) { + { + chuckKeyAdd(); + op9 = 1; + } + } else { + goto _L___0; + } + } else { + _L___0: /* CIL Label */ + if (!op10) { + { + tmp___0 = __VERIFIER_nondet_int(); + } + if (tmp___0) { + { + bobKeyChange(); + op10 = 1; + } + } else { + goto _L; + } + } else { + _L: /* CIL Label */ + if (!op11) { + { + tmp = __VERIFIER_nondet_int(); + } + if (tmp) { + { + chuckKeyAdd(); + op11 = 1; + } + } else { + goto while_0_break; + } + } else { + goto while_0_break; + } + } + } + } + } + } + } + } + } + } + } + } + while_0_break: /* CIL Label */; + } + { + bobToRjh(); + } + return; + } +} +#pragma merger(0, "libacc.i", "") +extern __attribute__((__nothrow__, __noreturn__)) void __assert_fail(char const *__assertion, + char const *__file, + unsigned int __line, + char const *__function); +extern __attribute__((__nothrow__)) void *malloc(size_t __size) __attribute__((__malloc__)); +extern __attribute__((__nothrow__)) void free(void *__ptr); +void __utac__exception__cf_handler_set(void *exception, int (*cflow_func)(int, int), + int val) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + void *tmp; + unsigned long __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + unsigned long __cil_tmp13; + unsigned long __cil_tmp14; + int (**mem_15)(int, int); + int *mem_16; + struct __UTAC__CFLOW_FUNC **mem_17; + struct __UTAC__CFLOW_FUNC **mem_18; + struct __UTAC__CFLOW_FUNC **mem_19; + + { + { + excep = (struct __UTAC__EXCEPTION *)exception; + tmp = malloc(24UL); + cf = (struct __UTAC__CFLOW_FUNC *)tmp; + mem_15 = (int (**)(int, int))cf; + *mem_15 = cflow_func; + __cil_tmp7 = (unsigned long)cf; + __cil_tmp8 = __cil_tmp7 + 8; + mem_16 = (int *)__cil_tmp8; + *mem_16 = val; + __cil_tmp9 = (unsigned long)cf; + __cil_tmp10 = __cil_tmp9 + 16; + __cil_tmp11 = (unsigned long)excep; + __cil_tmp12 = __cil_tmp11 + 24; + mem_17 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp10; + mem_18 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp12; + *mem_17 = *mem_18; + __cil_tmp13 = (unsigned long)excep; + __cil_tmp14 = __cil_tmp13 + 24; + mem_19 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp14; + *mem_19 = cf; + } + return; + } +} +void __utac__exception__cf_handler_free(void *exception) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + struct __UTAC__CFLOW_FUNC *tmp; + unsigned long __cil_tmp5; + unsigned long __cil_tmp6; + struct __UTAC__CFLOW_FUNC *__cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + void *__cil_tmp12; + unsigned long __cil_tmp13; + unsigned long __cil_tmp14; + struct __UTAC__CFLOW_FUNC **mem_15; + struct __UTAC__CFLOW_FUNC **mem_16; + struct __UTAC__CFLOW_FUNC **mem_17; + + { + excep = (struct __UTAC__EXCEPTION *)exception; + __cil_tmp5 = (unsigned long)excep; + __cil_tmp6 = __cil_tmp5 + 24; + mem_15 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp6; + cf = *mem_15; + { + while (1) { + while_1_continue: /* CIL Label */; + { + __cil_tmp7 = (struct __UTAC__CFLOW_FUNC *)0; + __cil_tmp8 = (unsigned long)__cil_tmp7; + __cil_tmp9 = (unsigned long)cf; + if (__cil_tmp9 != __cil_tmp8) { + + } else { + goto while_1_break; + } + } + { + tmp = cf; + __cil_tmp10 = (unsigned long)cf; + __cil_tmp11 = __cil_tmp10 + 16; + mem_16 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp11; + cf = *mem_16; + __cil_tmp12 = (void *)tmp; + free(__cil_tmp12); + } + } + while_1_break: /* CIL Label */; + } + __cil_tmp13 = (unsigned long)excep; + __cil_tmp14 = __cil_tmp13 + 24; + mem_17 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp14; + *mem_17 = (struct __UTAC__CFLOW_FUNC *)0; + return; + } +} +void __utac__exception__cf_handler_reset(void *exception) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + unsigned long __cil_tmp5; + unsigned long __cil_tmp6; + struct __UTAC__CFLOW_FUNC *__cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + int (*__cil_tmp10)(int, int); + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + int __cil_tmp13; + unsigned long __cil_tmp14; + unsigned long __cil_tmp15; + struct __UTAC__CFLOW_FUNC **mem_16; + int (**mem_17)(int, int); + int *mem_18; + struct __UTAC__CFLOW_FUNC **mem_19; + + { + excep = (struct __UTAC__EXCEPTION *)exception; + __cil_tmp5 = (unsigned long)excep; + __cil_tmp6 = __cil_tmp5 + 24; + mem_16 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp6; + cf = *mem_16; + { + while (1) { + while_2_continue: /* CIL Label */; + { + __cil_tmp7 = (struct __UTAC__CFLOW_FUNC *)0; + __cil_tmp8 = (unsigned long)__cil_tmp7; + __cil_tmp9 = (unsigned long)cf; + if (__cil_tmp9 != __cil_tmp8) { + + } else { + goto while_2_break; + } + } + { + mem_17 = (int (**)(int, int))cf; + __cil_tmp10 = *mem_17; + __cil_tmp11 = (unsigned long)cf; + __cil_tmp12 = __cil_tmp11 + 8; + mem_18 = (int *)__cil_tmp12; + __cil_tmp13 = *mem_18; + (*__cil_tmp10)(4, __cil_tmp13); + __cil_tmp14 = (unsigned long)cf; + __cil_tmp15 = __cil_tmp14 + 16; + mem_19 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp15; + cf = *mem_19; + } + } + while_2_break: /* CIL Label */; + } + { + __utac__exception__cf_handler_free(exception); + } + return; + } +} +void *__utac__error_stack_mgt(void *env, int mode, int count); +static struct __ACC__ERR *head = (struct __ACC__ERR *)0; +void *__utac__error_stack_mgt(void *env, int mode, int count) { + void *retValue_acc; + struct __ACC__ERR *new; + void *tmp; + struct __ACC__ERR *temp; + struct __ACC__ERR *next; + void *excep; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + unsigned long __cil_tmp13; + void *__cil_tmp14; + unsigned long __cil_tmp15; + unsigned long __cil_tmp16; + void *__cil_tmp17; + void **mem_18; + struct __ACC__ERR **mem_19; + struct __ACC__ERR **mem_20; + void **mem_21; + struct __ACC__ERR **mem_22; + void **mem_23; + void **mem_24; + + { + if (count == 0) { + return (retValue_acc); + } else { + } + if (mode == 0) { + { + tmp = malloc(16UL); + new = (struct __ACC__ERR *)tmp; + mem_18 = (void **)new; + *mem_18 = env; + __cil_tmp10 = (unsigned long)new; + __cil_tmp11 = __cil_tmp10 + 8; + mem_19 = (struct __ACC__ERR **)__cil_tmp11; + *mem_19 = head; + head = new; + retValue_acc = (void *)new; + } + return (retValue_acc); + } else { + } + if (mode == 1) { + temp = head; + { + while (1) { + while_3_continue: /* CIL Label */; + if (count > 1) { + + } else { + goto while_3_break; + } + { + __cil_tmp12 = (unsigned long)temp; + __cil_tmp13 = __cil_tmp12 + 8; + mem_20 = (struct __ACC__ERR **)__cil_tmp13; + next = *mem_20; + mem_21 = (void **)temp; + excep = *mem_21; + __cil_tmp14 = (void *)temp; + free(__cil_tmp14); + __utac__exception__cf_handler_reset(excep); + temp = next; + count = count - 1; + } + } + while_3_break: /* CIL Label */; + } + { + __cil_tmp15 = (unsigned long)temp; + __cil_tmp16 = __cil_tmp15 + 8; + mem_22 = (struct __ACC__ERR **)__cil_tmp16; + head = *mem_22; + mem_23 = (void **)temp; + excep = *mem_23; + __cil_tmp17 = (void *)temp; + free(__cil_tmp17); + __utac__exception__cf_handler_reset(excep); + retValue_acc = excep; + } + return (retValue_acc); + } else { + } + if (mode == 2) { + if (head) { + mem_24 = (void **)head; + retValue_acc = *mem_24; + return (retValue_acc); + } else { + retValue_acc = (void *)0; + return (retValue_acc); + } + } else { + } + return (retValue_acc); + } +} +void *__utac__get_this_arg(int i, struct JoinPoint *this) { + void *retValue_acc; + unsigned long __cil_tmp4; + unsigned long __cil_tmp5; + int __cil_tmp6; + int __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + void **__cil_tmp10; + void **__cil_tmp11; + int *mem_12; + void ***mem_13; + + { + if (i > 0) { + { + __cil_tmp4 = (unsigned long)this; + __cil_tmp5 = __cil_tmp4 + 16; + mem_12 = (int *)__cil_tmp5; + __cil_tmp6 = *mem_12; + if (i <= __cil_tmp6) { + + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 123U, "__utac__get_this_arg"); + } + } + } + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 123U, "__utac__get_this_arg"); + } + } + __cil_tmp7 = i - 1; + __cil_tmp8 = (unsigned long)this; + __cil_tmp9 = __cil_tmp8 + 8; + mem_13 = (void ***)__cil_tmp9; + __cil_tmp10 = *mem_13; + __cil_tmp11 = __cil_tmp10 + __cil_tmp7; + retValue_acc = *__cil_tmp11; + return (retValue_acc); + return (retValue_acc); + } +} +char const *__utac__get_this_argtype(int i, struct JoinPoint *this) { + char const *retValue_acc; + unsigned long __cil_tmp4; + unsigned long __cil_tmp5; + int __cil_tmp6; + int __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + char const **__cil_tmp10; + char const **__cil_tmp11; + int *mem_12; + char const ***mem_13; + + { + if (i > 0) { + { + __cil_tmp4 = (unsigned long)this; + __cil_tmp5 = __cil_tmp4 + 16; + mem_12 = (int *)__cil_tmp5; + __cil_tmp6 = *mem_12; + if (i <= __cil_tmp6) { + + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 131U, "__utac__get_this_argtype"); + } + } + } + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 131U, "__utac__get_this_argtype"); + } + } + __cil_tmp7 = i - 1; + __cil_tmp8 = (unsigned long)this; + __cil_tmp9 = __cil_tmp8 + 24; + mem_13 = (char const ***)__cil_tmp9; + __cil_tmp10 = *mem_13; + __cil_tmp11 = __cil_tmp10 + __cil_tmp7; + retValue_acc = *__cil_tmp11; + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "ClientLib.i", "") +int initClient(void); +char *getClientName(int handle); +void setClientName(int handle, char *value); +int getClientOutbuffer(int handle); +void setClientOutbuffer(int handle, int value); +int getClientAddressBookSize(int handle); +void setClientAddressBookSize(int handle, int value); +int createClientAddressBookEntry(int handle); +int getClientAddressBookAlias(int handle, int index); +void setClientAddressBookAlias(int handle, int index, int value); +int getClientAddressBookAddress(int handle, int index); +void setClientAddressBookAddress(int handle, int index, int value); +int getClientAutoResponse(int handle); +void setClientAutoResponse(int handle, int value); +int getClientPrivateKey(int handle); +int getClientKeyringSize(int handle); +int getClientForwardReceiver(int handle); +int getClientId(int handle); +int findPublicKey(int handle, int userid); +int findClientAddressBookAlias(int handle, int userid); +int __ste_Client_counter = 0; +int initClient(void) { + int retValue_acc; + + { + if (__ste_Client_counter < 3) { + __ste_Client_counter = __ste_Client_counter + 1; + retValue_acc = __ste_Client_counter; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +char *__ste_client_name0 = (char *)0; +char *__ste_client_name1 = (char *)0; +char *__ste_client_name2 = (char *)0; +char *getClientName(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_client_name0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_name1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_name2; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientName(int handle, char *value) { + + { + if (handle == 1) { + __ste_client_name0 = value; + } else { + if (handle == 2) { + __ste_client_name1 = value; + } else { + if (handle == 3) { + __ste_client_name2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_outbuffer0 = 0; +int __ste_client_outbuffer1 = 0; +int __ste_client_outbuffer2 = 0; +int __ste_client_outbuffer3 = 0; +int getClientOutbuffer(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_outbuffer0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_outbuffer1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_outbuffer2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientOutbuffer(int handle, int value) { + + { + if (handle == 1) { + __ste_client_outbuffer0 = value; + } else { + if (handle == 2) { + __ste_client_outbuffer1 = value; + } else { + if (handle == 3) { + __ste_client_outbuffer2 = value; + } else { + } + } + } + return; + } +} +int __ste_ClientAddressBook_size0 = 0; +int __ste_ClientAddressBook_size1 = 0; +int __ste_ClientAddressBook_size2 = 0; +int getClientAddressBookSize(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_ClientAddressBook_size0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_ClientAddressBook_size1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_ClientAddressBook_size2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookSize(int handle, int value) { + + { + if (handle == 1) { + __ste_ClientAddressBook_size0 = value; + } else { + if (handle == 2) { + __ste_ClientAddressBook_size1 = value; + } else { + if (handle == 3) { + __ste_ClientAddressBook_size2 = value; + } else { + } + } + } + return; + } +} +int createClientAddressBookEntry(int handle) { + int retValue_acc; + int size; + int tmp; + int __cil_tmp5; + + { + { + tmp = getClientAddressBookSize(handle); + size = tmp; + } + if (size < 3) { + { + __cil_tmp5 = size + 1; + setClientAddressBookSize(handle, __cil_tmp5); + retValue_acc = size + 1; + } + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_Client_AddressBook0_Alias0 = 0; +int __ste_Client_AddressBook0_Alias1 = 0; +int __ste_Client_AddressBook0_Alias2 = 0; +int __ste_Client_AddressBook1_Alias0 = 0; +int __ste_Client_AddressBook1_Alias1 = 0; +int __ste_Client_AddressBook1_Alias2 = 0; +int __ste_Client_AddressBook2_Alias0 = 0; +int __ste_Client_AddressBook2_Alias1 = 0; +int __ste_Client_AddressBook2_Alias2 = 0; +int getClientAddressBookAlias(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook0_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook0_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook0_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook1_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook1_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook1_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook2_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook2_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook2_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +int findClientAddressBookAlias(int handle, int userid) { + int retValue_acc; + + { + if (handle == 1) { + if (userid == __ste_Client_AddressBook0_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook0_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook0_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (userid == __ste_Client_AddressBook1_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook1_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook1_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (userid == __ste_Client_AddressBook2_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook2_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook2_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookAlias(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_AddressBook0_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook0_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook0_Alias2 = value; + } else { + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_AddressBook1_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook1_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook1_Alias2 = value; + } else { + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_AddressBook2_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook2_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook2_Alias2 = value; + } else { + } + } + } + } else { + } + } + } + return; + } +} +int __ste_Client_AddressBook0_Address0 = 0; +int __ste_Client_AddressBook0_Address1 = 0; +int __ste_Client_AddressBook0_Address2 = 0; +int __ste_Client_AddressBook1_Address0 = 0; +int __ste_Client_AddressBook1_Address1 = 0; +int __ste_Client_AddressBook1_Address2 = 0; +int __ste_Client_AddressBook2_Address0 = 0; +int __ste_Client_AddressBook2_Address1 = 0; +int __ste_Client_AddressBook2_Address2 = 0; +int getClientAddressBookAddress(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook0_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook0_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook0_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook1_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook1_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook1_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook2_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook2_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook2_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookAddress(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_AddressBook0_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook0_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook0_Address2 = value; + } else { + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_AddressBook1_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook1_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook1_Address2 = value; + } else { + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_AddressBook2_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook2_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook2_Address2 = value; + } else { + } + } + } + } else { + } + } + } + return; + } +} +int __ste_client_autoResponse0 = 0; +int __ste_client_autoResponse1 = 0; +int __ste_client_autoResponse2 = 0; +int getClientAutoResponse(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_autoResponse0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_autoResponse1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_autoResponse2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAutoResponse(int handle, int value) { + + { + if (handle == 1) { + __ste_client_autoResponse0 = value; + } else { + if (handle == 2) { + __ste_client_autoResponse1 = value; + } else { + if (handle == 3) { + __ste_client_autoResponse2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_privateKey0 = 0; +int __ste_client_privateKey1 = 0; +int __ste_client_privateKey2 = 0; +int getClientPrivateKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_privateKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_privateKey1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_privateKey2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientPrivateKey(int handle, int value) { + + { + if (handle == 1) { + __ste_client_privateKey0 = value; + } else { + if (handle == 2) { + __ste_client_privateKey1 = value; + } else { + if (handle == 3) { + __ste_client_privateKey2 = value; + } else { + } + } + } + return; + } +} +int __ste_ClientKeyring_size0 = 0; +int __ste_ClientKeyring_size1 = 0; +int __ste_ClientKeyring_size2 = 0; +int getClientKeyringSize(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_ClientKeyring_size0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_ClientKeyring_size1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_ClientKeyring_size2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringSize(int handle, int value) { + + { + if (handle == 1) { + __ste_ClientKeyring_size0 = value; + } else { + if (handle == 2) { + __ste_ClientKeyring_size1 = value; + } else { + if (handle == 3) { + __ste_ClientKeyring_size2 = value; + } else { + } + } + } + return; + } +} +int createClientKeyringEntry(int handle) { + int retValue_acc; + int size; + int tmp; + int __cil_tmp5; + + { + { + tmp = getClientKeyringSize(handle); + size = tmp; + } + if (size < 2) { + { + __cil_tmp5 = size + 1; + setClientKeyringSize(handle, __cil_tmp5); + retValue_acc = size + 1; + } + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_Client_Keyring0_User0 = 0; +int __ste_Client_Keyring0_User1 = 0; +int __ste_Client_Keyring0_User2 = 0; +int __ste_Client_Keyring1_User0 = 0; +int __ste_Client_Keyring1_User1 = 0; +int __ste_Client_Keyring1_User2 = 0; +int __ste_Client_Keyring2_User0 = 0; +int __ste_Client_Keyring2_User1 = 0; +int __ste_Client_Keyring2_User2 = 0; +int getClientKeyringUser(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring0_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring0_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring1_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring1_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring2_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring2_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringUser(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_Keyring0_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring0_User1 = value; + } else { + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_Keyring1_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring1_User1 = value; + } else { + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_Keyring2_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring2_User1 = value; + } else { + } + } + } else { + } + } + } + return; + } +} +int __ste_Client_Keyring0_PublicKey0 = 0; +int __ste_Client_Keyring0_PublicKey1 = 0; +int __ste_Client_Keyring0_PublicKey2 = 0; +int __ste_Client_Keyring1_PublicKey0 = 0; +int __ste_Client_Keyring1_PublicKey1 = 0; +int __ste_Client_Keyring1_PublicKey2 = 0; +int __ste_Client_Keyring2_PublicKey0 = 0; +int __ste_Client_Keyring2_PublicKey1 = 0; +int __ste_Client_Keyring2_PublicKey2 = 0; +int getClientKeyringPublicKey(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring0_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring0_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring1_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring1_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring2_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring2_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +int findPublicKey(int handle, int userid) { + int retValue_acc; + + { + if (handle == 1) { + if (userid == __ste_Client_Keyring0_User0) { + retValue_acc = __ste_Client_Keyring0_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring0_User1) { + retValue_acc = __ste_Client_Keyring0_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (userid == __ste_Client_Keyring1_User0) { + retValue_acc = __ste_Client_Keyring1_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring1_User1) { + retValue_acc = __ste_Client_Keyring1_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (userid == __ste_Client_Keyring2_User0) { + retValue_acc = __ste_Client_Keyring2_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring2_User1) { + retValue_acc = __ste_Client_Keyring2_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringPublicKey(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_Keyring0_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring0_PublicKey1 = value; + } else { + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_Keyring1_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring1_PublicKey1 = value; + } else { + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_Keyring2_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring2_PublicKey1 = value; + } else { + } + } + } else { + } + } + } + return; + } +} +int __ste_client_forwardReceiver0 = 0; +int __ste_client_forwardReceiver1 = 0; +int __ste_client_forwardReceiver2 = 0; +int __ste_client_forwardReceiver3 = 0; +int getClientForwardReceiver(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_forwardReceiver0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_forwardReceiver1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_forwardReceiver2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientForwardReceiver(int handle, int value) { + + { + if (handle == 1) { + __ste_client_forwardReceiver0 = value; + } else { + if (handle == 2) { + __ste_client_forwardReceiver1 = value; + } else { + if (handle == 3) { + __ste_client_forwardReceiver2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_idCounter0 = 0; +int __ste_client_idCounter1 = 0; +int __ste_client_idCounter2 = 0; +int getClientId(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_idCounter0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_idCounter1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_idCounter2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientId(int handle, int value) { + + { + if (handle == 1) { + __ste_client_idCounter0 = value; + } else { + if (handle == 2) { + __ste_client_idCounter1 = value; + } else { + if (handle == 3) { + __ste_client_idCounter2 = value; + } else { + } + } + } + return; + } +} +#pragma merger(0, "EmailLib.i", "") +int initEmail(void); +void setEmailId(int handle, int value); +char *getEmailSubject(int handle); +void setEmailSubject(int handle, char *value); +char *getEmailBody(int handle); +void setEmailBody(int handle, char *value); +void setEmailIsEncrypted(int handle, int value); +void setEmailEncryptionKey(int handle, int value); +int isSigned(int handle); +void setEmailIsSigned(int handle, int value); +int getEmailSignKey(int handle); +void setEmailSignKey(int handle, int value); +int isVerified(int handle); +void setEmailIsSignatureVerified(int handle, int value); +int __ste_Email_counter = 0; +int initEmail(void) { + int retValue_acc; + + { + if (__ste_Email_counter < 2) { + __ste_Email_counter = __ste_Email_counter + 1; + retValue_acc = __ste_Email_counter; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_email_id0 = 0; +int __ste_email_id1 = 0; +int getEmailId(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_id0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_id1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailId(int handle, int value) { + + { + if (handle == 1) { + __ste_email_id0 = value; + } else { + if (handle == 2) { + __ste_email_id1 = value; + } else { + } + } + return; + } +} +int __ste_email_from0 = 0; +int __ste_email_from1 = 0; +int getEmailFrom(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_from0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_from1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailFrom(int handle, int value) { + + { + if (handle == 1) { + __ste_email_from0 = value; + } else { + if (handle == 2) { + __ste_email_from1 = value; + } else { + } + } + return; + } +} +int __ste_email_to0 = 0; +int __ste_email_to1 = 0; +int getEmailTo(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_to0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_to1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailTo(int handle, int value) { + + { + if (handle == 1) { + __ste_email_to0 = value; + } else { + if (handle == 2) { + __ste_email_to1 = value; + } else { + } + } + return; + } +} +char *__ste_email_subject0; +char *__ste_email_subject1; +char *getEmailSubject(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_email_subject0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_subject1; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailSubject(int handle, char *value) { + + { + if (handle == 1) { + __ste_email_subject0 = value; + } else { + if (handle == 2) { + __ste_email_subject1 = value; + } else { + } + } + return; + } +} +char *__ste_email_body0 = (char *)0; +char *__ste_email_body1 = (char *)0; +char *getEmailBody(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_email_body0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_body1; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailBody(int handle, char *value) { + + { + if (handle == 1) { + __ste_email_body0 = value; + } else { + if (handle == 2) { + __ste_email_body1 = value; + } else { + } + } + return; + } +} +int __ste_email_isEncrypted0 = 0; +int __ste_email_isEncrypted1 = 0; +int isEncrypted(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isEncrypted0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isEncrypted1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsEncrypted(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isEncrypted0 = value; + } else { + if (handle == 2) { + __ste_email_isEncrypted1 = value; + } else { + } + } + return; + } +} +int __ste_email_encryptionKey0 = 0; +int __ste_email_encryptionKey1 = 0; +int getEmailEncryptionKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_encryptionKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_encryptionKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailEncryptionKey(int handle, int value) { + + { + if (handle == 1) { + __ste_email_encryptionKey0 = value; + } else { + if (handle == 2) { + __ste_email_encryptionKey1 = value; + } else { + } + } + return; + } +} +int __ste_email_isSigned0 = 0; +int __ste_email_isSigned1 = 0; +int isSigned(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isSigned0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isSigned1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsSigned(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isSigned0 = value; + } else { + if (handle == 2) { + __ste_email_isSigned1 = value; + } else { + } + } + return; + } +} +int __ste_email_signKey0 = 0; +int __ste_email_signKey1 = 0; +int getEmailSignKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_signKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_signKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailSignKey(int handle, int value) { + + { + if (handle == 1) { + __ste_email_signKey0 = value; + } else { + if (handle == 2) { + __ste_email_signKey1 = value; + } else { + } + } + return; + } +} +int __ste_email_isSignatureVerified0; +int __ste_email_isSignatureVerified1; +int isVerified(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isSignatureVerified0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isSignatureVerified1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsSignatureVerified(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isSignatureVerified0 = value; + } else { + if (handle == 2) { + __ste_email_isSignatureVerified1 = value; + } else { + } + } + return; + } +} +#pragma merger(0, "DecryptForward_spec.i", "") +inline static void __utac_acc__DecryptForward_spec__1(int msg) { + int tmp; + + { + { + puts("before forward\n"); + tmp = isReadable(msg); + } + if (tmp) { + + } else { + { + __automaton_fail(); + } + } + return; + } +} +#pragma merger(0, "Util.i", "") +int prompt(char *msg); +int prompt(char *msg) { + int retValue_acc; + int retval; + char const *__restrict __cil_tmp4; + + { + { + __cil_tmp4 = (char const *__restrict)"%s\n"; + printf(__cil_tmp4, msg); + retValue_acc = retval; + } + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "Client.i", "") +void queue(int client, int msg); +void mail(int client, int msg); +void deliver(int client, int msg); +void incoming(int client, int msg); +int createClient(char *name); +int isKeyPairValid(int publicKey, int privateKey); +void forward(int client, int msg); +int queue_empty = 1; +int queued_message; +int queued_client; +void mail(int client, int msg) { + int tmp; + + { + { + puts("mail sent"); + tmp = getEmailTo(msg); + incoming(tmp, msg); + } + return; + } +} +void outgoing__wrappee__Keys(int client, int msg) { + int tmp; + + { + { + tmp = getClientId(client); + setEmailFrom(msg, tmp); + mail(client, msg); + } + return; + } +} +void outgoing(int client, int msg) { + int receiver; + int tmp; + int pubkey; + int tmp___0; + + { + { + tmp = getEmailTo(msg); + receiver = tmp; + tmp___0 = findPublicKey(client, receiver); + pubkey = tmp___0; + } + if (pubkey) { + { + setEmailEncryptionKey(msg, pubkey); + setEmailIsEncrypted(msg, 1); + } + } else { + } + { + outgoing__wrappee__Keys(client, msg); + } + return; + } +} +void deliver(int client, int msg) { + + { + { + puts("mail delivered\n"); + } + return; + } +} +void incoming__wrappee__Encrypt(int client, int msg) { + + { + { + deliver(client, msg); + } + return; + } +} +void incoming__wrappee__Forward(int client, int msg) { + int fwreceiver; + int tmp; + + { + { + incoming__wrappee__Encrypt(client, msg); + tmp = getClientForwardReceiver(client); + fwreceiver = tmp; + } + if (fwreceiver) { + { + setEmailTo(msg, fwreceiver); + forward(client, msg); + } + } else { + } + return; + } +} +void incoming(int client, int msg) { + int privkey; + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + + { + { + tmp = getClientPrivateKey(client); + privkey = tmp; + } + if (privkey) { + { + tmp___0 = isEncrypted(msg); + } + if (tmp___0) { + { + tmp___1 = getEmailEncryptionKey(msg); + tmp___2 = isKeyPairValid(tmp___1, privkey); + } + if (tmp___2) { + { + setEmailIsEncrypted(msg, 0); + setEmailEncryptionKey(msg, 0); + } + } else { + } + } else { + } + } else { + } + { + incoming__wrappee__Forward(client, msg); + } + return; + } +} +int createClient(char *name) { + int retValue_acc; + int client; + int tmp; + + { + { + tmp = initClient(); + client = tmp; + retValue_acc = client; + } + return (retValue_acc); + return (retValue_acc); + } +} +void sendEmail(int sender, int receiver) { + int email; + int tmp; + + { + { + tmp = createEmail(0, receiver); + email = tmp; + outgoing(sender, email); + } + return; + } +} +void queue(int client, int msg) { + + { + queue_empty = 0; + queued_message = msg; + queued_client = client; + return; + } +} +int is_queue_empty(void) { + int retValue_acc; + + { + retValue_acc = queue_empty; + return (retValue_acc); + return (retValue_acc); + } +} +int get_queued_client(void) { + int retValue_acc; + + { + retValue_acc = queued_client; + return (retValue_acc); + return (retValue_acc); + } +} +int get_queued_email(void) { + int retValue_acc; + + { + retValue_acc = queued_message; + return (retValue_acc); + return (retValue_acc); + } +} +int isKeyPairValid(int publicKey, int privateKey) { + int retValue_acc; + char const *__restrict __cil_tmp4; + + { + { + __cil_tmp4 = (char const *__restrict)"keypair valid %d %d"; + printf(__cil_tmp4, publicKey, privateKey); + } + if (!publicKey) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (!privateKey) { + retValue_acc = 0; + return (retValue_acc); + } else { + } + } + retValue_acc = privateKey == publicKey; + return (retValue_acc); + return (retValue_acc); + } +} +void generateKeyPair(int client, int seed) { + + { + { + setClientPrivateKey(client, seed); + } + return; + } +} +void forward(int client, int msg) { + int __utac__ad__arg1; + + { + { + __utac__ad__arg1 = msg; + __utac_acc__DecryptForward_spec__1(__utac__ad__arg1); + puts("Forwarding message.\n"); + printMail(msg); + queue(client, msg); + } + return; + } +} diff --git a/test/regression/2023-10-06-Dubois-015.c b/test/regression/2023-10-06-Dubois-015.c new file mode 100644 index 0000000000..a7917dc82d --- /dev/null +++ b/test/regression/2023-10-06-Dubois-015.c @@ -0,0 +1,354 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2016 Gilles Audemard +// SPDX-FileCopyrightText: 2020 Dirk Beyer +// SPDX-FileCopyrightText: 2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: MIT + +extern void abort(void) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern void __assert_fail(const char *, const char *, unsigned int, + const char *) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); +#endif + abort(); +} +int __VERIFIER_nondet_int(); +void reach_error() { + abort_prog(); + __assert_fail("0", "Dubois-015.c", 5, "reach_error"); +} +void assume(int cond) { + if (!cond) + abort_prog(); +} +int main() { + int cond0; + int dummy = 0; + int N; + int var0; + var0 = __VERIFIER_nondet_int(); + assume(var0 >= 0); + assume(var0 <= 1); + int var1; + var1 = __VERIFIER_nondet_int(); + assume(var1 >= 0); + assume(var1 <= 1); + int var2; + var2 = __VERIFIER_nondet_int(); + assume(var2 >= 0); + assume(var2 <= 1); + int var3; + var3 = __VERIFIER_nondet_int(); + assume(var3 >= 0); + assume(var3 <= 1); + int var4; + var4 = __VERIFIER_nondet_int(); + assume(var4 >= 0); + assume(var4 <= 1); + int var5; + var5 = __VERIFIER_nondet_int(); + assume(var5 >= 0); + assume(var5 <= 1); + int var6; + var6 = __VERIFIER_nondet_int(); + assume(var6 >= 0); + assume(var6 <= 1); + int var7; + var7 = __VERIFIER_nondet_int(); + assume(var7 >= 0); + assume(var7 <= 1); + int var8; + var8 = __VERIFIER_nondet_int(); + assume(var8 >= 0); + assume(var8 <= 1); + int var9; + var9 = __VERIFIER_nondet_int(); + assume(var9 >= 0); + assume(var9 <= 1); + int var10; + var10 = __VERIFIER_nondet_int(); + assume(var10 >= 0); + assume(var10 <= 1); + int var11; + var11 = __VERIFIER_nondet_int(); + assume(var11 >= 0); + assume(var11 <= 1); + int var12; + var12 = __VERIFIER_nondet_int(); + assume(var12 >= 0); + assume(var12 <= 1); + int var13; + var13 = __VERIFIER_nondet_int(); + assume(var13 >= 0); + assume(var13 <= 1); + int var14; + var14 = __VERIFIER_nondet_int(); + assume(var14 >= 0); + assume(var14 <= 1); + int var15; + var15 = __VERIFIER_nondet_int(); + assume(var15 >= 0); + assume(var15 <= 1); + int var16; + var16 = __VERIFIER_nondet_int(); + assume(var16 >= 0); + assume(var16 <= 1); + int var17; + var17 = __VERIFIER_nondet_int(); + assume(var17 >= 0); + assume(var17 <= 1); + int var18; + var18 = __VERIFIER_nondet_int(); + assume(var18 >= 0); + assume(var18 <= 1); + int var19; + var19 = __VERIFIER_nondet_int(); + assume(var19 >= 0); + assume(var19 <= 1); + int var20; + var20 = __VERIFIER_nondet_int(); + assume(var20 >= 0); + assume(var20 <= 1); + int var21; + var21 = __VERIFIER_nondet_int(); + assume(var21 >= 0); + assume(var21 <= 1); + int var22; + var22 = __VERIFIER_nondet_int(); + assume(var22 >= 0); + assume(var22 <= 1); + int var23; + var23 = __VERIFIER_nondet_int(); + assume(var23 >= 0); + assume(var23 <= 1); + int var24; + var24 = __VERIFIER_nondet_int(); + assume(var24 >= 0); + assume(var24 <= 1); + int var25; + var25 = __VERIFIER_nondet_int(); + assume(var25 >= 0); + assume(var25 <= 1); + int var26; + var26 = __VERIFIER_nondet_int(); + assume(var26 >= 0); + assume(var26 <= 1); + int var27; + var27 = __VERIFIER_nondet_int(); + assume(var27 >= 0); + assume(var27 <= 1); + int var28; + var28 = __VERIFIER_nondet_int(); + assume(var28 >= 0); + assume(var28 <= 1); + int var29; + var29 = __VERIFIER_nondet_int(); + assume(var29 >= 0); + assume(var29 <= 1); + int var30; + var30 = __VERIFIER_nondet_int(); + assume(var30 >= 0); + assume(var30 <= 1); + int var31; + var31 = __VERIFIER_nondet_int(); + assume(var31 >= 0); + assume(var31 <= 1); + int var32; + var32 = __VERIFIER_nondet_int(); + assume(var32 >= 0); + assume(var32 <= 1); + int var33; + var33 = __VERIFIER_nondet_int(); + assume(var33 >= 0); + assume(var33 <= 1); + int var34; + var34 = __VERIFIER_nondet_int(); + assume(var34 >= 0); + assume(var34 <= 1); + int var35; + var35 = __VERIFIER_nondet_int(); + assume(var35 >= 0); + assume(var35 <= 1); + int var36; + var36 = __VERIFIER_nondet_int(); + assume(var36 >= 0); + assume(var36 <= 1); + int var37; + var37 = __VERIFIER_nondet_int(); + assume(var37 >= 0); + assume(var37 <= 1); + int var38; + var38 = __VERIFIER_nondet_int(); + assume(var38 >= 0); + assume(var38 <= 1); + int var39; + var39 = __VERIFIER_nondet_int(); + assume(var39 >= 0); + assume(var39 <= 1); + int var40; + var40 = __VERIFIER_nondet_int(); + assume(var40 >= 0); + assume(var40 <= 1); + int var41; + var41 = __VERIFIER_nondet_int(); + assume(var41 >= 0); + assume(var41 <= 1); + int var42; + var42 = __VERIFIER_nondet_int(); + assume(var42 >= 0); + assume(var42 <= 1); + int var43; + var43 = __VERIFIER_nondet_int(); + assume(var43 >= 0); + assume(var43 <= 1); + int var44; + var44 = __VERIFIER_nondet_int(); + assume(var44 >= 0); + assume(var44 <= 1); + int myvar0 = 1; + assume((var28 == 0 & var29 == 0 & var0 == 1) | + (var28 == 0 & var29 == 1 & var0 == 0) | + (var28 == 1 & var29 == 0 & var0 == 0) | + (var28 == 1 & var29 == 1 & var0 == 1) | 0); + assume((var1 == 0 & var31 == 0 & var2 == 1) | + (var1 == 0 & var31 == 1 & var2 == 0) | + (var1 == 1 & var31 == 0 & var2 == 0) | + (var1 == 1 & var31 == 1 & var2 == 1) | 0); + assume((var2 == 0 & var32 == 0 & var3 == 1) | + (var2 == 0 & var32 == 1 & var3 == 0) | + (var2 == 1 & var32 == 0 & var3 == 0) | + (var2 == 1 & var32 == 1 & var3 == 1) | 0); + assume((var3 == 0 & var33 == 0 & var4 == 1) | + (var3 == 0 & var33 == 1 & var4 == 0) | + (var3 == 1 & var33 == 0 & var4 == 0) | + (var3 == 1 & var33 == 1 & var4 == 1) | 0); + assume((var4 == 0 & var34 == 0 & var5 == 1) | + (var4 == 0 & var34 == 1 & var5 == 0) | + (var4 == 1 & var34 == 0 & var5 == 0) | + (var4 == 1 & var34 == 1 & var5 == 1) | 0); + assume((var5 == 0 & var35 == 0 & var6 == 1) | + (var5 == 0 & var35 == 1 & var6 == 0) | + (var5 == 1 & var35 == 0 & var6 == 0) | + (var5 == 1 & var35 == 1 & var6 == 1) | 0); + assume((var6 == 0 & var36 == 0 & var7 == 1) | + (var6 == 0 & var36 == 1 & var7 == 0) | + (var6 == 1 & var36 == 0 & var7 == 0) | + (var6 == 1 & var36 == 1 & var7 == 1) | 0); + assume((var7 == 0 & var37 == 0 & var8 == 1) | + (var7 == 0 & var37 == 1 & var8 == 0) | + (var7 == 1 & var37 == 0 & var8 == 0) | + (var7 == 1 & var37 == 1 & var8 == 1) | 0); + assume((var8 == 0 & var38 == 0 & var9 == 1) | + (var8 == 0 & var38 == 1 & var9 == 0) | + (var8 == 1 & var38 == 0 & var9 == 0) | + (var8 == 1 & var38 == 1 & var9 == 1) | 0); + assume((var9 == 0 & var39 == 0 & var10 == 1) | + (var9 == 0 & var39 == 1 & var10 == 0) | + (var9 == 1 & var39 == 0 & var10 == 0) | + (var9 == 1 & var39 == 1 & var10 == 1) | 0); + assume((var10 == 0 & var40 == 0 & var11 == 1) | + (var10 == 0 & var40 == 1 & var11 == 0) | + (var10 == 1 & var40 == 0 & var11 == 0) | + (var10 == 1 & var40 == 1 & var11 == 1) | 0); + assume((var11 == 0 & var41 == 0 & var12 == 1) | + (var11 == 0 & var41 == 1 & var12 == 0) | + (var11 == 1 & var41 == 0 & var12 == 0) | + (var11 == 1 & var41 == 1 & var12 == 1) | 0); + assume((var12 == 0 & var42 == 0 & var13 == 1) | + (var12 == 0 & var42 == 1 & var13 == 0) | + (var12 == 1 & var42 == 0 & var13 == 0) | + (var12 == 1 & var42 == 1 & var13 == 1) | 0); + assume((var0 == 0 & var30 == 0 & var1 == 1) | + (var0 == 0 & var30 == 1 & var1 == 0) | + (var0 == 1 & var30 == 0 & var1 == 0) | + (var0 == 1 & var30 == 1 & var1 == 1) | 0); + assume((var14 == 0 & var43 == 0 & var44 == 1) | + (var14 == 0 & var43 == 1 & var44 == 0) | + (var14 == 1 & var43 == 0 & var44 == 0) | + (var14 == 1 & var43 == 1 & var44 == 1) | 0); + assume((var13 == 0 & var43 == 0 & var44 == 1) | + (var13 == 0 & var43 == 1 & var44 == 0) | + (var13 == 1 & var43 == 0 & var44 == 0) | + (var13 == 1 & var43 == 1 & var44 == 1) | 0); + assume((var16 == 0 & var41 == 0 & var15 == 1) | + (var16 == 0 & var41 == 1 & var15 == 0) | + (var16 == 1 & var41 == 0 & var15 == 0) | + (var16 == 1 & var41 == 1 & var15 == 1) | 0); + assume((var17 == 0 & var40 == 0 & var16 == 1) | + (var17 == 0 & var40 == 1 & var16 == 0) | + (var17 == 1 & var40 == 0 & var16 == 0) | + (var17 == 1 & var40 == 1 & var16 == 1) | 0); + assume((var18 == 0 & var39 == 0 & var17 == 1) | + (var18 == 0 & var39 == 1 & var17 == 0) | + (var18 == 1 & var39 == 0 & var17 == 0) | + (var18 == 1 & var39 == 1 & var17 == 1) | 0); + assume((var19 == 0 & var38 == 0 & var18 == 1) | + (var19 == 0 & var38 == 1 & var18 == 0) | + (var19 == 1 & var38 == 0 & var18 == 0) | + (var19 == 1 & var38 == 1 & var18 == 1) | 0); + assume((var20 == 0 & var37 == 0 & var19 == 1) | + (var20 == 0 & var37 == 1 & var19 == 0) | + (var20 == 1 & var37 == 0 & var19 == 0) | + (var20 == 1 & var37 == 1 & var19 == 1) | 0); + assume((var21 == 0 & var36 == 0 & var20 == 1) | + (var21 == 0 & var36 == 1 & var20 == 0) | + (var21 == 1 & var36 == 0 & var20 == 0) | + (var21 == 1 & var36 == 1 & var20 == 1) | 0); + assume((var22 == 0 & var35 == 0 & var21 == 1) | + (var22 == 0 & var35 == 1 & var21 == 0) | + (var22 == 1 & var35 == 0 & var21 == 0) | + (var22 == 1 & var35 == 1 & var21 == 1) | 0); + assume((var23 == 0 & var34 == 0 & var22 == 1) | + (var23 == 0 & var34 == 1 & var22 == 0) | + (var23 == 1 & var34 == 0 & var22 == 0) | + (var23 == 1 & var34 == 1 & var22 == 1) | 0); + assume((var24 == 0 & var33 == 0 & var23 == 1) | + (var24 == 0 & var33 == 1 & var23 == 0) | + (var24 == 1 & var33 == 0 & var23 == 0) | + (var24 == 1 & var33 == 1 & var23 == 1) | 0); + assume((var25 == 0 & var32 == 0 & var24 == 1) | + (var25 == 0 & var32 == 1 & var24 == 0) | + (var25 == 1 & var32 == 0 & var24 == 0) | + (var25 == 1 & var32 == 1 & var24 == 1) | 0); + assume((var26 == 0 & var31 == 0 & var25 == 1) | + (var26 == 0 & var31 == 1 & var25 == 0) | + (var26 == 1 & var31 == 0 & var25 == 0) | + (var26 == 1 & var31 == 1 & var25 == 1) | 0); + assume((var27 == 0 & var30 == 0 & var26 == 1) | + (var27 == 0 & var30 == 1 & var26 == 0) | + (var27 == 1 & var30 == 0 & var26 == 0) | + (var27 == 1 & var30 == 1 & var26 == 1) | 0); + assume((var15 == 0 & var42 == 0 & var14 == 1) | + (var15 == 0 & var42 == 1 & var14 == 0) | + (var15 == 1 & var42 == 0 & var14 == 0) | + (var15 == 1 & var42 == 1 & var14 == 1) | 0); + assume((var28 == 0 & var29 == 0 & var27 == 0) | + (var28 == 0 & var29 == 1 & var27 == 1) | + (var28 == 1 & var29 == 0 & var27 == 1) | + (var28 == 1 & var29 == 1 & var27 == 0) | 0); + reach_error(); + return 0; /* 0 x[0]1 x[1]2 x[2]3 x[3]4 x[4]5 x[5]6 x[6]7 x[7]8 x[8]9 x[9]10 + x[10]11 x[11]12 x[12]13 x[13]14 x[14]15 x[15]16 x[16]17 x[17]18 + x[18]19 x[19]20 x[20]21 x[21]22 x[22]23 x[23]24 x[24]25 x[25]26 + x[26]27 x[27]28 x[28]29 x[29]30 x[30]31 x[31]32 x[32]33 x[33]34 + x[34]35 x[35]36 x[36]37 x[37]38 x[38]39 x[39]40 x[40]41 x[41]42 + x[42]43 x[43]44 x[44] */ +} + +// CHECK: generated tests = 2 \ No newline at end of file diff --git a/test/regression/2023-10-12-inner-types-fix.c b/test/regression/2023-10-12-inner-types-fix.c new file mode 100644 index 0000000000..2484dc6a1f --- /dev/null +++ b/test/regression/2023-10-12-inner-types-fix.c @@ -0,0 +1,89 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --entry-point=klee_entry --skip-not-lazy-initialized --min-number-elements-li=1 %t1.bc 2>&1 +// RUN: %ktest-tool %t.klee-out/test000003.ktest | FileCheck %s + +#include "klee/klee.h" + +struct StructWithPointer { + int x; + int *y; +}; + +struct StructWithDoublePointer { + int x; + int **y; +}; + +struct StructWithArrayOfPointer { + int x; + int *y[2]; +}; + +struct StructWithStructWithPointer { + struct StructWithPointer swp; + struct StructWithDoublePointer *swdp; +}; + +struct StructManyPointers { + int a; + int *b; + int **c; + int ***d; +}; + +struct StructComplex { + int x; + int *y; + int **z; + struct StructWithPointer *swp; + struct StructWithDoublePointer **swdp; + struct StructManyPointers smp; +}; + +int sumStructWithPointer(struct StructWithPointer par) { + return par.x + *par.y; +} + +int sumStructWithPointerAsPointer(struct StructWithPointer *par) { + return par->x + *par->y; +} + +int sumStructWithDoublePointer(struct StructWithDoublePointer par) { + return par.x + **par.y; +} + +int sumStructWithArrayOfPointer(struct StructWithArrayOfPointer par) { + return par.x + *(par.y[0]) + *(par.y[1]); +} + +int sumStructWithStructWithPointer(struct StructWithStructWithPointer par) { + int sswp = sumStructWithPointer(par.swp); + int sswdp = sumStructWithDoublePointer(*par.swdp); + return sswp + sswdp; +} + +int sumStructManyPointers(struct StructManyPointers par) { + return par.a + *par.b + **par.c + ***par.d; +} + +int sumStructComplex(struct StructComplex par) { + int sswp = sumStructWithPointer(*par.swp); + int sswdp = sumStructWithDoublePointer(**par.swdp); + int ssmp = sumStructManyPointers(par.smp); + return par.x + *par.y + **par.z + sswp + sswdp + ssmp; +} + +// CHECK: object 2: pointers: [(8, 3, 0)] +int klee_entry(int utbot_argc, char **utbot_argv, char **utbot_envp) { + struct StructComplex par; + klee_make_symbolic(&par, sizeof(par), "par"); + klee_prefer_cex(&par, par.x >= -10 & par.x <= 10); + klee_prefer_cex(&par, par.smp.a >= -10 & par.smp.a <= 10); + //////////////////////////////////////////// + int utbot_result; + klee_make_symbolic(&utbot_result, sizeof(utbot_result), "utbot_result"); + int utbot_tmp = sumStructComplex(par); + klee_assume(utbot_tmp == utbot_result); + return 0; +} \ No newline at end of file diff --git a/test/regression/2023-10-13-kbfiltr.i.cil-2.c b/test/regression/2023-10-13-kbfiltr.i.cil-2.c new file mode 100644 index 0000000000..e3ba31dc05 --- /dev/null +++ b/test/regression/2023-10-13-kbfiltr.i.cil-2.c @@ -0,0 +1,3646 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --mock-policy=all --use-forked-solver=false --max-memory=6008 --skip-not-lazy-initialized --istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --write-kqueries --write-xml-tests --only-output-states-covering-new=true --dump-states-on-halt=all --emit-all-errors=true --search=bfs %t1.bc +// RUN: ls %t.klee-out | grep _1.xml | wc -l | grep 8 + +#include "klee-test-comp.c" + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "kbfiltr.i.cil-2.c", 3, "reach_error"); } + +extern char __VERIFIER_nondet_char(void); +extern int __VERIFIER_nondet_int(void); +extern long __VERIFIER_nondet_long(void); +extern unsigned long __VERIFIER_nondet_ulong(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +/* Generated by CIL v. 1.3.6 */ +/* print_CIL_Input is true */ + +#pragma pack(push, 8) +#pragma pack(pop) +typedef unsigned short wchar_t; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef ULONG_PTR SIZE_T; +typedef void *PVOID; +typedef char CHAR; +typedef short SHORT; +typedef long LONG; +typedef wchar_t WCHAR; +typedef WCHAR *PWSTR; +typedef WCHAR const *PCWSTR; +typedef CHAR *PCHAR; +typedef LONG *PLONG; +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +typedef UCHAR *PUCHAR; +typedef ULONG *PULONG; +typedef void *HANDLE; +typedef HANDLE *PHANDLE; +typedef char CCHAR; +typedef short CSHORT; +typedef ULONG LCID; +typedef LONG NTSTATUS; +typedef long long LONGLONG; +struct __anonstruct____missing_field_name_1 { + ULONG LowPart; + LONG HighPart; +}; +struct __anonstruct_u_2 { + ULONG LowPart; + LONG HighPart; +}; +union _LARGE_INTEGER { + struct __anonstruct____missing_field_name_1 __annonCompField1; + struct __anonstruct_u_2 u; + LONGLONG QuadPart; +}; +typedef union _LARGE_INTEGER LARGE_INTEGER; +typedef LARGE_INTEGER *PLARGE_INTEGER; +struct _LUID { + ULONG LowPart; + LONG HighPart; +}; +typedef struct _LUID LUID; +typedef LARGE_INTEGER PHYSICAL_ADDRESS; +enum _EVENT_TYPE { + NotificationEvent = 0, + SynchronizationEvent = 1 +}; +typedef enum _EVENT_TYPE EVENT_TYPE; +typedef char const *PCSZ; +struct _STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +}; +typedef struct _STRING STRING; +typedef STRING *PSTRING; +typedef PSTRING PANSI_STRING; +struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}; +typedef struct _UNICODE_STRING UNICODE_STRING; +typedef UNICODE_STRING *PUNICODE_STRING; +typedef UCHAR BOOLEAN; +typedef BOOLEAN *PBOOLEAN; +struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +}; +typedef struct _LIST_ENTRY LIST_ENTRY; +typedef struct _LIST_ENTRY *PLIST_ENTRY; +struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +}; +typedef struct _OBJECT_ATTRIBUTES OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}; +typedef struct _GUID GUID; +typedef unsigned int size_t; +typedef UCHAR KIRQL; +struct _KTHREAD; +typedef struct _KTHREAD *PKTHREAD; +struct _ETHREAD; +typedef struct _ETHREAD *PETHREAD; +struct _EPROCESS; +typedef struct _EPROCESS *PEPROCESS; +struct _IO_TIMER; +typedef struct _IO_TIMER *PIO_TIMER; +struct _OBJECT_TYPE; +typedef struct _OBJECT_TYPE *POBJECT_TYPE; +typedef CCHAR KPROCESSOR_MODE; +struct _KAPC; +struct _KAPC; +typedef void (*PKNORMAL_ROUTINE)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); +struct _KAPC { + CSHORT Type; + CSHORT Size; + ULONG Spare0; + struct _KTHREAD *Thread; + LIST_ENTRY ApcListEntry; + void (*KernelRoutine)(struct _KAPC *Apc, PKNORMAL_ROUTINE *NormalRoutine, PVOID *NormalContext, + PVOID *SystemArgument1, PVOID *SystemArgument2); + void (*RundownRoutine)(struct _KAPC *Apc); + void (*NormalRoutine)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); + PVOID NormalContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + CCHAR ApcStateIndex; + KPROCESSOR_MODE ApcMode; + BOOLEAN Inserted; +}; +typedef struct _KAPC KAPC; +struct _KDPC; +struct _KDPC; +struct _KDPC { + CSHORT Type; + UCHAR Number; + UCHAR Importance; + LIST_ENTRY DpcListEntry; + void (*DeferredRoutine)(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, + PVOID SystemArgument2); + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + PULONG_PTR Lock; +}; +typedef struct _KDPC KDPC; +typedef struct _KDPC *PKDPC; +struct _MDL { + struct _MDL *Next; + CSHORT Size; + CSHORT MdlFlags; + struct _EPROCESS *Process; + PVOID MappedSystemVa; + PVOID StartVa; + ULONG ByteCount; + ULONG ByteOffset; +}; +typedef struct _MDL MDL; +typedef struct _MDL *PMDL; +typedef PVOID PACCESS_TOKEN; +typedef PVOID PSECURITY_DESCRIPTOR; +typedef ULONG ACCESS_MASK; +#pragma pack(push, 4) +struct _LUID_AND_ATTRIBUTES { + LUID Luid; + ULONG Attributes; +}; +typedef struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES; +#pragma pack(pop) +struct _PRIVILEGE_SET { + ULONG PrivilegeCount; + ULONG Control; + LUID_AND_ATTRIBUTES Privilege[1]; +}; +typedef struct _PRIVILEGE_SET PRIVILEGE_SET; +enum _SECURITY_IMPERSONATION_LEVEL { + SecurityAnonymous = 0, + SecurityIdentification = 1, + SecurityImpersonation = 2, + SecurityDelegation = 3 +}; +typedef enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL; +typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE; +struct _SECURITY_QUALITY_OF_SERVICE { + ULONG Length; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode; + BOOLEAN EffectiveOnly; +}; +typedef struct _SECURITY_QUALITY_OF_SERVICE *PSECURITY_QUALITY_OF_SERVICE; +typedef ULONG SECURITY_INFORMATION; +typedef LONG KPRIORITY; +typedef ULONG_PTR KSPIN_LOCK; +typedef KSPIN_LOCK *PKSPIN_LOCK; +struct _RTL_QUERY_REGISTRY_TABLE { + NTSTATUS(*QueryRoutine) + (PWSTR ValueName, ULONG ValueType, + PVOID ValueData, ULONG ValueLength, + PVOID Context, PVOID EntryContext); + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; +}; +typedef struct _RTL_QUERY_REGISTRY_TABLE *PRTL_QUERY_REGISTRY_TABLE; +union __anonunion____missing_field_name_6 { + NTSTATUS Status; + PVOID Pointer; +}; +struct _IO_STATUS_BLOCK { + union __anonunion____missing_field_name_6 __annonCompField4; + ULONG_PTR Information; +}; +typedef struct _IO_STATUS_BLOCK IO_STATUS_BLOCK; +typedef struct _IO_STATUS_BLOCK *PIO_STATUS_BLOCK; +enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation = 2, + FileBothDirectoryInformation = 3, + FileBasicInformation = 4, + FileStandardInformation = 5, + FileInternalInformation = 6, + FileEaInformation = 7, + FileAccessInformation = 8, + FileNameInformation = 9, + FileRenameInformation = 10, + FileLinkInformation = 11, + FileNamesInformation = 12, + FileDispositionInformation = 13, + FilePositionInformation = 14, + FileFullEaInformation = 15, + FileModeInformation = 16, + FileAlignmentInformation = 17, + FileAllInformation = 18, + FileAllocationInformation = 19, + FileEndOfFileInformation = 20, + FileAlternateNameInformation = 21, + FileStreamInformation = 22, + FilePipeInformation = 23, + FilePipeLocalInformation = 24, + FilePipeRemoteInformation = 25, + FileMailslotQueryInformation = 26, + FileMailslotSetInformation = 27, + FileCompressionInformation = 28, + FileObjectIdInformation = 29, + FileCompletionInformation = 30, + FileMoveClusterInformation = 31, + FileQuotaInformation = 32, + FileReparsePointInformation = 33, + FileNetworkOpenInformation = 34, + FileAttributeTagInformation = 35, + FileTrackingInformation = 36, + FileMaximumInformation = 37 +}; +typedef enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS; +struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + ULONG FileAttributes; +}; +typedef struct _FILE_BASIC_INFORMATION *PFILE_BASIC_INFORMATION; +struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +}; +typedef struct _FILE_STANDARD_INFORMATION *PFILE_STANDARD_INFORMATION; +struct _FILE_NETWORK_OPEN_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; +}; +typedef struct _FILE_NETWORK_OPEN_INFORMATION *PFILE_NETWORK_OPEN_INFORMATION; +enum _FSINFOCLASS { + FileFsVolumeInformation = 1, + FileFsLabelInformation = 2, + FileFsSizeInformation = 3, + FileFsDeviceInformation = 4, + FileFsAttributeInformation = 5, + FileFsControlInformation = 6, + FileFsFullSizeInformation = 7, + FileFsObjectIdInformation = 8, + FileFsMaximumInformation = 9 +}; +typedef enum _FSINFOCLASS FS_INFORMATION_CLASS; +enum _INTERFACE_TYPE { + InterfaceTypeUndefined = -1, + Internal = 0, + Isa = 1, + Eisa = 2, + MicroChannel = 3, + TurboChannel = 4, + PCIBus = 5, + VMEBus = 6, + NuBus = 7, + PCMCIABus = 8, + CBus = 9, + MPIBus = 10, + MPSABus = 11, + ProcessorInternal = 12, + InternalPowerBus = 13, + PNPISABus = 14, + PNPBus = 15, + MaximumInterfaceType = 16 +}; +typedef enum _INTERFACE_TYPE INTERFACE_TYPE; +typedef enum _INTERFACE_TYPE *PINTERFACE_TYPE; +struct _IO_ERROR_LOG_PACKET { + UCHAR MajorFunctionCode; + UCHAR RetryCount; + USHORT DumpDataSize; + USHORT NumberOfStrings; + USHORT StringOffset; + USHORT EventCategory; + NTSTATUS ErrorCode; + ULONG UniqueErrorValue; + NTSTATUS FinalStatus; + ULONG SequenceNumber; + ULONG IoControlCode; + LARGE_INTEGER DeviceOffset; + ULONG DumpData[1]; +}; +typedef struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET; +struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; +}; +typedef struct _KEY_VALUE_FULL_INFORMATION *PKEY_VALUE_FULL_INFORMATION; +struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +}; +typedef struct _CLIENT_ID CLIENT_ID; +typedef CLIENT_ID *PCLIENT_ID; +enum _SYSTEM_POWER_STATE { + PowerSystemUnspecified = 0, + PowerSystemWorking = 1, + PowerSystemSleeping1 = 2, + PowerSystemSleeping2 = 3, + PowerSystemSleeping3 = 4, + PowerSystemHibernate = 5, + PowerSystemShutdown = 6, + PowerSystemMaximum = 7 +}; +typedef enum _SYSTEM_POWER_STATE SYSTEM_POWER_STATE; +enum __anonenum_POWER_ACTION_11 { + PowerActionNone = 0, + PowerActionReserved = 1, + PowerActionSleep = 2, + PowerActionHibernate = 3, + PowerActionShutdown = 4, + PowerActionShutdownReset = 5, + PowerActionShutdownOff = 6, + PowerActionWarmEject = 7 +}; +typedef enum __anonenum_POWER_ACTION_11 POWER_ACTION; +enum _DEVICE_POWER_STATE { + PowerDeviceUnspecified = 0, + PowerDeviceD0 = 1, + PowerDeviceD1 = 2, + PowerDeviceD2 = 3, + PowerDeviceD3 = 4, + PowerDeviceMaximum = 5 +}; +typedef enum _DEVICE_POWER_STATE DEVICE_POWER_STATE; +union _POWER_STATE { + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; +}; +typedef union _POWER_STATE POWER_STATE; +enum _POWER_STATE_TYPE { + SystemPowerState = 0, + DevicePowerState = 1 +}; +typedef enum _POWER_STATE_TYPE POWER_STATE_TYPE; +typedef PVOID PASSIGNED_RESOURCE; +#pragma pack(push, 4) +struct __anonstruct_Generic_16 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Port_17 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Interrupt_18 { + ULONG Level; + ULONG Vector; + ULONG Affinity; +}; +struct __anonstruct_Memory_19 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Dma_20 { + ULONG Channel; + ULONG Port; + ULONG Reserved1; +}; +struct __anonstruct_DevicePrivate_21 { + ULONG Data[3]; +}; +struct __anonstruct_BusNumber_22 { + ULONG Start; + ULONG Length; + ULONG Reserved; +}; +struct __anonstruct_DeviceSpecificData_23 { + ULONG DataSize; + ULONG Reserved1; + ULONG Reserved2; +}; +union __anonunion_u_15 { + struct __anonstruct_Generic_16 Generic; + struct __anonstruct_Port_17 Port; + struct __anonstruct_Interrupt_18 Interrupt; + struct __anonstruct_Memory_19 Memory; + struct __anonstruct_Dma_20 Dma; + struct __anonstruct_DevicePrivate_21 DevicePrivate; + struct __anonstruct_BusNumber_22 BusNumber; + struct __anonstruct_DeviceSpecificData_23 DeviceSpecificData; +}; +struct _CM_PARTIAL_RESOURCE_DESCRIPTOR { + UCHAR Type; + UCHAR ShareDisposition; + USHORT Flags; + union __anonunion_u_15 u; +}; +typedef struct _CM_PARTIAL_RESOURCE_DESCRIPTOR CM_PARTIAL_RESOURCE_DESCRIPTOR; +#pragma pack(pop) +struct _CM_PARTIAL_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; +}; +typedef struct _CM_PARTIAL_RESOURCE_LIST CM_PARTIAL_RESOURCE_LIST; +struct _CM_FULL_RESOURCE_DESCRIPTOR { + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + CM_PARTIAL_RESOURCE_LIST PartialResourceList; +}; +typedef struct _CM_FULL_RESOURCE_DESCRIPTOR CM_FULL_RESOURCE_DESCRIPTOR; +struct _CM_RESOURCE_LIST { + ULONG Count; + CM_FULL_RESOURCE_DESCRIPTOR List[1]; +}; +typedef struct _CM_RESOURCE_LIST *PCM_RESOURCE_LIST; +#pragma pack(push, 1) +#pragma pack(pop) +struct __anonstruct_Port_25 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_Memory_26 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_Interrupt_27 { + ULONG MinimumVector; + ULONG MaximumVector; +}; +struct __anonstruct_Dma_28 { + ULONG MinimumChannel; + ULONG MaximumChannel; +}; +struct __anonstruct_Generic_29 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_DevicePrivate_30 { + ULONG Data[3]; +}; +struct __anonstruct_BusNumber_31 { + ULONG Length; + ULONG MinBusNumber; + ULONG MaxBusNumber; + ULONG Reserved; +}; +struct __anonstruct_AssignedResource_32 { + PASSIGNED_RESOURCE AssignedResource; +}; +struct __anonstruct_SubAllocateFrom_33 { + UCHAR Type; + UCHAR Reserved[3]; + PASSIGNED_RESOURCE AssignedResource; + PHYSICAL_ADDRESS Transformation; +}; +struct __anonstruct_ConfigData_34 { + ULONG Priority; + ULONG Reserved1; + ULONG Reserved2; +}; +union __anonunion_u_24 { + struct __anonstruct_Port_25 Port; + struct __anonstruct_Memory_26 Memory; + struct __anonstruct_Interrupt_27 Interrupt; + struct __anonstruct_Dma_28 Dma; + struct __anonstruct_Generic_29 Generic; + struct __anonstruct_DevicePrivate_30 DevicePrivate; + struct __anonstruct_BusNumber_31 BusNumber; + struct __anonstruct_AssignedResource_32 AssignedResource; + struct __anonstruct_SubAllocateFrom_33 SubAllocateFrom; + struct __anonstruct_ConfigData_34 ConfigData; +}; +struct _IO_RESOURCE_DESCRIPTOR { + UCHAR Option; + UCHAR Type; + UCHAR ShareDisposition; + UCHAR Spare1; + USHORT Flags; + USHORT Spare2; + union __anonunion_u_24 u; +}; +typedef struct _IO_RESOURCE_DESCRIPTOR IO_RESOURCE_DESCRIPTOR; +struct _IO_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + IO_RESOURCE_DESCRIPTOR Descriptors[1]; +}; +typedef struct _IO_RESOURCE_LIST IO_RESOURCE_LIST; +struct _IO_RESOURCE_REQUIREMENTS_LIST { + ULONG ListSize; + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ULONG SlotNumber; + ULONG Reserved[3]; + ULONG AlternativeLists; + IO_RESOURCE_LIST List[1]; +}; +typedef struct _IO_RESOURCE_REQUIREMENTS_LIST *PIO_RESOURCE_REQUIREMENTS_LIST; +enum _CONFIGURATION_TYPE { + ArcSystem = 0, + CentralProcessor = 1, + FloatingPointProcessor = 2, + PrimaryIcache = 3, + PrimaryDcache = 4, + SecondaryIcache = 5, + SecondaryDcache = 6, + SecondaryCache = 7, + EisaAdapter = 8, + TcAdapter = 9, + ScsiAdapter = 10, + DtiAdapter = 11, + MultiFunctionAdapter = 12, + DiskController = 13, + TapeController = 14, + CdromController = 15, + WormController = 16, + SerialController = 17, + NetworkController = 18, + DisplayController = 19, + ParallelController = 20, + PointerController = 21, + KeyboardController = 22, + AudioController = 23, + OtherController = 24, + DiskPeripheral = 25, + FloppyDiskPeripheral = 26, + TapePeripheral = 27, + ModemPeripheral = 28, + MonitorPeripheral = 29, + PrinterPeripheral = 30, + PointerPeripheral = 31, + KeyboardPeripheral = 32, + TerminalPeripheral = 33, + OtherPeripheral = 34, + LinePeripheral = 35, + NetworkPeripheral = 36, + SystemMemory = 37, + DockingInformation = 38, + RealModeIrqRoutingTable = 39, + MaximumType = 40 +}; +typedef enum _CONFIGURATION_TYPE CONFIGURATION_TYPE; +typedef enum _CONFIGURATION_TYPE *PCONFIGURATION_TYPE; +enum _KWAIT_REASON { + Executive = 0, + FreePage = 1, + PageIn = 2, + PoolAllocation = 3, + DelayExecution = 4, + Suspended = 5, + UserRequest = 6, + WrExecutive = 7, + WrFreePage = 8, + WrPageIn = 9, + WrPoolAllocation = 10, + WrDelayExecution = 11, + WrSuspended = 12, + WrUserRequest = 13, + WrEventPair = 14, + WrQueue = 15, + WrLpcReceive = 16, + WrLpcReply = 17, + WrVirtualMemory = 18, + WrPageOut = 19, + WrRendezvous = 20, + Spare2 = 21, + Spare3 = 22, + Spare4 = 23, + Spare5 = 24, + Spare6 = 25, + WrKernel = 26, + MaximumWaitReason = 27 +}; +typedef enum _KWAIT_REASON KWAIT_REASON; +struct _DISPATCHER_HEADER { + UCHAR Type; + UCHAR Absolute; + UCHAR Size; + UCHAR Inserted; + LONG SignalState; + LIST_ENTRY WaitListHead; +}; +typedef struct _DISPATCHER_HEADER DISPATCHER_HEADER; +struct _KDEVICE_QUEUE { + CSHORT Type; + CSHORT Size; + LIST_ENTRY DeviceListHead; + KSPIN_LOCK Lock; + BOOLEAN Busy; +}; +typedef struct _KDEVICE_QUEUE KDEVICE_QUEUE; +struct _KDEVICE_QUEUE_ENTRY { + LIST_ENTRY DeviceListEntry; + ULONG SortKey; + BOOLEAN Inserted; +}; +typedef struct _KDEVICE_QUEUE_ENTRY KDEVICE_QUEUE_ENTRY; +struct _KEVENT { + DISPATCHER_HEADER Header; +}; +typedef struct _KEVENT KEVENT; +typedef struct _KEVENT *PKEVENT; +typedef struct _KEVENT *PRKEVENT; +struct _KSEMAPHORE { + DISPATCHER_HEADER Header; + LONG Limit; +}; +typedef struct _KSEMAPHORE *PKSEMAPHORE; +typedef struct _KSEMAPHORE *PRKSEMAPHORE; +enum _MEMORY_CACHING_TYPE { + MmNonCached = 0, + MmCached = 1, + MmWriteCombined = 2, + MmHardwareCoherentCached = 3, + MmNonCachedUnordered = 4, + MmUSWCCached = 5, + MmMaximumCacheType = 6 +}; +typedef enum _MEMORY_CACHING_TYPE MEMORY_CACHING_TYPE; +enum _POOL_TYPE { + NonPagedPool = 0, + PagedPool = 1, + NonPagedPoolMustSucceed = 2, + DontUseThisType = 3, + NonPagedPoolCacheAligned = 4, + PagedPoolCacheAligned = 5, + NonPagedPoolCacheAlignedMustS = 6, + MaxPoolType = 7, + NonPagedPoolSession = 32, + PagedPoolSession = 33, + NonPagedPoolMustSucceedSession = 34, + DontUseThisTypeSession = 35, + NonPagedPoolCacheAlignedSession = 36, + PagedPoolCacheAlignedSession = 37, + NonPagedPoolCacheAlignedMustSSession = 38 +}; +typedef enum _POOL_TYPE POOL_TYPE; +struct _FAST_MUTEX { + LONG Count; + PKTHREAD Owner; + ULONG Contention; + KEVENT Event; + ULONG OldIrql; +}; +typedef struct _FAST_MUTEX *PFAST_MUTEX; +typedef ULONG_PTR ERESOURCE_THREAD; +union __anonunion____missing_field_name_38 { + LONG OwnerCount; + ULONG TableSize; +}; +struct _OWNER_ENTRY { + ERESOURCE_THREAD OwnerThread; + union __anonunion____missing_field_name_38 __annonCompField10; +}; +typedef struct _OWNER_ENTRY OWNER_ENTRY; +typedef struct _OWNER_ENTRY *POWNER_ENTRY; +union __anonunion____missing_field_name_39 { + PVOID Address; + ULONG_PTR CreatorBackTraceIndex; +}; +struct _ERESOURCE { + LIST_ENTRY SystemResourcesList; + POWNER_ENTRY OwnerTable; + SHORT ActiveCount; + USHORT Flag; + PKSEMAPHORE SharedWaiters; + PKEVENT ExclusiveWaiters; + OWNER_ENTRY OwnerThreads[2]; + ULONG ContentionCount; + USHORT NumberOfSharedWaiters; + USHORT NumberOfExclusiveWaiters; + union __anonunion____missing_field_name_39 __annonCompField11; + KSPIN_LOCK SpinLock; +}; +enum _MM_PAGE_PRIORITY { + LowPagePriority = 0, + NormalPagePriority = 16, + HighPagePriority = 32 +}; +typedef enum _MM_PAGE_PRIORITY MM_PAGE_PRIORITY; +struct _DRIVER_OBJECT; +struct _DRIVER_OBJECT; +struct _SECURITY_SUBJECT_CONTEXT { + PACCESS_TOKEN ClientToken; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + PACCESS_TOKEN PrimaryToken; + PVOID ProcessAuditId; +}; +typedef struct _SECURITY_SUBJECT_CONTEXT SECURITY_SUBJECT_CONTEXT; +struct _INITIAL_PRIVILEGE_SET { + ULONG PrivilegeCount; + ULONG Control; + LUID_AND_ATTRIBUTES Privilege[3]; +}; +typedef struct _INITIAL_PRIVILEGE_SET INITIAL_PRIVILEGE_SET; +union __anonunion_Privileges_40 { + INITIAL_PRIVILEGE_SET InitialPrivilegeSet; + PRIVILEGE_SET PrivilegeSet; +}; +struct _ACCESS_STATE { + LUID OperationID; + BOOLEAN SecurityEvaluated; + BOOLEAN GenerateAudit; + BOOLEAN GenerateOnClose; + BOOLEAN PrivilegesAllocated; + ULONG Flags; + ACCESS_MASK RemainingDesiredAccess; + ACCESS_MASK PreviouslyGrantedAccess; + ACCESS_MASK OriginalDesiredAccess; + SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; + PSECURITY_DESCRIPTOR SecurityDescriptor; + PVOID AuxData; + union __anonunion_Privileges_40 Privileges; + BOOLEAN AuditPrivileges; + UNICODE_STRING ObjectName; + UNICODE_STRING ObjectTypeName; +}; +typedef struct _ACCESS_STATE *PACCESS_STATE; +struct _DEVICE_OBJECT; +struct _DEVICE_OBJECT; +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _FILE_OBJECT; +struct _IRP; +struct _IRP; +struct _SCSI_REQUEST_BLOCK; +struct _SCSI_REQUEST_BLOCK; +typedef NTSTATUS (*PDRIVER_DISPATCH)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); +struct _COMPRESSED_DATA_INFO; +struct _FAST_IO_DISPATCH { + ULONG SizeOfFastIoDispatch; + BOOLEAN(*FastIoCheckIfPossible) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, + BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoRead) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryBasicInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PFILE_BASIC_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryStandardInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PFILE_STANDARD_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoLock) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, + BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockSingle) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockAll) + (struct _FILE_OBJECT *FileObject, PEPROCESS ProcessId, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockAllByKey) + (struct _FILE_OBJECT *FileObject, PVOID ProcessId, + ULONG Key, PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoDeviceControl) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, + ULONG OutputBufferLength, ULONG IoControlCode, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + void (*AcquireFileForNtCreateSection)(struct _FILE_OBJECT *FileObject); + void (*ReleaseFileForNtCreateSection)(struct _FILE_OBJECT *FileObject); + void (*FastIoDetachDevice)(struct _DEVICE_OBJECT *SourceDevice, struct _DEVICE_OBJECT *TargetDevice); + BOOLEAN(*FastIoQueryNetworkOpenInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, + struct _IO_STATUS_BLOCK *IoStatus, struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*AcquireForModWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER EndingOffset, + struct _ERESOURCE **ResourceToRelease, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlRead) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlReadComplete) + (struct _FILE_OBJECT *FileObject, PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*PrepareMdlWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlWriteComplete) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoReadCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PVOID Buffer, PMDL *MdlChain, + PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + ULONG CompressedDataInfoLength, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoWriteCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PVOID Buffer, + PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + ULONG CompressedDataInfoLength, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlReadCompleteCompressed) + (struct _FILE_OBJECT *FileObject, PMDL MdlChain, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlWriteCompleteCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryOpen) + (struct _IRP *Irp, PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, + struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*ReleaseForModWrite) + (struct _FILE_OBJECT *FileObject, struct _ERESOURCE *ResourceToRelease, + struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*AcquireForCcFlush) + (struct _FILE_OBJECT *FileObject, struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*ReleaseForCcFlush) + (struct _FILE_OBJECT *FileObject, struct _DEVICE_OBJECT *DeviceObject); +}; +typedef struct _FAST_IO_DISPATCH *PFAST_IO_DISPATCH; +enum _IO_ALLOCATION_ACTION { + KeepObject = 1, + DeallocateObject = 2, + DeallocateObjectKeepRegisters = 3 +}; +typedef enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION; +struct _IO_SECURITY_CONTEXT { + PSECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_STATE AccessState; + ACCESS_MASK DesiredAccess; + ULONG FullCreateOptions; +}; +typedef struct _IO_SECURITY_CONTEXT *PIO_SECURITY_CONTEXT; +struct _VPB { + CSHORT Type; + CSHORT Size; + USHORT Flags; + USHORT VolumeLabelLength; + struct _DEVICE_OBJECT *DeviceObject; + struct _DEVICE_OBJECT *RealDevice; + ULONG SerialNumber; + ULONG ReferenceCount; + WCHAR VolumeLabel[(32U * sizeof(WCHAR)) / sizeof(WCHAR)]; +}; +typedef struct _VPB *PVPB; +struct _WAIT_CONTEXT_BLOCK { + KDEVICE_QUEUE_ENTRY WaitQueueEntry; + IO_ALLOCATION_ACTION(*DeviceRoutine) + (struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp, + PVOID MapRegisterBase, PVOID Context); + PVOID DeviceContext; + ULONG NumberOfMapRegisters; + PVOID DeviceObject; + PVOID CurrentIrp; + PKDPC BufferChainingDpc; +}; +typedef struct _WAIT_CONTEXT_BLOCK WAIT_CONTEXT_BLOCK; +union __anonunion_Queue_43 { + LIST_ENTRY ListEntry; + WAIT_CONTEXT_BLOCK Wcb; +}; +struct _DEVOBJ_EXTENSION; +struct _DEVICE_OBJECT { + CSHORT Type; + USHORT Size; + LONG ReferenceCount; + struct _DRIVER_OBJECT *DriverObject; + struct _DEVICE_OBJECT *NextDevice; + struct _DEVICE_OBJECT *AttachedDevice; + struct _IRP *CurrentIrp; + PIO_TIMER Timer; + ULONG Flags; + ULONG Characteristics; + PVPB Vpb; + PVOID DeviceExtension; + ULONG DeviceType; + CCHAR StackSize; + union __anonunion_Queue_43 Queue; + ULONG AlignmentRequirement; + KDEVICE_QUEUE DeviceQueue; + KDPC Dpc; + ULONG ActiveThreadCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; + KEVENT DeviceLock; + USHORT SectorSize; + USHORT Spare1; + struct _DEVOBJ_EXTENSION *DeviceObjectExtension; + PVOID Reserved; +}; +typedef struct _DEVICE_OBJECT DEVICE_OBJECT; +typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT; +struct _DEVOBJ_EXTENSION { + CSHORT Type; + USHORT Size; + PDEVICE_OBJECT DeviceObject; +}; +struct _DRIVER_EXTENSION { + struct _DRIVER_OBJECT *DriverObject; + NTSTATUS(*AddDevice) + (struct _DRIVER_OBJECT *DriverObject, struct _DEVICE_OBJECT *PhysicalDeviceObject); + ULONG Count; + UNICODE_STRING ServiceKeyName; +}; +typedef struct _DRIVER_EXTENSION *PDRIVER_EXTENSION; +struct _DRIVER_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + PVOID DriverStart; + ULONG DriverSize; + PVOID DriverSection; + PDRIVER_EXTENSION DriverExtension; + UNICODE_STRING DriverName; + PUNICODE_STRING HardwareDatabase; + PFAST_IO_DISPATCH FastIoDispatch; + NTSTATUS(*DriverInit) + (struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath); + void (*DriverStartIo)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); + void (*DriverUnload)(struct _DRIVER_OBJECT *DriverObject); + PDRIVER_DISPATCH MajorFunction[28]; +}; +typedef struct _DRIVER_OBJECT DRIVER_OBJECT; +typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; +struct _SECTION_OBJECT_POINTERS { + PVOID DataSectionObject; + PVOID SharedCacheMap; + PVOID ImageSectionObject; +}; +typedef struct _SECTION_OBJECT_POINTERS SECTION_OBJECT_POINTERS; +typedef SECTION_OBJECT_POINTERS *PSECTION_OBJECT_POINTERS; +struct _IO_COMPLETION_CONTEXT { + PVOID Port; + PVOID Key; +}; +typedef struct _IO_COMPLETION_CONTEXT *PIO_COMPLETION_CONTEXT; +struct _FILE_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + PVPB Vpb; + PVOID FsContext; + PVOID FsContext2; + PSECTION_OBJECT_POINTERS SectionObjectPointer; + PVOID PrivateCacheMap; + NTSTATUS FinalStatus; + struct _FILE_OBJECT *RelatedFileObject; + BOOLEAN LockOperation; + BOOLEAN DeletePending; + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + ULONG Flags; + UNICODE_STRING FileName; + LARGE_INTEGER CurrentByteOffset; + ULONG Waiters; + ULONG Busy; + PVOID LastLock; + KEVENT Lock; + KEVENT Event; + PIO_COMPLETION_CONTEXT CompletionContext; +}; +typedef struct _FILE_OBJECT *PFILE_OBJECT; +union __anonunion_AssociatedIrp_44 { + struct _IRP *MasterIrp; + LONG IrpCount; + PVOID SystemBuffer; +}; +struct __anonstruct_AsynchronousParameters_46 { + void (*UserApcRoutine)(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); + PVOID UserApcContext; +}; +union __anonunion_Overlay_45 { + struct __anonstruct_AsynchronousParameters_46 AsynchronousParameters; + LARGE_INTEGER AllocationSize; +}; +struct __anonstruct____missing_field_name_50 { + PVOID DriverContext[4]; +}; +union __anonunion____missing_field_name_49 { + KDEVICE_QUEUE_ENTRY DeviceQueueEntry; + struct __anonstruct____missing_field_name_50 __annonCompField14; +}; +struct _IO_STACK_LOCATION; +union __anonunion____missing_field_name_52 { + struct _IO_STACK_LOCATION *CurrentStackLocation; + ULONG PacketType; +}; +struct __anonstruct____missing_field_name_51 { + LIST_ENTRY ListEntry; + union __anonunion____missing_field_name_52 __annonCompField16; +}; +struct __anonstruct_Overlay_48 { + union __anonunion____missing_field_name_49 __annonCompField15; + PETHREAD Thread; + PCHAR AuxiliaryBuffer; + struct __anonstruct____missing_field_name_51 __annonCompField17; + PFILE_OBJECT OriginalFileObject; +}; +union __anonunion_Tail_47 { + struct __anonstruct_Overlay_48 Overlay; + KAPC Apc; + PVOID CompletionKey; +}; +struct _IRP { + CSHORT Type; + USHORT Size; + PMDL MdlAddress; + ULONG Flags; + union __anonunion_AssociatedIrp_44 AssociatedIrp; + LIST_ENTRY ThreadListEntry; + IO_STATUS_BLOCK IoStatus; + KPROCESSOR_MODE RequestorMode; + BOOLEAN PendingReturned; + CHAR StackCount; + CHAR CurrentLocation; + BOOLEAN Cancel; + KIRQL CancelIrql; + CCHAR ApcEnvironment; + UCHAR AllocationFlags; + PIO_STATUS_BLOCK UserIosb; + PKEVENT UserEvent; + union __anonunion_Overlay_45 Overlay; + void (*CancelRoutine)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); + PVOID UserBuffer; + union __anonunion_Tail_47 Tail; +}; +typedef struct _IRP IRP; +typedef struct _IRP *PIRP; +enum _DEVICE_RELATION_TYPE { + BusRelations = 0, + EjectionRelations = 1, + PowerRelations = 2, + RemovalRelations = 3, + TargetDeviceRelation = 4 +}; +typedef enum _DEVICE_RELATION_TYPE DEVICE_RELATION_TYPE; +enum _DEVICE_USAGE_NOTIFICATION_TYPE { + DeviceUsageTypeUndefined = 0, + DeviceUsageTypePaging = 1, + DeviceUsageTypeHibernation = 2, + DeviceUsageTypeDumpFile = 3 +}; +typedef enum _DEVICE_USAGE_NOTIFICATION_TYPE DEVICE_USAGE_NOTIFICATION_TYPE; +struct _INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + void (*InterfaceReference)(PVOID Context); + void (*InterfaceDereference)(PVOID Context); +}; +typedef struct _INTERFACE *PINTERFACE; +struct _DEVICE_CAPABILITIES { + USHORT Size; + USHORT Version; + ULONG DeviceD1 : 1; + ULONG DeviceD2 : 1; + ULONG LockSupported : 1; + ULONG EjectSupported : 1; + ULONG Removable : 1; + ULONG DockDevice : 1; + ULONG UniqueID : 1; + ULONG SilentInstall : 1; + ULONG RawDeviceOK : 1; + ULONG SurpriseRemovalOK : 1; + ULONG WakeFromD0 : 1; + ULONG WakeFromD1 : 1; + ULONG WakeFromD2 : 1; + ULONG WakeFromD3 : 1; + ULONG HardwareDisabled : 1; + ULONG NonDynamic : 1; + ULONG WarmEjectSupported : 1; + ULONG Reserved : 15; + ULONG Address; + ULONG UINumber; + DEVICE_POWER_STATE DeviceState[7]; + SYSTEM_POWER_STATE SystemWake; + DEVICE_POWER_STATE DeviceWake; + ULONG D1Latency; + ULONG D2Latency; + ULONG D3Latency; +}; +typedef struct _DEVICE_CAPABILITIES *PDEVICE_CAPABILITIES; +struct _POWER_SEQUENCE { + ULONG SequenceD1; + ULONG SequenceD2; + ULONG SequenceD3; +}; +typedef struct _POWER_SEQUENCE *PPOWER_SEQUENCE; +enum __anonenum_BUS_QUERY_ID_TYPE_53 { + BusQueryDeviceID = 0, + BusQueryHardwareIDs = 1, + BusQueryCompatibleIDs = 2, + BusQueryInstanceID = 3, + BusQueryDeviceSerialNumber = 4 +}; +typedef enum __anonenum_BUS_QUERY_ID_TYPE_53 BUS_QUERY_ID_TYPE; +enum __anonenum_DEVICE_TEXT_TYPE_54 { + DeviceTextDescription = 0, + DeviceTextLocationInformation = 1 +}; +typedef enum __anonenum_DEVICE_TEXT_TYPE_54 DEVICE_TEXT_TYPE; +#pragma pack(push, 4) +struct __anonstruct_Create_56 { + PIO_SECURITY_CONTEXT SecurityContext; + ULONG Options; + USHORT FileAttributes; + USHORT ShareAccess; + ULONG EaLength; +}; +struct __anonstruct_Read_57 { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; +}; +struct __anonstruct_Write_58 { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; +}; +struct __anonstruct_QueryFile_59 { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; +}; +struct __anonstruct____missing_field_name_62 { + BOOLEAN ReplaceIfExists; + BOOLEAN AdvanceOnly; +}; +union __anonunion____missing_field_name_61 { + struct __anonstruct____missing_field_name_62 __annonCompField18; + ULONG ClusterCount; + HANDLE DeleteHandle; +}; +struct __anonstruct_SetFile_60 { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + union __anonunion____missing_field_name_61 __annonCompField19; +}; +struct __anonstruct_QueryVolume_63 { + ULONG Length; + FS_INFORMATION_CLASS FsInformationClass; +}; +struct __anonstruct_DeviceIoControl_64 { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG IoControlCode; + PVOID Type3InputBuffer; +}; +struct __anonstruct_QuerySecurity_65 { + SECURITY_INFORMATION SecurityInformation; + ULONG Length; +}; +struct __anonstruct_SetSecurity_66 { + SECURITY_INFORMATION SecurityInformation; + PSECURITY_DESCRIPTOR SecurityDescriptor; +}; +struct __anonstruct_MountVolume_67 { + PVPB Vpb; + PDEVICE_OBJECT DeviceObject; +}; +struct __anonstruct_VerifyVolume_68 { + PVPB Vpb; + PDEVICE_OBJECT DeviceObject; +}; +struct __anonstruct_Scsi_69 { + struct _SCSI_REQUEST_BLOCK *Srb; +}; +struct __anonstruct_QueryDeviceRelations_70 { + DEVICE_RELATION_TYPE Type; +}; +struct __anonstruct_QueryInterface_71 { + GUID const *InterfaceType; + USHORT Size; + USHORT Version; + PINTERFACE Interface; + PVOID InterfaceSpecificData; +}; +struct __anonstruct_DeviceCapabilities_72 { + PDEVICE_CAPABILITIES Capabilities; +}; +struct __anonstruct_FilterResourceRequirements_73 { + PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList; +}; +struct __anonstruct_ReadWriteConfig_74 { + ULONG WhichSpace; + PVOID Buffer; + ULONG Offset; + ULONG Length; +}; +struct __anonstruct_SetLock_75 { + BOOLEAN Lock; +}; +struct __anonstruct_QueryId_76 { + BUS_QUERY_ID_TYPE IdType; +}; +struct __anonstruct_QueryDeviceText_77 { + DEVICE_TEXT_TYPE DeviceTextType; + LCID LocaleId; +}; +struct __anonstruct_UsageNotification_78 { + BOOLEAN InPath; + BOOLEAN Reserved[3]; + DEVICE_USAGE_NOTIFICATION_TYPE Type; +}; +struct __anonstruct_WaitWake_79 { + SYSTEM_POWER_STATE PowerState; +}; +struct __anonstruct_PowerSequence_80 { + PPOWER_SEQUENCE PowerSequence; +}; +struct __anonstruct_Power_81 { + ULONG SystemContext; + POWER_STATE_TYPE Type; + POWER_STATE State; + POWER_ACTION ShutdownType; +}; +struct __anonstruct_StartDevice_82 { + PCM_RESOURCE_LIST AllocatedResources; + PCM_RESOURCE_LIST AllocatedResourcesTranslated; +}; +struct __anonstruct_WMI_83 { + ULONG_PTR ProviderId; + PVOID DataPath; + ULONG BufferSize; + PVOID Buffer; +}; +struct __anonstruct_Others_84 { + PVOID Argument1; + PVOID Argument2; + PVOID Argument3; + PVOID Argument4; +}; +union __anonunion_Parameters_55 { + struct __anonstruct_Create_56 Create; + struct __anonstruct_Read_57 Read; + struct __anonstruct_Write_58 Write; + struct __anonstruct_QueryFile_59 QueryFile; + struct __anonstruct_SetFile_60 SetFile; + struct __anonstruct_QueryVolume_63 QueryVolume; + struct __anonstruct_DeviceIoControl_64 DeviceIoControl; + struct __anonstruct_QuerySecurity_65 QuerySecurity; + struct __anonstruct_SetSecurity_66 SetSecurity; + struct __anonstruct_MountVolume_67 MountVolume; + struct __anonstruct_VerifyVolume_68 VerifyVolume; + struct __anonstruct_Scsi_69 Scsi; + struct __anonstruct_QueryDeviceRelations_70 QueryDeviceRelations; + struct __anonstruct_QueryInterface_71 QueryInterface; + struct __anonstruct_DeviceCapabilities_72 DeviceCapabilities; + struct __anonstruct_FilterResourceRequirements_73 FilterResourceRequirements; + struct __anonstruct_ReadWriteConfig_74 ReadWriteConfig; + struct __anonstruct_SetLock_75 SetLock; + struct __anonstruct_QueryId_76 QueryId; + struct __anonstruct_QueryDeviceText_77 QueryDeviceText; + struct __anonstruct_UsageNotification_78 UsageNotification; + struct __anonstruct_WaitWake_79 WaitWake; + struct __anonstruct_PowerSequence_80 PowerSequence; + struct __anonstruct_Power_81 Power; + struct __anonstruct_StartDevice_82 StartDevice; + struct __anonstruct_WMI_83 WMI; + struct __anonstruct_Others_84 Others; +}; +struct _IO_STACK_LOCATION { + UCHAR MajorFunction; + UCHAR MinorFunction; + UCHAR Flags; + UCHAR Control; + union __anonunion_Parameters_55 Parameters; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + NTSTATUS(*CompletionRoutine) + (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); + PVOID Context; +}; +typedef struct _IO_STACK_LOCATION IO_STACK_LOCATION; +typedef struct _IO_STACK_LOCATION *PIO_STACK_LOCATION; +#pragma pack(pop) +struct _CONFIGURATION_INFORMATION { + ULONG DiskCount; + ULONG FloppyCount; + ULONG CdRomCount; + ULONG TapeCount; + ULONG ScsiPortCount; + ULONG SerialCount; + ULONG ParallelCount; + BOOLEAN AtDiskPrimaryAddressClaimed; + BOOLEAN AtDiskSecondaryAddressClaimed; + ULONG Version; + ULONG MediumChangerCount; +}; +typedef struct _CONFIGURATION_INFORMATION CONFIGURATION_INFORMATION; +typedef struct _CONFIGURATION_INFORMATION *PCONFIGURATION_INFORMATION; +struct _OBJECT_HANDLE_INFORMATION { + ULONG HandleAttributes; + ACCESS_MASK GrantedAccess; +}; +typedef struct _OBJECT_HANDLE_INFORMATION *POBJECT_HANDLE_INFORMATION; +struct _KEYBOARD_INPUT_DATA { + USHORT UnitId; + USHORT MakeCode; + USHORT Flags; + USHORT Reserved; + ULONG ExtraInformation; +}; +typedef struct _KEYBOARD_INPUT_DATA *PKEYBOARD_INPUT_DATA; +struct _CONNECT_DATA { + PDEVICE_OBJECT ClassDeviceObject; + PVOID ClassService; +}; +typedef struct _CONNECT_DATA CONNECT_DATA; +typedef struct _CONNECT_DATA *PCONNECT_DATA; +enum _TRANSMIT_STATE { + Idle = 0, + SendingBytes = 1 +}; +typedef enum _TRANSMIT_STATE TRANSMIT_STATE; +struct _OUTPUT_PACKET { + PUCHAR Bytes; + ULONG CurrentByte; + ULONG ByteCount; + TRANSMIT_STATE State; +}; +typedef struct _OUTPUT_PACKET *POUTPUT_PACKET; +enum _KEYBOARD_SCAN_STATE { + Normal = 0, + GotE0 = 1, + GotE1 = 2 +}; +typedef enum _KEYBOARD_SCAN_STATE *PKEYBOARD_SCAN_STATE; +struct _INTERNAL_I8042_HOOK_KEYBOARD { + PVOID Context; + NTSTATUS(*InitializationRoutine) + (PVOID InitializationContext, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); + BOOLEAN(*IsrRoutine) + (PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, PUCHAR Byte, PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState); + void (*IsrWritePort)(PVOID Context, UCHAR Value); + void (*QueueKeyboardPacket)(PVOID Context); + PVOID CallContext; +}; +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD INTERNAL_I8042_HOOK_KEYBOARD; +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD *PINTERNAL_I8042_HOOK_KEYBOARD; +struct _DEVICE_EXTENSION { + PDEVICE_OBJECT Self; + PDEVICE_OBJECT PDO; + PDEVICE_OBJECT TopOfStack; + LONG EnableCount; + CONNECT_DATA UpperConnectData; + PVOID UpperContext; + NTSTATUS(*UpperInitializationRoutine) + (PVOID InitializationContext, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); + BOOLEAN(*UpperIsrHook) + (PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR Byte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState); + void (*IsrWritePort)(PVOID Context, UCHAR Value); + void (*QueueKeyboardPacket)(PVOID Context); + PVOID CallContext; + DEVICE_POWER_STATE DeviceState; + BOOLEAN Started; + BOOLEAN SurpriseRemoved; + BOOLEAN Removed; +}; +typedef struct _DEVICE_EXTENSION DEVICE_EXTENSION; +typedef struct _DEVICE_EXTENSION *PDEVICE_EXTENSION; +#pragma pack(push, 8) +#pragma pack(pop) +struct _KAPC; +struct _KDPC; +#pragma pack(push, 4) +#pragma pack(pop) +#pragma pack(push, 4) +#pragma pack(pop) +#pragma pack(push, 1) +#pragma pack(pop) +struct _DRIVER_OBJECT; +struct _DEVICE_OBJECT; +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _IRP; +struct _SCSI_REQUEST_BLOCK; +#pragma pack(push, 4) +#pragma pack(pop) +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +extern void *memcpy(void *, void const *, size_t); +extern void *memmove(void *, void const *, size_t); +extern void *memset(void *, int, size_t); +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, + PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, + PVOID Environment); +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, + PCWSTR ValueName); +void RtlInitString(PSTRING DestinationString, + PCSZ SourceString); +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString); +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString); +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); +SIZE_T RtlCompareMemory(void const *Source1, + void const *Source2, + SIZE_T Length); +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +LONG InterlockedIncrement(PLONG Addend) { + return ++(*Addend); +} +LONG InterlockedDecrement(PLONG Addend) { + return --(*Addend); +} +#pragma warning(disable : 4035) +#pragma warning(push) +#pragma warning(disable : 4164) +#pragma function(_enable) +#pragma function(_disable) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, + BOOLEAN State); +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, + BOOLEAN Wait); +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, + LONG Count, LONG Limit); +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, + LONG Adjustment, BOOLEAN Wait); +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval); +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout); +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock); +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql); +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, + SIZE_T NumberOfBytes, + ULONG Tag); +void ExFreePool(PVOID P); +void ExAcquireFastMutex(PFAST_MUTEX FastMutex); +void ExReleaseFastMutex(PFAST_MUTEX FastMutex); +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock); +void MmUnlockPages(PMDL MemoryDescriptorList); +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, + PVOID BaseAddress, + ULONG BugCheckOnFailure, + MM_PAGE_PRIORITY Priority); +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress); +void MmFreeContiguousMemory(PVOID BaseAddress); +void MmResetDriverPaging(PVOID AddressWithinSection); +PVOID MmPageEntireDriver(PVOID AddressWithinSection); +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ULONG DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + void (*StartRoutine)(PVOID StartContext), + PVOID StartContext); +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus); +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, + BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, + PIRP Irp); +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice); +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock); +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +void IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost); +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject); +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName); +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject); +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); +void IoDetachDevice(PDEVICE_OBJECT TargetDevice); +void IoFreeIrp(PIRP Irp); +void IoFreeMdl(PMDL Mdl); +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void); +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + NTSTATUS (*CalloutRoutine)(PVOID Context, + PUNICODE_STRING PathName, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION *BusInformation, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context); +void IoReleaseCancelSpinLock(KIRQL Irql); +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject); +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, + BOOLEAN Enable); +#pragma warning(disable : 4200) +#pragma warning(default : 4200) +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +void PoStartNextPowerIrp(PIRP Irp); +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID *Object, + POBJECT_HANDLE_INFORMATION HandleInformation); +void ObfDereferenceObject(PVOID Object); +NTSTATUS ZwClose(HANDLE Handle); +NTSTATUS KbFilter_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO); +NTSTATUS KbFilter_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_DispatchPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_InternIoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_IoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + if (__VERIFIER_nondet_int()) { + return 0L; + } else if (__VERIFIER_nondet_int()) { + return -1L; + } else { + return 259L; + } +} +NTSTATUS KbFilter_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_InitializationRoutine(PDEVICE_OBJECT DeviceObject, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); +BOOLEAN KbFilter_IsrHook(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState); +void KbFilter_ServiceCallback(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart, + PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed); +void KbFilter_Unload(PDRIVER_OBJECT Driver); +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, KbFilter_AddDevice) +#pragma alloc_text(PAGE, KbFilter_CreateClose) +#pragma alloc_text(PAGE, KbFilter_IoCtl) +#pragma alloc_text(PAGE, KbFilter_InternIoCtl) +#pragma alloc_text(PAGE, KbFilter_Unload) +#pragma alloc_text(PAGE, KbFilter_DispatchPassThrough) +#pragma alloc_text(PAGE, KbFilter_PnP) +#pragma alloc_text(PAGE, KbFilter_Power) +extern void *malloc(size_t); +void errorFn(void) { + + { + ERROR : { + reach_error(); + abort(); + } + } +} +int s; +int UNLOADED; +int NP; +int DC; +int SKIP1; +int SKIP2; +int MPR1; +int MPR3; +int IPC; +int pended; +NTSTATUS(*compFptr) +(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); +int compRegistered; +int lowerDriverReturn; +int setEventCalled; +int customIrp; +int myStatus; +void _BLAST_init(void) { + + { + UNLOADED = 0; + NP = 1; + DC = 2; + SKIP1 = 3; + SKIP2 = 4; + MPR1 = 5; + MPR3 = 6; + IPC = 7; + s = UNLOADED; + pended = 0; + compFptr = 0; + compRegistered = 0; + lowerDriverReturn = 0; + setEventCalled = 0; + customIrp = 0; + return; + } +} +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { + ULONG i = __VERIFIER_nondet_long(); + assume_abort_if_not(i < 28); + + { + DriverObject->MajorFunction[i] = &KbFilter_DispatchPassThrough; + DriverObject->MajorFunction[0] = &KbFilter_CreateClose; + DriverObject->MajorFunction[2] = &KbFilter_CreateClose; + DriverObject->MajorFunction[27] = &KbFilter_PnP; + DriverObject->MajorFunction[22] = &KbFilter_Power; + DriverObject->MajorFunction[15] = &KbFilter_InternIoCtl; + DriverObject->DriverUnload = &KbFilter_Unload; + (DriverObject->DriverExtension)->AddDevice = &KbFilter_AddDevice; + return (0L); + } +} +NTSTATUS KbFilter_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO) { + PDEVICE_EXTENSION devExt; + PDEVICE_OBJECT device; + NTSTATUS status; + + { + { + status = 0L; + status = IoCreateDevice(Driver, sizeof(DEVICE_EXTENSION), (void *)0, 11, 0, 0, + &device); + } + if (!(status >= 0L)) { + return (status); + } else { + } + { + memset(device->DeviceExtension, 0, sizeof(DEVICE_EXTENSION)); + devExt = (struct _DEVICE_EXTENSION *)device->DeviceExtension; + devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO); + devExt->Self = device; + devExt->PDO = PDO; + devExt->DeviceState = 1; + devExt->SurpriseRemoved = 0; + devExt->Removed = 0; + devExt->Started = 0; + device->Flags |= 8196UL; + device->Flags &= 4294967167UL; + } + return (status); + } +} +NTSTATUS KbFilter_Complete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) { + PKEVENT event; + + { + { + event = (struct _KEVENT *)Context; + KeSetEvent(event, 0, 0); + } + return (-1073741802L); + } +} +NTSTATUS KbFilter_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + PDEVICE_EXTENSION devExt; + LONG tmp; + LONG tmp___0; + NTSTATUS tmp___1; + + { + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + status = Irp->IoStatus.__annonCompField4.Status; + status = myStatus; + if (irpStack->MajorFunction == 0) { + goto switch_0_0; + } else { + if (irpStack->MajorFunction == 2) { + goto switch_0_2; + } else { + if (0) { + switch_0_0: /* CIL Label */; + if ((unsigned int)((void *)0) == (unsigned int)devExt->UpperConnectData.ClassService) { + status = -1073741436L; + } else { + { + tmp = InterlockedIncrement(&devExt->EnableCount); + } + if (1L == tmp) { + + } else { + } + } + goto switch_0_break; + switch_0_2 : /* CIL Label */ + { + tmp___0 = InterlockedDecrement(&devExt->EnableCount); + } + if (0L == tmp___0) { + + } else { + } + goto switch_0_break; + } else { + switch_0_break: /* CIL Label */; + } + } + } + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + tmp___1 = KbFilter_DispatchPassThrough(DeviceObject, Irp); + } + return (tmp___1); + } +} +NTSTATUS KbFilter_DispatchPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + NTSTATUS tmp; + + { + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + tmp = IofCallDriver(((struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->TopOfStack, + Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_InternIoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + PDEVICE_EXTENSION devExt; + PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard; + PCONNECT_DATA connectData; + NTSTATUS status; + NTSTATUS tmp; + + { + status = 0L; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + Irp->IoStatus.Information = 0; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (128 << 2)) | 3)) { + goto switch_1_exp_0; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (256 << 2)) | 3)) { + goto switch_1_exp_1; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (4080 << 2)) | 3)) { + goto switch_1_exp_2; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == 11 << 16) { + goto switch_1_exp_3; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (32 << 2))) { + goto switch_1_exp_4; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (16 << 2))) { + goto switch_1_exp_5; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (2 << 2))) { + goto switch_1_exp_6; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (8 << 2))) { + goto switch_1_exp_7; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (1 << 2))) { + goto switch_1_exp_8; + } else { + if (0) { + switch_1_exp_0: /* CIL Label */; + if ((unsigned int)devExt->UpperConnectData.ClassService != (unsigned int)((void *)0)) { + status = -1073741757L; + goto switch_1_break; + } else { + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < (ULONG)sizeof(CONNECT_DATA)) { + status = -1073741811L; + goto switch_1_break; + } else { + } + } + connectData = (struct _CONNECT_DATA *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; + devExt->UpperConnectData = *connectData; + connectData->ClassDeviceObject = devExt->Self; + connectData->ClassService = &KbFilter_ServiceCallback; + goto switch_1_break; + switch_1_exp_1: /* CIL Label */ + status = -1073741822L; + goto switch_1_break; + switch_1_exp_2: /* CIL Label */; + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < (ULONG)sizeof(INTERNAL_I8042_HOOK_KEYBOARD)) { + status = -1073741811L; + goto switch_1_break; + } else { + } + hookKeyboard = (struct _INTERNAL_I8042_HOOK_KEYBOARD *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; + devExt->UpperContext = hookKeyboard->Context; + hookKeyboard->Context = (void *)DeviceObject; + if (hookKeyboard->InitializationRoutine) { + devExt->UpperInitializationRoutine = hookKeyboard->InitializationRoutine; + } else { + } + hookKeyboard->InitializationRoutine = (NTSTATUS(*)(PVOID InitializationContext, + PVOID SynchFuncContext, + NTSTATUS(*ReadPort)(PVOID Context, + PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS(*WritePort)(PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn))(&KbFilter_InitializationRoutine); + if (hookKeyboard->IsrRoutine) { + devExt->UpperIsrHook = hookKeyboard->IsrRoutine; + } else { + } + hookKeyboard->IsrRoutine = (BOOLEAN(*)(PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, PUCHAR Byte, + PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState))(&KbFilter_IsrHook); + devExt->IsrWritePort = hookKeyboard->IsrWritePort; + devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket; + devExt->CallContext = hookKeyboard->CallContext; + status = 0L; + goto switch_1_break; + switch_1_exp_3: /* CIL Label */; + switch_1_exp_4: /* CIL Label */; + switch_1_exp_5: /* CIL Label */; + switch_1_exp_6: /* CIL Label */; + switch_1_exp_7: /* CIL Label */; + switch_1_exp_8: /* CIL Label */; + goto switch_1_break; + } else { + switch_1_break: /* CIL Label */; + } + } + } + } + } + } + } + } + } + } + if (!(status >= 0L)) { + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + IofCompleteRequest(Irp, 0); + } + return (status); + } else { + } + { + tmp = KbFilter_DispatchPassThrough(DeviceObject, Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PDEVICE_EXTENSION devExt; + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + KEVENT event; + PIO_STACK_LOCATION irpSp; + PIO_STACK_LOCATION nextIrpSp; + PIO_STACK_LOCATION irpSp___0; + + { + status = 0L; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (irpStack->MinorFunction == 0) { + goto switch_2_0; + } else { + if (irpStack->MinorFunction == 23) { + goto switch_2_23; + } else { + if (irpStack->MinorFunction == 2) { + goto switch_2_2; + } else { + if (irpStack->MinorFunction == 1) { + goto switch_2_1; + } else { + if (irpStack->MinorFunction == 5) { + goto switch_2_5; + } else { + if (irpStack->MinorFunction == 3) { + goto switch_2_3; + } else { + if (irpStack->MinorFunction == 6) { + goto switch_2_6; + } else { + if (irpStack->MinorFunction == 13) { + goto switch_2_13; + } else { + if (irpStack->MinorFunction == 4) { + goto switch_2_4; + } else { + if (irpStack->MinorFunction == 7) { + goto switch_2_7; + } else { + if (irpStack->MinorFunction == 8) { + goto switch_2_8; + } else { + if (irpStack->MinorFunction == 9) { + goto switch_2_9; + } else { + if (irpStack->MinorFunction == 12) { + goto switch_2_12; + } else { + if (irpStack->MinorFunction == 10) { + goto switch_2_10; + } else { + if (irpStack->MinorFunction == 11) { + goto switch_2_11; + } else { + if (irpStack->MinorFunction == 15) { + goto switch_2_15; + } else { + if (irpStack->MinorFunction == 16) { + goto switch_2_16; + } else { + if (irpStack->MinorFunction == 17) { + goto switch_2_17; + } else { + if (irpStack->MinorFunction == 18) { + goto switch_2_18; + } else { + if (irpStack->MinorFunction == 19) { + goto switch_2_19; + } else { + if (irpStack->MinorFunction == 20) { + goto switch_2_20; + } else { + { + goto switch_2_default; + if (0) { + switch_2_0 : /* CIL Label */ + { + irpSp = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + nextIrpSp = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation - 1; + memmove(nextIrpSp, irpSp, (long)(&((IO_STACK_LOCATION *)0)->CompletionRoutine)); + nextIrpSp->Control = 0; + /* KeInitializeEvent(& event, 0, 0); */ /* INLINED */ + } + if (s != NP) { + { + errorFn(); + } + } else { + if (compRegistered != 0) { + { + errorFn(); + } + } else { + compRegistered = 1; + compFptr = &KbFilter_Complete; + } + } + { + irpSp___0 = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation - 1; + irpSp___0->CompletionRoutine = &KbFilter_Complete; + irpSp___0->Context = &event; + irpSp___0->Control = 0; + irpSp___0->Control = 64; + irpSp___0->Control = (int)irpSp___0->Control | 128; + irpSp___0->Control = (int)irpSp___0->Control | 32; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + if (259L == status) { + { + KeWaitForSingleObject(&event, 0, + 0, 0, (void *)0); + } + } else { + } + if (status >= 0L) { + if ((long)myStatus >= 0L) { + devExt->Started = 1; + devExt->Removed = 0; + devExt->SurpriseRemoved = 0; + } else { + } + } else { + } + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + Irp->IoStatus.Information = 0; + IofCompleteRequest(Irp, 0); + } + goto switch_2_break; + switch_2_23: /* CIL Label */ + devExt->SurpriseRemoved = 1; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + goto switch_2_break; + switch_2_2: /* CIL Label */ + devExt->Removed = 1; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + IofCallDriver(devExt->TopOfStack, Irp); + /* IoDetachDevice(devExt->TopOfStack); */ /* INLINED */ + /* IoDeleteDevice(DeviceObject); */ /* INLINED */ + status = 0L; + } + goto switch_2_break; + switch_2_1: /* CIL Label */; + switch_2_5: /* CIL Label */; + switch_2_3: /* CIL Label */; + switch_2_6: /* CIL Label */; + switch_2_13: /* CIL Label */; + switch_2_4: /* CIL Label */; + switch_2_7: /* CIL Label */; + switch_2_8: /* CIL Label */; + switch_2_9: /* CIL Label */; + switch_2_12: /* CIL Label */; + switch_2_10: /* CIL Label */; + switch_2_11: /* CIL Label */; + switch_2_15: /* CIL Label */; + switch_2_16: /* CIL Label */; + switch_2_17: /* CIL Label */; + switch_2_18: /* CIL Label */; + switch_2_19: /* CIL Label */; + switch_2_20: /* CIL Label */; + switch_2_default: /* CIL Label */; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + goto switch_2_break; + } else { + switch_2_break: /* CIL Label */; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return (status); + } +} +NTSTATUS KbFilter_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + PDEVICE_EXTENSION devExt; + POWER_STATE powerState; + POWER_STATE_TYPE powerType; + NTSTATUS tmp; + + { + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + powerType = irpStack->Parameters.Power.Type; + powerState = irpStack->Parameters.Power.State; + if (irpStack->MinorFunction == 2) { + goto switch_3_2; + } else { + if (irpStack->MinorFunction == 1) { + goto switch_3_1; + } else { + if (irpStack->MinorFunction == 0) { + goto switch_3_0; + } else { + if (irpStack->MinorFunction == 3) { + goto switch_3_3; + } else { + { + goto switch_3_default; + if (0) { + switch_3_2: /* CIL Label */; + if ((int)powerType == 1) { + devExt->DeviceState = powerState.DeviceState; + } else { + } + switch_3_1: /* CIL Label */; + switch_3_0: /* CIL Label */; + switch_3_3: /* CIL Label */; + switch_3_default: /* CIL Label */; + goto switch_3_break; + } else { + switch_3_break: /* CIL Label */; + } + } + } + } + } + } + { + /* PoStartNextPowerIrp(Irp); */ /* INLINED */ + } + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + tmp = PoCallDriver(devExt->TopOfStack, Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_InitializationRoutine(PDEVICE_OBJECT DeviceObject, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn) { + PDEVICE_EXTENSION devExt; + NTSTATUS status; + + { + status = 0L; + devExt = DeviceObject->DeviceExtension; + if (devExt->UpperInitializationRoutine) { + { + status = (*(devExt->UpperInitializationRoutine))(devExt->UpperContext, SynchFuncContext, + ReadPort, WritePort, TurnTranslationOn); + } + if (!(status >= 0L)) { + return (status); + } else { + } + } else { + } + *TurnTranslationOn = 1; + return (status); + } +} +BOOLEAN KbFilter_IsrHook(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState) { + PDEVICE_EXTENSION devExt; + BOOLEAN retVal; + + { + retVal = 1; + devExt = DeviceObject->DeviceExtension; + if (devExt->UpperIsrHook) { + { + retVal = (*(devExt->UpperIsrHook))(devExt->UpperContext, CurrentInput, CurrentOutput, + StatusByte, DataByte, ContinueProcessing, ScanState); + } + if (!retVal) { + return (retVal); + } else { + if (!*ContinueProcessing) { + return (retVal); + } else { + } + } + } else { + } + *ContinueProcessing = 1; + return (retVal); + } +} +void KbFilter_ServiceCallback(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart, + PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed) { + PDEVICE_EXTENSION devExt; + + { + { + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + (*((void (*)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2, + PVOID SystemArgument3))devExt->UpperConnectData.ClassService))(devExt->UpperConnectData.ClassDeviceObject, + InputDataStart, + InputDataEnd, + InputDataConsumed); + } + return; + } +} +void KbFilter_Unload(PDRIVER_OBJECT Driver) { + + { + return; + } +} +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +#pragma warning(disable : 4035) +#pragma warning(push) +#pragma warning(disable : 4164) +#pragma function(_enable) +#pragma function(_disable) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4200) +#pragma warning(default : 4200) +IRP *pirp; +void stub_driver_init(void) { + + { + s = NP; + pended = 0; + compFptr = 0; + compRegistered = 0; + lowerDriverReturn = 0; + setEventCalled = 0; + customIrp = 0; + return; + } +} +extern unsigned char __VERIFIER_nondet_uchar(void); +int main(void) { + DRIVER_OBJECT d; + UNICODE_STRING u; + NTSTATUS status; + int we_should_unload = __VERIFIER_nondet_int(); + IRP irp; + int __BLAST_NONDET = __VERIFIER_nondet_int(); + int irp_choice = __VERIFIER_nondet_int(); + DEVICE_EXTENSION devext; + DEVICE_OBJECT devobj; + devobj.DeviceExtension = &devext; + struct _DRIVER_EXTENSION ext; + d.DriverExtension = &ext; + + INTERNAL_I8042_HOOK_KEYBOARD hookkb; + struct _IO_STACK_LOCATION stack[3]; + + stack[0].MajorFunction = __VERIFIER_nondet_uchar(); + stack[1].MajorFunction = __VERIFIER_nondet_uchar(); + stack[2].MajorFunction = __VERIFIER_nondet_uchar(); + stack[0].MinorFunction = __VERIFIER_nondet_uchar(); + stack[1].MinorFunction = __VERIFIER_nondet_uchar(); + stack[2].MinorFunction = __VERIFIER_nondet_uchar(); + + stack[0].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + stack[1].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + stack[2].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + + stack[0].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + stack[1].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + stack[2].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + + stack[0].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + stack[1].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + stack[2].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + + irp.Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation = &stack[1]; + + { + { + pirp = &irp; + _BLAST_init(); + status = DriverEntry(&d, &u); + } + if (status >= 0L) { + s = NP; + customIrp = 0; + setEventCalled = customIrp; + lowerDriverReturn = setEventCalled; + compRegistered = lowerDriverReturn; + compFptr = compRegistered; + pended = compFptr; + pirp->IoStatus.__annonCompField4.Status = 0L; + myStatus = 0L; + if (irp_choice == 0) { + pirp->IoStatus.__annonCompField4.Status = -1073741637L; + myStatus = -1073741637L; + } else { + } + { + status = KbFilter_AddDevice(&d, &devobj); + stub_driver_init(); + } + if (!(status >= 0L)) { + return (-1); + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_4_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_4_1; + } else { + if (__BLAST_NONDET == 2) { + goto switch_4_2; + } else { + if (__BLAST_NONDET == 3) { + goto switch_4_3; + } else { + if (__BLAST_NONDET == 4) { + goto switch_4_4; + } else { + if (__BLAST_NONDET == 8) { + goto switch_4_8; + } else { + { + goto switch_4_default; + if (0) { + switch_4_0 : /* CIL Label */ + { + status = KbFilter_CreateClose(&devobj, pirp); + } + goto switch_4_break; + switch_4_1 : /* CIL Label */ + { + status = KbFilter_CreateClose(&devobj, pirp); + } + goto switch_4_break; + switch_4_2 : /* CIL Label */ + { + status = KbFilter_IoCtl(&devobj, pirp); + } + goto switch_4_break; + switch_4_3 : /* CIL Label */ + { + status = KbFilter_PnP(&devobj, pirp); + } + goto switch_4_break; + switch_4_4 : /* CIL Label */ + { + status = KbFilter_Power(&devobj, pirp); + } + goto switch_4_break; + switch_4_8 : /* CIL Label */ + { + status = KbFilter_InternIoCtl(&devobj, pirp); + } + goto switch_4_break; + switch_4_default: /* CIL Label */; + return (-1); + } else { + switch_4_break: /* CIL Label */; + } + } + } + } + } + } + } + } + if (we_should_unload) { + { + /* KbFilter_Unload(& d); */ /* INLINED */ + } + } else { + } + } else { + } + if (pended == 1) { + if (s == NP) { + s = NP; + } else { + goto _L___2; + } + } else { + _L___2: /* CIL Label */ + if (pended == 1) { + if (s == MPR3) { + s = MPR3; + } else { + goto _L___1; + } + } else { + _L___1: /* CIL Label */ + if (s == UNLOADED) { + + } else { + if (status == -1L) { + + } else { + if (s != SKIP2) { + if (s != IPC) { + if (s != DC) { + + } else { + goto _L___0; + } + } else { + goto _L___0; + } + } else { + _L___0: /* CIL Label */ + if (pended == 1) { + if (status != 259L) { + { + errorFn(); + } + } else { + } + } else { + if (s == DC) { + if (status == 259L) { + { + errorFn(); + } + } else { + } + } else { + if (status != (NTSTATUS)lowerDriverReturn) { + + } else { + } + } + } + } + } + } + } + } + return (status); + } +} +char _SLAM_alloc_dummy; +void ExAcquireFastMutex(PFAST_MUTEX FastMutex); +void ExAcquireFastMutex(PFAST_MUTEX FastMutex) { + + { + return; + } +} +void ExReleaseFastMutex(PFAST_MUTEX FastMutex); +void ExReleaseFastMutex(PFAST_MUTEX FastMutex) { + + { + return; + } +} +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, + SIZE_T NumberOfBytes, + ULONG Tag); +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, SIZE_T NumberOfBytes, + ULONG Tag) { + PVOID x; + char *tmp; + + { + { + tmp = malloc(NumberOfBytes); + x = tmp; + } + return (x); + } +} +void ExFreePool(PVOID P); +void ExFreePool(PVOID P) { + + { + return; + } +} +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, + BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, + PIRP Irp); +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, BOOLEAN SecondaryBuffer, + BOOLEAN ChargeQuota, PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_5_0; + } else { + { + goto switch_5_default; + if (0) { + switch_5_0 : /* CIL Label */ + { + tmp = malloc(sizeof(MDL)); + } + return ((void *)tmp); + switch_5_default: /* CIL Label */; + return ((void *)0); + } else { + switch_5_break: /* CIL Label */; + } + } + } + } +} +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice); +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, PDEVICE_OBJECT TargetDevice) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_6_0; + } else { + { + goto switch_6_default; + if (0) { + switch_6_0: /* CIL Label */; + return (TargetDevice); + switch_6_default: /* CIL Label */; + return ((void *)0); + } else { + switch_6_break: /* CIL Label */; + } + } + } + } +} +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, PDEVICE_OBJECT DeviceObject, + PVOID Buffer, ULONG Length, PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + customIrp = 1; + if (__BLAST_NONDET == 0) { + goto switch_7_0; + } else { + { + goto switch_7_default; + if (0) { + switch_7_0 : /* CIL Label */ + { + tmp = malloc(sizeof(IRP)); + } + return ((void *)tmp); + switch_7_default: /* CIL Label */; + return ((void *)0); + } else { + switch_7_break: /* CIL Label */; + } + } + } + } +} +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, + ULONG OutputBufferLength, BOOLEAN InternalDeviceIoControl, + PKEVENT Event, PIO_STATUS_BLOCK IoStatusBlock) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + customIrp = 1; + if (__BLAST_NONDET == 0) { + goto switch_8_0; + } else { + { + goto switch_8_default; + if (0) { + switch_8_0 : /* CIL Label */ + { + tmp = malloc(sizeof(IRP)); + } + return ((void *)tmp); + switch_8_default: /* CIL Label */; + return ((void *)0); + } else { + switch_8_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject); +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_9_0; + } else { + { + goto switch_9_default; + if (0) { + switch_9_0 : /* CIL Label */ + { + tmp = malloc(sizeof(DEVICE_OBJECT)); + *DeviceObject = (void *)tmp; + (*DeviceObject)->DeviceExtension = malloc(DeviceExtensionSize); + } + return (0L); + switch_9_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_9_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName); +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, PUNICODE_STRING DeviceName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_10_0; + } else { + { + goto switch_10_default; + if (0) { + switch_10_0: /* CIL Label */; + return (0L); + switch_10_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_10_break: /* CIL Label */; + } + } + } + } +} +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject); +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject) { + + { + return; + } +} +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_11_0; + } else { + { + goto switch_11_default; + if (0) { + switch_11_0: /* CIL Label */; + return (0L); + switch_11_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_11_break: /* CIL Label */; + } + } + } + } +} +void IoDetachDevice(PDEVICE_OBJECT TargetDevice); +void IoDetachDevice(PDEVICE_OBJECT TargetDevice) { + + { + return; + } +} +void IoFreeIrp(PIRP Irp); +void IoFreeIrp(PIRP Irp) { + + { + return; + } +} +void IoFreeMdl(PMDL Mdl); +void IoFreeMdl(PMDL Mdl) { + + { + return; + } +} +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void); +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) { + char *tmp; + + { + { + tmp = malloc(sizeof(CONFIGURATION_INFORMATION)); + } + return ((void *)tmp); + } +} +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + NTSTATUS (*CalloutRoutine)(PVOID Context, + PUNICODE_STRING PathName, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION *BusInformation, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context); +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, PULONG BusNumber, PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, NTSTATUS (*CalloutRoutine)(PVOID Context, PUNICODE_STRING PathName, INTERFACE_TYPE BusType, ULONG BusNumber, PKEY_VALUE_FULL_INFORMATION *BusInformation, CONFIGURATION_TYPE ControllerType, ULONG ControllerNumber, PKEY_VALUE_FULL_INFORMATION *ControllerInformation, CONFIGURATION_TYPE PeripheralType, ULONG PeripheralNumber, PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_12_0; + } else { + { + goto switch_12_default; + if (0) { + switch_12_0: /* CIL Label */; + return (0L); + switch_12_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_12_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_13_0; + } else { + { + goto switch_13_default; + if (0) { + switch_13_0: /* CIL Label */; + return (0L); + switch_13_default: /* CIL Label */; + return (-1073741808L); + } else { + switch_13_break: /* CIL Label */; + } + } + } + } +} +void IoReleaseCancelSpinLock(KIRQL Irql); +void IoReleaseCancelSpinLock(KIRQL Irql) { + + { + return; + } +} +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, + BOOLEAN Enable); +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, BOOLEAN Enable) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_14_0; + } else { + { + goto switch_14_default; + if (0) { + switch_14_0: /* CIL Label */; + return (0L); + switch_14_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_14_break: /* CIL Label */; + } + } + } + } +} +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject); +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject) { + + { + return; + } +} +void stubMoreProcessingRequired(void) { + + { + if (s == NP) { + s = MPR1; + } else { + { + errorFn(); + } + } + return; + } +} +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + NTSTATUS returnVal2; + int compRetStatus; + PVOID lcontext = 0; + NTSTATUS tmp; + + { + if (compRegistered) { + { + tmp = KbFilter_Complete(DeviceObject, Irp, lcontext); + compRetStatus = tmp; + } + if ((long)compRetStatus == -1073741802L) { + { + stubMoreProcessingRequired(); + } + } else { + } + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_15_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_15_1; + } else { + { + goto switch_15_default; + if (0) { + switch_15_0: /* CIL Label */ + returnVal2 = 0L; + goto switch_15_break; + switch_15_1: /* CIL Label */ + returnVal2 = -1073741823L; + goto switch_15_break; + switch_15_default: /* CIL Label */ + returnVal2 = 259L; + goto switch_15_break; + } else { + switch_15_break: /* CIL Label */; + } + } + } + } + if (s == NP) { + s = IPC; + lowerDriverReturn = returnVal2; + } else { + if (s == MPR1) { + if (returnVal2 == 259L) { + s = MPR3; + lowerDriverReturn = returnVal2; + } else { + s = NP; + lowerDriverReturn = returnVal2; + } + } else { + if (s == SKIP1) { + s = SKIP2; + lowerDriverReturn = returnVal2; + } else { + { + errorFn(); + } + } + } + } + return (returnVal2); + } +} +void IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost); +void IofCompleteRequest(PIRP Irp, CCHAR PriorityBoost) { + + { + if (s == NP) { + s = DC; + } else { + { + errorFn(); + } + } + return; + } +} +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock); +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock) { + + { + return ((unsigned char)0); + } +} +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval); +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER Interval) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_16_0; + } else { + { + goto switch_16_default; + if (0) { + switch_16_0: /* CIL Label */; + return (0L); + switch_16_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_16_break: /* CIL Label */; + } + } + } + } +} +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, + BOOLEAN State); +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State) { + + { + return; + } +} +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, + LONG Count, LONG Limit); +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, LONG Count, LONG Limit) { + + { + return; + } +} +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock); +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock) { + + { + return; + } +} +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, + LONG Adjustment, BOOLEAN Wait); +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, LONG Adjustment, + BOOLEAN Wait) { + LONG r = __VERIFIER_nondet_long(); + + { + return (r); + } +} +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql); +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL NewIrql) { + + { + return; + } +} +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, + BOOLEAN Wait); +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, BOOLEAN Wait) { + LONG l = __VERIFIER_nondet_long(); + + { + setEventCalled = 1; + return (l); + } +} +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout); +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, PLARGE_INTEGER Timeout) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (s == MPR3) { + if (setEventCalled == 1) { + s = NP; + setEventCalled = 0; + } else { + goto _L; + } + } else { + _L: /* CIL Label */ + if (customIrp == 1) { + s = NP; + customIrp = 0; + } else { + if (s == MPR3) { + { + errorFn(); + } + } else { + } + } + } + if (__BLAST_NONDET == 0) { + goto switch_17_0; + } else { + { + goto switch_17_default; + if (0) { + switch_17_0: /* CIL Label */; + return (0L); + switch_17_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_17_break: /* CIL Label */; + } + } + } + } +} +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress); +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, PHYSICAL_ADDRESS HighestAcceptableAddress) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_18_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_18_1; + } else { + if (0) { + switch_18_0 : /* CIL Label */ + { + tmp = malloc(NumberOfBytes); + } + return (tmp); + switch_18_1: /* CIL Label */; + return ((void *)0); + } else { + switch_18_break: /* CIL Label */; + } + } + } + return ((void *)0); + } +} +void MmFreeContiguousMemory(PVOID BaseAddress); +void MmFreeContiguousMemory(PVOID BaseAddress) { + + { + return; + } +} +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, + PVOID BaseAddress, + ULONG BugCheckOnFailure, + MM_PAGE_PRIORITY Priority); +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, PVOID BaseAddress, + ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority) { + + { + return ((void *)0); + } +} +PVOID MmPageEntireDriver(PVOID AddressWithinSection); +PVOID MmPageEntireDriver(PVOID AddressWithinSection) { + + { + return ((void *)0); + } +} +void MmResetDriverPaging(PVOID AddressWithinSection); +void MmResetDriverPaging(PVOID AddressWithinSection) { + + { + return; + } +} +void MmUnlockPages(PMDL MemoryDescriptorList); +void MmUnlockPages(PMDL MemoryDescriptorList) { + + { + return; + } +} +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID *Object, + POBJECT_HANDLE_INFORMATION HandleInformation); +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, PVOID *Object, POBJECT_HANDLE_INFORMATION HandleInformation) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_19_0; + } else { + { + goto switch_19_default; + if (0) { + switch_19_0: /* CIL Label */; + return (0L); + switch_19_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_19_break: /* CIL Label */; + } + } + } + } +} +void ObfDereferenceObject(PVOID Object); +void ObfDereferenceObject(PVOID Object) { + + { + return; + } +} +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + int compRetStatus; + NTSTATUS returnVal; + PVOID lcontext = 0; + NTSTATUS tmp; + + { + if (compRegistered) { + { + tmp = KbFilter_Complete(DeviceObject, Irp, lcontext); + compRetStatus = tmp; + } + if ((long)compRetStatus == -1073741802L) { + { + stubMoreProcessingRequired(); + } + } else { + } + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_20_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_20_1; + } else { + { + goto switch_20_default; + if (0) { + switch_20_0: /* CIL Label */ + returnVal = 0L; + goto switch_20_break; + switch_20_1: /* CIL Label */ + returnVal = -1073741823L; + goto switch_20_break; + switch_20_default: /* CIL Label */ + returnVal = 259L; + goto switch_20_break; + } else { + switch_20_break: /* CIL Label */; + } + } + } + } + if (s == NP) { + s = IPC; + lowerDriverReturn = returnVal; + } else { + if (s == MPR1) { + if (returnVal == 259L) { + s = MPR3; + lowerDriverReturn = returnVal; + } else { + s = NP; + lowerDriverReturn = returnVal; + } + } else { + if (s == SKIP1) { + s = SKIP2; + lowerDriverReturn = returnVal; + } else { + { + errorFn(); + } + } + } + } + return (returnVal); + } +} +void PoStartNextPowerIrp(PIRP Irp); +void PoStartNextPowerIrp(PIRP Irp) { + + { + return; + } +} +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ULONG DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + void (*StartRoutine)(PVOID StartContext), + PVOID StartContext); +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, PCLIENT_ID ClientId, void (*StartRoutine)(PVOID StartContext), + PVOID StartContext) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_21_0; + } else { + { + goto switch_21_default; + if (0) { + switch_21_0: /* CIL Label */; + return (0L); + switch_21_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_21_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus); +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_22_0; + } else { + { + goto switch_22_default; + if (0) { + switch_22_0: /* CIL Label */; + return (0L); + switch_22_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_22_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString); +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_23_0; + } else { + { + goto switch_23_default; + if (0) { + switch_23_0: /* CIL Label */; + return (0L); + switch_23_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_23_break: /* CIL Label */; + } + } + } + } +} +SIZE_T RtlCompareMemory(void const *Source1, + void const *Source2, + SIZE_T Length); +SIZE_T RtlCompareMemory(void const *Source1, void const *Source2, + SIZE_T Length) { + SIZE_T r = __VERIFIER_nondet_long(); + + { + return (r); + } +} +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString) { + + { + return; + } +} +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, + PCWSTR ValueName); +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, PCWSTR ValueName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_24_0; + } else { + { + goto switch_24_default; + if (0) { + switch_24_0: /* CIL Label */; + return (0L); + switch_24_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_24_break: /* CIL Label */; + } + } + } + } +} +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) { + + { + return; + } +} +void RtlInitString(PSTRING DestinationString, + PCSZ SourceString); +void RtlInitString(PSTRING DestinationString, PCSZ SourceString) { + + { + return; + } +} +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString); +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString) { + + { + return; + } +} +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, + PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, + PVOID Environment); +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, PVOID Environment) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_25_0; + } else { + { + goto switch_25_default; + if (0) { + switch_25_0: /* CIL Label */; + return (0L); + switch_25_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_25_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS ZwClose(HANDLE Handle); +NTSTATUS ZwClose(HANDLE Handle) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_26_0; + } else { + { + goto switch_26_default; + if (0) { + switch_26_0: /* CIL Label */; + return (0L); + switch_26_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_26_break: /* CIL Label */; + } + } + } + } +} diff --git a/test/regression/2023-10-13-uninitialized-memory.c b/test/regression/2023-10-13-uninitialized-memory.c new file mode 100644 index 0000000000..bf13fd0986 --- /dev/null +++ b/test/regression/2023-10-13-uninitialized-memory.c @@ -0,0 +1,21 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char *s1 = (char *)malloc(1); + char *s2 = (char *)malloc(1); + if (s1[0] == s2[0]) { + printf("1) eq\n"); + } else { + printf("1) not eq\n"); + } + + // CHECK-DAG: 1) eq + // CHECK-DAG: 1) not eq +} diff --git a/test/regression/2023-27-10-SimpleComparison.c b/test/regression/2023-27-10-SimpleComparison.c new file mode 100644 index 0000000000..def7647d8c --- /dev/null +++ b/test/regression/2023-27-10-SimpleComparison.c @@ -0,0 +1,21 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --debug-assignment-validating-solver=false --use-fast-cex-solver=false --use-cex-cache=false --use-branch-cache=false --use-alpha-equivalence=true --use-independent-solver=false --use-concretizing-solver=false --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc + +#include + +struct Node { + int *x; +}; + +int main() { + struct Node *nodeA; + struct Node *nodeB; + klee_make_symbolic(&nodeA, sizeof(nodeA), "nodeA"); + klee_make_symbolic(&nodeB, sizeof(nodeB), "nodeB"); + + if (nodeA && nodeB && nodeA == nodeB && (*nodeA->x * 2) != (*nodeA->x + *nodeB->x)) { + assert(0); + } + return 0; +} diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp index 5488055bd2..2deedb3c0b 100644 --- a/tools/kleaver/main.cpp +++ b/tools/kleaver/main.cpp @@ -9,6 +9,7 @@ #include "klee/ADT/SparseStorage.h" #include "klee/Config/Version.h" +#include "klee/Expr/ArrayCache.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprBuilder.h" @@ -212,7 +213,8 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, std::move(coreSolver), getQueryLogPath(ALL_QUERIES_SMT2_FILE_NAME), getQueryLogPath(SOLVER_QUERIES_SMT2_FILE_NAME), getQueryLogPath(ALL_QUERIES_KQUERY_FILE_NAME), - getQueryLogPath(SOLVER_QUERIES_KQUERY_FILE_NAME), nullptr); + getQueryLogPath(SOLVER_QUERIES_KQUERY_FILE_NAME), nullptr, + P->getArrayCache()); unsigned Index = 0; for (std::vector::iterator it = Decls.begin(), ie = Decls.end(); diff --git a/tools/klee/CMakeLists.txt b/tools/klee/CMakeLists.txt index cabdfdfcbd..5d63f93901 100644 --- a/tools/klee/CMakeLists.txt +++ b/tools/klee/CMakeLists.txt @@ -20,6 +20,9 @@ target_compile_options(klee PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(klee PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) +# Copy run script +configure_file(${CMAKE_SOURCE_DIR}/scripts/kleef ${CMAKE_BINARY_DIR}/bin/kleef COPYONLY) + install(TARGETS klee RUNTIME DESTINATION bin) # The KLEE binary depends on the runtimes diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index e3e87da330..f6a6b8147f 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -15,7 +15,7 @@ #include "klee/Core/Context.h" #include "klee/Core/Interpreter.h" #include "klee/Core/TargetedExecutionReporter.h" -#include "klee/Expr/Expr.h" +#include "klee/Module/LocationInfo.h" #include "klee/Module/SarifReport.h" #include "klee/Module/TargetForest.h" #include "klee/Solver/SolverCmdLine.h" @@ -29,14 +29,14 @@ #include "klee/System/Time.h" #include "klee/Support/CompilerWarning.h" +#include "llvm/Analysis/CallGraph.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" @@ -52,8 +52,8 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/TargetSelect.h" DISABLE_WARNING_POP +#include #include -#include #include #include #include @@ -150,28 +150,10 @@ cl::opt cl::desc("Function in which to start execution (default=main)"), cl::init("main"), cl::cat(StartCat)); -cl::opt UTBotMode("utbot", cl::desc("Klee was launched by utbot"), - cl::init(false), cl::cat(StartCat)); - -cl::opt InteractiveMode("interactive", - cl::desc("Launch klee in interactive mode."), - cl::init(false), cl::cat(StartCat)); - cl::opt TimeoutPerFunction("timeout-per-function", cl::desc("Timeout per function in klee."), cl::init(0), cl::cat(StartCat)); -cl::opt - EntryPointsFile("entrypoints-file", - cl::desc("Path to file with entrypoints name."), - cl::init("entrypoints.txt"), cl::cat(StartCat)); - -const int MAX_PROCESS_NUMBER = 50; -cl::opt ProcessNumber("process-number", - cl::desc("Number of parallel process in klee, must " - "lie in [1, 50] (default = 1)."), - cl::init(1), cl::cat(StartCat)); - cl::opt AnalysisReproduce("analysis-reproduce", cl::desc("Path of JSON file containing static analysis " @@ -365,11 +347,69 @@ cl::opt XMLMetadataProgramHash( llvm::cl::desc("Test-Comp hash sum of original file for xml metadata"), llvm::cl::cat(TestCompCat)); +/*** Mocking options ***/ + +cl::OptionCategory MockCat("Mocking options"); + +cl::opt MockModeledFunction( + "mock-modeled-functions", + cl::desc("Link modeled mocks from libkleeRuntimeMocks (default=false)"), + cl::init(false), cl::cat(MockCat)); + +cl::opt + Mock("mock-policy", cl::desc("Specify policy for mocking external calls"), + cl::values(clEnumValN(MockPolicy::None, "none", + "No mock function generated (default)"), + clEnumValN(MockPolicy::Failed, "failed", + "Generate symbolic value for failed external " + "calls, test will be irreproducible"), + clEnumValN(MockPolicy::All, "all", + "Generate IR module with all external symbols")), + cl::init(MockPolicy::None), cl::cat(MockCat)); + +cl::opt MockStrategy( + "mock-strategy", cl::desc("Specify strategy for mocking external calls"), + cl::values( + clEnumValN(MockStrategyKind::Naive, "naive", + "Every time external function is called, new symbolic value " + "is generated for its return value (default)"), + clEnumValN( + MockStrategyKind::Deterministic, "deterministic", + "NOTE: this option is compatible with Z3 solver only. Each " + "external function is treated as a deterministic " + "function. Therefore, when function is called many times " + "with equal arguments, every time equal values will be returned.")), + cl::init(MockStrategyKind::Naive), cl::cat(MockCat)); + +cl::opt MockMutableGlobals( + "mock-mutable-globals", + cl::desc("Specify strategy for mocking global vars"), + cl::values( + clEnumValN(MockMutableGlobalsPolicy::None, "none", + "No mutable global object are allowed o mock except " + "external (default)"), + clEnumValN(MockMutableGlobalsPolicy::All, "all", + "Mock globals on module build stage and generate bicode " + "module for it")), + cl::init(MockMutableGlobalsPolicy::None), cl::cat(MockCat)); + +/*** Annotations options ***/ + +cl::opt + AnnotationsFile("annotations", cl::desc("Path to the annotation JSON file"), + cl::value_desc("path file"), cl::cat(MockCat)); + +cl::opt AnnotateOnlyExternal( + "annotate-only-external", + cl::desc("Ignore annotations for defined function (default=false)"), + cl::init(false), cl::cat(MockCat)); + } // namespace namespace klee { extern cl::opt MaxTime; extern cl::opt FunctionCallReproduce; +extern cl::opt DumpStatesOnHalt; class ExecutionState; } // namespace klee @@ -409,14 +449,16 @@ class KleeHandler : public InterpreterHandler { void processTestCase(const ExecutionState &state, const char *message, const char *suffix, bool isError = false); - void writeTestCaseXML(bool isError, const KTest &out, unsigned id); + void writeTestCaseXML(bool isError, const KTest &out, unsigned id, + unsigned version = 0); std::string getOutputFilename(const std::string &filename); std::unique_ptr openOutputFile(const std::string &filename); - std::string getTestFilename(const std::string &suffix, unsigned id); - std::unique_ptr openTestFile(const std::string &suffix, - unsigned id); + std::string getTestFilename(const std::string &suffix, unsigned id, + unsigned version = 0); + std::unique_ptr + openTestFile(const std::string &suffix, unsigned id, unsigned version = 0); // load a .path file static void loadPathFile(std::string name, std::vector &buffer); @@ -557,11 +599,14 @@ KleeHandler::openOutputFile(const std::string &filename) { return f; } -std::string KleeHandler::getTestFilename(const std::string &suffix, - unsigned id) { +std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id, + unsigned version) { std::stringstream filename; - filename << "test" << std::setfill('0') << std::setw(6) << id << '.' - << suffix; + filename << "test" << std::setfill('0') << std::setw(6) << id; + if (version) { + filename << '_' << version; + } + filename << '.' << suffix; return filename.str(); } @@ -570,8 +615,9 @@ SmallString<128> KleeHandler::getOutputDirectory() const { } std::unique_ptr -KleeHandler::openTestFile(const std::string &suffix, unsigned id) { - return openOutputFile(getTestFilename(suffix, id)); +KleeHandler::openTestFile(const std::string &suffix, unsigned id, + unsigned version) { + return openOutputFile(getTestFilename(suffix, id, version)); } /* Outputs all files (.ktest, .kquery, .cov etc.) describing a test case */ @@ -581,7 +627,10 @@ void KleeHandler::processTestCase(const ExecutionState &state, unsigned id = ++m_numTotalTests; if (!WriteNone && (FunctionCallReproduce == "" || strcmp(suffix, "assert.err") == 0 || - strcmp(suffix, "reachable.err") == 0)) { + strcmp(suffix, "reachable.err") == 0 || + (DumpStatesOnHalt == HaltExecution::Reason::UnreachedTarget && + m_interpreter->getHaltExecution() == + HaltExecution::Reason::UnreachedTarget))) { KTest ktest; ktest.numArgs = m_argc; ktest.args = m_argv; @@ -594,16 +643,18 @@ void KleeHandler::processTestCase(const ExecutionState &state, klee_warning("unable to get symbolic solution, losing test case"); const auto start_time = time::getWallTime(); - - if (WriteKTests) { - - if (success) { - if (!kTest_toFile( - &ktest, - getOutputFilename(getTestFilename("ktest", id)).c_str())) { - klee_warning("unable to write output test case, losing it"); - } else { - ++m_numGeneratedTests; + bool atLeastOneGenerated = false; + + if (success) { + if (WriteKTests) { + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + if (!kTest_toFile( + &ktest, + getOutputFilename(getTestFilename("ktest", id, i)).c_str())) { + klee_warning("unable to write output test case, losing it"); + } else { + atLeastOneGenerated = true; + } } if (WriteStates) { @@ -612,49 +663,36 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } - if (message) { - auto f = openTestFile(suffix, id); - if (f) - *f << message; - } - - if (m_pathWriter) { - std::vector concreteBranches; - m_pathWriter->readStream(m_interpreter->getPathStreamID(state), - concreteBranches); - auto f = openTestFile("path", id); - if (f) { - for (const auto &branch : concreteBranches) { - *f << branch << '\n'; - } + if (WriteXMLTests) { + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + writeTestCaseXML(message != nullptr, ktest, id, i); + atLeastOneGenerated = true; } } - } - if (message || WriteKQueries) { - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::KQUERY); - auto f = openTestFile("kquery", id); - if (f) - *f << constraints; + for (unsigned i = 0; i < ktest.numObjects; i++) { + delete[] ktest.objects[i].bytes; + delete[] ktest.objects[i].pointers; + } + delete[] ktest.objects; } - if (WriteCVCs) { - // FIXME: If using Z3 as the core solver the emitted file is actually - // SMT-LIBv2 not CVC which is a bit confusing - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); - auto f = openTestFile("cvc", id); + if (message) { + auto f = openTestFile(suffix, id); if (f) - *f << constraints; + *f << message; } - if (WriteSMT2s) { - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); - auto f = openTestFile("smt2", id); - if (f) - *f << constraints; + if (m_pathWriter) { + std::vector concreteBranches; + m_pathWriter->readStream(m_interpreter->getPathStreamID(state), + concreteBranches); + auto f = openTestFile("path", id); + if (f) { + for (const auto &branch : concreteBranches) { + *f << branch << '\n'; + } + } } if (m_symPathWriter) { @@ -669,42 +707,14 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } - if (WriteKPaths) { - std::string blockPath; - m_interpreter->getBlockPath(state, blockPath); - auto f = openTestFile("kpath", id); - if (f) - *f << blockPath; - } - - if (WriteCov) { - std::map> cov; - m_interpreter->getCoveredLines(state, cov); - auto f = openTestFile("cov", id); - if (f) { - for (const auto &entry : cov) { - for (const auto &line : entry.second) { - *f << *entry.first << ':' << line << '\n'; - } - } - } - } - - if (WriteXMLTests) { - writeTestCaseXML(message != nullptr, ktest, id); + if (atLeastOneGenerated) { ++m_numGeneratedTests; } - for (unsigned i = 0; i < ktest.numObjects; i++) { - delete[] ktest.objects[i].bytes; - delete[] ktest.objects[i].pointers; - } - delete[] ktest.objects; - if (m_numGeneratedTests == MaxTests) m_interpreter->setHaltExecution(HaltExecution::MaxTests); - if (!WriteXMLTests && WriteTestInfo) { + if (WriteTestInfo) { time::Span elapsed_time(time::getWallTime() - start_time); auto f = openTestFile("info", id); if (f) @@ -712,6 +722,53 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } // if (!WriteNone) + if (WriteKQueries) { + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::KQUERY); + auto f = openTestFile("kquery", id); + if (f) + *f << constraints; + } + + if (WriteCVCs) { + // FIXME: If using Z3 as the core solver the emitted file is actually + // SMT-LIBv2 not CVC which is a bit confusing + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); + auto f = openTestFile("cvc", id); + if (f) + *f << constraints; + } + + if (WriteSMT2s) { + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); + auto f = openTestFile("smt2", id); + if (f) + *f << constraints; + } + + if (WriteKPaths) { + std::string blockPath; + m_interpreter->getBlockPath(state, blockPath); + auto f = openTestFile("kpath", id); + if (f) + *f << blockPath; + } + + if (WriteCov) { + std::map> cov; + m_interpreter->getCoveredLines(state, cov); + auto f = openTestFile("cov", id); + if (f) { + for (const auto &entry : cov) { + for (const auto &line : entry.second) { + *f << entry.first << ':' << line << '\n'; + } + } + } + } + if (isError && OptExitOnError) { m_interpreter->prepareForEarlyExit(); klee_error("EXITING ON ERROR:\n%s\n", message); @@ -719,11 +776,11 @@ void KleeHandler::processTestCase(const ExecutionState &state, } void KleeHandler::writeTestCaseXML(bool isError, const KTest &assignments, - unsigned id) { + unsigned id, unsigned version) { // TODO: This is super specific to test-comp and assumes that the name is the // type information - auto file = openTestFile("xml", id); + auto file = openTestFile("xml", id, version); if (!file) return; @@ -852,7 +909,7 @@ std::string KleeHandler::getRunTimeLibraryPath(const char *argv0) { void KleeHandler::setOutputDirectory(const std::string &directoryName) { // create output directory - if (directoryName == "") { + if (directoryName.empty()) { klee_error("Empty name of new directory"); } SmallString<128> directory(directoryName); @@ -957,7 +1014,8 @@ static const char *modelledExternals[] = { "klee_check_memory_access", "klee_define_fixed_object", "klee_get_errno", "klee_get_valuef", "klee_get_valued", "klee_get_valuel", "klee_get_valuell", "klee_get_value_i32", "klee_get_value_i64", "klee_get_obj_size", - "klee_is_symbolic", "klee_make_symbolic", "klee_mark_global", + "klee_is_symbolic", "klee_make_symbolic", "klee_make_mock", + "klee_mark_global", "klee_open_merge", "klee_close_merge", "klee_prefer_cex", "klee_posix_prefer_cex", "klee_print_expr", "klee_print_range", "klee_report_error", "klee_set_forking", "klee_silent_exit", "klee_warning", "klee_warning_once", "klee_stack_trace", @@ -1051,12 +1109,14 @@ static const char *dontCareExternals[] = { "getwd", "gettimeofday", "uname", + "ioctl", // fp stuff we just don't worry about yet "frexp", "ldexp", "__isnan", "__signbit", + "llvm.dbg.label", }; // Extra symbols we aren't going to warn about with klee-libc @@ -1160,7 +1220,7 @@ void externalsAndGlobalsCheck(const llvm::Module *m) { } static Interpreter *theInterpreter = 0; -static nonstd::optional paths = nonstd::nullopt; +static std::optional paths = std::nullopt; static std::atomic_bool interrupted{false}; @@ -1209,22 +1269,6 @@ static void halt_via_gdb(int pid) { perror("system"); } -static void replaceOrRenameFunction(llvm::Module *module, const char *old_name, - const char *new_name) { - Function *new_function, *old_function; - new_function = module->getFunction(new_name); - old_function = module->getFunction(old_name); - if (old_function) { - if (new_function) { - old_function->replaceAllUsesWith(new_function); - old_function->eraseFromParent(); - } else { - old_function->setName(new_name); - assert(old_function->getName() == new_name); - } - } -} - static void createLibCWrapper(std::vector> &userModules, std::vector> &libsModules, @@ -1351,10 +1395,10 @@ static SarifReport parseInputPathTree(const std::string &inputPathTreePath) { return klee::convertAndFilterSarifJson(sarifJson); } -static nonstd::optional parseStaticAnalysisInput() { +static std::optional parseStaticAnalysisInput() { if (AnalysisReproduce != "") return parseInputPathTree(AnalysisReproduce); - return nonstd::nullopt; + return std::nullopt; } static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, @@ -1362,13 +1406,8 @@ static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, std::unique_ptr &interpreter, llvm::Module *finalModule, std::vector &replayPath) { - Function *mainFn = finalModule->getFunction(EntryPoint); - if ((UseGuidedSearch != Interpreter::GuidanceKind::ErrorGuidance) && - !mainFn) { // in error guided mode we do not need main function - klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); - } - externalsAndGlobalsCheck(finalModule); + Function *mainFn = finalModule->getFunction(EntryPoint); if (ReplayPathFile != "") { interpreter->setReplayPath(&replayPath); @@ -1580,6 +1619,232 @@ void wait_until_any_child_dies( } } +void mockModeledFunction( + const Interpreter::ModuleOptions &Opts, llvm::LLVMContext &ctx, + llvm::Module *mainModule, + std::vector> &loadedLibsModules, + std::vector> &redefinitions) { + std::string errorMsg; + std::vector> mockModules; + SmallString<128> Path(Opts.LibraryDir); + llvm::sys::path::append(Path, + "libkleeRuntimeMocks" + Opts.OptSuffix + ".bca"); + klee_message("NOTE: Using mocks model %s for linked externals", Path.c_str()); + if (!klee::loadFileAsOneModule(Path.c_str(), ctx, loadedLibsModules, + errorMsg)) { + klee_error("error loading mocks model '%s': %s", Path.c_str(), + errorMsg.c_str()); + } + + for (const auto &fmodel : loadedLibsModules.back()->functions()) { + if (fmodel.getName().str().substr(0, 15) != "__klee_wrapped_") { + continue; + } + if (llvm::Function *f = + mainModule->getFunction(fmodel.getName().str().substr(15))) { + klee_message("Renamed symbol %s to %s", f->getName().str().c_str(), + fmodel.getName().str().c_str()); + redefinitions.emplace_back(f->getName(), fmodel.getName()); + f->setName(fmodel.getName()); + } + } +} + +llvm::Value *createStringArray(LLVMContext &ctx, const char *str) { + auto type = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx), strlen(str) + 1); + std::vector chars; + for (size_t i = 0; i < strlen(str) + 1; ++i) { + chars.push_back(llvm::ConstantInt::get(llvm::Type::getInt8Ty(ctx), str[i])); + } + return llvm::ConstantArray::get(type, chars); +} + +void multiplexEntryPoint(llvm::Module *m, LLVMContext &ctx, + std::vector entryFns) { + + klee_message("Multiplexing entry point for the following functions:"); + for (auto fn : entryFns) { + klee_message("%s", fn->getName().data()); + } + klee_message("entry-point parameter is ignored. " + "Initial source can't be used for test replay."); + + llvm::IRBuilder<> builder(ctx); + + // todo 32 and 64 bit + std::vector kleeMakeSymbolicArgsType = { + llvm::Type::getInt8PtrTy(ctx), llvm::Type::getInt64Ty(ctx), + llvm::Type::getInt8PtrTy(ctx)}; + auto kleeMakeSymbolicFnType = llvm::FunctionType::get( + llvm::Type::getVoidTy(ctx), kleeMakeSymbolicArgsType, false); + + auto kleeMakeSymbolicFn = + m->getOrInsertFunction("klee_make_symbolic", kleeMakeSymbolicFnType); + + std::string multiplexedEntryName = "__klee_multiplexed_entry"; + auto type = llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), {}, false); + auto multiplexedEntry = llvm::Function::Create( + type, GlobalVariable::ExternalLinkage, multiplexedEntryName, m); + + auto entryBB = llvm::BasicBlock::Create(ctx, "entry", multiplexedEntry); + auto exitBB = llvm::BasicBlock::Create(ctx, "exit", multiplexedEntry); + + std::vector FnBlocks; + for (size_t i = 0; i < entryFns.size(); ++i) { + auto block = llvm::BasicBlock::Create(ctx, "func_" + llvm::utostr(i + 1), + multiplexedEntry); + FnBlocks.push_back(block); + } + + auto sizeType = llvm::Type::getInt64Ty(ctx); + size_t sizeByteWidth = 8; + + // populate entry + builder.SetInsertPoint(entryBB); + auto alloca = builder.CreateAlloca(sizeType); + auto bitcast = builder.CreateBitCast(alloca, llvm::Type::getInt8PtrTy(ctx)); + auto name = createStringArray(ctx, "__klee_multiplex_switch"); + auto nameAlloca = builder.CreateAlloca(name->getType()); + builder.CreateStore(name, nameAlloca); + auto nameBitcast = + builder.CreateBitCast(nameAlloca, llvm::Type::getInt8PtrTy(ctx)); + std::vector args; + args.push_back(bitcast); + args.push_back(llvm::ConstantInt::get(sizeType, sizeByteWidth)); + args.push_back(nameBitcast); + builder.CreateCall(kleeMakeSymbolicFn, args); + auto load = builder.CreateLoad(llvm::Type::getInt64Ty(ctx), alloca); + auto swtch = builder.CreateSwitch(load, exitBB, entryFns.size()); + + for (size_t i = 0; i < entryFns.size(); ++i) { + swtch->addCase(llvm::ConstantInt::get(sizeType, i + 1), FnBlocks[i]); + } + + // populate exit + builder.SetInsertPoint(exitBB); + builder.CreateRetVoid(); + + // populate funcs + for (size_t i = 0; i < entryFns.size(); ++i) { + builder.SetInsertPoint(FnBlocks[i]); + + // symbolize function arguments + std::vector args; + for (size_t arg_i = 0; arg_i < entryFns[i]->arg_size(); ++arg_i) { + std::string argName = "__klee_arg" + llvm::utostr(arg_i); + auto type = (entryFns[i]->arg_begin() + arg_i)->getType(); + auto byteWidth = + m->getDataLayout().getTypeSizeInBits(type) / 8; // check that + auto alloca = builder.CreateAlloca(type); + auto bitcast = + builder.CreateBitCast(alloca, llvm::Type::getInt8PtrTy(ctx)); + auto name = createStringArray(ctx, argName.c_str()); + auto nameAlloca = builder.CreateAlloca(name->getType()); + builder.CreateStore(name, nameAlloca); + auto nameBitcast = + builder.CreateBitCast(nameAlloca, llvm::Type::getInt8PtrTy(ctx)); + std::vector makeSymbolicArgs; + makeSymbolicArgs.push_back(bitcast); + makeSymbolicArgs.push_back(llvm::ConstantInt::get(sizeType, byteWidth)); + makeSymbolicArgs.push_back(nameBitcast); + builder.CreateCall(kleeMakeSymbolicFn, makeSymbolicArgs); + auto load = builder.CreateLoad(type, alloca); + args.push_back(load); + } + + builder.CreateCall(entryFns[i], args); + builder.CreateBr(exitBB); + } + + EntryPoint = multiplexedEntryName; + return; +} + +struct FunctionReachability { +public: + bool isReachableFrom(llvm::Module *m, llvm::Function *from, + llvm::Function *to) { + if (reachable.count(from) && reachable[from].count(to)) { + return true; + } + + std::unordered_set visited; + auto result = checkReachability(m, from, to, visited); + + for (auto f : visited) { + reachable[from].insert(f); + } + + return result; + } + +private: + bool checkReachability(llvm::Module *m, llvm::Function *from, + llvm::Function *to, + std::unordered_set &visited) { + if (from == to) { + visited.insert(from); + return true; + } + bool reachable = false; + llvm::CallGraph callGraph(*m); + auto node = callGraph[from]; + for (auto child : *node) { + auto f = child.second->getFunction(); + if (f && !visited.count(f)) { + visited.insert(f); + reachable = reachable || checkReachability(m, f, to, visited); + if (reachable) { + break; + } + } + } + return reachable; + } + + std::unordered_map> + reachable; +}; + +llvm::Function * +tryResolveEntryFunction(llvm::Module *mod, + std::vector> &trace) { + + llvm::Function *resKF = nullptr; + + FunctionReachability reachability; + + for (size_t i = 0; i < trace.size() && !resKF; ++i) { + for (size_t k = 0; k < trace[i].size(); ++k) { + resKF = trace[i][k]; + for (size_t j = i; j < trace.size(); ++j) { + if (i == j) { + continue; + } + + llvm::Function *curKf = nullptr; + for (size_t m = 0; m < trace[j].size() && !curKf; ++m) { + curKf = trace[j][m]; + if (!reachability.isReachableFrom(mod, resKF, curKf)) { + if (!reachability.isReachableFrom(mod, curKf, resKF)) { + curKf = nullptr; + } else { + i = j; + resKF = curKf; + } + } + } + if (!curKf) { + resKF = nullptr; + break; + } + } + } + } + + return resKF; +} + int main(int argc, char **argv, char **envp) { if (theInterpreter) { theInterpreter = nullptr; @@ -1672,9 +1937,10 @@ int main(int argc, char **argv, char **envp) { sys::SetInterruptFunction(interrupt_handle); - // Load the bytecode... std::string errorMsg; LLVMContext ctx; + + // Load the bytecode... std::vector> loadedUserModules; std::vector> loadedLibsModules; if (!klee::loadFileAsOneModule(InputFile, ctx, loadedUserModules, errorMsg)) { @@ -1691,40 +1957,69 @@ int main(int argc, char **argv, char **envp) { } llvm::Module *mainModule = loadedUserModules.front().get(); - std::unique_ptr origInfos; - std::unique_ptr assemblyFS; + FLCtoOpcode origInstructions; if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { - std::vector args; - origInfos = std::make_unique( - *mainModule, std::move(assemblyFS), true); - args.push_back(llvm::Type::getInt32Ty(ctx)); // argc - args.push_back(llvm::PointerType::get( - Type::getInt8PtrTy(ctx), - mainModule->getDataLayout().getAllocaAddrSpace())); // argv - args.push_back(llvm::PointerType::get( - Type::getInt8PtrTy(ctx), - mainModule->getDataLayout().getAllocaAddrSpace())); // envp - std::string stubEntryPoint = "__klee_entry_point_main"; - Function *stub = Function::Create( - llvm::FunctionType::get(llvm::Type::getInt32Ty(ctx), args, false), - GlobalVariable::ExternalLinkage, stubEntryPoint, mainModule); - BasicBlock *bb = BasicBlock::Create(ctx, "entry", stub); - - llvm::IRBuilder<> Builder(bb); - Builder.CreateRet(ConstantInt::get(Type::getInt32Ty(ctx), 0)); - EntryPoint = stubEntryPoint; - } - - std::unordered_set mainModuleFunctions; + for (const auto &Func : *mainModule) { + for (const auto &instr : llvm::instructions(Func)) { + auto locationInfo = getLocationInfo(&instr); + origInstructions[locationInfo.file][locationInfo.line] + [locationInfo.column] + .insert(instr.getOpcode()); + } + } + + std::vector entryFns; + + auto paths = parseStaticAnalysisInput(); + + if (paths->empty()) { + klee_warning("No paths were given to trace verify"); + return 0; + } + + for (const auto &path : paths->results) { + std::vector> trace; + for (const auto &loc : path.locations) { + std::vector funcs; + for (auto &f : *mainModule) { + if (loc->isInside(&f, origInstructions[getLocationInfo(&f).file])) { + funcs.push_back(&f); + } + } + if (!funcs.empty()) { + trace.push_back(funcs); + } else { + klee_warning("weird trace"); + } + } + auto entryFn = tryResolveEntryFunction(mainModule, trace); + if (entryFn) { + if (std::find(entryFns.begin(), entryFns.end(), entryFn) == + entryFns.end()) { + entryFns.push_back(entryFn); + } + } else { + klee_warning("Broken trace (entry fn not resolved)."); + } + } + + if (entryFns.empty()) { + klee_error("Entry function resolved for no trace"); + } + multiplexEntryPoint(mainModule, ctx, entryFns); + } + + std::set mainModuleFunctions; for (auto &Function : *mainModule) { if (!Function.isDeclaration()) { mainModuleFunctions.insert(Function.getName().str()); } } - std::unordered_set mainModuleGlobals; - for (const auto &gv : mainModule->globals()) + std::set mainModuleGlobals; + for (const auto &gv : mainModule->globals()) { mainModuleGlobals.insert(gv.getName().str()); + } const std::string &module_triple = mainModule->getTargetTriple(); std::string host_triple = llvm::sys::getDefaultTargetTriple(); @@ -1733,7 +2028,6 @@ int main(int argc, char **argv, char **envp) { klee_warning("Module and host target triples do not match: '%s' != '%s'\n" "This may cause unexpected crashes or assertion violations.", module_triple.c_str(), host_triple.c_str()); - // Detect architecture std::string bit_suffix = "64"; // Fall back to 64bit if (module_triple.find("i686") != std::string::npos || @@ -1751,13 +2045,18 @@ int main(int argc, char **argv, char **envp) { } std::string LibraryDir = KleeHandler::getRunTimeLibraryPath(argv[0]); - Interpreter::ModuleOptions Opts(LibraryDir.c_str(), EntryPoint, opt_suffix, - /*Optimize=*/OptimizeModule, - /*Simplify*/ SimplifyModule, - /*CheckDivZero=*/CheckDivZero, - /*CheckOvershift=*/CheckOvershift, - /*WithFPRuntime=*/WithFPRuntime, - /*WithPOSIXRuntime=*/WithPOSIXRuntime); + Interpreter::ModuleOptions Opts( + LibraryDir, EntryPoint, opt_suffix, + /*MainCurrentName=*/EntryPoint, + /*MainNameAfterMock=*/"__klee_mock_wrapped_main", + /*AnnotationsFile=*/AnnotationsFile, + /*Optimize=*/OptimizeModule, + /*Simplify*/ SimplifyModule, + /*CheckDivZero=*/CheckDivZero, + /*CheckOvershift=*/CheckOvershift, + /*AnnotateOnlyExternal=*/AnnotateOnlyExternal, + /*WithFPRuntime=*/WithFPRuntime, + /*WithPOSIXRuntime=*/WithPOSIXRuntime); // Get the main function for (auto &module : loadedUserModules) { @@ -1779,6 +2078,17 @@ int main(int argc, char **argv, char **envp) { if (!entryFn) klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); + std::vector> redefinitions; + if (Mock == MockPolicy::All || + MockMutableGlobals == MockMutableGlobalsPolicy::All || + AnnotationsFile.empty()) { + redefinitions.emplace_back(EntryPoint, Opts.MainNameAfterMock); + } + if (MockModeledFunction) { + mockModeledFunction(Opts, ctx, mainModule, loadedLibsModules, + redefinitions); + } + if (WithPOSIXRuntime) { SmallString<128> Path(Opts.LibraryDir); llvm::sys::path::append(Path, "libkleeRuntimePOSIX" + opt_suffix + ".bca"); @@ -1800,9 +2110,7 @@ int main(int argc, char **argv, char **envp) { errorMsg.c_str()); } - if (!UTBotMode) { - preparePOSIX(loadedUserModules); - } + preparePOSIX(loadedUserModules); } if (WithFPRuntime) { @@ -1947,6 +2255,10 @@ int main(int argc, char **argv, char **envp) { Interpreter::InterpreterOptions IOpts(paths); IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic; IOpts.Guidance = UseGuidedSearch; + IOpts.Mock = Mock; + IOpts.MockStrategy = MockStrategy; + IOpts.MockMutableGlobals = MockMutableGlobals; + std::unique_ptr interpreter( Interpreter::create(ctx, IOpts, handler.get())); theInterpreter = interpreter.get(); @@ -1958,90 +2270,48 @@ int main(int argc, char **argv, char **envp) { } handler->getInfoStream() << "PID: " << getpid() << "\n"; + std::set ignoredExternals; + ignoredExternals.insert(modelledExternals, + modelledExternals + NELEMS(modelledExternals)); + ignoredExternals.insert(dontCareExternals, + dontCareExternals + NELEMS(dontCareExternals)); + ignoredExternals.insert(unsafeExternals, + unsafeExternals + NELEMS(unsafeExternals)); + + switch (Libc) { + case LibcType::KleeLibc: + ignoredExternals.insert(dontCareKlee, dontCareKlee + NELEMS(dontCareKlee)); + break; + case LibcType::UcLibc: + ignoredExternals.insert(dontCareUclibc, + dontCareUclibc + NELEMS(dontCareUclibc)); + break; + case LibcType::FreestandingLibc: /* silence compiler warning */ + break; + } + + if (WithPOSIXRuntime) { + ignoredExternals.insert("syscall"); + } + + Opts.MainCurrentName = entryFn->getName().str(); + // Get the desired main function. klee_main initializes uClibc // locale and other data and then calls main. auto finalModule = interpreter->setModule( - loadedUserModules, loadedLibsModules, Opts, mainModuleFunctions, - mainModuleGlobals, std::move(origInfos)); + loadedUserModules, loadedLibsModules, Opts, + std::move(mainModuleFunctions), std::move(mainModuleGlobals), + std::move(origInstructions), ignoredExternals, redefinitions); + Function *mainFn = finalModule->getFunction(EntryPoint); + if (!mainFn) { + klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); + } externalsAndGlobalsCheck(finalModule); - if (InteractiveMode) { - klee_message("KLEE finish preprocessing."); - std::ifstream entrypoints(EntryPointsFile); - if (!entrypoints.good()) { - klee_error("Opening %s failed.", EntryPointsFile.c_str()); - } - - if (ProcessNumber < 1 || ProcessNumber > MAX_PROCESS_NUMBER) { - klee_error("Incorrect number of process, your value is %d, but it must " - "lie in [1, %d].", - ProcessNumber.getValue(), MAX_PROCESS_NUMBER); - } - klee_message("Start %d processes.", ProcessNumber.getValue()); - - SmallString<128> outputDirectory = handler->getOutputDirectory(); - const size_t PROCESS = ProcessNumber; - using time_point = std::chrono::time_point; - std::vector> child_processes; - signal(SIGCHLD, SIG_IGN); - while (true) { - std::string entrypoint; - if (!(entrypoints >> entrypoint)) { - break; - } - - if (child_processes.size() == PROCESS) { - if (TimeoutPerFunction != 0) { - wait_until_any_child_dies(child_processes); - } else { - wait(NULL); - } - } - std::vector> alive_child; - for (const auto &child_process : child_processes) { - if (kill(child_process.first, 0) == 0) { - alive_child.push_back(child_process); - } - } - child_processes = alive_child; - - pid_t pid = fork(); - if (pid < 0) { - klee_error("%s", "Cannot create child process."); - } else if (pid == 0) { - signal(SIGCHLD, SIG_DFL); - EntryPoint = entrypoint; - SmallString<128> newOutputDirectory = outputDirectory; - sys::path::append(newOutputDirectory, entrypoint); - handler->setOutputDirectory(newOutputDirectory.c_str()); - run_klee_on_function(pArgc, pArgv, pEnvp, handler, interpreter, - finalModule, replayPath); - exit(0); - } else { - child_processes.emplace_back(pid, std::chrono::steady_clock::now()); - } - } - if (TimeoutPerFunction != 0) { - while (!child_processes.empty()) { - wait_until_any_child_dies(child_processes); - std::vector> alive_child; - for (const auto &child_process : child_processes) { - if (kill(child_process.first, 0) == 0) { - alive_child.push_back(child_process); - } - } - child_processes = alive_child; - } - } else { - while (wait(NULL) > 0) - ; - } - } else { - run_klee_on_function(pArgc, pArgv, pEnvp, handler, interpreter, finalModule, - replayPath); - } + run_klee_on_function(pArgc, pArgv, pEnvp, handler, interpreter, finalModule, + replayPath); paths.reset(); diff --git a/unittests/Annotations/AnnotationsTest.cpp b/unittests/Annotations/AnnotationsTest.cpp new file mode 100644 index 0000000000..7c3b90de3f --- /dev/null +++ b/unittests/Annotations/AnnotationsTest.cpp @@ -0,0 +1,126 @@ +//===-- AnnotationTest.cpp ------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "klee/Module/Annotation.h" + +#include + +using namespace klee; + +TEST(AnnotationsTest, Empty) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [[]], + "properties" : [] + } +} +)"); + const AnnotationsMap expected = { + {"foo", + {/*functionName*/ "foo", + /*returnStatements*/ std::vector(), + /*argsStatements*/ std::vector>(), + /*properties*/ std::set()}}}; + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(expected, actual); +} + +TEST(AnnotationsTest, KnownProperties) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [[]], + "properties" : ["deterministic", "noreturn", "deterministic"] + } +} +)"); + const std::set properties{ + Statement::Property::Deterministic, Statement::Property::Noreturn}; + const AnnotationsMap expected = { + {"foo", + {/*functionName*/ "foo", + /*returnStatements*/ std::vector(), + /*argsStatements*/ std::vector>(), + /*properties*/ properties}}}; + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(expected, actual); +} + +TEST(AnnotationsTest, UnknownProperties) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [[]], + "properties" : ["noname", "noreturn", "deterministic"] + } +} +)"); + const std::set properties{ + Statement::Property::Deterministic, Statement::Property::Noreturn, + Statement::Property::Unknown}; + const AnnotationsMap expected = { + {"foo", + {/*functionName*/ "foo", + /*returnStatements*/ std::vector(), + /*argsStatements*/ std::vector>(), + /*properties*/ properties}}}; + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(expected, actual); +} + +TEST(AnnotationsTest, UnknownAnnotations) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [[], ["Ooo"]], + "properties" : [] + } +} +)"); + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(actual.at("foo").argsStatements[0][0]->getKind(), + Statement::Kind::Unknown); +} + +TEST(AnnotationsTest, KnownAnnotations) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [["MaybeInitNull"], ["Deref", "InitNull"]], + "properties" : [] + } +} +)"); + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(actual.at("foo").returnStatements[0]->getKind(), + Statement::Kind::MaybeInitNull); + ASSERT_EQ(actual.at("foo").argsStatements[0][0]->getKind(), + Statement::Kind::Deref); + ASSERT_EQ(actual.at("foo").argsStatements[0][1]->getKind(), + Statement::Kind::InitNull); +} + +TEST(AnnotationsTest, WithOffsets) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [["InitNull:*[10]*&"]], + "properties" : [] + } +} +)"); + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(actual.at("foo").returnStatements[0]->getKind(), + Statement::Kind::InitNull); + const std::vector expectedOffset{"*", "10", "*", "&"}; + ASSERT_EQ(actual.at("foo").returnStatements[0]->offset, expectedOffset); +} diff --git a/unittests/Annotations/CMakeLists.txt b/unittests/Annotations/CMakeLists.txt new file mode 100644 index 0000000000..cb9a7b1df1 --- /dev/null +++ b/unittests/Annotations/CMakeLists.txt @@ -0,0 +1,3 @@ +add_klee_unit_test(AnnotationsTest + AnnotationsTest.cpp) +target_link_libraries(AnnotationsTest PRIVATE kleaverExpr kleaverSolver) diff --git a/unittests/Assignment/AssignmentTest.cpp b/unittests/Assignment/AssignmentTest.cpp index 410a4ce357..419a4d0956 100644 --- a/unittests/Assignment/AssignmentTest.cpp +++ b/unittests/Assignment/AssignmentTest.cpp @@ -19,7 +19,7 @@ TEST(AssignmentTest, FoldNotOptimized) { SourceBuilder::makeSymbolic("simple_array", 0)); // Create a simple assignment std::vector objects; - SparseStorage value(1); + SparseStorage value(0); std::vector> values; objects.push_back(array); diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index d4b4d1f9f7..edb1f46361 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -272,6 +272,7 @@ function(add_klee_unit_test target_name) endfunction() # Unit Tests +add_subdirectory(Annotations) add_subdirectory(Assignment) add_subdirectory(Expr) add_subdirectory(Ref) diff --git a/unittests/Expr/ArrayExprTest.cpp b/unittests/Expr/ArrayExprTest.cpp index 68b6948612..c2c522007d 100644 --- a/unittests/Expr/ArrayExprTest.cpp +++ b/unittests/Expr/ArrayExprTest.cpp @@ -41,8 +41,8 @@ static ArrayCache ac; TEST(ArrayExprTest, HashCollisions) { klee::OptimizeArray = ALL; - std::vector> constVals(256, - ConstantExpr::create(5, Expr::Int8)); + SparseStorage> constVals( + ConstantExpr::create(5, Expr::Int8)); const Array *array = ac.CreateArray( ConstantExpr::create(256, sizeof(uint64_t) * CHAR_BIT), SourceBuilder::constant(constVals), Expr::Int32, Expr::Int8); diff --git a/unittests/Expr/ExprTest.cpp b/unittests/Expr/ExprTest.cpp index 2a34463d9f..f6d79683e7 100644 --- a/unittests/Expr/ExprTest.cpp +++ b/unittests/Expr/ExprTest.cpp @@ -128,9 +128,10 @@ TEST(ExprTest, ReadExprFoldingBasic) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -148,7 +149,7 @@ TEST(ExprTest, ReadExprFoldingBasic) { // Read - should be constant folded to Contents[i] // Check that constant folding worked ConstantExpr *c = static_cast(read.get()); - EXPECT_EQ(Contents[i]->getZExtValue(), c->getZExtValue()); + EXPECT_EQ(Contents.load(i)->getZExtValue(), c->getZExtValue()); } } @@ -156,9 +157,10 @@ TEST(ExprTest, ReadExprFoldingIndexOutOfBound) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = ac.CreateArray(ConstantExpr::create(size, sizeof(uint64_t) * CHAR_BIT), @@ -178,9 +180,10 @@ TEST(ExprTest, ReadExprFoldingConstantUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -205,9 +208,10 @@ TEST(ExprTest, ReadExprFoldingConstantMultipleUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -234,9 +238,10 @@ TEST(ExprTest, ReadExprFoldingSymbolicValueUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -263,9 +268,10 @@ TEST(ExprTest, ReadExprFoldingSymbolicIndexUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = diff --git a/unittests/Solver/Z3SolverTest.cpp b/unittests/Solver/Z3SolverTest.cpp index d10a7b853c..a9a2581d89 100644 --- a/unittests/Solver/Z3SolverTest.cpp +++ b/unittests/Solver/Z3SolverTest.cpp @@ -14,6 +14,7 @@ #include "gtest/gtest.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/ArrayCache.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" @@ -40,14 +41,13 @@ TEST_F(Z3SolverTest, GetConstraintLog) { constraints_ty Constraints; const std::vector ConstantValues{1, 2, 3, 4}; - std::vector> ConstantExpressions; + SparseStorage> ConstantExpressions( + ConstantExpr::create(0, Expr::Int8)); - std::transform( - ConstantValues.begin(), ConstantValues.end(), - std::back_inserter(ConstantExpressions), [](const uint64_t Value) { - ref ConstantExpr(ConstantExpr::alloc(Value, Expr::Int8)); - return ConstantExpr; - }); + for (unsigned i = 0; i < ConstantValues.size(); ++i) { + ConstantExpressions.store( + i, ConstantExpr::alloc(ConstantValues[i], Expr::Int8)); + } const Array *ConstantArray = AC.CreateArray(ConstantExpr::create(4, sizeof(uint64_t) * CHAR_BIT),