The specification automata language used here is similar to the BLAST Query Language.
Each specification (Specification) consists of one or more automata (Automaton), which alternatively can be presented as an assertion (Assertion).
Each automaton is defined by the following attributes:
- unique automaton identifier;
- type of automaton (OBSERVER or CONTROL);
- automata variables (LocalDefs);
- initial automaton state identifier (InitDef);
- automaton states (StateDefs).
Each automaton state contains the following information:
- state name;
- whether it is a target (error) state or not (StateTypeDef);
- whether it is a nondeterministic state or not (StateNonDetDef);
- automaton transitions (Transitions).
Each automaton transition is determined by:
- trigger (Trigger), which is a boolean expression;
- list of assertions (Assertions), which are checked, if a trigger is evaluated as true;
- list of actions (Actions), which are executed, if assertions are held;
- assumption (Assume), which is a C-expression, that is passed to the other CPAs for evaluation after actions execution;
- identifier of the state, in which automaton will transfer, if assumption is evaluated as true (Goto).
The semantics of the operations are presented in the next section.
The full grammar is presented in the parser.cup
file.
Here is a simplified version without actions:
Specification ::= Automaton Specification | Assertion ; Specification |
Automaton ::= OBSERVER Body | CONTROL Body | Body
Body ::= AUTOMATON IDENTIFIER LocalDefs InitDef StateDefs END AUTOMATON
InitDef ::= INITIAL STATE IDENTIFIER ;
LocalDefs ::= LocalDef LocalDefs |
LocalDef ::=
LOCAL IDENTIFIER IDENTIFIER ;
| LOCAL IDENTIFIER < IDENTIFIER > IDENTIFIER ;
| LOCAL IDENTIFIER < IDENTIFIER > IDENTIFIER = SQUAREEXPR ;
| LOCAL IDENTIFIER IDENTIFIER = ConstantInt ;
StateDefs ::= StateDef StateDefs |
StateDef ::= StateTypeDef STATE StateNonDetDef IDENTIFIER : Transitions
StateTypeDef ::= TARGET |
StateNonDetDef ::= USEFIRST | USEALL |
Transitions ::= Transition Transitions |
Transition ::= Trigger -> Assertions Assume Actions Goto ;
Trigger ::= Bool
Assertions ::= Assertion Assertions |
Assertion ::= ASSERT Bool
Assume ::= ASSUME CURLYEXPR |
Actions ::= Action Actions |
Goto ::= GOTO IDENTIFIER | ERROR | ERROR ( STRING_LITERAL ) | STOP | BREAK
Action ::=
DO IDENTIFIER = InnerInt
| DO IDENTIFIER SQUAREEXPR = SetValue
| PRINT PrintArguments
| MODIFY ( IDENTIFIER , STRING_LITERAL )
SetValue ::= TRUE | FALSE
PrintArguments ::= Expression PrintArguments |
Int ::= ConstantInt | ( Int ) | IDENTIFIER | InnerInt + InnerInt | InnerInt - InnerInt
InnerInt ::= Int | EVAL ( IDENTIFIER , STRING_LITERAL )
ConstantInt ::= INTEGER_LITERAL
Bool ::=
TRUE
| FALSE
| ! Bool
| ( Bool )
| InnerInt == InnerInt
| InnerInt != InnerInt
| Bool == Bool
| Bool != Bool
| Bool && Bool
| Bool || Bool
| MATCH STRING_LITERAL
| MATCH CURLYEXPR
| MATCH SQUAREEXPR
| MATCH LABEL STRING_LITERAL
| MATCH LABEL SQUAREEXPR
| MATCH ASSERT
| MATCH EXIT
| MATCH ENTRY
| MATCH FUNCTIONCALL STRING_LITERAL
| CHECK ( IDENTIFIER , STRING_LITERAL )
| CHECK ( STRING_LITERAL )
| CHECK ( IS_TARGET_STATE )
| COVERS_LINES ( Integers )
Integers ::= ConstantInt Integers |
Expression ::=
Int
| Bool
| STRING_LITERAL
| EVAL ( IDENTIFIER , STRING_LITERAL )
IDENTIFIER ::= LETTER [DIGIT | LETTER]*
LETTER ::= _$a-zA-Z
DIGIT ::= 0-9
STRING_LITERAL ::= " [^"\n\r]* "
INTEGER_LITERAL ::= 0 | 1-9 DIGIT*
CURLYEXPR ::= { [^{}\n\r]* }
SQUAREEXPR ::= [ [^[]\n\r]* ]
Specification automata represent a property, which can be expressed as a temporal logic formula, and thus indicate a set of correct program executions, for which this formula is evaluated as true. A property is held in a program, if all possible program executions are included into a corresponding set of correct program executions.
CPAchecker creates a CPA for each specification automaton depending on its type.
ObserverAutomatonCPA
is used if automaton type is OBSERVER, and ControlAutomatonCPA
is used if automaton type is CONTROL.
Observer automaton cannot modify other CPAs (i.e. it cannot use keywords MODIFY and STOP).
By default control automaton is used.
This CPA uses MergeSepOperator, StopSepOperator, BreakOnTargetsPrecisionAdjustment and FlatLatticeDomain. On transfer relation computation this CPA creates a new AutomatonState based on current CFA edge, automaton transitions and other CPA states. If a new state is error (target) state or transition assertion is violated, then automaton CPA sends a BREAK signal to other CPAs. If property is represented as several specification automata, then each of them will be transformed into a separated CPA.
More information about automaton CPA can be found in the third section of the paper On-the-Fly Decomposition of Specifications in Software Model Checking.
Automata variables are defined in the LocalDefs section, then can be read from the Bool sections (which can be part of sections Trigger, Assertions and Actions) and the Assume sections, and can be modified in the Actions section.
Supported variables types are int
and set
.
In order to access automata variable value from the Assume section one should add "$$" as a prefix to the variable name (for example, expression $$var
is used to read value of the automaton variable var
).
Represents an integer number.
Declaration:
LOCAL int var_name;
or
LOCAL int var_name = int_const;
where int_const
corresponds to INTEGER_LITERAL in grammar (which is a natural number or zero). If int_const
is not specified, then variable value is set to zero.
Integer variable returns its value on access, and changes its value on modification.
Represents a set of some elements.
Declaration:
LOCAL set var_name <elem_type>;
or
LOCAL set var_name <elem_type> = set_const;
where elem_type
is the type of set elements, set_const
is the initial set value.
The type of set elements can be either int
(corresponds to INTEGER_LITERAL in grammar) or string
(corresponds to STRING_LITERAL in grammar).
The initial set value is [elem_1, ..., elem_n]
, where n>=0 and elem_i is either INTEGER_LITERAL or STRING_LITERAL. Note, that type of elem_i must correspond to elem_type
.
Access operations:
var_name[elem]
- returns true, if elementelem
is contained in thevar_name
set and false otherwise;var_name.empty
- returns true, if thevar_name
set is empty and false otherwise.
Modification operations:
var_name[elem]=true|false
- on true
element elem
is added to the var_name
set, on false element elem
is removed from the var_name
set. Note, that type of element elem
must be the same as the type of the var_name
set elements.
There are 3 predefined automata states:
- ERROR represents error (target) state;
- STOP represents BOTTOM state in CPA (transfer relation is not calculated from this state);
- BREAK is used to halt the analysis without being a target state.
One automaton state must be marked as initial in InitDef.
Transition to the error (target) state means property violation. Any user-defined state can be marked as a target state (with keyword TARGET), which then will be treated similar to the ERROR state.
If automaton state is marked with the USEFIRST keyword, then its transitions are applied until the first successful match. Otherwise (i.e. if the USEALL keyword is specified) all matched for the current CFA edge automaton transitions are used.
Each checked property may contain several violation (in different automata transitions or in different automata specifications).
In order to differentiate those violations, transitions to the ERROR state can be marked with specific string: ERROR ("error message")
.
Each automaton transition must have identifier of the state, in which automaton will transfer, if assumption is evaluated as true (the Goto section). If automaton should stay in the same state on some transition, then identifier of the same state should be used.
Transition trigger is a Bool expression, which is evaluated on transfer relation computation based on the given CFA edge and other CPA states. If this expression is evaluated as true, then transition is taken, otherwise it is rejected.
This expression may contain standard boolean operations (!
, (
, )
, ==
, !=
, &&
and ||
), constants TRUE
and FALSE
and specific operations:
int_1 == int_2
orint_1 != int_2
matches if expression is true, whereint_i
is an expression of integer constants, automata variables, addition and subtraction operations andEVAL(cpa_name, query)
operation. In order to evaluate this query, the CPA with namecpa_name
name must present in aCompositeCPA
and must implement methodevaluateProperty
, which can parse stringquery
. If these conditions are not satisfied, then the operation returns warning message as a result. For example, operationEVAL(location, "lineno")
sends querylineno
to theLocationCPA
, which returns line number of the analyzed CFA edge.MATCH "stmt"
matches if stringstmt
is equal to the corresponding CFA edge C-statement.MATCH {stmt}
matches if evaluated C-statementstmt
is compared to the CFA edge C-statement with a tree comparison algorithm. Statementstmt
must be a correct C-statement. For this match a set of transition variables is created, which are filled with joker expressions ($?
and$<number>
). If statementstmt
containsCFunctionCallExpression
orCAssignment
inside, joker expressions are substituted to assignment right-hand side or left-hand side or function return value or function arguments. The expression$?
is substituted to any pattern, but is not tracked, whereas each substituted name by$<number>
is added to transition variables and can be used in this transition later. For example:- pattern
x = $?
matches CFA edgex = 5;
, transition variables are{}
; - pattern
x = $1
matches CFA edgex = 5;
, transition variables are{$1=5}
; - pattern
$1 = $?
matches CFA edgex = 5;
, transition variables are{$1=x}
; - pattern
f($?)
matches CFA edgesf()
andf(x, y)
, transition variables are{}
; - pattern
f($1)
matches CFA edgef(x)
, transition variables are{$1=x}
; - pattern
$1 = f($?)
matches CFA edgesy = f(x)
andy = f(x1, x2)
, transition variables are{$1=y}
; - pattern
$1 = f($2)
matches CFA edgey = f(x)
, transition variables are{$1=y, $2=x}
.
- pattern
MATCH [expr]
matches if the CFA edge C-statement matches regular expressionexpr
.MATCH LABEL name
matches if the CFA edge is a label with namename
.MATCH LABEL [expr]
matches if the CFA edge is a label with name, which matches regular expressionexpr
.MATCH ASSERT
matches special edge "assert fail" added by CPAchecker.MATCH EXIT
matches if successor state has no leaving edges.MATCH ENTRY
matches if predecessor state has no entering edges.MATCH FUNCTIONCALL functionname
matches if the CFA edge contains a functioncall with the givenfunctionname
.CHECK (cpa_name, query)
matches ifCompositeCPA
contains CPA with namecpa_name
, which implements methodcheckProperty
, which returns true for stringquery
. For example,CHECK(location, "functionName==f")
returns true, ifLocationCPA
is inside functionf
.CHECK (query)
matches if at least one CPA fromCompositeCPA
implements methodcheckProperty
, which returns true for stringquery
.CHECK (IS_TARGET_STATE)
matches if at least on CPA fromCompositeCPA
is in target state.COVERS_LINES (int_1 int_2 ... int_n)
matches if linesint_1 int_2 ... int_n
are covered.
Transition trigger must present on each automaton transition.
Transition assertions are Bool expressions, which are checked, if a transition trigger is evaluated as true. This expression is similar to the transition trigger. If this expression is evaluated as false, it is treated similar to transition to the ERROR state, otherwise automaton actions are executed. The automaton assertions may not be specified on automaton transition.
Transition actions are executed after successful checking of transition assertions. The following actions are supported:
DO
action allows to modify values of automata variables based on its type:- Int variables:
DO var = expr
, wherevar
is an integer automata variable name,expr
may contain integer automata variables and transition variables (ifMATCH {expr}
expression was used in the transition). For example, actionvar = var + 1
increments integer variablevar
, actionvar = $1
, where transition variables are{$1=1}
, assigns1
to thevar
variable. - Set variables:
DO var[elem] = true|false
, whereelem
should be either a constant (INTEGER_LITERAL or STRING_LITERAL correspondingly) or automata integer variable or transition variable (ifMATCH {expr}
expression was used in the transition). The type ofelem
element must be the same as the type of thevar
set elements. For example, assuming thatvar
is the set of strings, actionvar["elem"]=true
adds string elementelem
to thevar
set, actionvar[$1]=false
, where transition variables are{$1="x"}
, removes string elementx
from thevar
set.
- Int variables:
PRINT expr
action prints the value of specified expression. It does not affect the analysis. The expression may contain automata variables and transition variables. The following expressions are supported:- a boolean expression (the Bool section);
- an integer expression (the Int section);
- a string constant (STRING_LITERAL);
EVAL (cpa_name, query)
expression.
MODIFY (cpa_name, "expr")
action modifies CPAcpa_name
withexpr
. In order to support this operation corresponding CPA must implement methodmodifyProperty
, which can parse stringexpr
. This action can only be executes inside CONTROL automaton. Stringexpr
may contain automata variables and transition variables. For example, actionMODIFY (ValueAnalysis, "setvalue(x==$$var)")
sets to variablex
value of automata variablevar
inValueAnalysisCPA
.
The automaton actions may not be specified on automaton transition.
If trigger is evaluated as true and assertion holds for an automaton transition, then transition to the other automaton state will be created on transfer relation computation, but it may contain additional assumption (the Assume section):
ASSUME {expr_1; expr_2; ...; expr_n}
, where n>=1
, expr_i
is a C-expression.
This assumption represent a conjunction of expr_i
C-expressions, which are evaluated by other CPAs in general case.
The assumption may either restrict abstract state for the automation transition (for example, by adding assumption as a predicate) or reject the automaton transition, if it never evaluates as true. In order to create disjunction of assumptions one should add several transition, for example:
TRUE -> ASSUME {expr_1} ...
TRUE -> ASSUME {expr_2} ...
In this case 2 automaton transitions will be created with different assumptions, which is equal to the expression expr_1 || expr_2
.
Each C-expression expr_i
may contain automata variables or transition variable (if MATCH {expr}
expression was used in the transition), which are substituted before passing to the other CPAs.
It also must be successfully parsed by C-parser.
If expression expr_i
gets a conflicting type, then it should be casted to required type.
Note, that assumptions are evaluated after execution of actions, which may modify automaton variables from assumptions.
Let us consider, that there are int automaton variable var_1
with value 0, set automaton variable of strings var_2
with value ["arg_2"]
and transition variables {$1="arg_1", $2="arg_2"}
, where type of arg_1
is int
, type of arg_2
is size_t
.
Then assumption:
$$var_1 > 0
is evaluated to0 > 0
- transition will be rejected unconditionally;$$var_1 == 0
is evaluated to0 == 0
- transition will be taken unconditionally;$$var_2[$1]
is evaluated to0
- elementarg_1
is not contained in thevar_2
set - transition will be rejected unconditionally;$$var_2[$2]
is evaluated to1
- elementarg_2
is contained in thevar_2
set - transition will be taken unconditionally;$$var_2.empty
is evaluated to0
- thevar_2
set is not empty - transition will be rejected unconditionally;$1 > $$var_1
is evaluated toarg_1 > 0
- transition will be taken with additional predicatearg_1 > 0
;$2 > $$var_1
cannot be evaluated due to different types (size_t
andint
);((int)$2) > $$var_1
is evaluated to(int)arg_2 > 0
- transition will be taken with additional predicate(int)arg_2 > 0
;$1; ((int)$2) == 0; $$var_2[$2]
is evaluated toarg_1 != 0 && (int)arg_2 == 0 && 1
- transition will be taken with additional predicatearg_1 != 0 && (int)arg_2
;!$1; $$var_2[$1]
is evaluated toarg_1 == 0 && 0
— transition will be rejected unconditionally.
The examples of specification automata can be found in the config/specification
and test/config/automata
directories.