|
| 1 | +CBMC Mini Projects |
| 2 | +================== |
| 3 | + |
| 4 | +The following projects are short, focussed features that give new CBMC |
| 5 | +contributors an introduction to one part of the codebase. If you're |
| 6 | +interested in contributing to CBMC, feel free to start with any of these |
| 7 | +projects! |
| 8 | + |
| 9 | + |
| 10 | +Task List |
| 11 | +--------- |
| 12 | + |
| 13 | +### `__CPROVER_print` |
| 14 | + |
| 15 | +**Task**: Implement a CPROVER intrinsic that assigns an expression to a |
| 16 | +dummy value, to help with debugging and tracing. |
| 17 | + |
| 18 | +**Background**: |
| 19 | +Inserting `printf("value of expr: %d\n", expr);` is a common debugging |
| 20 | +and tracing technique. The CBMC equivalent is to assign an expression to |
| 21 | +a temporary variable and run `cbmc --trace`: |
| 22 | + |
| 23 | +```c |
| 24 | +$ cat foo.c |
| 25 | +#define __CPROVER_print(var) { int value_of_##var = (int) var; } |
| 26 | + |
| 27 | +void foo(int x) |
| 28 | +{ |
| 29 | + __CPROVER_print(x); |
| 30 | + assert(0); // Make CBMC halt its exploration and dump a trace up to |
| 31 | + // this point |
| 32 | +} |
| 33 | + |
| 34 | +int main() |
| 35 | +{ |
| 36 | + foo(3); |
| 37 | +} |
| 38 | +``` |
| 39 | +
|
| 40 | +This has several limitations (we need different variants of the macro |
| 41 | +for pointers, etc). It would be great to have `__CPROVER_print` as a |
| 42 | +CPROVER intrinsic, so that users don't need to do the awkward define or |
| 43 | +manual ghost assignment in their code. |
| 44 | +
|
| 45 | +**Hints**: Figure out how `__CPROVER_assume` and `__CPROVER_assert` work. |
| 46 | +Then figure out how to add new instructions into a goto-program. |
| 47 | +
|
| 48 | +
|
| 49 | +### Annotation to constrain function pointers |
| 50 | +
|
| 51 | +**Task**: implement a CPROVER intrinsic that tells CBMC what function a |
| 52 | +function pointer points to. |
| 53 | +
|
| 54 | +**Background**: CBMC often doesn't know which function a function |
| 55 | +pointer points to. If a function is called through a function pointer, |
| 56 | +CBMC currently assumes that *any* function that has the same signature |
| 57 | +could be called. This results in a combinatorial explosion of paths when |
| 58 | +CBMC is exploring the program. It would be useful to have an annotation |
| 59 | +that tells CBMC exactly what function a pointer is expected to point to. |
| 60 | +
|
| 61 | +
|
| 62 | +### Generalize loop-unwinding bounds to cover multiple loops |
| 63 | +
|
| 64 | +**Task**: allow users to specify a *combined* bound for the sum of |
| 65 | +several loop counters. |
| 66 | +
|
| 67 | +**Background**: consider a program that uses several nested while-loops |
| 68 | +to move a pointer through a buffer. Each of the nested loops may advance |
| 69 | +the pointer. We want to ensure that the pointer doesn't overflow the |
| 70 | +buffer. |
| 71 | +
|
| 72 | +Unfortunately, if we specify the buffer size `S` as the loop bound for |
| 73 | +those three loops, we can still overflow the buffer because all three of |
| 74 | +the loops can move the pointer forward `S` times. What we need is to |
| 75 | +specify that the *combined* loop bound for the three loops is `S`. |
| 76 | +
|
| 77 | +The current syntax for the `--unwindset` switch is |
| 78 | +
|
| 79 | +``` |
| 80 | +--unwindset LABEL:BOUND |
| 81 | +``` |
| 82 | +
|
| 83 | +You might like to generalize this so that it looks like |
| 84 | +
|
| 85 | +``` |
| 86 | +--unwindset LABEL<,LABEL2,LABEL3,...>:BOUND |
| 87 | +``` |
| 88 | +
|
| 89 | +which would have the effect that the loops with those labels would all |
| 90 | +share a bound. |
| 91 | +
|
| 92 | +*Hints*: |
| 93 | +- The current member that stores how many times a loop has been unwound |
| 94 | + is `goto_symex_statet::loop_iterations`. Have a look at where this |
| 95 | + member is accessed, and what is done with that value (e.g. read |
| 96 | + through `symex_bmct::should_stop_unwind()` and |
| 97 | + `symex_bmct::loop_unwind_handlert`). |
| 98 | +
|
| 99 | +- You may wish to add a map from a *set* of loop names to a loop bound, |
| 100 | + in addition to the current map from single loop names to loop bounds. |
| 101 | +
|
| 102 | +- If a loop has an individual bound, and is also part of a set of |
| 103 | + mutually-bound loops, then we should stop unwinding it if *either* of |
| 104 | + those bounds is reached. Good, thoughtful test cases are essential |
| 105 | + here! |
| 106 | +
|
| 107 | +Completed |
| 108 | +--------- |
| 109 | +
|
| 110 | +
|
| 111 | +### Add a `--print-internal-representation` switch |
| 112 | +
|
| 113 | +*Summary*: This switch should provide more detail than |
| 114 | +`--show-goto-functions`, by printing out the `irep` of every program |
| 115 | +instruction instead of a concise representation. |
| 116 | +
|
| 117 | +*Completed in* PR #991 |
0 commit comments