package mopsa
Install
Dune Dependency
Authors
Maintainers
Sources
md5=fdee20e988343751de440b4f6b67c0f4
sha512=f5cbf1328785d3f5ce40155dada2d95e5de5cce4f084ea30cfb04d1ab10cc9403a26cfb3fa55d0f9da72244482130fdb89c286a9aed0d640bba46b7c00e09500
doc/core/Core/Alarm/index.html
Module Core.Alarm
Source
Alarms - issues found by the analyzer in a program
During the analysis, domains can perform checks to verify whether some property of interest is preserved. Domains declare the list of checks that they are responsible for in their header, and can generate 4 types of diagnostics for a given check and regarding a given location range:
Safe
indicates that the property of interest is preserved for all execution paths reaching the check location.Error
represent issues that are proven true alarms for all execution paths.Warning
is used for potential alarms that maybe infeasible in some execution paths.Unreachable
indicates that the check location can't be reached in any execution path.
Checks
**********
Domains can add new checks by extending the type check
and registering them using register_check
. Note that checks should be simple variant constructs without any argument.
val register_check :
((Stdlib.Format.formatter -> check -> unit) ->
Stdlib.Format.formatter ->
check ->
unit) ->
unit
Register a check with its printer
Alarms
**********
Alarms are issues related to a check in a given range and a given callstack. Domains can add new kinds of alarms to store information related to the issue, such suspect values that raised the alarm. Nevertheless, domains can use the generic alarm A_generic of check
if they don't have addition static information to attach to the alarm.
type alarm = {
alarm_kind : alarm_kind;
alarm_check : check;
alarm_range : Mopsa_utils.Location.range;
alarm_callstack : Mopsa_utils.Callstack.callstack;
}
val mk_alarm :
alarm_kind ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
alarm
Create an alarm
Return the range of an alarm
Return the callstack of an alarm
Compare two kinds of alarms
Print an alarm kind
Join two alarm kinds by merging the static information attached to them
val register_alarm_compare :
((alarm_kind -> alarm_kind -> int) -> alarm_kind -> alarm_kind -> int) ->
unit
Register a comparison function for alarms
val register_alarm_pp :
((Stdlib.Format.formatter -> alarm_kind -> unit) ->
Stdlib.Format.formatter ->
alarm_kind ->
unit) ->
unit
Register a print function for alarms
Register a function giving the check of an alarm
val register_alarm_join :
((alarm_kind -> alarm_kind -> alarm_kind option) ->
alarm_kind ->
alarm_kind ->
alarm_kind option) ->
unit
Register a join function for alarms
type alarm_info = {
check : (alarm_kind -> check) -> alarm_kind -> check;
compare : (alarm_kind -> alarm_kind -> int) -> alarm_kind -> alarm_kind -> int;
print : (Stdlib.Format.formatter -> alarm_kind -> unit) -> Stdlib.Format.formatter -> alarm_kind -> unit;
join : (alarm_kind -> alarm_kind -> alarm_kind option) -> alarm_kind -> alarm_kind -> alarm_kind option;
}
Registration record for a new kind of alarms
Register a new kind of alarms
Diagnostic
**************
A diagnostic gives the status of all alarms raised at the program location for the same check
module AlarmSet : Mopsa_utils.SetExtSig.S with type elt = alarm
Set of alarms
Kind of a diagnostic
type 'a diagnostic_ = {
diag_range : Mopsa_utils.Location.range;
diag_check : check;
diag_kind : diagnostic_kind;
diag_alarms : AlarmSet.t;
diag_callstack : 'a;
}
val mk_safe_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnostic
Create a diagnostic that says that a check is safe
Create a diagnostic that says that a check is unsafe
val mk_warning_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnostic
Create a diagnostic that says that a check maybe unsafe
val mk_unreachable_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnostic
Create a diagnostic that says that a check is unreachable
Print a diagnostic kind
Print a diagnostic
Check whether a diagnostic is covered by another
Compute the union of two diagnostics
Compute the intersection of two diagnostics
Add an alarm to a diagnostic
Compare two diagnostics
Soundness assumption
************************
When a domain can't ensure total soundness when analyzing a piece of code, it can emit assumptions under which the result is still sound.
type assumption_scope =
| A_local of Mopsa_utils.Location.range
(*Local assumptions concern a specific location range in the program
*)| A_global
(*Global assumptions can concern the entire program
*)
Scope of an assumption
Domains can add new kinds of assumptions by extending the type assumption_kind
Generic assumptions for specifying potential unsoundness due to unsupported statements/expressions
Register a new kind of assumptions
Print an assumption kind
Print an assumption
Compare two assumption kinds
Compare two assumptions
Create a global assumption
Create a local assumption
Analysis report
*******************
Alarms are organized in a report that maps each range and each check to a diagnostic. A report also contains the set of soundness assumptions made by the domains.
module RangeMap :
Mopsa_utils.MapExtSig.S with type key = Mopsa_utils.Location.range
module RangeCallStackMap :
Mopsa_utils.MapExtSig.S
with type key =
Mopsa_utils.Location.range * Mopsa_utils.Callstack.callstack
module CheckMap : Mopsa_utils.MapExtSig.S with type key = check
module AssumptionSet : Mopsa_utils.SetExtSig.S with type elt = assumption
type report = {
report_diagnostics : diagnostic CheckMap.t RangeCallStackMap.t;
report_assumptions : AssumptionSet.t;
}
Checks whether a report is safe, i.e. it doesn't contain an error or a warning
subset_report r1 r2
checks whether report r1
is included in r2
filter_report p r
keeps only diagnostics in report r
that verify predicate p
add_alarm a r
adds alarm a
to a report r
. If a diagnostic exists for the same range and the same check as a
, join_diagnostic
is used to join it with an error diagnostic containing a
.
set_diagnostic d r
adds diagnostic d
to r
. Any existing diagnostic for the same range and the same check as d
is removed.
add_diagnostic d r
adds diagnostic d
to r
. If a diagnostic exists for the same range and the same check as d
, join_diagnostic
is used to join it with d
.
Remove a diagnostic from a report
val find_diagnostic :
(Mopsa_utils.Location.range * Mopsa_utils.Callstack.callstack) ->
check ->
report ->
diagnostic
find_diagnostic range chk r
finds the diagnostic of check chk
at location range
in report r
Check whether any diagnostic verifies a predicate
Check whether all diagnostics verify a predicate
module RangeDiagnosticWoCsMap :
Mopsa_utils.MapExtSig.S
with type key = Mopsa_utils.Location.range * diagnosticWoCs
module CallstackSet :
Mopsa_utils.SetExtSig.S with type elt = Mopsa_utils.Callstack.callstack
Set of callstacks
val group_diagnostics :
diagnostic CheckMap.t RangeCallStackMap.t ->
CallstackSet.t RangeDiagnosticWoCsMap.t
Group diagnostics by their range and diagnostic kind
Add an assumption to a report
Add a global assumption to a report
Add a local assumption to a report
val map2zo_report :
(diagnostic -> diagnostic) ->
(diagnostic -> diagnostic) ->
(diagnostic -> diagnostic -> diagnostic) ->
report ->
report ->
report
val fold2zo_report :
(diagnostic -> 'b -> 'b) ->
(diagnostic -> 'b -> 'b) ->
(diagnostic -> diagnostic -> 'b -> 'b) ->
report ->
report ->
'b ->
'b
val exists2zo_report :
(diagnostic -> bool) ->
(diagnostic -> bool) ->
(diagnostic -> diagnostic -> bool) ->
report ->
report ->
bool