GithubHelp home page GithubHelp logo

seahorn / seahorn Goto Github PK

View Code? Open in Web Editor NEW
429.0 20.0 132.0 7.7 MB

SeaHorn Verification Framework

Home Page: http://seahorn.github.io/

License: Other

CMake 0.61% C++ 29.61% C 44.02% LLVM 23.69% Python 1.93% SMT 0.03% Makefile 0.01% Dockerfile 0.04% Emacs Lisp 0.01% CLIPS 0.01% Shell 0.01% SourcePawn 0.03%
verification llvm model-checking abstract-interpretation horn-clauses program-analysis static-analysis

seahorn's Introduction

seahorn

os os Nighly Build codecov gitter

About

SeaHorn is an automated analysis framework for LLVM-based languages. This version compiles against LLVM 14.

Some of the supported features are

  • Abstract Interpretation-based static analysis
  • Unification-based Context-Sensitive pointer analysis
  • SMT-based Bounded Model Checking (i.e., symbolic execution)
  • CHC-based Software Model Checking (i.e., invariant inference)
  • Executable counterexamples (i.e., no reports, just bugs!)

SeaHorn is developed primarily as a framework for conducting research in automated verification. The frameworks provides many components that can be put together in a variety of ways. However, it is not an "out-of-the-box" static analysis tool.

Many analysis tools and examples are provided with the framework. We are constantly looking for new applications and provide support to new users. For more information on what is happening, check our (infrequently updated) blog.

License

SeaHorn is distributed under a modified BSD license. See license.txt for details.

Introduction

Demo

SeaHorn provides a python script called sea to interact with users. Given a C program annotated with assertions, users just need to type: sea pf file.c

The result of sea-pf is unsat if all assertions hold, an sat if any of the assertions are violated.

The option pf tells SeaHorn to translate file.c into LLVM bitcode, generate a set of verification conditions (VCs), and finally, solve them. The main back-end solver is spacer.

The command pf provides, among others, the following options:

  • --show-invars: display computed invariants if answer was unsat.

  • --cex=FILE : stores a counter-example in FILE if answer was sat.

  • -g : compiles with debug information for more trackable counterexamples.

  • --step=large: large-step encoding. Each transition relation corresponds to a loop-free fragments.

  • --step=small: small-step encoding. Each transition relation corresponds to a basic block.

  • --track=reg : model (integer) registers only.

  • --track=ptr : model registers and pointers (but not memory content)

  • --track=mem: model both scalars, pointers, and memory contents

  • --inline : inlines the program before verification

  • --crab : inject invariants in spacer generated by the Crab abstract-interpretation-based tool. Read here for details about all Crab options (prefix --crab). You can see which invariants are inferred by Crab by typing option --log=crab.

  • --bmc: use BMC engine.

sea pf is a pipeline that runs multiple commands. Individual parts of the pipeline can be run separately as well:

  1. sea fe file.c -o file.bc: SeaHorn frontend translates a C program into optimized LLVM bitcode including mixed-semantics transformation.

  2. sea horn file.bc -o file.smt2: SeaHorn generates the verification conditions from file.bc and outputs them into SMT-LIB v2 format. Users can choose between different encoding styles with several levels of precision by adding:

    • --step={small,large,fsmall,flarge} where small is small step encoding, large is block-large encoding, fsmall is small step encoding producing flat Horn clauses (i.e., it generates a transition system with only one predicate), and flarge: block-large encoding producing flat Horn clauses.

    • --track={reg,ptr,mem} where reg only models integer scalars, ptr models reg and pointer addresses, and mem models ptr and memory contents.

  3. sea smt file.c -o file.smt2: Generates CHC in SMT-LIB2 format. Is an alias for sea fe followed by sea horn. The command sea pf is an alias for sea smt --prove.

  4. sea clp file.c -o file.clp: Generates CHC in CLP format.

  5. sea lfe file.c -o file.ll : runs the legacy front-end

To see all the commands, type sea --help. To see options for each individual command CMD (e.g, horn), type sea CMD --help (e.g., sea horn --help).

Static Analysis with Abstract Interpretation

Inference of Inductive Invariants using Crab

SeaHorn does not use Crab by default. To enable Crab, add the option --crab to the sea command.

The abstract interpreter is by default intra-procedural and it uses the Zones domain as the numerical abstract domain. These default options should be enough for normal users. For developers, if you want to use other abstract domains you need to:

  1. Compile with cmake options -DCRAB_USE_LDD=ON -DCRAB_USE_ELINA=ON
  2. Run sea with option --crab-dom=DOM where DOM can be:
    • int for intervals
    • term-int for intervals with uninterpreted functions
    • boxes: for disjunctive intervals
    • oct for octagons
    • pk for polyhedra

To use the crab inter-procedural analysis you need to run sea with option --crab-inter

By default, the abstract interpreter only reasons about scalar variables (i.e., LLVM registers). Run sea with the options --crab-track=mem --crab-singleton-aliases=true to reason about memory contents.

How to use Invariants generated by Crab in Spacer

Crab is mostly path-insensitive while Spacer, our Horn clause solver, is path-sensitive. Although path-insensitive analyses are more efficient, path-sensitivity is typically required to prove the property of interest. This motivates our decision of running first Crab (if option --crab) and then pass the generated invariants to Spacer. There are currently two ways for Spacer to use the invariants generated by Crab. The sea option --horn-use-invs=VAL tells spacer how to use those invariants:

  • If VAL is equal to bg then invariants are only used to help spacer in proving a lemma is inductive.
  • If VAL is equal to always then the behavior is similar to bg but in addition invariants are also used to help spacer to block a counterexample.

The default value is bg. Of course, if Crab can prove the program is safe then Spacer does not incur in any extra cost.

Property Specification

Properties are assumed to be assertions. SeaHorn provides a static assertion command sassert, as illustrated in the following example

/* verification command: sea pf --horn-stats test.c */
#include "seahorn/seahorn.h"
extern int nd();

int main(void) {
    int k = 1;
    int i = 1;
    int j = 0;
    int n = nd();
    while (i < n) {
        j = 0;
        while (j < i) {
            k += (i - j);
            j++;
        }
        i++;
    }
    sassert(k >= n);
}

Internally, SeaHorn follows SV-COMP convention of encoding error locations by a call to the designated error function __VERIFIER_error(). SeaHorn returns unsat when __VERIFIER_error() is unreachable, and the program is considered safe. SeaHorn returns sat when __VERIFIER_error() is reachable and the program is unsafe. sassert() method is defined in seahorn/seahorn.h.

Inspect Code

Apart from proving properties or producing counterexamples, it is sometimes useful to inspect the code under analysis to get an idea of its complexity. For this, SeaHorn provides a command sea inspect. For instance, given a C program ex.c type:

sea inspect ex.c --sea-dsa=cs+t --mem-dot 

The option --sea-dsa=cs+t enables the new context-, type-sensitive sea-dsa analysis described in FMCAD19. This command generates a FUN.mem.dot file for each function FUN in the input program. To visualize the graph of the main function, use web graphivz interface, or the following commands:

$ dot -Tpdf main.mem.dot -o main.mem.pdf

More details on the memory graphs is in the SeaDsa repository: here.

Use sea inspect --help to see all options. Currently, the available options are:

  • sea inspect --profiler prints the number of functions, basic blocks, loops, etc.
  • sea inspect --mem-callgraph-dot prints to dot format the call graph constructed by SeaDsa.
  • sea inspect --mem-callgraph-stats prints to standard output some statstics about the call graph construction done by SeaDsa.
  • sea inspect --mem-smc-stats prints the number of memory accesses that can be proven safe by SeaDsa.

Installation

The easiest way to get started with SeaHorn is via a docker distribution.

$ docker pull seahorn/seahorn-llvm10:nightly
$ docker run --rm -it seahorn/seahorn-llvm10:nightly

Start with exploring what the sea command can do:

$ sea --help
$ sea pf --help

The nightly tag is automatically refreshed daily and contains the latest development version. We maintain all other tags (that require manual update) infrequently. Check the dates on DockerHub and log an issue on GitHub if they are too stale.

Additional examples and configuration options are on the blog. The blog is updated infrequently. In particular, options change, features are phased out, new things are added. If you find problems in the blog, let us know. We at least will update the blog post to indicate that it is not expected to work with the latest version of the code.

You can also manually install by:

Following the instructions in the Docker file Dockerfile: docker/seahorn-builder.Dockerfile.

If this does not work, run:

$ wget https://apt.llvm.org/llvm.sh
$ chmod +x llvm.sh
$ sudo ./llvm.sh 14
$ apt download libpolly-14-dev && sudo dpkg --force-all -i libpolly-14-dev*

The first 3 commands will install LLVM 14, the 4th will install libpolly which is wrongly omitted from LLVM 14 (but included in subsequent versions)

Next, follow the instruction in the Docker file above

Developer's Zone

The information from this point on is for developers only. If you would like to contribute to SeaHorn, build your own tools based on it, or just interested in how it works inside, keep reading.

Compilation Instructions

SeaHorn requires LLVM, Z3, and boost. The exact versions of the libraries keep changing, but cmake craft is used to check that right version is available.

To specify a specific version of any of the dependencies, use the usual <PackageName>_ROOT and/or <PackageName>_DIR (see find_package() for details) cmake variables.

SeaHorn is broken into multiple components that live in different repositories (under SeaHorn organization). The build process automatically checks out everything as necessary. For current build instructions, check the CI scripts.

These are the generic steps. Do NOT use them. Read on for a better way:

  1. cd seahorn ; mkdir build ; cd build (The build directory can also be outside the source directory.)
  2. cmake -DCMAKE_INSTALL_PREFIX=run ../ (Install is required!)
  3. cmake --build . --target extra && cmake .. (clones components that live elsewhere)
  4. cmake --build . --target crab && cmake .. (clones crab library)
  5. cmake --build . --target install (build and install everything under run)
  6. cmake --build . --target test-all (run tests)

Note: install target is required for tests to work!

Better Compilation Instructions

For an enhanced development experience:

  1. Use clang
  2. On Linux, use lld linker
  3. Include debug symbols in Release builds
  4. Use Ninja
  5. Export compile_commands.json

On Linux, we suggest the following cmake configuration:

$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=run \
      -DCMAKE_BUILD_TYPE=RelWithDebInfo \
      -DCMAKE_CXX_COMPILER="clang++-14" \
      -DCMAKE_C_COMPILER="clang-14" \
      -DSEA_ENABLE_LLD=ON  \
      -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \
      ../ \
      -DZ3_ROOT=<Z3_ROOT> \
      -DLLVM_DIR=<LLMV_CMAKE_DIR> \
      -GNinja
$ (cd .. && ln -sf build/compile_commands.json .)

where <Z3_ROOT is a directory containing Z3 binary distribution, and LLMV_CMAKE_DIR is directory containing LLVMConfig.cmake.

Other legal options for CMAKE_BUILD_TYPE are Debug and Coverage. Note that the CMAKE_BUILD_TYPE must be compatible with the one used to compile LLVM. In particular, you will need a Debug build of LLVM to compile SeaHorn in `Debug** mode. Make sure you have plenty of patience, disk space, and time if you decide to go this route.

Alternatively, the project can be configured using cmake presets. To do this, simply run the following command:

$ cmake --preset <BUILD_TYPE>-<PRESET_NAME>

to configure cmake, where <BUILD_TYPE> is one of: Debug, RelWithDebInfo or Coverage and <PRESET_NAME> is the preset you would like to use. The presets that are currently available are: jammy. These presets assume that you have Z3 installed in /opt/z3-4.8.9 and Yices installed in /opt/yices-2.6.1.

This will also allow the project to be configured and compiled within VS Code using the CMake Tools extension.

If you would like to use different compilation settings or if you have Z3 or Yices installed in any other directory, you will need to make your own CMakeUserPresets.json file with your own presets.

Compiling on a Mac

Do not include -DSEA_ENABLE_LLD=ON. The default compiler is clang, so you might not need to set it explicitly.

The EXTRA Target

SeaHorn provides several components that are automatically cloned and installed via the extra target. These components can be used by other projects outside of SeaHorn.

  • sea-dsa: git clone https://github.com/seahorn/sea-dsa.git

    sea-dsa is a new DSA-based heap analysis. Unlike llvm-dsa, sea-dsa is context-sensitive and therefore, a finer-grained partition of the heap can be generated in presence of function calls.

  • clam: git clone https://github.com/seahorn/crab-llvm.git

    clam provides inductive invariants using abstract interpretation techniques to the rest of SeaHorn's backends.

  • llvm-seahorn: git clone https://github.com/seahorn/llvm-seahorn.git

    llvm-seahorn provides tailored-to-verification versions of InstCombine and IndVarSimplify LLVM passes as well as a LLVM pass to convert undefined values into nondeterministic calls, among other things.

SeaHorn doesn't come with its own version of Clang and expects to find it either in the build directory (run/bin) or in PATH. Make sure that the version of Clang matches the version of LLVM that was used to compile SeaHorn (currently LLVM14). The easiest way to provide the right version of Clang is to download it from llvm.org, unpact it somewhere and create a symbolic link to clang and clang++ in run/bin.

$ cd seahorn/build/run/bin
$ ln -s <CLANG_ROOT>/bin/clang clang
$ ln -s <CLANG_ROOT>/bin/clang++ clang++

where <CLANG_ROOT> is the location at which Clang was unpacked.

Tests

Testing infrastructure depends on several Python packages. These have their own dependencies. If you cannot figure them out, use docker instead.

$ pip install lit OutputCheck networkx pygraphviz

Coverage

We can use gcov and lcov to generate test coverage information for SeaHorn. To build with coverage enabled, we need to run build under a different directory and set CMAKE_BUILD_TYPE to Coverage during cmake configuration.

Example steps for generating coverage report for the test-opsem target:

  1. mkdir coverage; cd coverage create and enter coverage build directory
  2. cmake -DCMAKE_BUILD_TYPE=Coverage <other flags as you wish> ../
  3. Complete the build as usual
  4. cmake --build . --target test-opsem Run OpSem tests, now .gcda and .gcno files should be created in the corresponding CMakeFiles directories
  5. lcov -c --directory lib/seahorn/CMakeFiles/seahorn.LIB.dir/ -o coverage.info collect coverage data from desired module, if clang is used as the compiler instead of gcc, create a bash script llvm-gcov.sh:
#!/bin/bash
exec llvm-cov gcov "$@"
$ chmod +x llvm-gcov.sh

then append --gcov-tool <path_to_wrapper_script>/llvm-gcov.sh to the lcov -c ... command. 6. extract data from desired directories and generate html report:

lcov --extract coverage.info "*/lib/seahorn/*" -o lib.info
lcov --extract coverage.info "*/include/seahorn/*" -o header.info
cat header.info lib.info > all.info
genhtml all.info --output-directory coverage_report

then open coverage_report/index.html in browser to view the coverage report

Also see scripts/coverage for scripts used by the CI. Coverage report for nightly builds is available at codecov

Code indexing

Compilation database for the seahorn project and all its sub-projects is generated using -DCMAKE_EXPORT_COMPILE_COMMANDS=ON option for cmake.

An easy way to get code indexing to work with with compilation database support is to link the compilation_database.json file into the main project directory and follow instructions specific to your editor.

Remote Configuration for CLion

For a detailed guide for a remote workflow with CLion check Clion-configuration.

Remote Configuration for Emacs (and other Editors)

Use our fork of mainframer. Don't miss the example configuration.

Contributors

seahorn's People

Contributors

agurfinkel avatar andrewreiter avatar borisjancicuwaterloo avatar caballa avatar chenguang-zhu avatar colinxm avatar danblitzhou avatar fshaked avatar igcontreras avatar jorgenavas avatar kuhar avatar lememta avatar linersu avatar mrthefakeperson avatar nhamlv-55 avatar parvmor avatar priyasiddharth avatar sankeerth26 avatar scottwe avatar sei-eschwartz avatar shaobo-he avatar shvamath avatar thomashart17 avatar waffle-iron avatar wuestholz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

seahorn's Issues

Possible non-determinism in spacer

This command

sea pf --cpu=250 --mem=4096 --step=large -g --horn-global-constraints=true --track=mem --horn-stats --enable-nondet-init --strip-extern --externalize-addr-taken-functions --horn-singleton-aliases=true --show-invars --horn-pdr-contexts=600 --devirt-functions --horn-ignore-calloc=false --enable-indvar --enable-loop-idiom sv-benchmarks/c/product-lines/email_spec4_product32_false-unreach-call.cil.c

shows a possible non-determistic behaviour in spacer. Running two consecutive executions of the above command has two very different outcomes:

  1. found a cex after some time around 80 seconds (attached file log.1.txt)
  2. unknown after timeout of 250 seconds. (attached file log.2.txt)

I observed similar problem for unsat instances and also when Crab invariants are injected.

I attach the logs with -v=1 of the consecutive executions.
log.1.txt
log.2.txt

Note that the above command does not inline. At least for this example if we inline the non-deterministic behaviour seems to be gone. Looking at the logs, It might be that when a cex from the queue is extended across functions spacer chooses non-deterministically.

Issue when installing seahorn

I am new to both Linux and Seahorn. My computer is running Ubuntu 14.04 LTS. I was following the steps in the installation. When I typed in "cmake -DCMAKE_INSTALL_PREFIX=run ../" in the terminal. It says "Could NOT find Git (Git_Executable)". Could anyone help me to solve this problem? Thanks!

test harness example within SeaHorn tutorial

Hi,

I am looking into the creation of the test harness file mentioned in the SeaHorn tutorial. The issue is that my witness file (test.ll) is empty beside the moduleId and datalayout.

I use the code which is used as example in the tutorial and the following cmd: ./sea pf test.c --m64 --cex=test2.ll (the tutorial mentions -m64 and -cex=.., but that is incorrect.)

root@osboxes:/home/osboxes/Downloads# /home/osboxes/Downloads/seahorn/build/run/bin/sea pf test2.c --m64 --cex=test3.ll --horn-stats
/usr/bin/clang-3.6 -c -emit-llvm -D__SEAHORN__ -fgnu89-inline -m32 -I/home/osboxes/Downloads/seahorn/build/run/include -o /tmp/sea-9dBKh3/test2.bc test2.c
/home/osboxes/Downloads/seahorn/build/run/bin/seapp -o /tmp/sea-9dBKh3/test2.pp.bc --strip-extern=false --kill-vaarg=true /tmp/sea-9dBKh3/test2.bc
/home/osboxes/Downloads/seahorn/build/run/bin/seapp -o /tmp/sea-9dBKh3/test2.pp.ms.bc --horn-mixed-sem --ms-reduce-main /tmp/sea-9dBKh3/test2.pp.bc
/home/osboxes/Downloads/seahorn/build/run/bin/seaopt -f -funit-at-a-time -o /tmp/sea-9dBKh3/test2.pp.ms.o.bc -O3 --enable-indvar=false --enable-loop-idiom=false --enable-nondet-init=false --unroll-threshold=150 --disable-loop-vectorization=true --disable-slp-vectorization=true --vectorize-slp-aggressive=false /tmp/sea-9dBKh3/test2.pp.ms.bc
/home/osboxes/Downloads/seahorn/build/run/bin/seahorn --keep-shadows=true --horn-solve -horn-cex-pass -horn-cex=test3.ll -horn-inter-proc -horn-sem-lvl=mem --horn-step=large /tmp/sea-9dBKh3/test2.pp.ms.o.bc --horn-stats
sat

************** BRUNCH STATS *****************
BRUNCH_STAT Result FALSE
BRUNCH_STAT Horn 0.00
BRUNCH_STAT HornClauseDB::loadZFixedPoint 0.00
BRUNCH_STAT HornifyModule 0.00
BRUNCH_STAT LargeHornifyFunction 0.00
BRUNCH_STAT seahorn_total 0.01
************** BRUNCH STATS END *****************

The assert is SAT, therefore there should be a valid witness, which is as expected. I can run the debugger and see that it fails. So the ./out is successfully created, but how can the witness be empty?

Thanks in advance,

Integrate sea-dsa (https://github.com/seahorn/sea-dsa)

This requires, among other things:

  • remove directories include/Analysis/DSA and lib/Analysis/DSA
  • modify CMakeLists.txt to download sea-dsa repository
  • add in the CMakeLists.txt the lines:
    • include_directories (sea_dsa/include)
    • add_subdirectory(sea_dsa)

Also, make sure that the sea-dsa options match with the ones expected in seahorn (some of them changed), and of course, that all the necessary sea-dsa passes are executed.

--entry generates empty bitcode file

Using version 0.1.0-RC2 linux x86_64 build.

I hope that I am using this properly, so I apologize if I am mistaken in my use. I am wanting to test individual functions and so I am attempting to use the --entry= option to 'sea fe'. I found --entry from looking at master and also from browsing a closed Issue. I am using the test code:

extern int nd();
extern void __VERIFIER_assume(int);
extern void __VERIFIER_error() __attribute__((noreturn));
void assert (int cond) { if (!cond) __VERIFIER_error (); }

int
dingus()
{
    int n,k,j;
    n = nd();
    __VERIFIER_assume(n > 0);
    k = nd();
    __VERIFIER_assume(k > n);
    j = 0;

    while (j < n) {
        j++;
        k--;
    }
    assert(k >= 0);
    return 0;
}

With dingus renamed to main, things work as expected. If I attempt to use the above, however, with --entry=dingus:

momo@momo-droiddev:~/SeaHorn-0.1.0-rc2-Linux-x86_64$ bin/sea fe --entry=dingus foo2.c -o foo2.bc
/usr/bin/clang-3.6 -c -emit-llvm -D__SEAHORN__ -m32 -o /tmp/sea-E9xw5j/foo2.bc foo2.c
/home/momo/SeaHorn-0.1.0-rc2-Linux-x86_64/bin/seapp -o /tmp/sea-E9xw5j/foo2.pp.bc /tmp/sea-E9xw5j/foo2.bc
/home/momo/SeaHorn-0.1.0-rc2-Linux-x86_64/bin/seapp -o /tmp/sea-E9xw5j/foo2.pp.ms.bc --horn-mixed-sem --ms-reduce-main /tmp/sea-E9xw5j/foo2.pp.bc
/home/momo/SeaHorn-0.1.0-rc2-Linux-x86_64/bin/seaopt -f -funit-at-a-time -o foo2.bc -O3 --enable-indvar=false --enable-loop-idiom=false /tmp/sea-E9xw5j/foo2.pp.ms.bc
momo@momo-droiddev:~/SeaHorn-0.1.0-rc2-Linux-x86_64$ /usr/lib/llvm-3.6/bin/llvm-dis foo2.bc
momo@momo-droiddev:~/SeaHorn-0.1.0-rc2-Linux-x86_64$ cat foo2.ll
; ModuleID = 'foo2.bc'
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i386-pc-linux-gnu"

!llvm.ident = !{!0}

!0 = !{!"Ubuntu clang version 3.6.2-3ubuntu2 (tags/RELEASE_362/final) (based on LLVM 3.6.2)"}

I tried to issue commands manually (per what I was reading on master branch) and was thinking [-]-entry-point= would work as an option to seapp, but no dice. Part of me is guessing the binary 0.1.0 release does not have the --entry option sprinkled through?

Thanks for any assistance.

C++ mangled names

I am uncertain of the level of desire for C++ support, so please let me know if I should not think about this stuff. There is the expectation in some of the seahorn passes that names be in C naming form (not mangled), so the compiler emitting _Z17__VERIFIER_assumei, etc causes analysis to fail because the PromoteVerifierCalls pass skips over these. I am guessing two ways to handle this... one is a hack that I have made a pull request for. The other is doing another pass that can be invoked to do a rename:

/** Rename certain C++ mangled functions of interest */

#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
namespace seahorn
{
  class CppRename : public ModulePass
  {
    std::map<std::string, std::string> mangledMap = {
      std::make_pair("_Z17__VERIFIER_assumei", "__VERIFIER_assume"),
      std::make_pair("_Z16__VERIFIER_errorv", "__VERIFIER_error")
// Insert others that might be mangled that are wanted in a certain form
    }; 
   public:
    static char ID;
    CppRename () : ModulePass (ID) {}
    bool runOnModule (Module &M)
    {
      bool changed = false;
      for (auto ii = mangledMap.begin(); ii != mangledMap.end();
       ++ii) {
        std::string fname = *ii; 
        Function *f = M.getFunction(fname);
        if (f != NULL) {
          f.setName(mangledMap[fname]); 
          changed = true;
        }
      }
      return changed;
    }
    void getAnalysisUsage (AnalysisUsage &AU)
    { }
    virtual const char* getPassName () const 
    {return "Rename certain C++ mangled naming for later use";}
  };
  char CppRename::ID = 0;
  Pass* createCppRenamePass (){
    return new CppRename ();
  }
}

Or likely there is another generic way to do it with cxxabi.

The hack pull req is #86

Seahorn crashes on example with "-g --inline" flags

When I use Seahorn with both “-g” and “--inline” flags on the example, below, Seahorn crashes (And prints the stack trace).
When either of the two flags is removed, the run terminates with a correct result (sat).
The complete command I used was:
sea pf -g --inline seahorn_crash_example.c

#include "seahorn.h"

int havoc_int();

int comm4 = 0;
int p = 1;

void second()
{
if (havoc_int())
{
comm4 = havoc_int();
}
}

void first(int new_p)
{
int comm4_COPY = comm4;
p = new_p;

comm4 = havoc_int();
__VERIFIER_assume(comm4 == comm4_COPY);
if (havoc_int())
{
__VERIFIER_assume((comm4 == 1) || (p != 1));
}
}

int main()
{
first(1);
second();
sassert(comm4 == 1);
while (1)
{
first(2);
second();
}
}

Use of WTO in Houdini

Houdini pass should traverse the HornDb using WTO graph over dependency structure (call-graph) instead of using a worklist algorithm.

[No issue] Explanation request regarding BMC trace print

Hi All,

Could not find a better area to post this request for information. What I would like to know what is how to understand the values given by the BMC trace.

For example (relates to the code below):
` %12 = call i32 @ValidateFunc() #3
%13 = icmp eq i32 %12, 0'

%12 has the value of 1, which means that %13 get the value FALSE.
Looking at the BMC trace, %13, has a value of FALSE written behind it. This seems clear.

What I don't get is the value behind: %10 or %11. I would expect the result of add(1,1) = 2, but that is not the case.

Full code snippet with all convertions:
int x=add(1,1); int y=add(2,2); if(ValidateFunc()) { int t1 = x; int t2 = y; x = t1+ t2; y = t1 + t2; } sassert(y < 1);

The code snippet has the following IR code after some pp:
`precall6: ; preds = %precheck
br label %count

count: ; preds = %precall6
call void @seahorn.fn.enter() #3
%10 = call fastcc i32 @add(i32 1, i32 1) #3
%11 = call fastcc i32 @add(i32 2, i32 2) #3
%12 = call i32 @ValidateFunc() #3
%13 = icmp eq i32 %12, 0
%14 = select i1 %13, i32 0, i32 %10
%..i = add nsw i32 %11, %14
%15 = icmp slt i32 %..i, 1
call void @verifier.assume.not(i1 %15)
%16 = xor i1 %15, true
call void @llvm.assume(i1 %16), !seahorn !1
br label %17

; :17 ; preds = %count
br label %verifier.error

verifier.error: ; preds = %17
call void @seahorn.fail()
ret i32 42`

The BMC trace has the following result when generating the CEX:
precall6: count: %_10 0 %_11 1 %_12 1 %_13 false %_14 0 %..i 1 %_15 false %_16 true _bb: verifier.error: verifier.error.split:

Thanks in advance,

ABC instrumentation is not correct with -m64 option

  • sea pf -O0 -m32 --abc=global --dsa=sea-ci ./test/abc/test-2-false.c returns the correct answer sat.
  • sea pf -O0 -m64 --abc=global --dsa=sea-ci ./test/abc/test-2-false.c returns the wrong answer unsat

I think the difference is in the align attribute in the allocation of the array:

  1. -m32: %a = alloca [10 x i32], align 4
  2. -m64: %a = alloca [10 x i32], align 16

For 1) our pass calculates that the size of the array %a is 40.
For 2) our pass calculates that the size of the array %a is 48.

In test-2-false.c, for the statement read(a[(nd()>0?i-1:i)]);:
the access a[i] would be translated to something similar like this:

  1. assert(40+4 <= 40) (with -m32)
  2. assert(40+4 <= 48) (with -m64)

where 40 from the lhs of the leq operator is the value of i and 4 is the size of the array element. The 40 (48) from the rhs of the leq operator is the size of the array.

That's why with -m64 we report incorrectly that the program is safe.

We need to adjust the sizes of allocated memory taking the alignment into consideration.

The size of allocated memory is inferred by the function getObjectSize in seahorn/lib/Transformations/BufferBoundsCheck.cc. It's almost a copy of the one defined in llvm. I don't remember now why we made a copy but we needed to make some modification to it. To use the one defined by llvm changes nothing. Note also that this adjustment is needed in all the encodings Local, Global and GlobalCCallBacks.

Building SeaHorn following installation guide does not work

Hi all,

I am not able to build SeaHorn if I follow the installation instruction. The problem occurs when its building LLVM that is checked out from SVN.

The only way that I know, to be able to build SeaHorn, is to follow the steps in the Travis jobs overview. Here LLVM is extracted from dropbox.

Is this known?

seaopt affects seahorn's performance

While running seahorn on a small example, I observed that the optimizer might have a negative effect on seahorn.

Specifically, I am getting the following behavior:

$ time seahorn --keep-shadows=true --horn-solve -horn-inter-proc -horn-sem-lvl=mem --horn-step=large test.bc
sat

real    0m8.709s
user    0m8.688s
sys     0m0.012s

$ time seahorn --keep-shadows=true --horn-solve -horn-inter-proc -horn-sem-lvl=mem --horn-step=large test.o.bc
^C
real    5m35.210s
user    5m34.892s
sys     0m0.032s

I stopped the second run after five minutes.

I got test.o.bc by running the following:

$ seaopt -f -funit-at-a-time -o test.o.bc -O3 --enable-indvar=false --enable-loop-idiom=false --enable-nondet-init=false -disable-loop-vectorization -disable-loop-unrolling test.bc

Do you have any idea what might be causing this?

The input files can be found here:

Set C_INCLUDE_PATH on Docker image

A docker image of seahorn/seahorn:v1 doesn't set a include path for seahorn.h.

Therefore commands like sudo docker run seahorn/seahorn:v1 sea pf examples/simple_1.c fail.

How about setting environment variables of include path (e.g. C_INCLUDE_PATH) to seahorn.h?

sext

sext is interpreted as zext

Spacer/Z3 fails with small step and interproc encoding

I think this error has been there for a while.
The commands are:

clang -c -emit-llvm ntdrivers-simplified/cdaudio_simpl1_false-unreach-call_true-termination.cil.c -o cdaudio_simpl1_false-unreach-call_true-termination.cil.bc

seapp cdaudio_simpl1_false-unreach-call_true-termination.cil.bc -horn-mixed-sem -o cdaudio_simpl1_false-unreach-call_true-termination.cil.mixed.pp.bc

seahorn cdaudio_simpl1_false-unreach-call_true-termination.cil.mixed.pp.bc -horn-inter-proc -horn-solve

produces the error:

ASSERTION VIOLATION
File: ../src/ast/ast.cpp
Line: 2484
to_app(get_fact(p2))->get_arg(0) == get_fact(p1)
(C)ontinue, (A)bort, (S)top, (T)hrow exception, Invoke (G)DB

warning: main function could not be found so program is trivially safe

Hello all,

Created this issue to understand what is causing the warning mentioned in the title. I want to prove memory safety on an project of my own, same as the example that is used in the blog:

sea pf -O0 abc2.c --abc=global --show-invars

The only difference is, is that I execute each command seperately

I performed the following steps to get to the warning:

/* select .c file and create .bc */
/usr/bin/clang-3.6 -c -emit-llvm -D__SEAHORN__ -fgnu89-inline -m32 -Iinclude -o /tmp/main.bc ../../../../MBED_Source/Application/main.cpp

/* use .bc file and create pp */
/home/osboxes/Downloads/seahorn/build/run/bin/seapp -o /tmp/main.pp.bc --strip-extern=false --abc=global --abc-dsa-node=0 --abc-alloc-site=0 --kill-vaarg=true /tmp/main.bc

/* use pp and create ms */
/home/osboxes/Downloads/seahorn/build/run/bin/seapp -o /tmp/main.pp.ms.bc --horn-mixed-sem --ms-reduce-main /tmp/main.pp.bc

/* use ms and create .o */
/home/osboxes/Downloads/seahorn/build/run/bin/seaopt -f -funit-at-a-time -o /tmp/main.pp.ms.o.bc --enable-indvar=false --enable-loop-idiom=false --enable-nondet-init=false --unroll-threshold=150 --disable-loop-vectorization=true --disable-slp-vectorization=true --vectorize-slp-aggressive=false /tmp/main.pp.ms.bc

/home/osboxes/Downloads/seahorn/build/run/bin/seahorn --keep-shadows=true --horn-solve --horn-answer -horn-inter-proc -horn-sem-lvl=mem --horn-step=large /tmp/main.pp.ms.o.bc

If I understood it correctly then it not needed to apply additional code to prove the memory safety, because SeaHorn takes care of this. Is this correct?

Thanks for helping out!

Robbin

Handling remainder operator

Hi,

I have a small example to test the remainder operator (%).
The SeaHorn version I have is https://github.com/seahorn/seahorn/releases/download/v0.1.0/SeaHorn-0.1.0-Linux-x86_64.tar.gz.
It seems that the tool does not work well with this operator, I think the results should be TRUE for this example.

extern _Bool __VERIFIER_nondet_bool();
extern void __VERIFIER_error();

int i = 3;
int main(void) {

  if (__VERIFIER_nondet_bool()) {
    i = 3;
  } else {
    i = 7;
  }

  if (i > 1 && (8 % i) == 0) {
    __VERIFIER_error();
  }

  return 0;
}

The command line I used is ./sea_svcomp -p no_inline <file> and here is the log:

Working directory /tmp/seahornpar-Bte0Yk
BRUNCH_STAT Result UNKNOWN
SeaHorn/bin/sea --mem=-1 -m32 pf --step=large -g --horn-global-constraints=true --track=mem --horn-stats --enable-nondet-init --strip-extern --externalize-addr-taken-functions --horn-singleton-aliases=true --horn-pdr-contexts=600 --devirt-functions --horn-ignore-calloc=false --enable-indvar --enable-loop-idiom --cex=/tmp/seahornpar-Bte0Yk/testseahorn2.no_inline.trace ../../../regression/testseahorn2.c
Running:  [2339]
Finished pid 2339 with  code 0 and signal 0
/usr/bin/clang-3.6 -c -emit-llvm -D__SEAHORN__ -fgnu89-inline -m32 -g -o /tmp/sea-r9aqe4/testseahorn2.bc ../../../regression/testseahorn2.c
SeaHorn/bin/seapp -o /tmp/sea-r9aqe4/testseahorn2.pp.bc --strip-extern=true --devirt-functions --externalize-addr-taken-funcs --kill-vaarg=true /tmp/sea-r9aqe4/testseahorn2.bc
SeaHorn/bin/seapp -o /tmp/sea-r9aqe4/testseahorn2.pp.ms.bc --horn-mixed-sem --ms-reduce-main /tmp/sea-r9aqe4/testseahorn2.pp.bc
SeaHorn/bin/seaopt -f -funit-at-a-time -o /tmp/sea-r9aqe4/testseahorn2.pp.ms.o.bc -O3 /tmp/sea-r9aqe4/testseahorn2.pp.ms.bc
SeaHorn/bin/seahorn --keep-shadows=true --horn-solve -horn-cex -horn-svcomp-cex=/tmp/seahornpar-Bte0Yk/testseahorn2.no_inline.trace -horn-inter-proc -horn-sem-lvl=mem --horn-step=large /tmp/sea-r9aqe4/testseahorn2.pp.ms.o.bc --horn-global-constraints=true --horn-stats --horn-singleton-aliases=true --horn-pdr-contexts=600 --horn-ignore-calloc=false
sat


************** BRUNCH STATS ***************** 
BRUNCH_STAT Result FALSE
BRUNCH_STAT Horn 0.00
BRUNCH_STAT HornifyModule 0.00
BRUNCH_STAT seahorn_total 0.01
************** BRUNCH STATS END ***************** 
Copying /tmp/seahornpar-Bte0Yk/testseahorn2.no_inline.trace to ../../../regression/testseahorn2.c.xml
Counterexample trace is in ../../../regression/testseahorn2.c.xml
WINNER:  SeaHorn/bin/sea --mem=-1 -m32 pf --step=large -g --horn-global-constraints=true --track=mem --horn-stats --enable-nondet-init --strip-extern --externalize-addr-taken-functions --horn-singleton-aliases=true --horn-pdr-contexts=600 --devirt-functions --horn-ignore-calloc=false --enable-indvar --enable-loop-idiom --cex=/tmp/seahornpar-Bte0Yk/testseahorn2.no_inline.trace
BRUNCH_STAT config 0
BRUNCH_STAT config_name no_inline

Can you please check this?

Thanks,
Truc

Problem when building Seahorn

I am trying to build Seahorn in Mac OS X (is this supposed to work?). I've installed LLVM and Boost dependencies and CMake does succesfully find them.

However, when I execute cmake --build . I obtain the following error:

[ 11%] Building CXX object lib/CMakeFiles/shadow.dir/Transforms/Instrumentation/ShadowMemDsa.cc.o
/Users/baha/seahorn/lib/Transforms/Instrumentation/ShadowMemDsa.cc:516:50: error: 
      unknown type name 'StripShadowMem'
  Pass * createStripShadowMemPass () {return new StripShadowMem ();}
                                                 ^
/Users/baha/seahorn/lib/Transforms/Instrumentation/ShadowMemDsa.cc:521:36: error: 
      no member named 'StripShadowMem' in namespace 'seahorn'
static llvm::RegisterPass<seahorn::StripShadowMem> Y ("strip-shadow-dsa",
                          ~~~~~~~~~^
2 errors generated.
make[2]: *** [lib/CMakeFiles/shadow.dir/Transforms/Instrumentation/ShadowMemDsa.cc.o] Error 1
make[1]: *** [lib/CMakeFiles/shadow.dir/all] Error 2
make: *** [all] Error 2

Maybe it is because you are commiting changes and I know it is not wise to build the master branch, but...

Refactor predicate discovery

Factor out predicate discovery from Houdini algorithm. It should be possible to try different strategies for discovering predicates independently of which algorithm (for now just Houdini) is used to reason with them.

Unknown command line argument '--enable-indvar=false'.

I am unable to run seahorn due the following errors. Kindly help me.

Error:-
/home/ezudheen/workspace/seahorn/build/run/bin/sea pf example.c/usr/bin/clang-3.6 -c -emit-llvm -D__SEAHORN__ -fgnu89-inline -m32 -I/home/ezudheen/workspace/seahorn/build/run/include -o /tmp/sea-O6tcvl/example.bc example.c
/home/ezudheen/workspace/seahorn/build/run/bin/seapp -o /tmp/sea-O6tcvl/example.pp.bc --strip-extern=false --kill-vaarg=true /tmp/sea-O6tcvl/example.bc
/home/ezudheen/workspace/seahorn/build/run/bin/seapp -o /tmp/sea-O6tcvl/example.pp.ms.bc --horn-mixed-sem --ms-reduce-main /tmp/sea-O6tcvl/example.pp.bc
/usr/bin/opt-3.6 -f -funit-at-a-time -o /tmp/sea-O6tcvl/example.pp.ms.o.bc -O3 --enable-indvar=false --enable-loop-idiom=false --enable-nondet-init=false --disable-loop-vectorization=true --disable-slp-vectorization=true --vectorize-slp-aggressive=false /tmp/sea-O6tcvl/example.pp.ms.bc
opt-3.6: Unknown command line argument '--enable-indvar=false'. Try: '/usr/bin/opt-3.6 -help'
opt-3.6: Did you mean '-enable-fp-mad=false'?
opt-3.6: Unknown command line argument '--enable-loop-idiom=false'. Try: '/usr/bin/opt-3.6 -help'
opt-3.6: Did you mean '-enable-lsr-phielim=false'?
opt-3.6: Unknown command line argument '--enable-nondet-init=false'. Try: '/usr/bin/opt-3.6 -help'
opt-3.6: Did you mean '-enable-load-pre=false'?

Environment:-
Ubuntu 16.04 LTS
LLVM version 3.6.2
Optimized build.
Built Apr 18 2016 (16:31:56).
Default target: x86_64-pc-linux-gnu
Host CPU: core-avx2
Clang version -3.6

Seg fault when try to get live info from unreachable basic block

This is an old error that I though we already solved.

These are the commands:

  • clang -c -emit-llvm ntdrivers-simplified/cdaudio_simpl1_false-unreach-call_true-termination.cil.c -o cdaudio_simpl1_false-unreach-call_true-termination.cil.bc
  • seapp cdaudio_simpl1_false-unreach-call_true-termination.cil.bc -horn-inline-all -o cdaudio_simpl1_false-unreach-call_true-termination.cil.pp.bc
  • seahorn cdaudio_simpl1_false-unreach-call_true-termination.cil.pp.bc -horn-solve -horn-step=large

The error is:

seahorn: ../lib/seahorn/LiveSymbols.cc:227: const ExprVector& seahorn::LiveSymbols::live(const llvm::BasicBlock*) const: Assertion it != m_liveInfo.end ()' failed.`

It looks like that the pass that removes unreachable blocks (RemoveUnreachableBlocksPass) is indeed never executed although in seahorn.cpp we call it several times.

I though that we needed to replace
void RemoveUnreachableBlocksPass::getAnalysisUsage (AnalysisUsage &AU) const { }

with

void RemoveUnreachableBlocksPass::getAnalysisUsage (AnalysisUsage &AU) const { AU.setPreservesAll (); }

but it doesn't help.

Docker-based binary distribution

Build a docker-based binary distribution for seahorn.

Must include LLVM + clang 3.8 (from llvm.org) and be able to run the lit tests.

The docker container with the distribution should be hosted on docker hub.
We currently have a binary distribution created by @lememta here: https://hub.docker.com/r/seahorn/seahorn/

We can get credentials from @lememta to take over that space.

We can follow the example from KLEE project: http://klee.github.io/docker/
Although I don't like that the user must copy their program into the container to use it.

Another example is to look at Python packaging on docker hub: https://hub.docker.com/_/python/


Additionally, the docker for it should be minimal, i.e. not include any packages and tools needed to build seahorn.

multiplication handling

I am not sure if this is a bug or a limitation of certain analyses, so I apologize if my ignorance gets the better of me.

I have the following code I was using to test (cropping some):

int g();
int
main()
{
   int i, j, k;

   i = g();
   __VERIFIER_assume(i > 0);
   __VERIFIER_assume(i < 50);
   j = g();
   __VERIFIER_assume(j > i);
   __VERIFIER_assume(j < 100);
   k = i * j;
   my_vassert(k > 0);
   return 0;
}

and with 'sea pf --horn-stats' i am getting false. If I set i = 2, for example, I will get true.

Am I making a dumb mistake?

Thank you for any insight,
Best

Docker-bases Seahorn build using the precompiled dependencies

Continuing from #78, we want to be able to build SeaHorn with docker.

  1. Prebuilt dependencies should be stored on a new repo, e.g. seahorn-bin-deps. Tarballs for debug versions of llvm are quite big (1.7 GB), so we will have to settle on release-only configurations for now. Keeping binaries on github is far from perfect, but it should do for now, as we don't expect them to change.
  2. The existing docker files should be modified to copy the tarballs to host's directory mounted inside containers.
  3. Dockerfile for boost can be updated to use the same configuration as in .travis.yaml.

Generate tests for harness generation

and include them in travis. It should be straightforward. Just to take the couple of examples we have in the blog posts so that we can check that nothing is broken.

Building issues with existing Z3 installation

Hi there,

I have a version of Z3 installed on my computer: Z3 version 4.3.2
When I try to compile seahorn, it detects my current version of Z3 and decide to use it.
This is apparently the cause for an error during the compilation process:

Scanning dependencies of target seahorn.LIB
[ 64%] Building CXX object lib/seahorn/CMakeFiles/seahorn.LIB.dir/LoadIkos.cc.o
In file included from /home/arnaud/data/work/repositories/github/seahorn/include/ufo/Smt/ZExprConverter.hpp:7:0,
                 from /home/arnaud/data/work/repositories/github/seahorn/include/ufo/Smt/EZ3.hh:3,
                 from /home/arnaud/data/work/repositories/github/seahorn/include/seahorn/HornifyModule.hh:8,
                 from /home/arnaud/data/work/repositories/github/seahorn/lib/seahorn/LoadIkos.cc:53:
/home/arnaud/data/work/repositories/github/seahorn/include/ufo/Smt/Z3n.hpp: In member function ‘void ufo::ZFixedPoint<Z>::getCexRules(expr::ExprVector&)’:
/home/arnaud/data/work/repositories/github/seahorn/include/ufo/Smt/Z3n.hpp:839:73: error: there are no arguments to ‘Z3_fixedpoint_get_rules_along_trace’ that depend on a template parameter, so a declaration of ‘Z3_fixedpoint_get_rules_along_trace’ must be available [-fpermissive]
                             Z3_fixedpoint_get_rules_along_trace (ctx, fp));
                                                                         ^
/home/arnaud/data/work/repositories/github/seahorn/include/ufo/Smt/Z3n.hpp:839:73: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
At global scope:
cc1plus: warning: unrecognized command line option "-Wno-covered-switch-default"
cc1plus: warning: unrecognized command line option "-Wno-sometimes-uninitialized"
cc1plus: warning: unrecognized command line option "-Wno-redeclared-class-member"
lib/seahorn/CMakeFiles/seahorn.LIB.dir/build.make:54: recipe for target 'lib/seahorn/CMakeFiles/seahorn.LIB.dir/LoadIkos.cc.o' failed
make[2]: *** [lib/seahorn/CMakeFiles/seahorn.LIB.dir/LoadIkos.cc.o] Error 1
CMakeFiles/Makefile2:1915: recipe for target 'lib/seahorn/CMakeFiles/seahorn.LIB.dir/all' failed
make[1]: *** [lib/seahorn/CMakeFiles/seahorn.LIB.dir/all] Error 2
Makefile:143: recipe for target 'all' failed
make: *** [all] Error 2

Pre-building dependencies

Pre-build dependencies for most common platform and host them on
github under seahorn/deps. The dependencies are

The common platforms are Ubuntu 14.04 and 16.04, 32bit and 64bit,
Release and Debug.

There should be Docker scripts to automate rebuilding the
dependencies. For example, each configuration has a Dockerfile such
that running docker on it produces packaged dependencies.

The docker container for building the dependencies can start from
buildpack-deps.

For example, see docker container for Python
(https://hub.docker.com/_/python/).

Latest fix for ExternalizeAddressTakingFunction is wrong

This is the original command that triggers the error that we tried to fix with commit 8d5e1fa:

sea pf -O3 -g --step=large --track=mem --horn-global-constraints=true --horn-stats --enable-nondet-init --strip-extern --externalize-addr-taken-functions --horn-singleton-aliases=true --horn-pdr-contexts=600 --devirt-functions --horn-ignore-calloc=false --enable-indvar --enable-loop-idiom --horn-estimate-size-invars --dsa-stats --dsa=sea-ci --inline ./linux-3.14__complex_emg__linux-kernel-locking-spinlock__drivers-net-ethernet-atheros-alx-alx__23_true-unreach-call.cil.c 

This the zip file test.zip containing the program.

The fix is wrong because it might replace all uses of a taken-address function rather than specific uses as we are interested in. Moreover, replaceAllUsesWith might modify the uses iterator so not sure we were ending with some undefined behavior.

Nightly builds

Nightly/weekly binary builds.

Nightly build should be automatically put onto dockerhub when all the tests pass. It should be possible to hook this up into the CI infrastructure.

The description needs to be further refined.

LLVM bitcode generated using new Clang on OSX not recognized

I'm on OSX 10.11.4, Xcode 7.3 with Clang:

Apple LLVM version 7.3.0 (clang-703.0.29)

seapp, llvm-dis and other tools built within seahorn cannot recognize any bit code files generated by the above Clang, giving errors like this:

error: Invalid type for value

The error occurred somewhere in function BitcodeReader::ParseConstants() in file ext/llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Is this a compatibility issue with the old LLVM seahorn is using now?

Clang-3.6 on Ubuntu had no issue.

Counter-example does not violate the assertion

Hi there,

I'm verifying the following code:

#include "seahorn/seahorn.h"

int nondet();

int square(int x)
{
    return x*x;
}

int main()
{
    int x = nondet();
    assume(x>1);
    assume(x<100);
    int y = square(x);
    sassert(y>0);
    return 0;
}

SeaHorn gives SAT for this assertion.
When I generate the counter-example, the error location is not executed.
Besides, when debugging, it says the values are x=2 and y=4, which shouldn't violate the assertion.

Any clues on what could be wrong here?

Cheers,
Leonardo

Incorrect CHC

The sea smt script generates incorrect CHC for the following C program:

extern void __SEAHORN_fail (void);
int main() {
    int y = 42;
    int x = 84;
    while (x >= 0) {
            y = 2*y - x;
            x = (y + x) / 2;
    }       
    __SEAHORN_fail();
    return 0;
}

The .ll file resulting from

sea smt -o weird.smt2 weird.c -O0 --step=flarge --oll=weird.ll

is fine. In particular the loop body is simplified to this:

_y.0:                                             ; preds = %_4, %_br
  %y.0 = phi i32 [ 42, %_br ], [ %_br2, %_4 ]
  %x.0 = phi i32 [ 84, %_br ], [ %y.0, %_4 ]
  %_br1 = icmp sgt i32 %x.0, -1
  br i1 %_br1, label %_4, label %_call

_4:                                               ; preds = %_y.0
  %_5 = mul nsw i32 %y.0, 2
  %_br2 = sub nsw i32 %_5, %x.0
  br label %_y.0

where, after renaming, y_new = 2*y_old - x_old and x_new = y_old.
However, the loop body in the .smt2 file becomes this

(rule (let ((a!1 (and (main_1 1 main@%y.0_0 main@%x.0_0)
                true
                (= main@%_br1_0 (> main@%x.0_0 (- 1)))
                (=> main@_4_0 (and main@_y.0_0 |tuple(main@_y.0_0, main@_4_0)|))
                (=> (and main@_y.0_0 |tuple(main@_y.0_0, main@_4_0)|)
                    main@%_br1_0)
                (=> main@_4_0 (= main@%_5_0 (* main@%y.0_0 2)))
                (=> main@_4_0 (= main@%_br2_0 (- main@%_5_0 main@%x.0_0)))
                (=> main@_y.0_1 (and main@_4_0 |tuple(main@_4_0, main@_y.0_1)|))
                main@_y.0_1
                (=> (and main@_4_0 |tuple(main@_4_0, main@_y.0_1)|)
                    (= main@%y.0_1 main@%_br2_0))
                (=> (and main@_4_0 |tuple(main@_4_0, main@_y.0_1)|)
                    (= main@%x.0_1 main@%y.0_1))    <--- here it should be main@%y.0_0
                (=> (and main@_4_0 |tuple(main@_4_0, main@_y.0_1)|)
                    (= main@%y.0_2 main@%y.0_1))
                (=> (and main@_4_0 |tuple(main@_4_0, main@_y.0_1)|)
                    (= main@%x.0_2 main@%x.0_1)))))
  (=> a!1 (main_1 1 main@%y.0_2 main@%x.0_2))))

where, after renaming y_new = 2*y_old - x_old and x_new = y_new.
In particular the difference is between x_new = y_old (correct) and x_new = y_new (wrong).

Problem in normalizingHornClauseHeads

replaceNonVarsInHead() introduces new variables to the rule, but does not add them to the list of bound variables.

In general, a better solution is to replace rules in transformation instead of patching them directly. This would have exposed this problem sooner.

A latest tag of Docker image

When I pulled a docker image of SeaHorn, it failed.

$ sudo docker pull seahorn/seahorn
Using default tag: latest
Error response from daemon: manifest for seahorn/seahorn:latest not found

There is only a tag v1 therefore a following command succeeded.

 $ sudo docker pull seahorn/seahorn:v1

So how about creating the latest tag?

Environment: Ubuntu 14.04 LTS, Docker version 1.13.0

refactor Houdini into Analysis and a Pass

Refactor Houdini so that the analysis can be used outside of LLVM pass infrastructure. It is convenient to be able to run Houdini directly on a HornDB from other passes.

Compile error

On modular_inc branch, Ubuntu 14.04, cc=Clang 3.6.1, Boost 1.60.0

export CMAKE_INCLUDE_PATH="/homes/dejan/Software/boost_1_60_0/include"
export CMAKE_LIBRARY_PATH="/homes/dejan/Software/boost_1_60_0/lib"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=run ../
[lots of compilation]
cmake --build .

Then gives linking problem.

[ 15%] Built target DSA
[ 28%] Built target AssistDS
[ 28%] Built target SeaLlvmIpo
[ 37%] Built target SeaInstCombine
[ 39%] Built target SeaInstNondet
[ 45%] Built target seaopt
[ 48%] Built target CrabLlvmAnalysis
[ 48%] Built target CrabLlvmInstrumentation
[ 48%] Built target avy
[ 53%] Built target checks
[ 59%] Built target shadow
[ 63%] Built target seabmc.LIB
[ 75%] Built target seahorn.LIB
[ 78%] Built target SeaAnalysis
[ 86%] Built target SeaInstrumentation
[ 92%] Built target SeaTransformsScalar
[ 98%] Built target SeaTransformsUtils
[100%] Built target SeaSupport
Linking CXX executable seahorn
../../run/lib/libz3.a(api_bv.o): In function `mpq_manager<true>::del(mpq&)':
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3delER3mpq[_ZN11mpq_managerILb1EE3delER3mpq]+0x1d): undefined reference to `omp_set_nest_lock'
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3delER3mpq[_ZN11mpq_managerILb1EE3delER3mpq]+0x3b): undefined reference to `omp_unset_nest_lock'
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3delER3mpq[_ZN11mpq_managerILb1EE3delER3mpq]+0x59): undefined reference to `omp_set_nest_lock'
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3delER3mpq[_ZN11mpq_managerILb1EE3delER3mpq]+0x77): undefined reference to `omp_unset_nest_lock'
../../run/lib/libz3.a(api_bv.o): In function `mpq_manager<true>::set(mpq&, int)':
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3setER3mpqi[_ZN11mpq_managerILb1EE3setER3mpqi]+0x22): undefined reference to `omp_set_nest_lock'
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3setER3mpqi[_ZN11mpq_managerILb1EE3setER3mpqi]+0x40): undefined reference to `omp_unset_nest_lock'
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3setER3mpqi[_ZN11mpq_managerILb1EE3setER3mpqi]+0x61): undefined reference to `omp_set_nest_lock'
../src/api/api_bv.cpp:(.text._ZN11mpq_managerILb1EE3setER3mpqi[_ZN11mpq_managerILb1EE3setER3mpqi]+0x7f): undefined reference to `omp_unset_nest_lock'
../../run/lib/libz3.a(api_arith.o): In function `Z3_get_numerator':
../src/api/api_arith.cpp:(.text+0x1cd1): undefined reference to `omp_set_nest_lock'
../src/api/api_arith.cpp:(.text+0x1cf0): undefined reference to `omp_unset_nest_lock'
[and so on]

Have you seen something like this before?

ashr

I think that the ashr instruction is not interpreted correctly.
For example:

ashr i32 -1, 31

should not return -1 as a result.

********* C code *********

extern int nd (void);
extern void __VERIFIER_error (void);
void assert (int v) { if (!v) __VERIFIER_error (); }
extern void __VERIFIER_assume (int);

define assume __VERIFIER_assume

int main() {
int x = nd();
int r = x < 0 ? -x : x;
while (x != 0) {
r = r - 1;
if (! (r >= 0)) __VERIFIER_error();
if (x < 0) {
x = x + 1;
} else {
x = x - 1;
}
}
return 0;
}

********* LLVM Code *********

define i32 @main() #1 {
entry:
%_0 = call i32 @nd() #3
%_1 = icmp slt i32 %_0, 0
%_2 = sub nsw i32 0, %_0
%_3 = select i1 %_1, i32 %_2, i32 %_0
br label %_bb

_bb: ; preds = %_bb3, %entry
%x.0.i = phi i32 [ %_0, %entry ], [ %x.1.i, %_bb3 ]
%r.0.i = phi i32 [ %_3, %entry ], [ %_10, %_bb3 ]
%_5 = icmp eq i32 %x.0.i, 0
call void @verifier.assume.not(i1 %_5)
br label %_bb1

_bb1: ; preds = %_bb
%_7 = icmp sgt i32 %r.0.i, 0
br i1 %_7, label %_bb3, label %_bb2

_bb2: ; preds = %_bb1
br label %verifier.error

_bb3: ; preds = %_bb1
%_10 = add nsw i32 %r.0.i, -1
%_11 = ashr i32 %x.0.i, 31
%_12 = and i32 %_11, 2
%_13 = add nsw i32 %_12, -1
%x.1.i = add i32 %x.0.i, %_13
br label %_bb

verifier.error: ; preds = %_bb2
ret i32 42
}

********* SeaHorn (Wrong) Counterexample *********

TRACE BEGIN
_bb C
_bb C
verifier.error C
TRACE END
Solver: sat
entry:
%_0 -1
%_1 true
%_2 1
%_3 1
_bb:
%x.0.i -1
%r.0.i 1
%_5 false
_bb1:
%_7 true
_bb3:
%_10 0
%_11 -1 <--- should be the negative i32 number 111...111 (I think)
%_12 3 <--- should be 2
%_13 2 <--- should be 1
%x.1.i 1 <--- should be 0
_bb:
%x.0.i 1
%r.0.i 0
%_5 false
_bb1:
%_7 false
_bb2:

False negative results for verification

Here I attach two programs from SVCOMP-16

dtuc.c.log
sqrt.c.log

The verification results by seahorn indicated the assertion fails (error state is reachable)
But actually the assertion is satisfiable and (error state is not reachable)

I have run the program using the following command
sea --crab --step=small --track=mem pf dtuc.c

Let me know how I can produce the correct verification result

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.