I have a test Promela program (a model of UI) that can be verified with Spin:
int secrets = 0;
int success = 0;
int fails = 0;
int total = 0;
//variables to control
bool windowLogin = false;
bool windowSecret = false;
bool windowNoSecret = false;
//ltl formulas
ltl secret_to_success_password { [] (secrets<=success)}
ltl check_total { [] (total == success + fails || total + 1 == success + fails)}
ltl we_open_nosecret { <> (windowNoSecret) }
ltl we_open_secret { <> (windowSecret) }
ltl we_open_any { [] <> (windowSecret || windowNoSecret)}
ltl login_check { <> windowLogin -> <> windowSecret}
ltl no_secret_nosecret { [] !(windowSecret && windowNoSecret) }
//channels
chan login=[0] of {short};
chan nonsecret = [0] of {short};
chan secret = [0] of {short};
//main
active proctype MainWindow(){
int buf;
printf("Main started");
do
//infinite loop
:: {
printf("Main: go to Login window");
login! 1;
login? buf;
if
:: buf == 1 -> {//ok
success++;
printf("Main: open secret window");
//"open" secret
secret ! 1;
secret ? buf;//и ждем его
}
:: buf == 0 -> {//fail
fails++;
printf("Main: open nosecret window");
//"open" nonsecret
nonsecret ! 1;
nonsecret ? buf
}
fi
}
od
}
active proctype LoginWindow(){
int buf;
printf("Login started");
do
:: {
login? buf;
windowLogin = true;
if
::true-> { printf("Login fail"); windowLogin = false; login ! 0 }
::true-> { printf("Login fail"); windowLogin = false; login ! 0 }
::true-> { printf("Login ok!"); windowLogin = false; login ! 1 }//p= 1/3
fi
}
od
}
active proctype NonSecretWindow(){
int buf;
printf("Non Secret started");
do
:: {
nonsecret ? buf;
printf("Non Secret window opened");
windowNoSecret = true;
total++;
windowNoSecret = false;
nonsecret ! 1;
printf("Non Secret window closed");
}
od
}
active proctype SecretWindow(){
int buf;
printf(" Secret started");
do
:: {
secret ? buf;
printf("Secret window opened");
windowSecret = true;
secrets++;
total++;
windowSecret = false;
secret ! 1;
printf("Secret window closed");
}
od
}
Then I created a corresponding C program (for first step, without a loop in Main Window):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool windowLogin = false;
bool windowNoSecret = false;
bool windowSecret = false;
int total = 0;
int secrets = 0;
int success = 0;
int fails = 0;
int LoginWindow();
int NonSecretWindow();
int SecretWindow();
int MainWindow() {
//printf("Main started\n");
{
//printf("Main: go to Login window\n");
int r = LoginWindow();
if (r == 1) {
//printf("Main: open secret window\n");
success++;
SecretWindow();
} else {
//printf("Main: open nosecret window\n");
fails++;
NonSecretWindow();
}
}
return 0;
}
int LoginWindow() {
//printf("Login started\n");
windowLogin = true;
if (rand() %3 ==0) {
// windowLogin = false;
return 1;
} else {
// windowLogin = false;
return 0;
}
return 0;
}
int NonSecretWindow() {
//printf("Non Secret started\n");
//printf("Non Secret window opened\n");
windowNoSecret = true;
total++;
//windowNoSecret = false; --- aorai will controll the variable change only in the end of function
//printf("Non Secret window closed\n");
return 0;
}
int SecretWindow() {
//printf("Secret window opened\n");
windowSecret = true;
secrets++;
total++;
//windowSecret = false;
//printf("Secret window closed\n");
return 0;
}
int main() {
MainWindow();
return 0;
}
I want to try using Aoraï LTL (don't want to create .ya by hand) in Frama-C and WP plugins. First, I created a .ltl file
CALL(main) && _X_ (CALL (MainWindow) && _X_ (CALL (LoginWindow) && _X_ (RETURN (LoginWindow) &&
((_X_ (CALL(NonSecretWindow)))||(_X_ (CALL(SecretWindow)))))))
and can get 2 unknown goals:
[wp] [Alt-Ergo] Goal typed_MainWindow_call_NonSecretWindow_pre : Unknown (Qed:3ms) (81ms)
[wp] [Alt-Ergo] Goal typed_MainWindow_call_SecretWindow_pre : Unknown (Qed:4ms) (79ms)
Also I tried
CALL(main) && _X_ (CALL (MainWindow) && _X_ (CALL (LoginWindow) && _X_ (RETURN (LoginWindow) &&
((_X_ (CALL(NonSecretWindow)||CALL(SecretWindow)))))))
with the same result. This one
CALL(main) && _X_ (CALL (MainWindow) && _X_ (CALL (LoginWindow) && _X_ (RETURN (LoginWindow) && (
(_F_ (CALL(NonSecretWindow)||CALL(SecretWindow)))))))
can be proved, but I belive that that one should be not correct:
CALL(main) && _X_ (CALL (MainWindow) && _X_ (CALL (LoginWindow) && _X_ (RETURN (LoginWindow) &&
((_F_ (CALL(NonSecretWindow)))))))
but it is correct (all goals were proved). Also, I tried to test my LTL formulas like in Promela (without CALL/RETURN/X):
_G_ (windowLogin => _F_ (windowSecret || windowNoSecret))
and I got a lot of unproved goals or even for testing
_G_ (total == success + fails || total + 1 == success + fails)
an internal error
[aorai] Welcome to the Aorai plugin
[aorai] failure: Term cannot be transformed into exp.
[kernel] Current source was: test_ltl.c:112
The full backtrace is:
Raised at file "src/libraries/project/project.ml", line 402, characters 50-57
Called from file "src/plugins/aorai/aorai_register.ml", line 385, characters 4-31
...
I use the commandline
rm test_ltl_annot.c
frama-c test_ltl.c -aorai-ltl test_ltl.ltl
frama-c -wp test_ltl_annot.c
and Frama-C version is Phosphorus-20170501.
How should I use this plugin to verify my test program with respect to LTL?