Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making Bounded Model Checking Interprocedural in (Static Analysis) Style

Exactpro
PRO
November 09, 2019

Making Bounded Model Checking Interprocedural in (Static Analysis) Style

Daniil Stepanov, Marat Akhin and Mikhail Belyaev

International Conference on Software Testing, Machine Learning and Complex Process Analysis (TMPA-2019)
7-9 November 2019, Tbilisi

Video: https://youtu.be/kVsQJnSlgfI

TMPA Conference website https://tmpaconf.org/
TMPA Conference on Facebook https://www.facebook.com/groups/tmpaconf/

Exactpro
PRO

November 09, 2019
Tweet

More Decks by Exactpro

Other Decks in Technology

Transcript

  1. 1 / 23
    Making Bounded Model Checking Interprocedural
    in (Static Analysis) Style
    Daniil Stepanov, Marat Akhin, and Mikhail Belyaev
    Saint Petersburg Polytechnic University, Russia
    Jetbrains Research, Russia
    Novemver 9, 2019

    View Slide

  2. 2 / 23
    Static analysis
    Static program analysis is the analysis of computer software which
    is performed without actually executing programs

    View Slide

  3. 3 / 23
    Interprocedural analysis
    One of the hardest problems in BMC is interprocedural analysis
    Standard approach is function inlining
    An alternative to function inlining is context-sensitive analyses

    View Slide

  4. 4 / 23
    Related work
    Craig interpolant for an inconsistent pair of formulas (B, Q) is
    a formula I such that:
    • B → I
    • (I, Q) is also an inconsistent pair of formulae
    • I contains only uninterpreted symbols common to B and Q
    External specications
    • specialized annotation comments
    • embedded domain-specic language (DSL)
    • external DSL
    Another tools:
    • Saturn - function summaries

    View Slide

  5. 5 / 23
    Bounded model checking algorithm

    View Slide

  6. 6 / 23
    Verication example
    Program:
    int x;
    int y=8,z=0,w=0;
    if (x)
    z = y - 1;
    else
    w = y + 1;
    assert (z == 7 || w == 9)
    Constraints:
    y = 8,
    z = x ? y -1 : 0,
    w = x ? 0 : y + 1,
    z != 7,
    w != 9
    UNSAT. Assert always true

    View Slide

  7. 7 / 23
    Verication example
    Program:
    int x;
    int y=8,z=0,w=0;
    if (x)
    z = y - 1;
    else
    w = y + 1;
    assert (z == 5 || w == 9)
    Constraints:
    y = 8,
    z = x ? y -1 : 0,
    w = x ? 0 : y + 1,
    z != 5,
    w != 9
    SAT. Program contains a bug
    Counterexample: y = 8, x = 1, w = 0, z = 7

    View Slide

  8. 8 / 23
    Borealis

    View Slide

  9. 9 / 23
    Program representation

    View Slide

  10. 10 / 23
    Problem
    void print_element(int* arr , int num){
    printf("arr=%i\n", arr[num]); // Check
    }
    void print_next_element(int* arr , int num){
    print_element(arr , num + 1);
    }
    int main(int argc , char* argv [])
    {
    int a[] = {1, 2, 3};
    print_element(a, 0);
    print_next_element(a, 0);
    return 0;
    }

    View Slide

  11. 11 / 23
    Solution
    Call graph traversal
    Extraction of information which aects variables from security
    properties
    Combining of extracted information

    View Slide

  12. 12 / 23
    Call graph for program example
    void print_element(int* arr , int num){
    printf("arr=%i\n", arr[num]);
    }
    void print_next_element(int* arr , int
    num){
    print_element(arr , num + 1);
    }
    int main(int argc , char* argv [])
    {
    int a[] = {1, 2, 3};
    print_element(a, 0);
    print_next_element(a, 0);
    return 0;
    }

    View Slide

  13. 13 / 23
    Collect phase
    Given a function F and its safety property Q, we collecting
    argument-specic information, which is relevant to Q, from all call
    sites of F
    Slicing function w.r.t current query
    Dealing with recursion
    Handling of nested calls

    View Slide

  14. 14 / 23
    Nested call inuence example
    int get_next_index(int a) {
    return a + 1;
    }
    void print_element(int* arr , int num)
    {
    printf("arr=%i\n", arr[num]);
    }
    void print_next_element(int* arr , int
    num) {
    int idx = get_next_index(num);
    print_element(arr , idx);
    }
    int main(int argc , char* argv []) {
    int a[] = {1, 2, 3};
    print_element(a, 0);
    print_next_element(a, 0);
    return 0;
    }

    View Slide

  15. 15 / 23
    Merging information
    void print_element(int* arr , int num){
    printf("arr=%i\n", arr[num]); // Check
    }
    int main(int argc , char* argv [])
    {
    int a[] = {1, 2, 3};
    print_element(a, 0);
    return 0;
    }
    Equality predicates at junctions
    arr = a; num = 0

    View Slide

  16. 16 / 23
    Resulting PS for example
    int get_next_index(int a) {
    return a + 1;
    }
    void print_element(int* arr ,
    int num) {
    printf("arr=%i\n",
    arr[num]);
    }
    void print_next_element(int*
    arr , int num) {
    int idx =
    get_next_index(num);
    print_element(arr , idx);
    }
    int main(int argc , char*
    argv []) {
    int a[] = {1, 2, 3};
    print_element(a, 0);
    print_next_element(a, 0);
    return 0;
    }
    main_ %0= alloca (3,(3 * 1)),
    @I arraydecay1=gep[inbounds ](main_ %0 ,0+0+0),
    print_next_element_num =0
    print_next_element_arr=arraydecay1
    )->(
    @I next_index =( print_next_element_num + 1),
    print_next_element_call=next_index
    )->(
    num=print_next_element_call
    arr=print_next_element_arr
    )->(
    @I idxprom=cast(+ Integer (64), num),
    @I arrayidx=gep(arr ,0+ idxprom))

    View Slide

  17. 17 / 23
    Combining phase
    PS corresponds to a formula of the form P0 ∨ P1 ∨ . . . ∨ Pn
    Pi
    - distinct calling context
    For PS we have to create synthetic variable free_var

    View Slide

  18. 18 / 23
    Resulting PS example
    (BEGIN
    (
    @P free_var =0
    )->(
    main_ %0= alloca (3,(3 * 1)),
    @I main_arraydecay=gep[inbounds ]( main_ %0 ,0+0+0),
    num=0
    arr=main_arraydecay
    )->(
    @I idxprom=cast(+ Integer (64), num),
    @I arrayidx=gep(arr ,0+ idxprom)
    ),
    (
    @P free_var =1
    )->(
    main_ %0= alloca (3,(3 * 1)),
    @I main_arraydecay1=gep[inbounds ]( main_ %0 ,0+0+0),
    print_next_element_num =0
    print_next_element_arr=main_arraydecay1
    )->(
    @I get_next_index_add =( print_next_element_num + 1),
    print_next_element_call=get_next_index_add
    )->(
    num=print_next_element_call
    arr=print_next_element_arr
    )->(
    @I idxprom=cast(+ Integer (64), num),
    @I arrayidx=gep(arr ,0+ idxprom)
    )
    END)

    View Slide

  19. 19 / 23
    Processing to solver
    There are 2 equivalent ways of processing it via an SMT solver
    As one large formula
    Each small disjunct separately

    View Slide

  20. 20 / 23
    Testing
    We tested the prototype in the following congurations:
    Basic intraprocedural BMC (intra)
    BMC with full inlining (inline)
    Our interprocedural BMC approach (inter)

    View Slide

  21. 21 / 23
    Testing

    View Slide

  22. 22 / 23
    Conclusion
    Our main takeaways are as follows:
    Interprocedural analysis is a bottleneck for BMC
    The speed of the algorithm depends not so much on the size
    of the project as the complexity of its internal connections

    View Slide

  23. 23 / 23
    Contact information
    {stepanov, akhin, belyaev}@kspt.icc.spbstu.ru
    Borealis repository:
    https://bitbucket.org/vorpal-research/borealis

    View Slide