Vérification de bytecode
6.2 Instanciation du modèle de BCV
Dans cette section, nous pr´esentons l’instanciation faite de note mod`ele de v´erificateur de code octet du chapitre pr´ec´edent avec les machines vir-tuelles des chapitres 3 et 4. Nous n’entrerons cependant pas dans le d´etail des preuves n´ecessaires, une esquisse de celles-ci ainsi que les moyens de les d´emontrer sera donn´ee aux sections suivantes.
6.2.1 Machine virtuelle défensive
D´efinir notre machine virtuelle par l’interm´ediaire du module
Defensive_VM ne pose pas de probl`eme particulier. Seuls cinq param`etres sont `a fournir.
Les ´etats, les contextes d’ex´ecution et la fonction d’ex´ecution sont ceux d´ej`a d´efinis lors de la construction de notre machine virtuelle d´efensive au chapitre 3. La fonction getstack correspond au champ stack_f de l’enre-gistrement repr´esentant les ´etats. Quant au pr´edicat err_frame, il agit par filtrage sur le type des ´etats et discrimine les ´etats ´etiquet´es parAbnormal.
6.2.2 Machine virtuelle abstraite
Concernant la machine virtuelle abstraite cette fois, les ´etats ne sont pas directement ceux de la machine virtuelle d´efinie `a la section 4.3. Il est n´ecessaire de s´eparer les points de programme de ces ´etats. Le param`etre
loc du moduleAbstract_VMdevient alors :
Definition loc := (cap_method_idx * bytecode_idx).
et le param`etre state est d´efini `a l’aide d’un nouveau type d’´etats ne com-portant que pile d’op´erandes et variables locales :
Record s_jcvm_state : Set := { (∗ operand s t a c k ∗)
s_opstack : (list avm.valu);
(∗ l o c a l v a r i a b l e s ∗)
s_locvars : (list (option avm.valu)) }.
Inductive s_returned_state : Set :=
s_Normal : s_jcvm_state→s_returned_state
| s_Abnormal : s_returned_state.
Inductive state
On fournit cependant des fonctions de conversion de et vers le type
jcvm_statede la machine virtuelle abstraite de la section 4.3.
La fonction exec fait directement appel `a la fonction d’ex´ecution de la machine virtuelle abstraite. Les ´etats d’erreurs sont `a nouveau discrimin´es par filtrage sur leur ´etiquette (s_Abnormal). Enfin, la fonction successeurs
succs analyse l’instruction point´ee par l’emplacement de programme et re-tourne :
– les branchements possibles pour les instructions de branchement ; – l’adresse de retour contenue dans la variable vis´ee par l’op´erande pour
l’instruction ret;
– une liste vide pour l’instruction return
– l’adresse de l’instruction suivante pour les autres instructions.
Il manque encore pour satisfaire le type de module Abstract_VM, outre les preuves, faciles, portant sur les d´efinitions pr´ec´edentes, la d´efinition de l’ordre sur les ´etats de la machine virtuelle.
6.2.3 Ordre sur les types et sur les états
La v´erification de code octet repose sur un ordre sur les ´etats. Ce dernier est d´eriv´e d’un ordre induit par la relation de sous-typage des types de la machine virtuelle abstraite.
Ordre sur les types
Afin de simplifier l’ordre sur les types, nous n’ajoutons pas aux types d’´el´ement maximal > afin de former un treillis. `A la place, l’unification de deux ´etats normaux (sNormal) contenant des types incomparables ne sera pas un ´etat normal contenant>l`a o`u les types ´etaient incomparables, mais un ´etat d’erreur (sAbnormal). On perd ainsi le registre ou l’emplacement de la pile posant probl`eme, mais on ´evite de devoir consid´erer > comme un type de la machine virtuelle abstraite.
Les types primitifs de la machine virtuelle sont incomparables entre eux pour l’ordre utilis´e sur les types.
Parmi les types de r´ef´erences, la classe Java Object est la super-classe commune et le typeNulll’´el´ement minimal. On introduit ensuite une com-paraison entre les instances de classe et les interfaces, l’unification d’une instance de classe et d’une interface pouvant ˆetre une interface si elle est impl´ement´ee par l’instance de classe consid´er´ee.
Objet
P rim Interf aces T ableaux OOOOOO
OOOOOO
Instances
N ull
~~
~~
~~
~~
~~
~~
~~
~~
~~
~
Fig. 6.1 –Ordre sur les types de la machine virtuelle.
Toutes les comparaisons ne sont pas indiqu´ees sur le treillis, les instances de classes peuvent par exemple ˆetre compar´ees entre elles si l’une est une super-classe de l’autre, et de mˆeme pour les interfaces. Quant aux tableaux, on introduit une r´ecursivit´e dans le treillis, le r´esultat de la comparaison de deux tableaux de typesτ1 etτ2 ´etant le r´esultat de la comparaison deτ1 et τ2.
L’ordre ≺sur le treillis est donn´e par les r`egles d’inf´erence suivantes de la figure 6.2.
Les interfaces (resp. classes) sont indic´ees de telle sorte que siImest une super-interface deIn (resp. Cm est une super-classe de Cn) alorsm≤Nn.
{ρ:type ref} `ρ≺N ull (Nul) {ρ:type ref} `Obj≺ρ (Obj)
{m,n:N} `I(m)≺C(n) (ClI) {m,n:N} `m≤Nn
I(m)≺I(n)
(Int) {m,n:N} `m≤Nn
C(m)≺C(n)
(Cla) {σ,τ :type} `σ≺τ
A(σ)≺A(τ)
(Arr)
Fig. 6.2 –R`egles d’inf´erences de l’ordre sur les types.
Bonne fondation de l’ordre sur les types
Tel que d´ecrit par les r`egles de la figure 6.1, l’ordre ≺ n’est pas bien fond´e. Il est en effet possible de construire une chaˆıne infinie d´ecroissante pour cet ordre :
1. par l’axiome (Obj), on a Obj≺A[Obj] ;
2. par la r`egle (Arr), on d´eduitA[Obj]≺A[A[Obj]] ; 3. par transitivit´e, Obj≺A[Obj]≺A[A[Obj]]
4. par applications successives de la r`egle (Arr), on arrive `a : Obj≺A[Obj]≺A[A[Obj]]≺A[A[A[Obj]]]≺...
On peut toutefois, en modifiant la r`egle (Arr), obtenir un ordre bien fond´e. On d´efinit d’abord la taille |σ| d’un type σ comme le nombre de fois o`u le constructeur Array apparaˆıt dans ce type. On d´efinit ensuite la restriction σ|m d’un type σ aux m derniers constructeurs Array du type σ, par exemple :
Obj|2 =Obj A(A(P rim))|2 =A(A(P rim)) A(A(A(A(P rim))))|2 =A(A(P rim)) On remarquera que :
|σ| ≤Nm⇔σ|m =σ (6.1) L’ordre ≺devient donc param´etr´e par un entiermet on change la r`egle (Arr) pour la r`egle :
{σ,τ :type} `σ≺m τ |σ| ≤Nm |τ| ≤Nm A(σ)≺mA(τ)
(Arrm)
Ainsi, il n’est plus possible d’obtenir une chaˆıne d´ecroissante de tableaux de longueur sup´erieure `a m.
Pour assurer la correction de ≺m vis-`a-vis de ≺, il faut montrer que pour un programme donn´e, on peut borner la taille des types utilis´es dans ce programme. Il suffit pour cela d’une simple analyse statique effectuant un parcours complet du programme `a la recherche du plus grand type utilis´e.
Notons toutefois que dans le cas deJava Card, les tableaux de tableaux ne sont pas permis et qu’alors pour les programmesJava Card m vaut 1.
Ordre sur les états
A partir de l’ordre sur les types de la machine virtuelle abstraite, on` construit un ordre sur les ´etatsstate du moduleAbstract_VM.
On ´el`eve ainsi d’abord cet ordre au typeoption(pour le cas des variables locales) en un ordre≺opt avec les conventions :
{s:type} `(Some s)≺None (Nul) {s,t:type} `s≺t
`(Some s)≺(Somet)
(Some)
Pour la pile d’op´erande et les variables locales, on ´etend respectivement les ordres ≺et≺opt en ≺ops et≺loc, ordres point `a point sur les listes.
Deux ´etatss_jcvm_statesont alors comparables par≺sst si : {s,t:s jcvm state} `(s locvars s)loc(s locvars t)
(s opstacks)≺ops(s opstackt) s≺sstt
(Ops)
{s,t:s jcvm state} `(s locvars s)≺loc(s locvarst) (s opstacks)ops(s opstack t)
s≺sstt
(Loc)
o`uest la clˆoture r´eflexive d’un ordre ≺.
Enfin on construit un ordre≺st sur les ´etatsstatedu Abstract_VM: {s:s jcvm state} `s Abnormal≺sts (Norm)
{s,t:s jcvm state} `s≺sst t
`(s Normals)≺st (s Normalt)
(Abn)