package mopsa
Install
dune-project
Dependency
Authors
Maintainers
Sources
md5=9f673f79708b44a7effb3b6bb3618d2c
sha512=cb91cb428e43a22f1abbcb8219710d0c10a5b3756d0da392d4084b3b3a6157350776c596983e63def344f617d39964e91f244f60c07958695ee5c8c809a9f0f4
doc/core/Core/All/index.html
Module Core.AllSource
include module type of struct include Ast.Semantic end
include module type of struct include Ast.Constant end
type constant = Ast.Constant.constant = ..Extensible constants
compare_constant c1 c2 provides a total order between any pair c1 and c2 of registered constants
val pp_constant : Stdlib.Format.formatter -> constant -> unitpp_constant fmt c pretty-prints a registered constant c with formatter fmt
Registration
val register_constant : constant Mopsa_utils.TypeExt.info -> unitregister_constant info registers a new constant with a comparison function info.compare and a pretty-printer info.print
val register_constant_compare : constant Mopsa_utils.TypeExt.compare -> unitregister_constant_compare compare registers a new comparison function for constants
val register_constant_pp : constant Mopsa_utils.TypeExt.print -> unitregister_constant_compare compare registers a new pretty-printer for constants
Common constants
include module type of struct include Ast.Expr end
type expr_kind = Ast.Expr.expr_kind = ..Extensible type of expression kinds
type expr = Ast.Expr.expr = {ekind : expr_kind;(*kind of the expression
*)etyp : Ast.Typ.typ;(*type of the expression
*)erange : Mopsa_utils.Location.range;(*location range of the expression
*)etrans : expr Ast.Semantic.SemanticMap.t;(*translations of the expression into other semantics
*)ehistory : expr list;(*History of preceding evaluations of the expression
*)
}Expressions
compare_expr e1 e2 implements a total order between expressions
val pp_expr : Stdlib.Format.formatter -> expr -> unitpp_expr fmt e pretty-prints expression e with format fmt
val etyp : expr -> Ast.Typ.typGet the type of an expression
val erange : expr -> Mopsa_utils.Location.rangeGet the location of an expression
val etrans : expr -> expr Ast.Semantic.SemanticMap.tGet the translation map of an expression
val mk_expr :
?etyp:Ast.Typ.typ ->
?etrans:expr Ast.Semantic.SemanticMap.t ->
?ehistory:expr list ->
expr_kind ->
Mopsa_utils.Location.range ->
exprConstruct an expression
val add_expr_translation : Ast.Semantic.semantic -> expr -> expr -> exprAdd a translation of an expression
val get_expr_translations : expr -> expr Ast.Semantic.SemanticMap.tGet all translations of an expression
val get_expr_translation : Ast.Semantic.semantic -> expr -> exprGet the translation of an expression into a given semantic
Get the ancestor expression verifying a predicate
Registration
val register_expr : expr Mopsa_utils.TypeExt.info -> unitregister_expr info registers new expressions with their comparison function info.compare and pretty-printer info.print
val register_expr_compare : expr Mopsa_utils.TypeExt.compare -> unitregister_expr_compare compare registers a new expression comparison
val register_expr_pp : expr Mopsa_utils.TypeExt.print -> unitregister_expr_compare compare registers a new expression printer
Some common expressions
Variable expressions
type expr_kind += | E_var of Ast.Var.var * Ast.Var.mode option(*optional access mode overloading the variable's access mode
*)
Variables
val mk_var :
Ast.Var.var ->
?mode:Ast.Var.mode option ->
Mopsa_utils.Location.range ->
exprCreate a variable expression
val var_mode : Ast.Var.var -> Ast.Var.mode option -> Ast.Var.modeGet the overloaded access mode of a variable
Heap addresses expressions
type expr_kind += | E_addr of Ast.Addr.addr * Ast.Var.mode option(*optional access mode overloading the address access mode
*)| E_alloc_addr of Ast.Addr.addr_kind * Ast.Var.mode
Heap addresses
val mk_addr :
Ast.Addr.addr ->
?etyp:Ast.Typ.typ ->
?mode:Ast.Var.mode option ->
Mopsa_utils.Location.range ->
exprCreate an address expression
val mk_alloc_addr :
?mode:Ast.Var.mode ->
Ast.Addr.addr_kind ->
Mopsa_utils.Location.range ->
exprCreate an allocation expression
Constant expressions
Constants
val mk_constant :
?etyp:Ast.Typ.typ ->
Ast.Constant.constant ->
Mopsa_utils.Location.range ->
exprCreate a constant expression
val mk_top : Ast.Typ.typ -> Mopsa_utils.Location.range -> exprCreate ⊤ expression of a given type
Unary expressions
Unary operator expressions
val mk_unop :
?etyp:Ast.Typ.typ ->
Ast.Operator.operator ->
expr ->
Mopsa_utils.Location.range ->
exprCreate a unary operator expression
val mk_not : expr -> Mopsa_utils.Location.range -> exprmk_not e range returns the negation of expression e using the operator Operator.O_log_not
Binary expressions
Binary operator expressions
val mk_binop :
?etyp:Ast.Typ.typ ->
expr ->
Ast.Operator.operator ->
expr ->
Mopsa_utils.Location.range ->
exprCreate a binary operator expression
Expressions containers
module ExprSet = Ast.Expr.ExprSetSets of expression
module ExprMap = Ast.Expr.ExprMapMaps of expressions
include module type of struct include Ast.Stmt end
type stmt_kind = Ast.Stmt.stmt_kind = ..Extensible kinds of statements
type stmt = Ast.Stmt.stmt = {skind : stmt_kind;(*kind of the statement
*)srange : Mopsa_utils.Location.range;(*location range of the statement
*)
}Statements
val mk_stmt : stmt_kind -> Mopsa_utils.Location.range -> stmtCreate a statement
val srange : stmt -> Mopsa_utils.Location.rangeGet the location range of a statement
val pp_stmt : Stdlib.Format.formatter -> stmt -> unitPretty-printer of statements
Registration
val register_stmt : stmt Mopsa_utils.TypeExt.info -> unitregister_stmt info registers a new statement by registering its compare function info.compare and pretty-printer info.print
val register_stmt_compare : stmt Mopsa_utils.TypeExt.compare -> unitRegister a comparison function for statements
val register_stmt_pp : stmt Mopsa_utils.TypeExt.print -> unitRegister a pretty-printer function for statements
Blocks
type block = stmt listBlocks are sequences of statements
val pp_block : Stdlib.Format.formatter -> block -> unitPretty-printer for blocks
Common statements
type stmt_kind += | S_program of Ast.Program.program * string list option(*Command-line arguments as given to Mopsa after
*)--
Programs
Assignments
val mk_assign :
Ast.Expr.expr ->
Ast.Expr.expr ->
Mopsa_utils.Location.range ->
stmtmk_assign lhs rhs range creates the assignment lhs = rhs;
Tests
val mk_assume : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmtCreate a test statement
type stmt_kind += | S_add of Ast.Expr.expr(*Add a dimension to the environment
*)| S_remove of Ast.Expr.expr(*Remove a dimension from the environment and invalidate all references to it
*)| S_invalidate of Ast.Expr.expr(*Invalidate all references to a dimension without removing it
*)| S_rename of Ast.Expr.expr * Ast.Expr.expr(*new
*)| S_forget of Ast.Expr.expr(*Forget a dimension by putting ⊤ (all possible values) in it. Note that the dimension is not removed
*)| S_project of Ast.Expr.expr list(*Project the environment on the given list of dimensions. All other dimensions are removed
*)| S_expand of Ast.Expr.expr * Ast.Expr.expr list(*Expand a dimension into a list of other dimensions. The expanded dimension is untouched
*)| S_fold of Ast.Expr.expr * Ast.Expr.expr list(*Fold a list of dimensions into a single one. The folded dimensions are removed
*)| S_block of stmt list * Ast.Var.var list(*local variables declared within the block
*)| S_breakpoint of string(*Trigger a breakpoint
*)
Dimensions
val mk_rename :
Ast.Expr.expr ->
Ast.Expr.expr ->
Mopsa_utils.Location.range ->
stmtUtility functions to create various statements for dimension management
val mk_rename_var :
Ast.Var.var ->
Ast.Var.var ->
Mopsa_utils.Location.range ->
stmtval mk_remove : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmtval mk_remove_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmtval mk_invalidate : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmtval mk_invalidate_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmtval mk_add : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmtval mk_add_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmtval mk_project : Ast.Expr.expr list -> Mopsa_utils.Location.range -> stmtval mk_project_vars : Ast.Var.var list -> Mopsa_utils.Location.range -> stmtval mk_forget : Ast.Expr.expr -> Mopsa_utils.Location.range -> stmtval mk_forget_var : Ast.Var.var -> Mopsa_utils.Location.range -> stmtval mk_expand :
Ast.Expr.expr ->
Ast.Expr.expr list ->
Mopsa_utils.Location.range ->
stmtval mk_expand_var :
Ast.Var.var ->
Ast.Var.var list ->
Mopsa_utils.Location.range ->
stmtval mk_fold :
Ast.Expr.expr ->
Ast.Expr.expr list ->
Mopsa_utils.Location.range ->
stmtval mk_fold_var :
Ast.Var.var ->
Ast.Var.var list ->
Mopsa_utils.Location.range ->
stmtval mk_breakpoint : string -> Mopsa_utils.Location.range -> stmtContainers of statements
module StmtSet = Ast.Stmt.StmtSetSets of statements
module StmtMap = Ast.Stmt.StmtMapMaps of statements
include module type of struct include Ast.Typ end
type typ = Ast.Typ.typ = ..Extensible types
val pp_typ : Stdlib.Format.formatter -> typ -> unitPretty-print a type
Registration
val register_typ : typ Mopsa_utils.TypeExt.info -> unitRegister a new type
val register_typ_compare : typ Mopsa_utils.TypeExt.compare -> unitRegister a new type comparison
val register_typ_pp : typ Mopsa_utils.TypeExt.print -> unitRegister a new type pretty-printer
Common types
include module type of struct include Ast.Program end
type prog_kind = Ast.Program.prog_kind = ..Extensible type of program kinds
type program = Ast.Program.program = {prog_kind : prog_kind;(*kind of the program
*)prog_range : Mopsa_utils.Location.range;(*program location
*)
}Programs
val pp_program : Stdlib.Format.formatter -> program -> unitPretty-printer for programs
Registration
val register_program : program Mopsa_utils.TypeExt.info -> unitregister_program info registers a new program kind by registering its comparison function info.compare and pretty-printer info.print
val register_program_compare : program Mopsa_utils.TypeExt.compare -> unitRegister a comparison function between programs
val register_program_pp : program Mopsa_utils.TypeExt.print -> unitRegister a pretty-printer for programs
include module type of struct include Ast.Frontend end
type frontend = Ast.Frontend.frontend = {lang : string;(*Language of the frontend
*)parse : string list -> Ast.Program.program;(*Parser function that translates a list of input source files into a Mopsa
*)Program.program
}Frontends
val register_frontend : frontend -> unitRegister a new frontend
val find_language_frontend : string -> frontendFind the frontend of a given language
include module type of struct include Ast.Operator end
type operator = Ast.Operator.operator = ..Extensible type of operators
val pp_operator : Stdlib.Format.formatter -> operator -> unitPretty-printer of operators
Registration
val register_operator : operator Mopsa_utils.TypeExt.info -> unitregister_operator info registers a new operator by registering its compare function info.compare and pretty-printer info.print
val register_operator_compare : operator Mopsa_utils.TypeExt.compare -> unitRegister a comparison function for operators
val register_operator_pp : operator Mopsa_utils.TypeExt.print -> unitRegister a pretty-printer for operators
Some common operators
type operator += | O_eq(*equality ==
*)| O_ne(*inequality !=
*)| O_lt(*less than <
*)| O_le(*less or equal <=
*)| O_gt(*greater than >
*)| O_ge(*greater or equal >=
*)| O_log_not(*logical negation
*)| O_log_or(*logical disjunction ||
*)| O_log_and(*logical conjunction &&
*)| O_log_xor(*logical strict disjonction xor
*)| O_cast(*type cast
*)
Common operators
val is_comparison_op : operator -> boolTest whether an operator is a comparison operator
val is_logic_op : operator -> boolTest whether an is a logical operator
include module type of struct include Ast.Var end
Access modes
type var_kind = Ast.Var.var_kind = ..Extensible kind of variables
type mode = Ast.Var.mode = Access mode of a variable
val pp_mode : Stdlib.Format.formatter -> mode -> unitPretty-print an access mode
Variables
type var = Ast.Var.var = {vname : string;(*unique name of the variable
*)vkind : var_kind;(*kind the variable
*)vtyp : Ast.Typ.typ;(*type of the variable
*)vmode : mode;(*access mode of the variable
*)vsemantic : Ast.Semantic.semantic;(*semantic of the variable
*)
}Variables
val vname : var -> stringAccessor function to the fields of a variable
val vtyp : var -> Ast.Typ.typval vsemantic : var -> Ast.Semantic.semanticval mkv :
string ->
var_kind ->
?mode:mode ->
?semantic:Ast.Semantic.semantic ->
Ast.Typ.typ ->
varCreate a variable with a unique name, a kind, a type and an access mode (STRONG if not given)
val pp_var : Stdlib.Format.formatter -> var -> unitPretty-print a variable
Registration
val register_var : var Mopsa_utils.TypeExt.info -> unitRegister a new kind of variables
val register_var_compare : var Mopsa_utils.TypeExt.compare -> unitRegister a new variable comparison
val register_var_pp : var Mopsa_utils.TypeExt.print -> unitRegister a new variable pretty-printer
Common variables
type var_kind += | V_uniq of string * int(*Unique ID
*)| V_tmp of int(*Unique ID
*)| V_var_attr of var * string(*Attribute
*)| V_range_attr of Mopsa_utils.Location.range * string(*Attribute
*)
val mk_uniq_var : string -> int -> ?mode:mode -> Ast.Typ.typ -> varCreate a unique variable
val mk_fresh_uniq_var : string -> ?mode:mode -> Ast.Typ.typ -> unit -> varCreate a fresh variable with a fresh ID
val mktmp : ?typ:Ast.Typ.typ -> ?mode:mode -> unit -> varCreate a fresh temporary variable
val mk_attr_var :
var ->
string ->
?mode:mode ->
?semantic:Ast.Semantic.semantic ->
Ast.Typ.typ ->
varmk_attr_var v a t creates a variable representing an attribute a of another variable v
val mk_range_attr_var :
Mopsa_utils.Location.range ->
string ->
?mode:mode ->
?semantic:Ast.Semantic.semantic ->
Ast.Typ.typ ->
varmk_range_attr_var r a t creates a variable representing an attribute a of a program location r
Containers for variables
module VarSet = Ast.Var.VarSetSets of variables
module VarMap = Ast.Var.VarMapMaps of variables
Deprecated
val get_orig_vname : var -> stringinclude module type of struct include Ast.Addr end
type addr_kind = Ast.Addr.addr_kind = ..Kind of heap addresses, used to store extra information.
val addr_kind_pp_chain :
(Stdlib.Format.formatter -> addr_kind -> unit) Stdlib.refval pp_addr_kind : Stdlib.Format.formatter -> addr_kind -> unitval register_addr_kind : addr_kind Mopsa_utils.TypeExt.info -> unittype addr_partitioning = Ast.Addr.addr_partitioning = ..Addresses are grouped by static criteria to make them finite
val addr_partitioning_compare_chain :
(addr_partitioning -> addr_partitioning -> int) Stdlib.refval addr_partitioning_pp_chain :
(Stdlib.Format.formatter -> addr_partitioning -> unit) Stdlib.refval pp_addr_partitioning_hash :
Stdlib.Format.formatter ->
addr_partitioning ->
unitval pp_addr_partitioning :
?full:bool ->
Stdlib.Format.formatter ->
addr_partitioning ->
unitPrint a partitioning policy. Flag full overloads the option opt_hash_addr and displays the full partitioning string (not its hash, which is useful for creating unique names of addresses)
val pp_addr_partitioning_full :
Stdlib.Format.formatter ->
addr_partitioning ->
unitval compare_addr_partitioning : addr_partitioning -> addr_partitioning -> intval register_addr_partitioning :
addr_partitioning Mopsa_utils.TypeExt.info ->
unittype addr = Ast.Addr.addr = {addr_kind : addr_kind;(*Kind of the address.
*)addr_partitioning : addr_partitioning;(*Partitioning policy of the address
*)addr_mode : Ast.Var.mode;(*Assignment mode of address (string or weak)
*)
}Heap addresses.
val pp_addr : Stdlib.Format.formatter -> addr -> unitval addr_uniq_name : addr -> stringGet the unique name of an address. This is safer and faster than calling Format.asprintf "%s" pp_addr a when opt_hash_addr is set.
val addr_mode : addr -> Ast.Var.mode option -> Ast.Var.modeAddress variables
val mk_addr_attr : addr -> string -> Ast.Typ.typ -> Ast.Var.varinclude module type of struct include Ast.Visitor end
type parts = Ast.Visitor.parts = {exprs : Ast.Expr.expr list;(*sub-expressions
*)stmts : Ast.Stmt.stmt list;(*sub-statements
*)
}Parts of a statement/expression
val structure_of_expr : Ast.Expr.expr -> Ast.Expr.expr structureGet the structure of an expression
val structure_of_stmt : Ast.Stmt.stmt -> Ast.Stmt.stmt structureGet the structure of a statement
val leaf : 'a -> 'a structureVisitor for leaf statements/expressions that have no sub-elements
Registration
type 'a visit_info = 'a Ast.Visitor.visit_info = {compare : 'a Mopsa_utils.TypeExt.compare;(*Comparison function for
*)'aprint : 'a Mopsa_utils.TypeExt.print;(*Pretty-printer for
*)'a'visit : ('a -> 'a structure) -> 'a -> 'a structure;(*Visitor for
*)'a
}Registration descriptor for visitors
val register_expr_with_visitor : Ast.Expr.expr visit_info -> unitRegister an expression with its visitor
val register_expr_visitor :
((Ast.Expr.expr -> Ast.Expr.expr structure) ->
Ast.Expr.expr ->
Ast.Expr.expr structure) ->
unitRegister a visitor of an expression
val register_stmt_with_visitor : Ast.Stmt.stmt visit_info -> unitRegister a statement with its visitor
val register_stmt_visitor :
((Ast.Stmt.stmt -> Ast.Stmt.stmt structure) ->
Ast.Stmt.stmt ->
Ast.Stmt.stmt structure) ->
unitRegister a visitor of a statement
Visiting iterators
type 'a visit_action = 'a Ast.Visitor.visit_action = Actions of a visiting iterator
val map_expr :
(Ast.Expr.expr -> Ast.Expr.expr visit_action) ->
(Ast.Stmt.stmt -> Ast.Stmt.stmt visit_action) ->
Ast.Expr.expr ->
Ast.Expr.exprmap_expr fe fs e transforms the expression e into a new one by applying visitor action fe and fs on its sub-expression and sub-statements respectively
val map_stmt :
(Ast.Expr.expr -> Ast.Expr.expr visit_action) ->
(Ast.Stmt.stmt -> Ast.Stmt.stmt visit_action) ->
Ast.Stmt.stmt ->
Ast.Stmt.stmtSimilar to map_expr but on statements
val fold_expr :
('a -> Ast.Expr.expr -> 'a visit_action) ->
('a -> Ast.Stmt.stmt -> 'a visit_action) ->
'a ->
Ast.Expr.expr ->
'afold_expr fe fs e folds the accumulated result of visitors fe and fs on the structure of expression e
val fold_stmt :
('a -> Ast.Expr.expr -> 'a visit_action) ->
('a -> Ast.Stmt.stmt -> 'a visit_action) ->
'a ->
Ast.Stmt.stmt ->
'aSimilar to fold_expr but on statements
val fold_map_expr :
('a -> Ast.Expr.expr -> ('a * Ast.Expr.expr) visit_action) ->
('a -> Ast.Stmt.stmt -> ('a * Ast.Stmt.stmt) visit_action) ->
'a ->
Ast.Expr.expr ->
'a * Ast.Expr.exprCombination of map and fold for expressions
val fold_map_stmt :
('a -> Ast.Expr.expr -> ('a * Ast.Expr.expr) visit_action) ->
('a -> Ast.Stmt.stmt -> ('a * Ast.Stmt.stmt) visit_action) ->
'a ->
Ast.Stmt.stmt ->
'a * Ast.Stmt.stmtCombination of map and fold for statements
val exists_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
boolval for_all_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
boolval exists_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
boolval for_all_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
boolval exists_child_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
boolval for_all_child_expr :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Expr.expr ->
boolval exists_child_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
boolval for_all_child_stmt :
(Ast.Expr.expr -> bool) ->
(Ast.Stmt.stmt -> bool) ->
Ast.Stmt.stmt ->
boolUtility functions
val is_leaf_expr : Ast.Expr.expr -> boolTest whether an expression is a leaf expression
val is_atomic_expr : Ast.Expr.expr -> boolTest whether an expression has no sub-statement
val is_atomic_stmt : Ast.Stmt.stmt -> boolTest whether a statement has no sub-statement
val expr_vars : Ast.Expr.expr -> Ast.Var.var listGet all variables present in an expression
val stmt_vars : Ast.Stmt.stmt -> Ast.Var.var listGet all variables present in a statement
val is_var_in_expr : Ast.Var.var -> Ast.Expr.expr -> boolCheck whether a variable appears in an expression
val is_var_in_stmt : Ast.Var.var -> Ast.Stmt.stmt -> boolCheck whether a variable appears in a statement
Deprecated
val fold_sub_expr :
('a -> Ast.Expr.expr -> 'a visit_action) ->
('a -> Ast.Stmt.stmt -> 'a visit_action) ->
'a ->
Ast.Expr.expr ->
'ainclude module type of struct include Alarm end
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) ->
unitRegister 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.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 ->
alarmCreate 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) ->
unitRegister a comparison function for alarms
val register_alarm_pp :
((Stdlib.Format.formatter -> alarm_kind -> unit) ->
Stdlib.Format.formatter ->
alarm_kind ->
unit) ->
unitRegister 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) ->
unitRegister a join function for alarms
type alarm_info = Alarm.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 = Alarm.AlarmSetSet of alarms
Kind of a diagnostic
type 'a diagnostic_ = 'a Alarm.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 ->
diagnosticCreate 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 ->
diagnosticCreate a diagnostic that says that a check maybe unsafe
val mk_unreachable_diagnostic :
check ->
Mopsa_utils.Callstack.callstack ->
Mopsa_utils.Location.range ->
diagnosticCreate 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 = Alarm.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
type assumption = Alarm.assumption = {assumption_scope : assumption_scope;assumption_kind : assumption_kind;
}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 = Alarm.RangeMapmodule RangeCallStackMap = Alarm.RangeCallStackMapmodule CheckMap = Alarm.CheckMapmodule AssumptionSet = Alarm.AssumptionSettype report = Alarm.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 ->
diagnosticfind_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 = Alarm.RangeDiagnosticWoCsMapmodule CallstackSet = Alarm.CallstackSetSet of callstacks
val group_diagnostics :
diagnostic CheckMap.t RangeCallStackMap.t ->
CallstackSet.t RangeDiagnosticWoCsMap.tGroup 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 ->
reportval fold2zo_report :
(diagnostic -> 'b -> 'b) ->
(diagnostic -> 'b -> 'b) ->
(diagnostic -> diagnostic -> 'b -> 'b) ->
report ->
report ->
'b ->
'bval exists2zo_report :
(diagnostic -> bool) ->
(diagnostic -> bool) ->
(diagnostic -> diagnostic -> bool) ->
report ->
report ->
boolinclude module type of struct include Context end
Key to access an element in the context
The context
mem_ctx k ctx returns true when an element at key k is in the context ctx.
find_ctx k ctx returns the element at key k in the context ctx. Raises Not_found if no element is found.
find_ctx k ctx returns the element of the key k in the context ctx. Returns None if no element is found.
add_ctx k v ctx add element v at key k in the context ctx. The previous element is overwritten if present.
add_ctx k v ctx removes the element at key k in the context ctx. If key k was not in ctx, ctx is returned unchanged.
Print a context
type ctx_pool = Context.ctx_pool = {ctx_pool_equal : 'a 'v 'w. ('a, 'v) ctx_key -> ('a, 'w) ctx_key -> ('v, 'w) Mopsa_utils.Eq.eq option;ctx_pool_print : 'a 'v. (Print.printer -> 'a -> unit) -> Stdlib.Format.formatter -> ('a, 'v) ctx_key -> 'v -> unit;
}Pool registered keys
type ctx_info = Context.ctx_info = {ctx_equal : 'a 'v 'w. ctx_pool -> ('a, 'v) ctx_key -> ('a, 'w) ctx_key -> ('v, 'w) Mopsa_utils.Eq.eq option;ctx_print : 'a 'v. ctx_pool -> (Print.printer -> 'a -> unit) -> Stdlib.Format.formatter -> ('a, 'v) ctx_key -> 'v -> unit;
}Registration information for a new key
Generate a new key
Key for storing the callstack
val bind :
('a Cases.case -> 'b Flow.flow -> ('b, 'c) Cases.cases) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.casesval (>>=) :
('a, 'b) Cases.cases ->
('b Cases.case -> 'a Flow.flow -> ('a, 'c) Cases.cases) ->
('a, 'c) Cases.casesval bind_opt :
('a Cases.case -> 'b Flow.flow -> ('b, 'c) Cases.cases option) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.cases optionval (>>=?) :
('a, 'b) Cases.cases ->
('b Cases.case -> 'a Flow.flow -> ('a, 'c) Cases.cases option) ->
('a, 'c) Cases.cases optionval bind_result :
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.casesval (>>$) :
('a, 'b) Cases.cases ->
('b -> 'a Flow.flow -> ('a, 'c) Cases.cases) ->
('a, 'c) Cases.casesval bind_result_opt :
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases option) ->
('b, 'a) Cases.cases ->
('b, 'c) Cases.cases optionval (>>$?) :
('a, 'b) Cases.cases ->
('b -> 'a Flow.flow -> ('a, 'c) Cases.cases option) ->
('a, 'c) Cases.cases optionval bind_list :
'a list ->
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases) ->
'b Flow.flow ->
('b, 'c list) Cases.casesval bind_list_opt :
'a list ->
('a -> 'b Flow.flow -> ('b, 'c) Cases.cases option) ->
'b Flow.flow ->
('b, 'c list) Cases.cases optionval (>>%?) :
'a Post.post ->
('a Flow.flow -> ('a, 'b) Cases.cases option) ->
('a, 'b) Cases.cases optioninclude module type of struct include Effect end
Effects
Fold over the statements in the effect
Effect trees
Effects are presented as binary trees. Each node of the tree is associated to a domain in the abstraction and stores the statements executed by the domain when computing a post-condition.
Note that this representation is also useful when we have an abstraction DAG (i.e. when there are shared domains) thanks to the compose (stack) operator:
A x B \___/ | C
is represented as:
o / \ x C / \ A B
mk_teffect effect left right creates an effect tree with a root containing effect and having left and right as the two sub-trees
get_right_teffect te returns the right sub-tree of te
get_log_stmts te returns the effect at the root node of te
get_left_teffect left te sets left as the left sub-tree of te
get_right_teffect right te sets right as the right sub-tree of te
map_left_teffect f te is equivalent to set_left_teffect (f (get_left_teffect te)) te
map_right_teffect f te is equivalent to set_right_teffect (f (get_right_teffect te)) te
add_stmt_to_teffect stmt teffect adds stmt to the the effects of the root no of te
val merge_teffect :
(effect -> effect) ->
(effect -> effect) ->
(effect -> effect -> effect) ->
teffect ->
teffect ->
teffectmerge_teffect f1 f2 f te1 te2 combines te1 and te2
concat_teffect old recent puts effects in old before those in recent
merge_teffect te1 te2 computes the effects of two intersected post-states
merge_teffect te1 te2 computes the effects of two joined post-states
Fold over the statements in the effects tree
Generic merge
type var_effect = Effect.var_effect = {modified : Ast.Var.VarSet.t;removed : Ast.Var.VarSet.t;
}Effect of a statement in terms of modified and removed variables
val generic_merge :
add:(Ast.Var.var -> 'b -> 'a -> 'a) ->
find:(Ast.Var.var -> 'a -> 'b) ->
remove:(Ast.Var.var -> 'a -> 'a) ->
?custom:(Ast.Stmt.stmt -> var_effect option) ->
('a * effect) ->
('a * effect) ->
'a * 'aGeneric merge operator. generic_merge ~add ~find ~remove ~custom (a1,e1) (a2,e2) applies a generic merge of states a1 and a2:
- It searches for modified variables in one state's effects, gets their value using
findand adds them to the other state usingadd. - It searches for removed variables in one state's effects and remove them from the other state using
remove. This function handles common statements (assign,assume,add,remove,fold,expand and rename). Other statements can be handled using thecustomfunction that returns thevar_effectof a given statement.
include module type of struct include Query end
Extensible type of queries
val join_query :
?ctx:'a Context.ctx option ->
?lattice:'a Lattice.lattice option ->
('a, 'r) query ->
'r ->
'r ->
'rJoin two queries
val meet_query :
?ctx:'a Context.ctx option ->
?lattice:'a Lattice.lattice option ->
('a, 'r) query ->
'r ->
'r ->
'rMeet two queries
Registration
****************
type query_pool = Query.query_pool = {pool_join : 'a 'r. ('a, 'r) query -> 'r -> 'r -> 'r;pool_meet : 'a 'r. ('a, 'r) query -> 'r -> 'r -> 'r;
}Pool of registered queries
type query_info = Query.query_info = {join : 'a 'r. query_pool -> ('a, 'r) query -> 'r -> 'r -> 'r;meet : 'a 'r. query_pool -> ('a, 'r) query -> 'r -> 'r -> 'r;
}Registraction info for new queries
Register a new query
type lattice_query_pool = Query.lattice_query_pool = {pool_join : 'a 'r. 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;pool_meet : 'a 'r. 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;
}Pool of registered lattice queries. Lattice queries are queries that return elements of the global abstract state lattice. Join/meet operators are enriched with the lattice and the context so that we can compute join/meet over the abstract elements.
type lattice_query_info = Query.lattice_query_info = {join : 'a 'r. lattice_query_pool -> 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;meet : 'a 'r. lattice_query_pool -> 'a Context.ctx -> 'a Lattice.lattice -> ('a, 'r) query -> 'r -> 'r -> 'r;
}Registration info for new lattice queries
Register a new lattice query
Common queries
******************
type query += | Q_defined_variables : string option -> ('a, Ast.Var.var list) query(*Extract the list of defined variables, in a given function call site, or in all scopes
*)| Q_allocated_addresses : ('a, Ast.Addr.addr list) query(*Query to extract the list of addresses allocated in the heap
*)| Q_variables_linked_to : Ast.Expr.expr -> ('a, Ast.Var.VarSet.t) query(*Query to extract the auxiliary variables related to an expression
*)
include module type of struct include Token end
Flow tokens are used to distinguish between different control flows
Register a new token with its compare and print functions
include module type of struct include Ast.Semantic end
val pp_semantic : Stdlib.Format.formatter -> semantic -> unitval any_semantic : semanticval is_any_semantic : semantic -> boolmodule SemanticSet = Ast.Semantic.SemanticSetmodule SemanticMap = Ast.Semantic.SemanticMapinclude module type of struct include Route end
type route = Route.route = | Below of domain(*Sub-tree below a domain
*)| Semantic of Ast.Semantic.semantic(*Sub-tree identified by a semantic
*)
Routes
module DomainSet = Route.DomainSetRouting table providing the domains that are part of a route
Empty routing table
Resolve a route into domains
Add a route between a route and a domain
Add a set of routing_table linking a route and a set of domains
Get all routing_table in a routing table
Join two routing_table table
Print a routing table
include module type of struct include Lattice end
Signature of a lattice module.
type 'a lattice = 'a Lattice.lattice = {bottom : 'a;top : 'a;is_bottom : 'a -> bool;subset : 'a Context.ctx -> 'a -> 'a -> bool;join : 'a Context.ctx -> 'a -> 'a -> 'a;meet : 'a Context.ctx -> 'a -> 'a -> 'a;widen : 'a Context.ctx -> 'a -> 'a -> 'a;merge : 'a -> ('a * Effect.teffect) -> ('a * Effect.teffect) -> 'a;print : Print.printer -> 'a -> unit;
}Lattice operators
include module type of struct include Id end
type witness = Id.witness = {eq : 'a 'b. 'a id -> 'b id -> ('a, 'b) Mopsa_utils.Eq.eq option;
}type witness_chain = Id.witness_chain = {eq : 'a 'b. witness -> 'a id -> 'b id -> ('a, 'b) Mopsa_utils.Eq.eq option;
}Equality witness of an identifier
Register a new descriptor
Equality witness of identifiers
Generator of a new domain identifier
Generator of a new identifier for stateless domains
Generator of a new value identifier
include module type of struct include Manager end
Managers
type ('a, 't) man = ('a, 't) Manager.man = {lattice : 'a Lattice.lattice;(*Access to lattice operators on the toplevel abstract element
*)'a.get : 'a -> 't;(*Returns the domain's abstract element
*)'t.set : 't -> 'a -> 'a;(*Sets the domain's abstract element
*)'t.exec : ?route:Route.route -> Ast.Stmt.stmt -> 'a Flow.flow -> 'a Post.post;(*
*)man.exec stmt flowexecutesstmtinflowand returns the post state.eval : ?route:Route.route -> ?translate:Ast.Semantic.semantic -> ?translate_when:(Ast.Semantic.semantic * (Ast.Expr.expr -> bool)) list -> Ast.Expr.expr -> 'a Flow.flow -> 'a Eval.eval;(*man.eval expr flowevaluatesexprinflowand returns the result expression.There are two kinds of evaluations: within the same semantic (simplifications), or to another semantic (translations). Calling
*)man.eval expr flowperforms both kinds of evaluations. The resulte'ofman.eval expr flowis a simplification ofewithin the same semantic. To retrieve a translation to another semantic, one can use the?translateparameter:man.eval expr flow ~translate:semanticis a translation of the simplification ofeinsemantic. A common use case is to translate expressions to Universal withman.eval expr flow ~translate:"Universal". It is possible to control when the translation is applied with?translate_when.ask : 'r. ?route:Route.route -> ('a, 'r) Query.query -> 'a Flow.flow -> ('a, 'r) Cases.cases;(*
*)man.ask query flowperforms a query to other domains. If no domain can answer the query,man.ask query flowresults in a runtime error.print_expr : ?route:Route.route -> 'a Flow.flow -> Print.printer -> Ast.Expr.expr -> unit;(*
*)man.print_expr flowis the expression printer for the type'a.get_effects : Effect.teffect -> Effect.teffect;(*Gets the effects tree.
*)set_effects : Effect.teffect -> Effect.teffect -> Effect.teffect;(*Sets the effect tree.
*)
}Managers provide access to full analyzer.
'a is the type of the toplevel abstract element, and 't is the type of local abstract element (that is, the type of the domain that calls the manager).
include module type of struct include Print end
Print objects
Symbols for printing maps, lists and sets
Structured print objects
type print_object = Print.print_object = | Empty| Bool of bool| Int of Z.t| Float of float| String of string| Var of Ast.Var.var| Map of (print_object, print_object) map * symbols| List of print_object list * symbols| Set of print_object set * symbols
Printers
Printers encapsulate the structured objects to print along the history of printed expression
Get the structured print object of a printer
Get the expressions that were already printed
Mark an expression as printed
Check whether an expression was already printed
Print paths
type print_selector = Print.print_selector = | Key of string| Index of int| Obj of print_object
Selectors of print objects
Path of a print object
find_print_object path obj returns the object placed at path in obj
match_print_object_keys re obj slices obj to paths containing keys that match re
Generic print functions
pprint ~path:p printer o prints object o at path p in printer.
pbox f x returns a boxed object created by f when applied to x. It is equivalent to
let printer = empty_printer () in
f printer x;
get_printed_object printerfbox fmt returns a string object of a formatted value
sprint f x returns the string representing the boxed object pbox f x
fkey fmt returns a key selector with a formatted string
pkey f x returns a key selector with a printed string
Typed print functions
Print a string object
Print a boolean object
Print an integer object
Print an integer object
Print a float object
Print a variable
val pp_list :
?path:print_path ->
?lopen:string ->
?lsep:string ->
?lclose:string ->
(printer -> 'a -> unit) ->
printer ->
'a list ->
unitpp_list ~path:p f printer l prints a list l at path p by boxing f on every element of l
val pp_obj_list :
?path:print_path ->
?lopen:string ->
?lsep:string ->
?lclose:string ->
printer ->
print_object list ->
unitpp_obj_list ~path:p printer l prints a list of objects at path p. Useful for printing heterogenous lists.
val pp_map :
?path:print_path ->
?mopen:string ->
?msep:string ->
?mclose:string ->
?mbind:string ->
(printer -> 'k -> unit) ->
(printer -> 'v -> unit) ->
printer ->
('k * 'v) list ->
unitpp_smap ~path:p fk fv printer l prints a map from a list l of pairs of keys and values. Keys are boxed with function fk and values with function fv.
val pp_mapi :
?path:print_path ->
?mopen:string ->
?msep:string ->
?mclose:string ->
?mbind:string ->
(printer -> 'k -> unit) ->
(printer -> ('k * 'v) -> unit) ->
printer ->
('k * 'v) list ->
unitval pp_obj_map :
?path:print_path ->
?mopen:string ->
?msep:string ->
?mclose:string ->
?mbind:string ->
printer ->
(print_object * print_object) list ->
unitpp_obj_smap ~path:p printer l prints a map from a list of pairs of print objects
val pp_obj_set :
?path:print_path ->
?sopen:string ->
?ssep:string ->
?sclose:string ->
printer ->
print_object set ->
unitpp_obj_set ~path:p printer l prints a set of objects at path p. Useful for printing heterogenous sets.
val pp_set :
?path:print_path ->
?sopen:string ->
?ssep:string ->
?sclose:string ->
(printer -> 'a -> unit) ->
printer ->
'a set ->
unitpp_set ~path:p f printer l prints a set from a list l at path p by boxing f on every element of l
Format
Pretty-print a printer objct
Pretty-print the printer output in a format string
Convert a printer function into a format function
val unformat :
?path:print_path ->
(Stdlib.Format.formatter -> 'a -> unit) ->
printer ->
'a ->
unitConvert a format function into a printer
JSON
Convert a printer object to JSON
Convert JSON to a printer object
include module type of struct include Avalue end
type avalue_pool = Avalue.avalue_pool = {pool_typ : 'v. 'v avalue_kind -> Ast.Typ.typ;pool_bottom : 'v. 'v avalue_kind -> 'v;pool_top : 'v. 'v avalue_kind -> 'v;pool_join : 'v. 'v avalue_kind -> 'v -> 'v -> 'v;pool_meet : 'v. 'v avalue_kind -> 'v -> 'v -> 'v;pool_compare : 'v 'w. 'v avalue_kind -> 'v -> 'w avalue_kind -> 'w -> int;pool_print : 'v. 'v avalue_kind -> Stdlib.Format.formatter -> 'v -> unit;
}type avalue_info = Avalue.avalue_info = {typ : 'v. avalue_pool -> 'v avalue_kind -> Ast.Typ.typ;bottom : 'v. avalue_pool -> 'v avalue_kind -> 'v;top : 'v. avalue_pool -> 'v avalue_kind -> 'v;join : 'v. avalue_pool -> 'v avalue_kind -> 'v -> 'v -> 'v;meet : 'v. avalue_pool -> 'v avalue_kind -> 'v -> 'v -> 'v;compare : 'v 'w. avalue_pool -> 'v avalue_kind -> 'v -> 'w avalue_kind -> 'w -> int;print : 'v. avalue_pool -> 'v avalue_kind -> Stdlib.Format.formatter -> 'v -> unit;
}include module type of struct include Utils end
val exec_cleaner :
Ast.Stmt.stmt ->
('a, 'b) Manager.man ->
'a Flow.flow ->
('a, unit) Cases.casesval assume :
Ast.Expr.expr ->
?route:Route.route ->
?translate:Ast.Semantic.semantic ->
fthen:('a Flow.flow -> ('a, 'b) Cases.cases) ->
felse:('a Flow.flow -> ('a, 'b) Cases.cases) ->
?fboth:('a Flow.flow -> 'a Flow.flow -> ('a, 'b) Cases.cases) ->
?fnone:('a Flow.flow -> 'a Flow.flow -> ('a, 'b) Cases.cases) ->
?eval:bool ->
('a, 'c) Manager.man ->
'a Flow.flow ->
('a, 'b) Cases.casesval switch :
(Ast.Expr.expr list * ('a Flow.flow -> ('a, 'r) Cases.cases)) list ->
?route:Route.route ->
('a, 'b) Manager.man ->
'a Flow.flow ->
('a, 'r) Cases.casesval map_env :
Token.token ->
('t -> 't) ->
('a, 't) Manager.man ->
'a Flow.flow ->
'a Flow.flowval env_exec :
('a Flow.flow -> 'a Post.post) ->
'a Context.ctx ->
('a, 't) Manager.man ->
'a ->
'aval ask_and_reduce_cases :
(('a, 'b) Query.query -> 'c -> ('d, 'b) Cases.cases) ->
('a, 'b) Query.query ->
?bottom:(unit -> 'b) ->
'c ->
'bval ask_and_reduce_list :
(('a, 'b) Query.query -> 'c -> ('d * 'b) list) ->
('a, 'b) Query.query ->
?bottom:(unit -> 'b) ->
'c ->
'bval ask_and_reduce :
(('a, 'b) Query.query -> 'c -> ('d, 'b) Cases.cases) ->
('a, 'b) Query.query ->
?bottom:(unit -> 'b) ->
'c ->
'bval find_var_by_name :
?function_scope:string option ->
string ->
('a, 'b) Manager.man ->
'a Flow.flow ->
Ast.Var.varval pp_vars_info :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
Ast.Var.var list ->
unitval pp_vars_info_by_name :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
string list ->
unitval pp_expr_vars_info :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
Ast.Expr.expr ->
unitval pp_stmt_vars_info :
('a, 'b) Manager.man ->
'a Flow.flow ->
Stdlib.Format.formatter ->
Ast.Stmt.stmt ->
unit