• Aucun résultat trouvé

Interaction avec le monde ext´erieur

x = v.mx v.mx <- v.my;

v.my <- x

;;

val rot_mvector : (’a, ’a) mvector -{’a ||}-> unit

Puisqu’ils sont modifi´es par cette fonction, les entiers du vecteur donn´e en argument sont suscep-tibles de porter de l’information `a la fois sur le contexte d’appel de la fonction et l’identit´e du vecteur modifi´e lui-mˆeme.

Dans la section3.1(page53), j’ai introduit les r´ef´erences. Toutefois il s’agit simplement d’un cas particulier d’enregistrement `a un champ mutable, qui peut ˆetre d´efini comme suit :

(’a, ’b) ref =

{ contents: ’a } # ’b

;;

type (=’a:type, #’b:level) ref = { mutable contents: ’a } # ’b

De plus, les trois op´erations primitivesref,:=et!sur les r´ef´erences sont des fonctions normales qui sont impl´ement´ees dans le module Pervasives `a partir de la repr´esentation des r´ef´erences comme enregistrements :

ref x =

{ contents = x }

;;

val ref : ’a -> (’a, _) ref

(:=) r x = r.contents <- x

;;

val ( := ) : (’a, ’b) ref -> ’a -{’b ||}-> unit with ’b < level(’a)

( ! ) r = r.contents

;;

val ( ! ) : (’a, ’b) ref -> ’c with ’b < level(’c) and ’a < ’c

4.2 Interaction avec le monde ext´ erieur

Un programme Flow Caml peut ˆetre consid´er´e comme un processus qui re¸coit de l’information d’une ou plusieurs sources ext´erieures, effectue des calculs et envoie ses r´esultats (interm´ediaires ou finaux) `a un ou plusieurs receveurs ´egalement ext´erieurs. Avec ce point de vue, le but ultime du syst`eme de types est de v´erifier que chaque flot d’information potentiel entre une source et un receveur engendr´e par l’ex´ecution du programme est l´egal au regard de la politique de s´ecurit´e du syst`eme informatique. Il me faut expliquer comment ces entit´es externes sont repr´esent´ees en Flow Caml, et comment les r`egles de propagation de l’information peuvent ˆetre d´efinies par le programmeur.

4.2 ·Interaction avec le monde ext´erieur 71

Dans la litt´erature, les d´etenteurs d’information sont g´en´eralement appel´esprincipaux. Du point de vue d’un programme donn´e, chacun d’entre eux peut ˆetre une source, un receveur ou mˆeme les deux `a la fois. Suivant les contextes, la notion de principal peut recouvrir une grande vari´et´e de concepts : des (groupes d’)utilisateurs, des niveaux de confidentialit´e (public,secret, etc.), des sous-ensembles d’un espace de stockage, des canaux de communication via une interface r´eseau, etc.

Cependant, Flow Caml n’est pas concern´e par la mat´erialisation de ces entit´es, et les traite d’une mani`ere uniforme : dans son syst`eme de type, les principaux sont repr´esent´es par les constantes de niveau d’information, comme!alice,!bobet!charlieque nous avons rencontr´e jusqu’`a pr´esent dans les exemples. Leur introduction ´etait cependant relativement artificielle, puisque je n’ai pas pr´ecis´e comment il ´etait effectivement possible d’´echanger de l’information avec les principaux qu’ils symbolisent. Je donne maintenant un exemple plus r´ealiste avec les canaux de communication

´etablis par l’entr´ee et la sortie standards du programme.

4.2.1 L’exemple de l’entr´ee et de la sortie standards

L’entr´ee standard et la sortie standard sont des canaux de communications ouverts respecti-vement en lecture et en ´ecriture. Ils sont par convention repr´esent´es par les deux niveaux d’infor-mation :!stdinet !stdout. Le modulePervasivesde la biblioth`eque standard fournit quelques primitives pour utiliser ces canaux. Par exemple, la fonctionprint_intimprime un entier sur la sortie standard :

print_int;;

- : !stdout int -{!stdout ||}-> unit

Puisque l’entier donn´e en argument est envoy´e sur la sortie standard, son niveau doit ˆetre inf´erieur ou ´egal `a!stdout. Le litt´eral1ayant le type’a intpour tout niveau’a, il peut ˆetre pass´e comme argument `aprint_int:

print_int 1;;

- : unit

A l’inverse, l’entier` x1ayant le niveau!alice, il n’est pas possible — pour l’instant — de l’afficher sur la sortie standard :

print_int x1;;

This expression generates the following information flow:

from !alice to !stdout which is not legal.

En effet, ce fragment de code g´en`ere un flot d’information du principal«Alice»vers le principal

« sortie standard ». Il requiert par cons´equent l’in´egalit´e !alice < !stdout. Celle-ci n’est pas satisfaite par le treillis par d´efaut o`u tous les principaux sont incomparables, i.e. ne peuvent

´echanger d’information. Cette politique de s´ecurit´e peut ˆetre relax´ee en d´eclarant de nouvelles in´egalit´es entre niveaux grˆace aux d´eclarations introduites par le mot-clef :

!alice < !stdout;;

Cette d´eclaration modifie la structure du treillis sous-jacent de telle sorte que le point correspondant

`

a!alicedevienne inf´erieur ou ´egal `a celui de!stdout. Concr`etement, cela revient `a autoriser les flots d’information du principal repr´esent´e par le premier (Alice) vers celui du second (la sortie standard). Ces d´eclarations sont transitives. Par exemple, si on d´eclare :

!bob < !alice;;

alors Bob peut envoyer de l’information `a Alice, mais aussi, par transitivit´e, `a la sortie standard : print_int x2;;

- : unit

Il faut bien noter que ces niveaux d’informations sontglobaux, de mˆeme que les d´eclarations qui les relient. Cela est naturel puisque les principaux et la politique de s´ecurit´e qu’ils repr´esentent le sont ´egalement. Cependant, de mani`ere `a pr´eserver son caract`ere incr´emental, la boucle interactive

72 Chapitre 4·D´efinitions de types et de modules

permet au programmeur de relaxer la politique de s´ecurit´e progressivement : il peut entrer une d´eclaration `a chaque invite, laquelle reste valide jusqu’`a la fin de la session. Cette flexibilit´e ne va pas `a l’encontre de la correction du syst`eme, puisqu’un fragment de programme typ´e dans un certain treillis reste bien typ´e dans un affaiblissement de ce treillis.

Le niveau de s´ecurit´e!stdin repr´esente le canal de communication reli´e `a l’entr´ee standard dans le syst`eme de types. Par exemple, la fonction read_linea le type suivant :

read_line;;

- : unit -{[< !stdout, !stdin] | End_of_file: !stdin |}-> !stdin string

D’apr`es la documentation de la librairie standard d’Objective Caml, la fonctionread_linevide le tampon de la sortie standard, puis lit des caract`eres sur l’entr´ee standard jusqu’`a ce qu’un retour `a la ligne soit rencontr´e. Ainsi, une invocation deread_lineproduit des effets sur `a la fois l’entr´ee et la sortie standard, ce qui explique la premi`ere annotation sur la fl`eche du type ci-dessus. De plus, si l’utilisateur envoie le caract`ere de fin de fichier (e.g.en tapant^D), la fonction l`eve une exception End_of_file, d’o`u la deuxi`eme annotation sur la fl`eche. Enfin, la chaˆıne obtenue en lisant l’entr´ee standard doit avoir le niveau!stdin:

Remarquons que, si on veut ´ecrire sur la sortie standard une chaˆıne lue sur l’entr´ee standard (ou toute valeur calcul´ee `a partir de celle-ci), la politique de s´ecurit´e doit autoriser les transferts d’information de la seconde vers la premi`ere. Pour cela, il suffit d’entrer la d´eclaration suivante :

!stdin < !stdout;;

On peut alors ´ecrire une fonction echo qui r´ep`ete sur la sortie standard les caract`eres lus sur l’entr´ee standard :

val echo : unit -{[< !stdout, !stdin] ||}-> unit

4.2.2 Principaux

Les programmes r´eels peuvent g´en´eralement communiquer avec l’ext´erieur en utilisant d’autres canaux que les simples entr´ee et sortie standards, comme le syst`eme de fichiers, une interface r´eseau ou un p´eriph´erique d’affichage. Cependant, la librairie standard de Flow Caml ne fournit pas de fonction permettant de telles communications : analyser ces op´erations de bas niveau `a l’aide de son syst`eme de types ne permettrait pas d’obtenir une description pertinente de leur contenu

vis-`

a-vis de la politique de s´ecurit´e. Des consid´erations tr`es raffin´ees sont g´en´eralement n´ecessaires pour prouver leur sˆuret´e. C’est pourquoi l’interaction avec ces entit´es externes doit ˆetre mod´elis´ee, en Flow Caml, `a un plus haut niveau, d´ependant de la mani`ere dont elles sont utilis´ees dans le programme.

C’est la raison pour laquelle un programme ´ecrit et v´erifi´e avec le syst`eme Flow Caml doit g´en´e-ralement ˆetre divis´e en deux parties. La premi`ere fournit un mod`ele de haut niveau des principaux externes. Cela consiste g´en´eralement d’une s´erie de fonctions permettant de communiquer avec ces entit´es, qui sont impl´ement´ees dans un ou plusieurs modules ´ecrits en Objective Caml, en utilisant