## Model Checking ### cbmc `簡介:` cbmc 就像編譯器, 會翻譯程式並集結所有 functions, 但他不會產生 binary code, 而是進行其他的模擬。 * A bounded model checker for C and C++ programs * It supports C89, C99, most of C11 and most compiler extensions provided by gcc and Visual Studio, and also SystemC using Scoot * It allows verifying array bounds (buffer overflows), pointer safety, exceptions and user-specified assertions * It can check C and C++ for consistency with other languages * The verification is performed by [unwinding the loops](https://en.wikipedia.org/wiki/Loop_unrolling) in the program and passing the resulting equation to a decision procedure `應用:` * [Applications of CBMC](http://www.cprover.org/cbmc/applications/) * 主要用來除錯及偵測潛在的錯誤 ### cbmc 開源碼測試 `cbmc -h` ``` * * CBMC 5.8 - Copyright (C) 2001-2017 (64-bit version) * * * * Daniel Kroening, Edmund Clarke * * * * Carnegie Mellon University, Computer Science Department * * * * kroening@kroening.com * * * * Protected in part by U.S. patent 7,225,417 * * Usage: Purpose: cbmc [-?] [-h] [--help] show help cbmc file.c ... source file names Analysis options: --show-properties show the properties, but don't run analysis --symex-coverage-report f generate a Cobertura XML coverage report in f --property id only check one specific property --stop-on-fail stop analysis once a failed property is detected --trace give a counterexample trace for failed properties C/C++ frontend options: -I path set include path (C/C++) -D macro define preprocessor macro (C/C++) --preprocess stop after preprocessing --16, --32, --64 set width of int --LP64, --ILP64, --LLP64, --ILP32, --LP32 set width of int, long and pointers --little-endian allow little-endian word-byte conversions --big-endian allow big-endian word-byte conversions --unsigned-char make "char" unsigned by default --mm model set memory model (default: sc) --arch set architecture (default: x86_64) --os set operating system (default: linux) --c89/99/11 set C language standard (default: c99) --cpp98/03/11 set C++ language standard (default: cpp98) --no-arch don't set up an architecture --no-library disable built-in abstract C library --round-to-nearest rounding towards nearest even (default) --round-to-plus-inf rounding towards plus infinity --round-to-minus-inf rounding towards minus infinity --round-to-zero rounding towards zero --function name set main function name Program representations: --show-parse-tree show parse tree --show-symbol-table show symbol table --show-goto-functions show goto program --drop-unused-functions drop functions trivially unreachable from main function Program instrumentation options: --bounds-check enable array bounds checks --pointer-check enable pointer checks (always enabled for Java) --memory-leak-check enable memory leak checks --div-by-zero-check enable division by zero checks --signed-overflow-check enable signed arithmetic over- and underflow checks --unsigned-overflow-check enable arithmetic over- and underflow checks --pointer-overflow-check enable pointer arithmetic over- and underflow checks --conversion-check check whether values can be represented after type cast --undefined-shift-check check shift greater than bit-width --float-overflow-check check floating-point for +/-Inf --nan-check check floating-point for NaN --no-built-in-assertions ignore assertions in built-in library --no-assertions ignore user assertions --no-assumptions ignore user assumptions --error-label label check that label is unreachable --cover CC create test-suite with coverage criterion CC --mm MM memory consistency model for concurrent programs Semantic transformations: --nondet-static add nondeterministic initialization of variables with static lifetime BMC options: --program-only only show program expression --show-loops show the loops in the program --depth nr limit search depth --unwind nr unwind nr times --unwindset L:B,... unwind loop L with a bound of B (use --show-loops to get the loop IDs) --show-vcc show the verification conditions --slice-formula remove assignments unrelated to property --unwinding-assertions generate unwinding assertions --partial-loops permit paths with partial loops --no-pretty-names do not simplify identifiers --graphml-witness filename write the witness in GraphML format to filename Backend options: --object-bits n number of bits used for object addresses --dimacs generate CNF in DIMACS format --beautify beautify the counterexample (greedy heuristic) --localize-faults localize faults (experimental) --smt1 use default SMT1 solver (obsolete) --smt2 use default SMT2 solver (Z3) --boolector use Boolector --mathsat use MathSAT --cvc4 use CVC4 --yices use Yices --z3 use Z3 --refine use refinement procedure (experimental) --refine-strings use string refinement (experimental) --string-non-empty add constraint that strings are non empty (experimental) --string-printable add constraint that strings are printable (experimental) --string-max-length add constraint on the length of strings --string-max-input-length add constraint on the length of input strings --outfile filename output formula to given file --arrays-uf-never never turn arrays into uninterpreted functions --arrays-uf-always always turn arrays into uninterpreted functions Other options: --version show version and exit --xml-ui use XML-formatted output --xml-interface bi-directional XML interface --json-ui use JSON-formatted output --verbosity # verbosity level ``` #### binary_search `$ cbmc --unwind 20 binary_search.c` Output: ``` ** Results: [test_bsearch.assertion.1] assertion linear_search_result == binary_search_result: SUCCESS [test_sort.assertion.1] assertion is_sorted(x, size): SUCCESS ** 0 of 2 failed (1 iteration) VERIFICATION SUCCESSFUL ``` 參考 [Understanding Loop Unwinding](http://www.cprover.org/cprover-manual/cbmc-loops.shtml) * 一般情況, cbmc 自動判斷要執行多少次 iterations * 當 iterations 次數是 data-dependent 的, unwind bound 可能會失敗, 因此要加上 command `--unwind B`, B 為在每個迴圈裡 loop unwindings cbmc 的最大值。 `$ cbmc --unwind 20 binary_search.c` ``` size of program expression: 10135 steps simple slicing removed 10 assignments Generated 22 VCC(s), 19 remaining after simplification Passing problem to propositional reduction converting SSA Running propositional reduction Post-processing Solving with MiniSAT 2.2.1 with simplifier 200202 variables, 764586 clauses SAT checker: instance is UNSATISFIABLE Runtime decision procedure: 1.159s ``` `$ cbmc --unwind 100 binary_search.c` ``` size of program expression: 26935 steps simple slicing removed 10 assignments Generated 22 VCC(s), 19 remaining after simplification Passing problem to propositional reduction converting SSA Running propositional reduction Post-processing Solving with MiniSAT 2.2.1 with simplifier 868336 variables, 4119797 clauses SAT checker: instance is UNSATISFIABLE Runtime decision procedure: 7s ``` #### fft-structure `$ cbmc fft.c` Output: ``` ** Results: [main.assertion.1] assertion !ok: FAILURE ** 1 of 1 failed (1 iteration) VERIFICATION FAILED ``` `$ cbmc --unwind 4 fft.c` ``` ** Results: [main.assertion.1] assertion !ok: SUCCESS ** 0 of 1 failed (1 iteration) ``` `$ cbmc --unwind 5 fft.c` ``` ** Results: [main.assertion.1] assertion !ok: FAILURE ** 0 of 1 failed (1 iteration) ``` 從以上的測試看出, bug 出現在第五個 loop #### logic `$ cbmc logic.c` Output: ``` size of program expression: 28102 steps simple slicing removed 0 assignments Generated 0 VCC(s), 0 remaining after simplification VERIFICATION SUCCESSFUL ``` `$ cbmc --bounds-check --pointer-check logic.c` Output: ``` [run_program.pointer_dereference.27] dereference failure: deallocated dynamic object in STACK[(signed long int)STACKPTR]: SUCCESS [run_program.pointer_dereference.28] dereference failure: dead object in STACK[(signed long int)STACKPTR]: FAILURE [run_program.pointer_dereference.29] dereference failure: pointer outside dynamic object bounds in STACK[(signed long int)STACKPTR]: SUCCESS [run_program.pointer_dereference.30] dereference failure: pointer outside object bounds in STACK[(signed long int)STACKPTR]: FAILURE [run_program.pointer_dereference.31] dereference failure: pointer outside dynamic object bounds in STACK[(signed long int)((signed int)STACKPTR - 1)]: SUCCESS [run_program.pointer_dereference.32] dereference failure: pointer outside object bounds in STACK[(signed long int)((signed int)STACKPTR - 1)]: FAILURE ... ** 54 of 170 failed (29 iterations) VERIFICATION FAILED ``` `$ cbmc logic.c --bounds-check --pointer-check --trace` ``` Violated property: file logic.c line 136 function run_program dereference failure: pointer outside object bounds in STACK[(signed long int)STACKPTR] POINTER_OFFSET(STACK) + (signed long int)STACKPTR >= 0l && OBJECT_SIZE(STACK) >= 1ul + (unsigned long int)POINTER_OFFSET(STACK) + (unsigned long int)(signed long int)STACKPTR || DYNAMIC_OBJECT(STACK) Violated property: file logic.c line 184 function run_program dereference failure: pointer outside object bounds in STACK[(signed long int)STACKPTR] POINTER_OFFSET(STACK) + (signed long int)STACKPTR >= 0l && OBJECT_SIZE(STACK) >= 1ul + (unsigned long int)POINTER_OFFSET(STACK) + (unsigned long int)(signed long int)STACKPTR || DYNAMIC_OBJECT(STACK) Violated property: file logic.c line 305 function main array `STACK' upper bound in STACK[(signed long int)((signed int)STACKPTR - 2)] !((signed long int)(-2 + (signed int)STACKPTR) >= 16l) Violated property: file logic.c line 306 function main array `STACK' upper bound in STACK[(signed long int)((signed int)STACKPTR - 1)] !((signed long int)(-1 + (signed int)STACKPTR) >= 16l) Violated property: file logic.c line 136 function run_program dereference failure: pointer outside object bounds in STACK[(signed long int)STACKPTR] POINTER_OFFSET(STACK) + (signed long int)STACKPTR >= 0l && OBJECT_SIZE(STACK) >= 1ul + (unsigned long int)POINTER_OFFSET(STACK) + (unsigned long int)(signed long int)STACKPTR || DYNAMIC_OBJECT(STACK) Violated property: file logic.c line 148 function run_program dereference failure: dead object in STACK[(signed long int)STACKPTR] !(POINTER_OBJECT(STACK) == POINTER_OBJECT(__CPROVER_dead_object)) Violated property: file logic.c line 77 function run_program dereference failure: dead object in STACK[(signed long int)tmp_post$4] !(POINTER_OBJECT(STACK) == POINTER_OBJECT(__CPROVER_dead_object)) Violated property: file logic.c line 83 function run_program dereference failure: dead object in STACK[(signed long int)STACKPTR] !(POINTER_OBJECT(STACK) == POINTER_OBJECT(__CPROVER_dead_object)) Violated property: file logic.c line 220 function run_program dereference failure: dead object in STACK[(signed long int)STACKPTR] !(POINTER_OBJECT(STACK) == POINTER_OBJECT(__CPROVER_dead_object)) Violated property: file logic.c line 202 function run_program dereference failure: pointer outside object bounds in STACK[(signed long int)STACKPTR] POINTER_OFFSET(STACK) + (signed long int)STACKPTR >= 0l && OBJECT_SIZE(STACK) >= 1ul + (unsigned long int)POINTER_OFFSET(STACK) + (unsigned long int)(signed long int)STACKPTR || DYNAMIC_OBJECT(STACK) Violated property: file logic.c line 211 function run_program dereference failure: pointer outside object bounds in STACK[(signed long int)STACKPTR] POINTER_OFFSET(STACK) + (signed long int)STACKPTR >= 0l && OBJECT_SIZE(STACK) >= 1ul + (unsigned long int)POINTER_OFFSET(STACK) + (unsigned long int)(signed long int)STACKPTR || DYNAMIC_OBJECT(STACK) Violated property: file logic.c line 227 function run_program dereference failure: dead object in *stackptr !(POINTER_OBJECT(stackptr) == POINTER_OBJECT(__CPROVER_dead_object)) ``` ### 自動機理論 (automata theory) `簡介:` * 自動機是一個機器的虛擬模型, 用來計算一個輸入, 並轉移到一連串的狀態。 * 在每個狀態中, 利用 transition function 決定下一個狀態。 * 直到計算過程進到目標狀態, 則接受該輸入, 結束整個計算過程。 * 代表性的自動機: Turing machine `目標:` * 建立一個描述及分析離散系統動態行為的方法。 * 自動機元件包含: inputs, outputs, states `學派:` * Finite-state machine (simplest) * Pushdown automata * Linear-bounded automata * Turing machine (most complex) ### model checking 中局部狀態表示每個主題執行通訊協定的過程,而所有局部狀態構成全域狀態,每個局部狀態的改變由主體的訊息接收、發送來觸發,能否舉出實際案例說明? ### 是否已編譯 cbmc 並用來分析 C 程式呢?若是,舉出詳細的操作和你的解讀 務必詳閱 [CBMC: Bounded Model Checking for C/C++ and Java: A Short Tutorial](http://www.cprover.org/cprover-manual/cbmc.shtml) ### 以 moxiebox 為例,能否使用 cbmc 來找出程式碼實作的缺陷 (或者自己創造) 呢? ### 在 GitHub 專案中找出使用 model checking 的案例,並且具體說明其作用 (當然要親自實驗) * [PRISM Model Checker](http://www.prismmodelchecker.org/) [Github Link](https://github.com/prismmodelchecker/prism) [PRISM Tutorial](http://www.prismmodelchecker.org/tutorial/die.php) ### 參考資料 * [Understanding Loop Unwinding](http://www.cprover.org/cprover-manual/cbmc-loops.shtml) * [cbmc Github](https://github.com/diffblue/cbmc) * [Stanford University Course - Automata Theory](https://cs.stanford.edu/people/eroberts/courses/soco/projects/2004-05/automata-theory/basics.html) * [自動機理論筆記](http://www.evanlin.com/moocs-coursera-automata-note1/)