-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path9-Annexes.tex
363 lines (336 loc) · 13.2 KB
/
9-Annexes.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
%%
%% Annexes.
%%
%% Note: Ne pas modifier la ligne ci-dessous.
\addcontentsline{toc}{compteur}{ANNEXES}
%%
%%
%% Toutes les annexes doivent être inclues dans ce document
%% les unes à la suite des autres.
\begin{landscape}
\Annexe{Types de propriétés supportés par différents model-checkers}
\begin{table}[ht]
\centering
\caption{Types de propriétés prises en charge par les outils présentés.}
\begin{tabular}{|l|c|c|c|c|c|c|c|c|c|}
\hline
Outils & \multicolumn{9}{c|}{Types de propriétés vérifiées} \\
& Assertions & LTL & Arithmétique & Tableaux & Pointeurs & Data races & Deadlock & Cast & Init \\ \hline
SPIN & & $\checkmark$ & & & & & & & \\
Pancam & $\checkmark$ & & & & & & & & \\
Inspect & $\checkmark$ & & & & & & & & \\
Divine & $\checkmark$ & $\checkmark$ & & & & & & & \\
CIVL & $\checkmark$ & & $\checkmark$ & $\checkmark$ & $\checkmark$ & $\checkmark$ & $\checkmark$ & $\checkmark$ & $\checkmark$ \\
Impara & $\checkmark$ & & & & & & & & \\
Satabs & $\checkmark$ & & $\checkmark$ & $\checkmark$ & $\checkmark$ & & & & \\
Threader & $\checkmark$ & & & & & & & & \\
CPAChecker & $\checkmark$ & & & & & & & & \\
CBMC & $\checkmark$ & & $\checkmark$ & $\checkmark$ & $\checkmark$ & & & & \\
ESBMC & $\checkmark$ & & $\checkmark$ & $\checkmark$ & $\checkmark$ & $\checkmark$ & $\checkmark$ & & \\
CSeq & $\checkmark$ & & & & & & & & \\
Lazy-CSeq & $\checkmark$ & & & & & & $\checkmark$ & & \\
Mu-CSeq & $\checkmark$ & & & & & & & & \\
UL-CSeq & $\checkmark$ & & & & & & & & \\ \hline
\end{tabular}
\label{tab:prop_type_table}
\end{table}
\end{landscape}
\Annexe{Exemple de spécification}
Dans cette annexe, nous présentons un exemple détaillé de spécification et de
vérification d'un problème simple à l'aide de baProduct. Nous détaillons les
étapes intermédiaires.
Considérons le problème suivant : un système contient deux batteries. Les
batteries se vident simultanément au fil de l'utilisation. Lorsqu'une batterie
est épuisée, elle est remplacée. Une batterie est suffisante pour que le système
fonctionne, cependant, si les deux batteries sont vides en même temps, le
système n'a plus d'énergie et cesse de fonctionner.
Un tel système peut être modélisé par le code ci-dessous. Deux threads,
\texttt{battery1} et \texttt{battery2} contrôlent le rythme auquel les
batteries se vident. Le pourcentage d'énergie dans la batterie est représenté
par la variable \texttt{energy}. Celle-ci est décrémentée dans une
boucle, ce qui représente la consommation de l'énergie, avant d'être remise à
une valeur de 10, ce qui simule le remplacement. Dans ce système simpliste,
aucune synchronisation n'existe entre les threads.
On peut aussi noter que la boucle principale des threads ne s'exécute que trois
fois, afin que la trace soit finie. Dans un cas d'utilisation réel, on
utiliserait une boucle infinie et les options du model-checker permettraient de
limiter le nombre de dépliages, mais pour des raisons de simplicité, nous codons
directement ce comportement.
\noindent\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language=C, frame=single, caption=Thread 1]
void* battery1(void* d) {
int energy;
int i;
// Initialization
energy = 10;
for(i=0; i<3; i++) {
// Empty the battery
while (energy > 0)
energy--;
// Replace the battery
energy = 10;
}
pthread_exit(NULL);
}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language=C, frame=single, caption=Thread 2]
void* battery2(void* d) {
int energy;
int i;
// Initialization
energy = 10;
for(i=0; i<3; i++) {
// Empty the battery
while (energy > 0)
energy--;
// Replace the battery
energy = 10;
}
pthread_exit(NULL);
}
\end{lstlisting}
\end{minipage}
Pour s'assurer que le système fonctionne correctement, on souhaite s'assurer
qu’une des deux batteries a toujours un niveau d'énergie supérieur à 20\%, une
fois le système initialisé.
Nous allons tout d'abord spécifier cette propriété sur le système. Pour cela, on
délimite tout d'abord les zones de validités. L'initialisation des batteries ne
doit pas en faire partie, mais la boucle principale du programme y est incluse.
\noindent\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language=C, frame=single, caption=Thread 1 avec labels]
void* battery1(void* d) {
int energy;
int i;
energy = 10;
b1: for(i=0; i<3; i++) {
// Empty the battery
while (energy > 0)
energy--;
// Replace the battery
energy = 10;
}
e1: pthread_exit(NULL);
}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language=C, frame=single, caption=Thread 2 avec labels]
void* battery2(void* d) {
int energy;
int i;
energy = 10;
b2: for(i=0; i<3; i++) {
// Empty the battery
while (energy > 0)
energy--;
// Replace the battery
energy = 10;
}
e2: pthread_exit(NULL);
}
\end{lstlisting}
\end{minipage}
On définit ensuite les fonctions d'évaluation. Ici, nous allons utiliser deux
propositions atomiques, chacune indiquant si une batterie a un niveau
d'énergie faible. Cependant, une seule fonction d'évaluation est nécessaire
puisque les deux propositions atomiques s'évaluent selon la même formule.
\begin{lstlisting}[language=C, frame=single, caption=Fonction d'évaluation]
int low_power(int energy) {
return energy <= 2;
}
\end{lstlisting}
Il ne reste alors qu'à exprimer la spécification en elle même.
\pagebreak
\begin{lstlisting}[frame=single, caption=Spécification]
{ "ltl": "G(! (p1 && p2))",
"pa": [
{"name": "p1",
"default": false,
"expr": "low_power",
"span": ["b1", "e1"],
"params": ["battery1::energy"]
},
{ "name": "p2",
"default": false,
"expr": "low_power",
"span": ["b2", "e2"],
"params": ["battery2::energy"]
}
]
}
\end{lstlisting}
On utilise alors baProduct pour instrumenter ce code. On utilise pour cela
la commande \texttt{baProduct.py -i battery.c -s battery.spec}. Cette commande
réalise tout d'abord un appel à LTL2BA afin de générer l'automate correspondant
à la négation de la formule LTL (étape 1 dans la
Figure~\ref{fig:baProduct_func}). On obtient l'automate en
Figure~\ref{fig:ba_battery}.
\begin{figure}[ht]
\begin{center}
\includegraphics[height=0.2\textheight]{ba_battery.png}
\end{center}
\caption{Automate de Büchi généré par LTL2BA pour la spécification des
batteries.}
\label{fig:ba_battery}
\end{figure}
Cet automate est ensuite représenté en C. On obtient le code suivant (on suppose
ici que CBMC va être utilisé comme backend).
\begin{lstlisting}[language=C, frame=single, caption=Automate encodé en C]
// Current values of atomic propositions
int _ltl2ba_atomic_p1 = 0;
int _ltl2ba_atomic_p2 = 0;
// Is a proposition atomic in its validity area ?
int _ltl2ba_active_p1 = 0;
int _ltl2ba_active_p2 = 0;
// In a validity area, point to local variables
// used in evaluation functions
int *_ltl2ba_pointer_thread2_energy = 0;
int *_ltl2ba_pointer_thread1_energy = 0;
// Current state of the automaton
int _ltl2ba_state_var = 0;
// Transition function of the automaton
void _ltl2ba_transition() {
int choice = nondet_uint(); // Choose a transition
switch (_ltl2ba_state_var) {
case 0: // Transitions from state 0
if (choice == 0) {
__CPROVER_assume(_ltl2ba_atomic_p1 && _ltl2ba_atomic_p2);
_ltl2ba_state_var = 1;
} else if (choice == 1) {
__CPROVER_assume(1);
_ltl2ba_state_var = 0;
} else {
__CPROVER_assume(0);
}
break;
case 1: // State one is an accepting pit
__CPROVER_assert(0, "ERROR_SURE");
break;
}
}
// Pre-calculated results for stutter acceptance
int _ltl2ba_surely_reject[2] = {0, 0};
int _ltl2ba_surely_accept[2] = {0, 1};
int _ltl2ba_stutter_accept[8] = {0, 1, 0, 1, 0, 1, 1, 1,};
int _ltl2ba_sym_to_id() {
int id = 0;
id |= (_ltl2ba_atomic_p2 << 1);
id |= (_ltl2ba_atomic_p1 << 0);
return id;
}
// Raise an assertion according to the final state
void _ltl2ba_result() {
// The automaton accept the word, whatever the suffix
int reject_sure = _ltl2ba_surely_accept[_ltl2ba_state_var];
__CPROVER_assert(!reject_sure, "ERROR SURE");
// The automaton accept the word in stutter-extension semantic
int id = _ltl2ba_sym_to_id();
int accept_stutter =_ltl2ba_stutter_accept[id * 2
+ _ltl2ba_state_var];
__CPROVER_assert(!accept_stutter, "ERROR MAYBE");
// The automaton does not surely reject the word
int valid_sure = _ltl2ba_surely_reject[_ltl2ba_state_var];
__CPROVER_assert(valid_sure, "VALID MAYBE");
}
\end{lstlisting}
Le code est ensuite instrumenté pour construire le produit avec l'automate
(étape 2 dans la Figure~\ref{fig:baProduct_func}).
\begin{lstlisting}[language=C, frame=single, caption=Code instrumenté]
void *battery1(void *d )
{
int energy ;
int i;
energy = 10;
// Beginning of the validity area
// Open an atomic bloc
__CPROVER_atomic_begin();
_ltl2ba_pointer_thread1_energy = &energy;
_ltl2ba_atomic_p1 =
low_power(*_ltl2ba_pointer_thread1_energy);
_ltl2ba_active_p1 = 1;
_ltl2ba_transition();
__CPROVER_atomic_end();
b1: for(i=0; i<3; i++) {
while (energy > 0) {
// Variable modification
__CPROVER_atomic_begin();
energy--;
// Compute the new value of the atomic proposition
_ltl2ba_atomic_p1 =
low_power(*_ltl2ba_pointer_thread1_energy);
// Take a transition in the automaton
_ltl2ba_transition();
__CPROVER_atomic_end();
}
__CPROVER_atomic_begin();
energy = 10;
_ltl2ba_atomic_p1 =
low_power(*_ltl2ba_pointer_thread1_energy);
_ltl2ba_transition();
__CPROVER_atomic_end();
}
// End of the validity area
__CPROVER_atomic_begin();
// Set the atomic proposition to the default value
_ltl2ba_atomic_p1 = 0;
// Deactivate the atomic proposition
_ltl2ba_active_p1 = 0;
// Take a transition in the automaton
_ltl2ba_transition();
__CPROVER_atomic_end();
e1: pthread_exit(0);
}
void *battery2(void *d )
{
int energy ;
int i;
energy = 10;
__CPROVER_atomic_begin();
_ltl2ba_pointer_thread2_energy = & energy;
_ltl2ba_atomic_p2 = low_power(*_ltl2ba_pointer_thread2_energy);
_ltl2ba_active_p2 = 1;
_ltl2ba_transition();
__CPROVER_atomic_end();
b2: for(i=0; i<3; i++) {
while (energy > 0) {
__CPROVER_atomic_begin();
energy--;
_ltl2ba_atomic_p2 =
low_power(*_ltl2ba_pointer_thread2_energy);
_ltl2ba_transition();
__CPROVER_atomic_end();
}
__CPROVER_atomic_begin();
energy = 10;
_ltl2ba_atomic_p2 =
low_power(*_ltl2ba_pointer_thread2_energy);
_ltl2ba_transition();
__CPROVER_atomic_end();
}
__CPROVER_atomic_begin();
_ltl2ba_atomic_p2 = 0;
_ltl2ba_active_p2 = 0;
_ltl2ba_transition();
__CPROVER_atomic_end();
e2: pthread_exit(0);
}
int main(int argc , char **argv )
{
pthread_t t1 ;
pthread_t t2 ;
pthread_create(&t1, 0, &battery1, 0);
pthread_create(&t2, 0, &battery2, 0);
pthread_join(t1, 0);
pthread_join(t2, 0);
__CPROVER_atomic_begin();
_ltl2ba_result();
__CPROVER_atomic_end();
return 0;
}
\end{lstlisting}
Il ne reste plus qu'à vérifier ce code instrumenté à l'aide d'un model-checker.
Ici, nous avons utilisé CBMC, à l'aide de la commande \texttt{cbmc
battery\_instr.c}. La sortie indique que l'assertion \texttt{ERROR\_SURE} a été
violée : une erreur est donc détectée de manière certaine dans le code.