@@ -2679,6 +2679,162 @@ Flag | Check
2679
2679
` --uninitialized-check ` | add checks for uninitialized locals (experimental)
2680
2680
` --error-label label ` | check that given label is unreachable
2681
2681
2682
+ #### Generating/Replacing function bodies
2683
+
2684
+ Sometimes implementations for called functions are not available in the goto
2685
+ program, or it is desirable to replace bodies of functions with certain
2686
+ predetermined stubs (for example to confirm that these functions are never
2687
+ called, or to indicate that these functions will never return). For this purpose
2688
+ goto-instrument provides the ` --generate-function-body ` and
2689
+ ` --replace-function-body ` options, that take a regular expression (in
2690
+ [ ECMAScript syntax] ( http://en.cppreference.com/w/cpp/regex/ecmascript ) ) that
2691
+ describes the names of the functions to generate or replace, the difference
2692
+ being that ` --generate-function-body ` will only generate bodies of functions
2693
+ that do not already have one, whereas ` --replace-function-body ` will do this and
2694
+ in addition also replace existing bodies of functions with the stub.
2695
+
2696
+ The shape of the stub itself can be chosen with the ` --replace-function-body-options `
2697
+ parameter, which can take the following values:
2698
+
2699
+ Option | Result
2700
+ -----------------------------|-------------------------------------------------------------
2701
+ ` nondet-return ` | Do nothing and return a nondet result (this is the default)
2702
+ ` empty ` | Delete the body of the function
2703
+ ` assert-false ` | Make the body contain an assert(false)
2704
+ ` assume-false ` | Make the body contain an assume(false)
2705
+ ` assert-false-assume-false ` | Combines assert-false and assume-false
2706
+ ` havoc ` | Set the contents of parameters and globals to nondet
2707
+
2708
+ The various combinations of assert-false and assume-false can be used to
2709
+ indicate that functions shouldn't be called, that they will never return or
2710
+ both.
2711
+
2712
+ Example: We have a program like this:
2713
+
2714
+ // error_example.c
2715
+ #include <stdlib.h>
2716
+
2717
+ void api_error(void);
2718
+ void internal_error(void);
2719
+
2720
+ int main(void)
2721
+ {
2722
+ int arr[ 10] = {1,2,3,4,5, 6, 7, 8, 9, 10};
2723
+ int sum = 0;
2724
+ for(int i = 1; i < 10; ++i)
2725
+ {
2726
+ sum += arr[ i] ;
2727
+ }
2728
+ if(sum != 55)
2729
+ {
2730
+ // we made a mistake when calculating the sum
2731
+ internal_error();
2732
+ }
2733
+ if(rand() < 0)
2734
+ {
2735
+ // we think this cannot happen
2736
+ api_error();
2737
+ }
2738
+ return 0;
2739
+ }
2740
+
2741
+ Now, we can compile the program and detect that the error functions are indeed
2742
+ called by invoking these commands
2743
+
2744
+ goto-cc error_example.c -o error_example.goto
2745
+ # Replace all functions ending with _error
2746
+ # (Excluding those starting with __)
2747
+ # With ones that have an assert(false) body
2748
+ goto-instrument error_example.goto error_example_replaced.goto \
2749
+ --replace-function-body '(?!__).*_error' \
2750
+ --replace-function-body-options assert-false
2751
+ cbmc error_example_replaced.goto
2752
+
2753
+ Which gets us the output
2754
+
2755
+ > ** Results:
2756
+ > [ internal_error.assertion.1] assertion false: FAILURE
2757
+ > [ api_error.assertion.1] assertion false: FAILURE
2758
+ >
2759
+ >
2760
+ > ** 2 of 2 failed (2 iterations)
2761
+ > VERIFICATION FAILED
2762
+
2763
+ As opposed to the verification success we would have gotten without the
2764
+ replacement
2765
+
2766
+
2767
+ The havoc option takes further parameters ` globals ` and ` params ` with this
2768
+ syntax: ` havoc[,globals:<regex>][,params:<regex>] ` (where the square brackets
2769
+ indicate an optional part). The regular expressions have the same format as the
2770
+ those for the ` --replace-function-body ` and ` --generate-function-body ` options
2771
+ and indicate which globals and function parameters should be set to nondet. All
2772
+ regular expressions require exact matches (i.e. the regular expression ` ab? `
2773
+ will match 'a' and 'b' but not 'adrian' or 'bertha').
2774
+
2775
+ Example: With a C program like this
2776
+
2777
+ struct Complex {
2778
+ double real;
2779
+ double imag;
2780
+ };
2781
+
2782
+ struct Complex AGlobalComplex;
2783
+ int do_something_with_complex(struct Complex *complex);
2784
+
2785
+ And the command line
2786
+
2787
+ goto-instrument in.goto out.goto
2788
+ --replace-function-body do_something_with_complex
2789
+ --replace-function-body-options
2790
+ 'havoc,params:.*,globals:AGlobalComplex'
2791
+
2792
+ The goto code equivalent of the following will be generated:
2793
+
2794
+ int do_something_with_complex(struct Complex *complex)
2795
+ {
2796
+ if(complex)
2797
+ {
2798
+ complex->real = nondet_double();
2799
+ complex->imag = nondet_double();
2800
+ }
2801
+ return nondet_int();
2802
+ }
2803
+
2804
+ A note on limitations: Because only static information is used for code
2805
+ generation, arrays of unknown size and pointers will not be affected by this;
2806
+ Which means that for code like this:
2807
+
2808
+ struct Node {
2809
+ int val;
2810
+ struct Node *next;
2811
+ };
2812
+
2813
+ void do_something_with_node(struct Node *node);
2814
+
2815
+ Code like this will be generated:
2816
+
2817
+ void do_something_with_node(struct Node *node)
2818
+ {
2819
+ if(node)
2820
+ {
2821
+ node->val = nondet_int();
2822
+ node->next = nondet_0();
2823
+ }
2824
+ }
2825
+
2826
+ Note that no attempt to follow the ` next ` pointer is made. If an array of
2827
+ unknown (or 0) size is encountered, a diagnostic is emitted and the array
2828
+ is not further examined.
2829
+
2830
+ Some care must be taken when choosing the regular expressions for globals and
2831
+ functions. Names starting with ` __ ` are reserved for internal purposes; For
2832
+ example, replacing functions or setting global variables with the ` __CPROVER `
2833
+ prefix might make analysis impossible. To avoid doing this by accident, negative
2834
+ lookahead can be used. For example, ` (?!__).* ` matches all names not starting
2835
+ with ` __ ` .
2836
+
2837
+
2682
2838
\subsection man_instrumentation-api The CPROVER API Reference
2683
2839
2684
2840
The following sections summarize the functions available to programs
0 commit comments