Chapitre 3 Frama-C et PathCrawler
4.4 Le slicing
5 i n t i , len ; 60 //@ a s s e r t \ v a l i d ( s t r +0); 6 i f ( str [0] >=97 && str [0] <=122) 7 str [0] -=32; 8 i f ( str [0] < ’I ’ || str [0] > ’Z ’) 9 return; 10 i f ( strlen ( str ) != 12) 11 return; 12 len = strlen ( str ); 14 f o r ( i =1; i < len ; i ++){ 150 //@ a s s e r t \ v a l i d ( s t r+i ) ; 15 i f ( str [ i ] <48 || str [ i ] >57) 16 return ;}}
Figure 4.6 – Le programme de la figure 4.4 simplifi´e par rapport `a l’alarme `a la ligne 15
4.4
Le slicing
Le slicing [Wei81] est une technique de transformation de programmes qui permet d’ex- traire un sous-programme ex´ecutable, appel´e slice, `a partir d’un programme plus grand. Une slice a le mˆeme comportement que le programme original par rapport au crit`ere du slicing. Le slicing de Frama-C est bas´e sur l’analyse de d´ependance qui comprend le calcul du graphe de d´ependance de programme (PDG) [FOW87] montrant les relations de d´ependance entre les instructions du programme, et une analyse de d´ependance inter- proc´edurale permettant de traiter les appels de fonction. Le crit`ere classique du slicing est une paire compos´ee d’une instruction et d’un ensemble de variables du programme. Le slicing de Frama-C accepte d’autres crit`eres de slicing, par exemple un ensemble d’instructions.
Notons ;, la fermeture r´eflexive et transitive de la relation de d´ependance de donn´ees
ou de contrˆole. En d’autres termes, l1 ; l2 si l1 = l2, ou si l’ex´ecution de l2 d´epend de
l’ex´ecution de l1 (directement ou via des ´etats interm´ediaires). Cette relation n’est pas
sym´etrique : si l1 ;l2, cela n’implique pas que l2 ; l1. Par exemple pour les lignes 7 et
8 de la figure 4.3, nous avons 7 ; 8, mais nous n’avons pas 8 ; 7. Mais nous pouvons
avoir des d´ependances mutuelles l1 ; l2 et l2 ; l1 entre instructions. C’est le cas pour
les deux lignes 21 et 22 de la figure 4.3.
Nous d´esignons par labels(p) l’ensemble des ´etiquettes des instructions d’un programme p. Soit L un sous-ensemble de labels(p). Essentiellement, dans les techniques de slicing bas´e
sur les d´ependances (voir par exemple [RY88, Sec. 2.2] et [BBD+
10, d´efinition 4.6]), la
slice de p par rapport `a L, not´ee slice(p, L) ou pL, est d´efinie comme le sous-programme
de p contenant les instructions suivantes :
labels(pL) = { l ∈ labels(p) | ∃ l ′
∈ L, l ; l′
Pour un singleton L = {l}, la slice pL est ´egalement not´ee pl. Comme ; est r´eflexive,
L ⊆ labels(pL) et l ∈ labels(pl).
La slice d’un programme par rapport `a une alarme a est d´efinie comme ´etant la slice
par rapport `a l’instruction mena¸cante la de a, et on ´ecrit pa au lieu de pla. De mˆeme,
la slice d’un programme par rapport `a un ensemble d’alarmes A est d´efinie comme la
slice par rapport `a l’ensemble des instructions mena¸cantes de A, et on ´ecrit pA au lieu de
slice(p, {la| a ∈ A} ).
L’´etape du slicing produit une ou plusieurs versions simplifi´ees de p, chacune d’elles contenant un sous-ensemble d’alarmes qui peuvent ˆetre d´eclench´ees. Nous avons ´etudi´e et impl´ement´e cinq utilisations du slicing qui correspondent aux cinq options pr´esentes dans sante.
1. none : Le programme p est directement analys´e par analyse dynamique sans aucune simplification par le slicing.
2. all : Le slicing est appliqu´e une fois et le crit`ere de simplification est l’ensemble de toutes les alarmes de p. Nous obtenons une version simplifi´ee contenant les mˆemes menaces que le programme original p. Ensuite, l’analyse dynamique est appliqu´ee `a cette version simplifi´ee.
3. each : Soit n le nombre d’alarmes dans p. Le slicing est effectu´e n fois, une fois par rapport `a chaque alarme ai, produisant n programmes simplifi´es p1, p2, . . . , pn.
Ensuite, l’analyse dynamique est appel´ee n fois pour analyser les n programmes simplifi´es.
4. min : On s´electionne des sous-ensembles d’alarmes A1, A2, . . . , Ak de A tels que
A1 ∪ A2 ∪ . . . ∪ Ak = A avec k ≤ n. L’op´eration de slicing est effectu´ee k fois
pour A1, A2, . . . , Ak. Ainsi k programmes simplifi´es pA1, pA2, . . . , pAk sont produits. Ensuite, l’analyse dynamique est appel´ee k fois pour analyser les k programmes r´e- sultants pAi.
5. smart : Cette option applique l’option min it´erativement en r´eduisant la taille des sous-ensembles quand c’est n´ecessaire.
Les trois premi`eres options (none, all et each) sont les options de base. Elles sont pr´esent´ees en d´etail dans la partie 4.6. min et smart sont des options plus avanc´ees, qui se basent sur une analyse de d´ependances entre les alarmes pr´esent´ee en partie 4.7. Les options min et smart sont d´etaill´ees en partie 4.8.
Pour le programme en figure 4.4, le programme simplifi´e qui pr´eserve toutes les alarmes est pr´esent´e dans la figure 4.5. Afin de faciliter la comparaison avec la version initiale,
4.4. Le slicing les parties ray´ees montrent le code enlev´e par le slicing et les parties non ray´ees corres- pondent au code du programme simplifi´e. Un autre programme simplifi´e est donn´e par la figure 4.6. Il pr´esente la version simplifi´ee par rapport `a l’alarme `a la ligne 15. On notera que le code restant a ´et´e l´eg`erement simplifi´e par suppression des initialisations de i et de len et par suppression des valeurs retourn´ees. On constate que la slice par rapport `a une seule alarme est plus simple que celle relative `a toutes les alarmes.
Certaines propri´et´es du slicing utilisent une s´emantique `a base des trajectoires finies
que nous pr´esentons bri`evement dans la partie 4.4.1, en s’inspirant de [BBD+10].
4.4.1
S´emantique `a base de trajectoires
Un ´etat est une fonction totale qui associe une valeur `a chaque variable. Une valeur non d´efinie est not´ee ⊥. La restriction d’un ´etat `a un ensemble de variables V , not´ee par s ↓ V , est d´efinie par :
(s ↓ V )x =
(
s(x) si x ∈ V,
⊥ sinon.
Une s´equence non vide T = (l1, s1)(l2, s2) . . . (lk, sk) . . . de couples (instruction, ´etat)
est appel´ee trajectoire de p si, `a partir d’un ´etat d’entr´ee s1, le programme p ex´ecute la s´e-
quence d’instructions l1, l2, . . . , lk, . . . o`u li est l’´etiquette de la i-`eme instruction ex´ecut´ee
et si est l’´etat avant l’ex´ecution de li. On dit aussi que T est la trajectoire du programme
p `a partir de l’´etat d’entr´ee s1.
On dit que U est une trajectoire partielle de T si U est finie et T commence avec U. En d’autres termes, les trajectoires partielles de T sont les pr´efixes finis de T . Ils ont la forme suivante :
(l1, s1)(l2, s2) . . . (lm, sm), m ≥ 1.
Soit M ⊆ labels(p) un ensemble d’´etiquettes de p. La restriction d’un ´el´ement de trajectoire (l, s) sur M est d´efinie comme suit :
(l, s) ↓ M =
(
(l, s ↓ ref(l)) si l ∈ M,
ε sinon,
o`u ref(l) est l’ensemble des variables lues `a l’instruction l et ε est la s´equence vide.
Pour une trajectoire T = (l1, s1) . . . (lk, sk) . . ., la projection de T sur M est d´efinie
par :
ProjM(T ) = (l1, s1) ↓ M . . . (lk, sk) ↓ M . . .
0 void e u r o c h e c k( char * str ){ 5 i n t i , len ; 60 //@ a s s e r t \ v a l i d ( s t r +0); 61 i f (0 >= length ( str )) 62 error (); 63 e l s e 6 i f ( str [0] >=97 && str [0] <=122) 7 str [0] -=32; 8 i f ( str [0] < ’I ’ || str [0] > ’Z ’) 9 return ; 10 i f ( strlen ( str ) != 12) 11 return ; 12 len = strlen ( str ); 14 f o r ( i =1; i < len ; i ++){ 150 //@ a s s e r t \ v a l i d ( s t r+i ) ; 151 i f ( i >= length ( str )) 152 error (); 153 e l s e 15 i f ( str [ i ] <48 || str [ i ] >57) 16 return ;}}
Figure 4.7 – Le programme simplifi´e par rapport `a l’alarme `a la ligne 15 auquel ont ´et´e ajout´ees les branches d’erreurs
Proposition 4.4.1 (Propri´et´es du slicing)
Soit L un ensemble d’instructions dans p, pL la slice de p par rapport `a l’ensemble d’ins-
tructions L et s0 un ´etat d’entr´ee pour p. Soit T et T′ respectivement les trajectoires de p
et pL ex´ecut´ees `a partir de l’´etat d’entr´ee s0.
(a) labels(pL) est inclus dans labels(p).
(b) Si U est une trajectoire partielle de T , alors il existe une trajectoire partielle U′
de T′
telle que les projections de U et U′
sur L sont ´egales : ProjL(U) = ProjL(U
′
).