Take the following C code example.
struct foo_t {
int bar;
};
int my_entry_point(const struct foo_t *foo) {
return foo->bar;
}
In our case, my_entry_point
will be called from assembly, and *foo
here must be assumed to always be correct.
Running with the command line...
frama-c -eva -report -report-classify -report-unclassified-warning ERROR -c11 -main my_entry_point /tmp/test.c
... results in ...
[report] Monitoring events
[kernel] Parsing /tmp/override.c (with preprocessing)
[eva] Analyzing a complete application starting at my_entry_point
[eva] Computing initial state
[eva] Initial state computed
[eva:initial-state] Values of globals at initialization
[eva:alarm] /tmp/override.c:6: Warning:
out of bounds read. assert \valid_read(&foo->bar);
[eva] done for function my_entry_point
[eva] ====== VALUES COMPUTED ======
[eva:final-states] Values at end of function my_entry_point:
__retres ∈ [--..--]
[eva:summary] ====== ANALYSIS SUMMARY ======
----------------------------------------------------------------------------
1 function analyzed (out of 1): 100% coverage.
In this function, 2 statements reached (out of 2): 100% coverage.
----------------------------------------------------------------------------
No errors or warnings raised during the analysis.
----------------------------------------------------------------------------
1 alarm generated by the analysis:
1 invalid memory access
----------------------------------------------------------------------------
No logical properties have been reached by the analysis.
----------------------------------------------------------------------------
[report] Classification
[ERROR:eva.unclassified.warning] Unclassified Warning (Plugin 'eva')
[REVIEW:unclassified.unknown] my_entry_point_assert_Eva_mem_access
[report] Reviews : 1
[report] Errors : 1
[report] Unclassified: 2
[report] User Error: Classified errors found
[kernel] Plug-in report aborted: invalid user input.
Of course, we can always add a base-case NULL
check, which satisfies the checker (this is probably how we'll solve this for now, anyway).
if (!foo) return 0;
But I'm more curious (for learning purposes) about how this might be done with e.g. ACSL annotations telling the checker "hey, we understand this is pointer could, in theory, be invalid - however, please assume that, since it's the entry point, it is indeed valid".
Is this something that ACSL supports, or can the behavior be altered via command line arguments to frama-c
? I can see why the standards committee might be hesitant on adding such a mechanism to ACSL since it could be abused, but seeing as how I'm just learning ACSL I was curious to know what the common approach might be here.