GithubHelp home page GithubHelp logo

seahorn / crab Goto Github PK

View Code? Open in Web Editor NEW
220.0 12.0 32.0 6.93 MB

A library for building abstract interpretation-based analyses

License: Apache License 2.0

CMake 1.27% C++ 98.23% Shell 0.10% Dockerfile 0.27% Makefile 0.14%
static-analysis abstract-interpretation program-analysis invariants verification

crab's Introduction

Crab: A C++ Library for Building Program Static Analyses

Crab is a C++ library for building program static analyses based on Abstract Interpretation. Crab provides a rich set of abstract domains, Kleene-based fixpoint solvers, as well as different analyses such as dataflow, inter-procedural and backward. The design of Crab is quite modular so that it is easy to plugin new abstract domains and solvers or build new analyses.

Crab abstract domains can reason about memory contents, C-like arrays and numerical properties. Crab uses efficient implementations of popular numerical domains such as Zones and Octagons and novel domains to reason, for instance, about symbolic terms (aka uninterpreted functions). Crab also implements popular non-relational domains such as interval or congruences using efficient environment maps, and allows the combination of arbitrary domains via standard reduced product constructions. Crab also provides non-convex domains such as specialized disjunctive intervals called Boxes based on linear decision diagrams and a more general value partitioning strategy that lifts an arbitrary domain to an over-approximation of its disjunction completion. In addition to these domains, all developed by Crab authors, the Crab library integrates popular abstract domain libraries such as Apron, Elina, and PPLite.

Crab provides the state-of-the-art interleaved fixpoint solver that uses Bourdoncle's Weak Topological Ordering to select the set of widening points. To mitigate precision losses during widening, Crab implements some popular techniques such as widening with thresholds and lookahead widening.

Crab provides two different implementations of inter-procedural analyses: a top-down with memoization inter-procedural analysis with support for recursive calls, and a hybrid of bottom-up + top down analysis. Last but not least, Crab also implements a more experimental backward analysis that can be used to compute necessary preconditions and/or reduce the number of false alarms.

Crab does not analyze directly a mainstream programming language but instead it analyzes its own CFG-based intermediate representation called CrabIR. CrabIR is three-address code and it is strongly typed. In CrabIR, control flow is defined via non-deterministic goto instructions. Apart from standard boolean and arithmetic operations, CrabIR provides special assume and assert statements. The former can be used to refine the control flow and the latter provides a simple mechanishm to check for user-defined properties. In spite of its simple design, CrabIR is rich enough to represent languages such as LLVM.

Crab is actively under development. If you find a bug please open an Github issue. Pull requests with new features are very welcome. The available documentation can be found in our wiki. If you use this library please cite this paper.


WindowsUbuntuOS XCoverage
TBD TBD

Docker

A (nightly) pre-built version of Crab that runs all tests can be obtained using Docker:

docker pull seahorn/crab:bionic
docker run -v `pwd`:/host -it seahorn/crab:bionic

Requirements

Crab is written in C++ and relies on the Boost library. The main requirements are:

  • C++11 compiler
  • Boost >= 1.65
  • GMP
  • MPFR (if -DCRAB_USE_APRON=ON or -DCRAB_USE_ELINA=ON)
  • FLINT (only if -DCRAB_USE_PPLITE=ON)

In linux, you can install requirements typing the commands:

sudo apt-get install libboost-all-dev libboost-program-options-dev
sudo apt-get install libgmp-dev
sudo apt-get install libmpfr-dev	
sudo apt-get install libflint-dev

Compilation and Installation

To install Crab, type:

 1. mkdir build && cd build
 2. cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ../
 3. cmake --build . --target install 

The tests directory contains many examples of how to build programs written in CrabIR and compute invariants using different analyses and abstract domains. To compile these tests add option -DCRAB_ENABLE_TESTS=ON to line 2.

and then, for instance, to run test1:

build/test-bin/test1

Include third-party abstract domain libraries

The Boxes/Apron/Elina/PPLite domains require third-party libraries. To avoid the burden to users who are not interested in those domains, the installation of the libraries is optional.

  • If you want to use the Boxes domain then add -DCRAB_USE_LDD=ON option.

  • If you want to use the Apron library domains then add -DCRAB_USE_APRON=ON option.

  • If you want to use the Elina library domains then add -DCRAB_USE_ELINA=ON option.

  • If you want to use the PPLite library domains then add -DCRAB_USE_PPLITE=ON option.

Important: Apron and Elina are currently not compatible so you cannot enable -DCRAB_USE_APRON=ON and -DCRAB_USE_ELINA=ON at the same time.

For instance, to install Crab with Boxes and Apron, type:

 1. mkdir build && cd build
 2. cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DCRAB_USE_LDD=ON -DCRAB_USE_APRON=ON ../
 3. cmake --build . --target ldd && cmake ..
 4. cmake --build . --target apron && cmake ..	
 5. cmake --build . --target install 	

Lines 3 and 4 will download, compile and install the Boxes and Apron domains, respectively. Replace apron at line 4 with elina or pplite if you want to use Elina or PPLite instead. If you have already compiled and installed these libraries in your machine then skip commands at line 3 and 4 and add the following options at line 2.

  • For Apron: -DAPRON_ROOT=$APRON_INSTALL_DIR
  • For Elina: -DELINA_ROOT=$ELINA_INSTALL_DIR
  • For Boxes: -DCUDD_ROOT=$CUDD_INSTALL_DIR -DLDD_ROOT=$LDD_INSTALL_DIR
  • For PPLite: -DPPLITE_ROOT=$PPLITE_INSTALL_DIR -DFLINT_ROOT=$FLINT_INSTALL_DIR

Using Crab library in other C++ projects

To include Crab in your C++ application you need to:

  • Include the C++ header files located at the $INSTALL_DIR/crab/include, and

  • Link your application with the Crab libraries installed in $INSTALL_DIR/crab/lib.

If you compile with Boxes/Apron/Elina/PPLite you need also to include $INSTALL_DIR/EXT/include and link with $INSTALL_DIR/EXT/lib where EXT=apron|elina|ldd|pplite.

CMake

If your project uses cmake then you just need to add in your project's CMakeLists.txt:

add_subdirectory(crab)
include_directories(${CRAB_INCLUDE_DIRS})

And then link your executable with ${CRAB_LIBS}

Make

If your project uses make, read this sample Makefile.

crab's People

Contributors

adrianherrera avatar caballa avatar gkgange avatar gretadolcetti avatar jorgenavas avatar lememta avatar linersu avatar priyasiddharth 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

crab's Issues

Bug in flat_boolean_domain

This line looks very suspicious. Shouldn't the inequation be the other way around? I didn't try to create an example that triggers the bug (if it is one), I just stumbled across this line when I was looking at the code to understand how Booleans are handled.

Question regarding the CFG input encoding for the analysis

Hello, this might be a silly question but I can not wrap my head around on how to encode my cfg representation to the crab cfg representation properly. Consider given the following program P:
image
As I can not express statements such as NOT(activate) AND b I converted my input to SSA and three-address code as follows:
image
where SEQ is simply my representation of a basic block. The marshaling to crab looks as follows:

entry:
  havoc(P.activate_1003);
  goto bb_1;
bb_1:
  P.v_bool_1001 = true;
  P.b_1002 = P.v_bool_1001;
  goto bb_2;
bb_2:
  P.temp_0 = not(P.activate_1003);
  P.temp_1 = P.temp_0&P.b_1002;
  goto bb_3,bb_4;
bb_3:
  assume(P.temp_1);
  P.v_int_1004 = 0;
  P.y_1005 = P.v_int_1004;
  goto exit;
exit:

bb_4:
  assume(not(P.temp_1));
  P.temp_2 = not(P.b_1002);
  P.temp_3 = P.activate_1003|P.temp_2;
  goto bb_5,bb_6;
bb_5:
  assume(P.temp_3);
  P.v_int_1006 = 1;
  P.y_1007 = P.v_int_1006;
  goto exit;
bb_6:
  assume(not(P.temp_3));
  P.v_int_1008 = 2;
  P.y_1009 = P.v_int_1008;
  goto exit;

and running a forward analysis using a flat boolean numerical domain with intervals results in the following output:

bb_6:({P.b_1002 -> true; P.temp_1 -> false; P.temp_2 -> false; P.v_bool_1001 -> true}, {})
bb_5:({P.b_1002 -> true; P.temp_1 -> false; P.temp_2 -> false; P.v_bool_1001 -> true}, {})
bb_3:({P.b_1002 -> true; P.v_bool_1001 -> true}, {})
bb_4:({P.b_1002 -> true; P.v_bool_1001 -> true}, {})
bb_2:({P.b_1002 -> true; P.v_bool_1001 -> true}, {})
bb_1:({}, {})
exit:({P.b_1002 -> true; P.v_bool_1001 -> true}, {})
entry:({}, {})

which, sadly, is not helpful to me. I was hoping to detect the unreachability of bb_6, but the information of the value P.activate_1003 is dropped somewhere in between. Any hints on how to encode my problem instance properly such that information is not dropped?

zones with bignum seems to be imprecise for computing summaries

The tests

  • simple/test-arr-4.c
  • simple/test-arr-4.unsafe.c
  • simple/fntest-1.c
  • simple/fntest-1.unsafe.c

from crab-llvm do not pass if we use:

  typedef SDBM_impl::BigNumDefaultParams<number_t> SplitDBMGraph;
  typedef SplitDBM<number_t, varname_t, SplitDBMGraph> BASE(split_dbm_domain_t);

in include/crab_llvm/crab_domains.hh

Bug with apron-domains and rationals

From @caballa on February 16, 2017 21:22

Added test case in branch crab2 (commit 9a21877) that triggers the bug.
The test is actually quite simple. If we just add two constraints x >= 1/2 and x <= 1/2 we get bottom rather than x = 1/2.

If we use integers we get the expected result so something is wrong with how we handle rationals.

Copied from original issue: caballa/crab#12

Copy-on-write optimization in apron_domains, split_dbm, and sparse_dbm seems flaky

I noticed some cases with split_dbm and sparse_dbm where the analysis does not converge because one of the widening operands is wrong due to COW. For now, I decide to disable COW but with some time I should revisit it and fix it.

For future debugging (it requires to use crab-llvm)

crabllvm ./simple_array_index_value_true-unreach-call4_true-termination.pp.bc --crab-turn-undef-nondet --crab-lower-select --crab-dom=zones --crab-inter-sum-dom=zones --crab-widening-delay=2 --crab-widening-jump-set=0 --crab-narrowing-iterations=2 --crab-relational-threshold=10000 --crab-track=arr --crab-singleton-aliases --crab-add-invariants=none --crab-check=assert --crab-stats

cow_bug_program.zip

Question regarding "cyclic" encoding and propagation of analysis results

I want to analyze PLC programs which exhibit "cyclic" behavior using symbolic execution but sometimes the code is written poorly and there are unreachable branches. For this purpose I need some kind of value-set analysis, but I stumbled upon a few problems. Here is an example of a simple program as a crab cfg:

void declare main()
initialization:
  cycle = 0;
  x = 0;
  goto main_entry;
main_entry:
  assume(cycle <= 100);
  goto cycle_entry;
cycle_entry:
  cycle = cycle+1;
  goto main_body;
main_body:
  x_res:int32 = call increment(x:int32);
  goto cycle_exit;
cycle_exit:
  x = x_res;
  goto main_entry,main_exit;
main_exit:
  assume(-cycle < -100);

x_out:int32 declare increment(x_in:int32)
entry:
  goto body;
body:
  x_out = x_in+1;
  goto exit;
exit:

The program should simply increment the value of x by 1 through the use of a function call in each "iteration" for a couple of "cycles".

Using the top-down interprocedural analyzer with the boxes domain of the ldd library I get the following invariants:

Callgraph=
main--> increment
=================================
void declare main()
cycle_exit={-cycle <= -1; cycle <= 101; -x <= -1; -x_res <= -1}
main_exit={-cycle <= -101; cycle <= 101; -x <= -1; -x_res <= -1}
main_body={-cycle <= -2; cycle <= 101; -x <= -1; -x_res <= -1} or 
{-cycle <= -1; cycle <= 1; -x <= 0; x <= 0; -x_res <= -1}
cycle_entry={-cycle <= -2; cycle <= 101; -x <= -1; -x_res <= -1} or 
{-cycle <= -1; cycle <= 1; -x <= 0; x <= 0}
main_entry={-cycle <= -1; cycle <= 100; -x <= -1; -x_res <= -1} or 
{-cycle <= 0; cycle <= 0; -x <= 0; x <= 0}
initialization={-cycle <= 0; cycle <= 0; -x <= 0; x <= 0}
=================================
x_out:int32 declare increment(x_in:int32)
exit={-x_in <= 0; -x_out <= -1}
body={-x_in <= 0; -x_out <= -1}
entry={-x_in <= 0}
=================================

I would have expected that the value of x is propagated, e.g., main_exit={x>=1;x<=101,...} and that the generated function summary holds must summaries for each valuation of x_in, e.g., x_in = 0, x_in = 1, x_in = 2, ....

What is wrong with my encoding?

Create tree expressions and adapt abstract domains to use them

Abstract domains only support arithmetic operations in three-address form (e.g., +,-,*,/) and addition of linear constraints.

Abstract domains do not support addition of non-linear constraints. Moreover, linear constraints are simplified on-the-fly to keep a normalized form. This does not work well if linear constraints are defined over machine arithmetic because those simplifications are not sound. To address these issues, we should have tree expressions (similar to those defined by Apron) which can be converted to linear constraints (if possible/wanted) by each abstract domain.

Elina does not compile on mac: `'stdlib.h' file not found`

(seems like an issue in elina, but I thought it might be helpful to open it here)

ebpf-verifier$ make crab_install
[...]
[ 75%] Performing build step for 'elina'
CMake Error at [...]/workspace/ebpf-verifier/external/crab/build/elina-prefix/src/elina-stamp/elina-build-RelWithDebInfo.cmake:16 (message):
  Command failed: 2

   'make' 'CC=/Library/Developer/CommandLineTools/usr/bin/cc' 'CXX=/Library/Developer/CommandLineTools/usr/bin/c++' 'IS_VECTOR=-DVECTOR' 'ELINA_PREFIX=[...]/workspace/ebpf-verifier/external/crab/build/run/elina' 'GMP_PREFIX=/usr/local' 'MPFR_PREFIX=/usr/local'

  See also

    [...]/workspace/ebpf-verifier/external/crab/build/elina-prefix/src/elina-stamp/elina-build-*.log

make[4]: *** [elina-prefix/src/elina-stamp/elina-build] Error 1
make[3]: *** [CMakeFiles/elina.dir/all] Error 2
make[2]: *** [CMakeFiles/elina.dir/rule] Error 2
make[1]: *** [elina] Error 2
make: *** [crab_install] Error 2

Error:

$ cat elina-build-err.log
clang: warning: -lmpfr: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: -lgmp: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: -lm: 'linker' input unused [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-L../elina_linearize' [-Wunused-command-line-argument]
elina_scalar.c:27:10: fatal error: 'stdlib.h' file not found
#include <stdlib.h>
         ^~~~~~~~~~
1 error generated.
make[6]: *** [elina_scalar.o] Error 1
make[5]: *** [c] Error 2

Optimize/cleanup array graph domain

From @caballa on April 9, 2017 8:34

The current implementation works for toy programs but two main things
must to be done for being able to analyze real programs:

  1. landmarks must be kept as local state as part of each abstract
    state.

  2. reduction between scalar and weight domains must be done
    incrementally. For that, we need some assumptions about the
    underlying scalar domain. For instance, if we assume zones then
    after each operation we know which are the indexes affected by
    the operation. We can use that information for doing reduction
    only on those indexes. This would remove the need of having
    methods such as array_sgraph_domain_traits::is_unsat and
    array_sgraph_domain_traits::active_variables which are anyway
    domain dependent.

Copied from original issue: caballa/crab#15

Should we add the bitwise complement (~) operation in Crab?

I noticed that this bitwise operation type is not included in Crab, and there is no need to add specialized abstraction design of this operation for each abstract domain in Crab. So, should we add the bitwise complement (~) operation in Crab? Or perhaps we have already implemented this operation in some other way, since -x = ~x +1 ?

Valgrind warnings

Running valgrind when using the sdbm domain I get a warning about "use of uninitialized value of size 8" and "Conditional jump depends on uninitialized value" in this line.

I'm not sure which of the variables triggers this error; I would guess it's the dense field since it is of size 8.

(I used the file samples/self/accept_DIV32_overflow_check_1.3 in the bpf verifier)

Add a logico-numerical abstract domain

From @caballa on October 15, 2016 23:32

One simple option is to integrate BDDApron but it is implemented in OCaml so it will add more dependencies to Crab and it would still require changes for supporting Crab domains.

Instead, I prefer to re-implement BDDApron by combining the ADD library (MTBDD) provided by CUDD with the existing Crab domains.

Copied from original issue: caballa/crab#6

What is the difference between the wrapped_interval implemented in crab and the one implemented in TOPLAS15 paper?

I noticed that these operations are not implemented in crab's wrapped_interval:

/// wrapped_interval_domain implements only standard abstract
/// operations of a numerical domain so it is intended to be used as
/// a leaf domain in the hierarchy of domains.
BOOL_OPERATIONS_NOT_IMPLEMENTED(wrapped_interval_domain_t)
ARRAY_OPERATIONS_NOT_IMPLEMENTED(wrapped_interval_domain_t)
REGION_AND_REFERENCE_OPERATIONS_NOT_IMPLEMENTED(wrapped_interval_domain_t)
DEFAULT_SELECT(wrapped_interval_domain_t)

Can this implementation retain the ideas of the TOPLAS15 paper?

For example, to handle branch condition like s < t, the paper update s and t respectively. But, in crab, we may transform this condition to a linear constraint s - t < 0, and solve this? Does this handling method safe in machine integer operation semantics?

I'm not very familiar with crab.

Reaching Definitions Analysis

Hello, is it possible to add a reaching definitions analysis to this framework to obtain a data dependence graph?
I am interested in obtaining a program dependence graph of a control flow graph, however, currently only the control dependence graph is obtainable.

General question on "backward_assign_operations"

Two questions:

  1. Is it possible to use crab's "backwards assignment"s to calculate inputs at the "beginning" of a program? For example:
void foo(int y)
{
    y++;
    if (y > 10); // <-- if this was SSA, it would be something like "y__0 > 9"
}
  1. Are there any domains which support wrapped bit vectors and "work backwards"?

Python API

From @caballa on April 17, 2017 4:40

Copied from original issue: caballa/crab#16

g++-8:

g++-8 now warns about "writing to an object of non-trivially copyable type" using memcpy:

crab/install/include/crab/domains/graphs/adapt_sgraph.hpp:59:15: 
   error: ‘void* memcpy(void*, const void*, size_t)’
   writing to an object of non-trivially copyable type ‘class crab::AdaptSMap<long unsigned int>::elt_t’; 
   use copy-assignment or copy-initialization instead [-Werror=class-memaccess]
         memcpy(dense, o.dense, sizeof(elt_t)*sz);
         ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The warning is enabled automatically on -Wall.

How to correctly represent "else" when manually working with `powerset_domain`

Current situation

Following on from #34, I am able to successfully represent something like:

void foo(int y) {
  int w = 0;
  if (y > 10) {
    w = 1;
  } else {
    w = 2;
  }
}

which I can correctly encode and obtain:

{y -> [[11, 2147483647]]_32; w -> [[2, 2]]_32} or
{y -> [[-2147483648, 10]]_32; w -> [[3, 3]]_32}

My code looks like this like:

using z_wrapped_interval_domain = wrapped_interval_domain<z_number, varname_t>;
using powerset_of_z_wrapped_intervals =
    powerset_domain<z_wrapped_interval_domain>;

using analysis_domain = powerset_of_z_wrapped_intervals;

int main(void) {
  variable_factory_t vfac;
  z_var y(vfac["y"], crab::INT_TYPE, 32);
  z_var w(vfac["w"], crab::INT_TYPE, 32);

  analysis_domain start;
  start.assign(w, 0);

  analysis_domain tt_1 = start;
  tt_1 += (y > 10);
  tt_1.assign(w, 1);

  analysis_domain ff_1 = start;
  ff_1 += (y <= 10);
  ff_1.assign(w, 2);

  analysis_domain after1 = tt_1 | ff_1;
  crab::outs() << after1 << "\n\n\n";
 
  return 0;
}

Current issue

However, I am not sure how to encode things when the condition in the false branch is "more complicated":

void foo(int y) {
  int w = 0;
  if (y > 10 && y < 20) {
    w = 1;
  } else {
    w = 2;
  }
}

(notice the if now contains a conjunction)

While encoding the true branch is fine:

  analysis_domain tt_1 = start;
  tt_1 += (y > 10);
  tt_1 += (y < 20);
  tt_1.assign(w, 1);

the false branch is more complicated:

  analysis_domain ff_1 = start;
  ff_1 += (y <= 10);
  ff_1 += (y >= 20);
  ff_1.assign(w, 2);

because it seems that crab says that this is bottom.

Question

What is the best way to represent the negation of a conditional that contains Booleans when working with crab?

Is there a simple way to build up a Boolean expression, and then use that both positively and then negate it (to represent an else)? It is fine if I need to manually build-up the else, but I'm really unsure about how to encode it.

Adapt numerical domains for supporting reals

From @caballa on October 15, 2016 23:18

For intervals and zones, we need at least:

  • make sure rounding is correct (e.g., if upper bounds towards +oo, etc)
  • make sure division is correct
  • etc.

Copied from original issue: caballa/crab#4

Make generic weights of adaptative sparse graph

adapt_sgraph.hpp assumes that the graph weights are basic types. The assumption for basic types is because we use memcpy and realloc for efficiency reasons. Thus, to use bignums as weights we should change the implementation which might affect performance. The changes are needed here:

domains/graphs/adapt_sgraph.hpp
domains/graphs/util/Vec.h

This is related to issue #21. Thanks to @elazarg to bring it in!

none-optional dereference on array-expansion domain with elina-pk

The issue seem to come from array_expansion.hpp:1287 - missing if (!ignore_array_store) in the condition.

Valgrind traceback:

ebpf-verifier (post-submission)$ valgrind ./check ebpf-samples/cilium/bpf_lxc.o 2/7 --domain=polyElina
==31540== Memcheck, a memory error detector
==31540== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31540== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==31540== Command: ./check ebpf-samples/cilium/bpf_lxc.o 2/7 --domain=polyElina
==31540== 
exception vector product
exception vector product
exception vector product
exception vector product
check: /usr/include/boost/optional/optional.hpp:1205: boost::optional<T>::reference_type boost::optional<T>::get() [with T = ikos::z_number; boost::optional<T>::reference_type = ikos::z_number&]: Assertion `this->is_initialized()' failed.
==31540== 
==31540== Process terminating with default action of signal 6 (SIGABRT)
==31540==    at 0x5967077: raise (raise.c:51)
==31540==    by 0x5948534: abort (abort.c:79)
==31540==    by 0x594840E: __assert_fail_base.cold.0 (assert.c:92)
==31540==    by 0x5958141: __assert_fail (assert.c:101)
==31540==    by 0x31666E: get (optional.hpp:1205)
==31540==    by 0x31666E: operator* (optional.hpp:1222)
==31540==    by 0x31666E: crab::domains::array_expansion_domain<crab::domains::elina_domain_<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, (crab::domains::elina_domain_id_t)2> >::array_store_range(ikos::variable<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string>, ikos::linear_expression<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string>, ikos::linear_expression<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string>, ikos::linear_expression<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string>, ikos::linear_expression<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string>) (array_expansion.hpp:1287)
==31540==    by 0x317107: crab::analyzer::intra_abs_transformer<crab::domains::array_expansion_domain<crab::domains::elina_domain_<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, (crab::domains::elina_domain_id_t)2> > >::exec(crab::cfg::array_store_stmt<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string>&) (abs_transformer.hpp:518)
==31540==    by 0x2ACA8E: crab::analyzer::fwd_analyzer<crab::cfg::cfg_ref<crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number> >, crab::analyzer::intra_abs_transformer<crab::domains::array_expansion_domain<crab::domains::elina_domain_<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, (crab::domains::elina_domain_id_t)2> > > >::analyze(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::domains::array_expansion_domain<crab::domains::elina_domain_<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, (crab::domains::elina_domain_id_t)2> >&) (fwd_analyzer.hpp:80)
==31540==    by 0x2B4E71: ikos::interleaved_fwd_fixpoint_iterator_impl::wto_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::cfg_ref<crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number> >, crab::domains::array_expansion_domain<crab::domains::elina_domain_<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, (crab::domains::elina_domain_id_t)2> > >::visit(ikos::wto_vertex<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::cfg_ref<crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number> > >&) (fwd_fixpoint_iterators.hpp:419)
==31540==    by 0x201409: ikos::wto<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::cfg_ref<crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number> > >::accept(ikos::wto_component_visitor<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::cfg_ref<crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number> > >*) (wto.hpp:743)
==31540==    by 0x1D2C79: run (fwd_fixpoint_iterators.hpp:261)
==31540==    by 0x1D2C79: Run (fwd_analyzer.hpp:138)
==31540==    by 0x1D2C79: run (fwd_analyzer.hpp:285)
==31540==    by 0x1D2C79: crab::checker::checks_db analyze<crab::domains::array_expansion_domain<crab::domains::elina_domain_<ikos::z_number, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, (crab::domains::elina_domain_id_t)2> > >(crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&) (crab_verifier.cpp:156)
==31540==    by 0x1DA725: std::_Function_handler<crab::checker::checks_db (crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&), crab::checker::checks_db (*)(crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&)>::_M_invoke(std::_Any_data const&, crab::cfg::cfg<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, crab::cfg::var_factory_impl::variable_factory<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::indexed_string, ikos::z_number>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&, boost::signals2::signal<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&), boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::function<void (boost::signals2::connection const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, boost::signals2::mutex>&) (std_function.h:283)
==31540==    by 0x1D14F5: operator() (std_function.h:687)
==31540==    by 0x1D14F5: analyze (crab_verifier.cpp:232)
==31540==    by 0x1D14F5: abs_validate(Cfg const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, program_info) (crab_verifier.cpp:72)
==31540== 
==31540== HEAP SUMMARY:
==31540==     in use at exit: 463,322,523 bytes in 4,653,262 blocks
==31540==   total heap usage: 48,232,624 allocs, 43,579,362 frees, 4,789,812,024 bytes allocated
==31540== 
==31540== LEAK SUMMARY:
==31540==    definitely lost: 2,784,843 bytes in 142,118 blocks
==31540==    indirectly lost: 326,439 bytes in 16,535 blocks
==31540==      possibly lost: 155,348,967 bytes in 1,107,462 blocks
==31540==    still reachable: 304,862,274 bytes in 3,387,147 blocks
==31540==         suppressed: 0 bytes in 0 blocks
==31540== Rerun with --leak-check=full to see details of leaked memory
==31540== 
==31540== For counts of detected and suppressed errors, rerun with: -v
==31540== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Aborted (core dumped)

CMake Options

CMake top-level options should be prefixed with CRAB. For example,

USE_LDD --> CRAB_ENABLE_LDD
USE_APRON --> CRAB_ENABLE_APRON

etc.

"compress" `powerset_domain` domain after projection

Current status

I have code that looks like this:

using z_wrapped_interval_domain = wrapped_interval_domain<z_number, varname_t>;
using powerset_of_z_wrapped_intervals =
    powerset_domain<z_wrapped_interval_domain>;

using analysis_domain = powerset_of_z_wrapped_intervals;

int main(void) {
  variable_factory_t vfac;
  z_var y(vfac["y"], crab::INT_TYPE, 32);
  z_var x(vfac["x"], crab::INT_TYPE, 32);

  analysis_domain d1;
  d1 += (y > 10);
  d1.assign(x, 0);

  analysis_domain d2;
  d2 += (y > 20);
  d2.assign(x, 1);

  analysis_domain d3;
  d3 += (y > 30);
  d3.assign(x, 2);

  analysis_domain d4 = d1 | d2 | d3;
  crab::outs() << d4 << "\n\n\n";

  std::vector<z_var> vars;
  vars.push_back(x);

  analysis_domain proj = d4;
  proj.project(vars);
  crab::outs() << proj << "\n\n\n";

  return 0;
}

(the code is purposely brain-dead, but that's fine)

Which gives this:

{y -> [[11, 2147483647]]_32; x -> [[0, 0]]_32} or
{y -> [[21, 2147483647]]_32; x -> [[1, 1]]_32} or
{y -> [[31, 2147483647]]_32; x -> [[2, 2]]_32}


{x -> [[0, 0]]_32} or
{x -> [[1, 1]]_32} or
{x -> [[2, 2]]_32}

Question

After doing the projection, I get a powerset domain that has three elements (0, 1 and 2). Is it possible to ask crab to "compress" this domain into a single range of [0, 2]?

Question: "range of intervals"

Hi,

I just started playing around with crab (so I am very inexperienced here!) and I wanted to model something like this:

void foo(int x) {
  int y = 0;
  if (x >= 10 && x <= 20) {
    y = x;
  } else if (x >= -20 && x <= -10) {
    y = x;
  } else {
    y = 0;
  }

  // y = ([-20, -10], [0], [10, 20])

  ++y;

  // y = ([-10, -9], [1], [11, 21])
}

Using one of the examples, I got this far:

#include <crab/common/types.hpp>
#include <crab/config.h>
#include <crab/domains/wrapped_interval_domain.hpp>
#include <crab/numbers/wrapint.hpp>
#include <iostream>

using namespace std;
using namespace crab::domains;

typedef wrapped_interval<ikos::z_number> wrapped_interval_t;

int main(void) {
  wrapped_interval_t i1(crab::wrapint(10, 32), crab::wrapint(20, 32));
  wrapped_interval_t i2(crab::wrapint(-10, 32), crab::wrapint(-20, 32));
  crab::outs() << "i1 & i2: " << (i1 & i2) << "\n";
  return 0;
}

but this just seems to expand the domain to be [-20, 20], rather than join the "disjointly" (apologies for wrong terminology) -- that is, what I want is ([-20, -10], [10, 20]).

Is this something I can do with crab or are these just "disjoint intervals" not possible with the library?

Thanks!

Possibly stack overflow while computing WTO of a large CFG

Problem07_label52_true-unreach-call.pp.bc.zip

Command to reproduce the problem using crab-llvm:

crabllvm Problem07_label52_true-unreach-call.pp.bc --crab-verbose=2 --crab-dom=int --crab-widening-delay=2 --crab-widening-jump-set=0 --crab-narrowing-iterations=2 --crab-track=arr --crab-singleton-aliases --crab-check=assert --crab-stats --crab-disable-warnings

silently produces signal 11 (SEGFAULT).
I did some gdb and it seems that we run out of stack while computing WTO using recursion.

Compiler warning with `dev`

I tried playing with the dev branch today (71fea99), but got this warning:

In file included from /home/avj/clones/crab/dev/build/_INSTALL_DIR_/../../tests/./crab_dom.hpp:6,
                 from /home/avj/clones/crab/dev/build/_INSTALL_DIR_/../../tests/common.hpp:6,
                 from 01_simple_crab.cpp:1:
/home/avj/clones/crab/dev/build/_INSTALL_DIR_/crab/include/crab/domains/array_adaptive.hpp:64:35: warning: comparison between ‘enum crab::domains::array_adaptive_impl::DefaultParams::<unnamed>’ and ‘enum crab::domains::array_adaptive_impl::DefaultParams::<unnamed>’ [-Wenum-compare]
   static_assert(max_array_size <= max_smashable_cells,
                                   ^~~~~~~~~~~~~~~~~~~
/home/avj/clones/crab/dev/build/_INSTALL_DIR_/crab/include/crab/domains/array_adaptive.hpp:77:35: warning: comparison between ‘enum crab::domains::array_adaptive_impl::NoSmashableParams::<unnamed>’ and ‘enum crab::domains::array_adaptive_impl::NoSmashableParams::<unnamed>’ [-Wenum-compare]
   static_assert(max_array_size <= max_smashable_cells,

It seems that this is a legitimate issue, as max_array_size and max_smashable_cells come from different enums.

GCC version

g++ (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Restrict API of CFG array_assume method

From @caballa on June 25, 2017 23:18

it takes two parameters that delimits a symbolic interval: lower and upper bounds, which can only be number or variables but the current type is a linear expression. So it's more general than it should be.

Copied from original issue: caballa/crab#18

An instance of boxes domain can be in an inconsistent state due to global state

From @caballa on June 25, 2017 21:40

A crab variable can contain a pointer (e.g., crab-llvm stores Value* in a crab variable and seahorn stores Expr). This is very useful when we want to map back crab results to the client. The boxes domain keeps a global map from variables to internal ids. If the destructor of the factory that created the pointer to Value or Expr is called before than the global map is released then it leaves the instance of the boxes domain in an inconsistent state.

Copied from original issue: caballa/crab#17

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.