une introduction à frama-c - linux-francedmentre/gulliver/presentations/expose-frama-c... ·...
TRANSCRIPT
David MentréDavid Mentré
[email protected]@linux-france.orgGulliverGulliver
Une introduction à Frama-CUne introduction à Frama-C
Analyse et preuve de programmes CAnalyse et preuve de programmes C
2011-01-31 Introduction à Frama-C 2
Prélude : quelques exemples illustratifs
2011-01-31 Introduction à Frama-C 3
Ce code contient une erreur !
Calcul de la valeur absolue d’un nombre en langage C
int z_abs_x(const int x) {
int z; if (x < 0) z = -x; else /* x >= 0 */ z = x; return z; }
2011-01-31 Introduction à Frama-C 4
Ce code contient une erreur !
Calcul de la valeur absolue d’un nombre en langage C
int z_abs_x(const int x) {
int z; if (x < 0) z = -x; else /* x >= 0 */ z = x; return z; }
Si x = -231, 231 n'existe pas (seulement 231 -1)
2011-01-31 Introduction à Frama-C 5
Un autre exemple, en Java
Recherche par Dichotomie dans un tableau triépublic static int binarySearch(int[] a, int key) { int low = 0; int high = a.length - 1;
while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid];
if (midVal < key) low = mid + 1 else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found.}
2011-01-31 Introduction à Frama-C 6
Un autre exemple, en Java
Recherche par Dichotomie dans un tableau triépublic static int binarySearch(int[] a, int key) { int low = 0; int high = a.length - 1;
while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid];
if (midVal < key) low = mid + 1 else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found.}
Solution6: int mid = low + ((high - low) / 2);
ProblèmeBug présent dans le JDK de Sun !
Recherche par Dichotomie dans un tableau triépublic static int binarySearch(int[] a, int key) { int low = 0; int high = a.length - 1;
while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid];
if (midVal < key) low = mid + 1 else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found.}
http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
2011-01-31 Introduction à Frama-C 7
Un cas d'école
Un exemple concret de l'utilité des méthodes d'analyse statique
http://esamultimedia.esa.int/docs/esa-x-1819eng.pdf
2011-01-31 Introduction à Frama-C 8
Un cas d'école : causes
Chaine d'événements techniques
2011-01-31 Introduction à Frama-C 9
Un cas d'école : suite des causes
Chaîne d'événements techniques (suite)
[...]
2011-01-31 Introduction à Frama-C 10
Un cas d'école : recommandations pour Ariane 501
Plus de tests
Plus de formel (indirectement)
→ Analyse abstraite (PolySpace, A. Deutsch)
2011-01-31 Introduction à Frama-C 11
Analyse abstraite
2011-01-31 Introduction à Frama-C 12
Analyse abstraite : PolySpace
PolySpaceLogiciel expérimental puis industrialisé d'analyse de code Ada, C, C++ (PolySpace → MathWorks)Vérification automatique à 95% de l'absence de Run Time Error pour Ariane 502, 503, …
Inertial Measurement Unit (30.000 lignes)Flight Software (60.000 lignes)
2011-01-31 Introduction à Frama-C 13
Analyse abstraite : interprétation abstraite
Basée sur l'interprétation abstraiteApproximations faites sur le sens (la sémantique) du langage C
Formalisé par Patrick et Radia Cousot (fin 70)Signale toutes les erreurs possibles pour des classes d'erreurs
Division par zéro, débordement de tableau, dépassement de capacité sur des entiers, …
Parfois signale des erreurs qui n'en sont pas (fausses alarmes)
2011-01-31 Introduction à Frama-C 14
Analyse abstraite : aperçu
Un exemple : signe d'un calculSign(x) = -1 si x < 0, +1 sinonSign(x * y) = Sign(x) * Sign(y) Sign(x / y) = Sign(x) * Sign(y)Sign(x + y) = ? Sign(x – y) = ? => approximation
Analyse abstraiteAller de l'espace concret (programme) dans l'espace abstrait d'analyseFaire l'analyse
Dans un temps et espace fini et raisonnable sur des propriétés potentiellement infinies
Projeter le résultat sur l'espace concret
2011-01-31 Introduction à Frama-C 15
Analyse abstraite : fondements
Fondements théoriques plus compliquésGarantir que l'analyse est valide
Tout ce qui est démontré sur l'abstraction l'est aussi sur le vrai système
Idéalement, garantir que l'analyse est complèteToute erreur signalée sur l'analyse est une erreur sur le vrai systèmeTout du moins, limiter les fausses alarmes
2011-01-31 Introduction à Frama-C 16
Analyse abstraite : outils
Outils commerciaux et propriétairesAstrée http://www.absint.de/astree/
Vérification du logiciel embarqué d'AirbusPolySpace http://www.mathworks.com/products/polyspace
Issu des vérifications pour Ariane 502Outil libre et gratuit
Frama-C http://frama-c.com/ Framework plus général d'analyse et de preuve de code C
2011-01-31 Introduction à Frama-C 17
Analyse abstraite : grille de lecture
Domaine d'application : code Ada / C / C++À vérifier : les fausses alarmesNiveau d'expertise : NulNiveau d'intervention : sur le code final de production, annotations
Fidèle, suit les changementsOutils disponibles et automatiquesExpressivité : que certaines classes de propriétés
Division par zéro, non débordement de tableaux et entiers, ...
2011-01-31 Introduction à Frama-C 18
Analyse de code C avec Frama-C(un peu de concret !)
2011-01-31 Introduction à Frama-C 19
Qu'est-ce que Frama-C ?
Framework d'analyse de code C http://frama-c.com/ Développé par le CEA LIST et INRIA SaclayProgrammé et extensible (plugins) en OCamlDifférentes analyses, combinables entre elles
Analyse de valeurs, vérification déductive, slicing, code mort, propagation de constantes, dépendances entre variables, ...
Interface graphique pour montrer les résultats d'analysePaquets Debian et Ubuntu frama-c
2011-01-31 Introduction à Frama-C 20
Plugin fondamental : analyse de valeur
Activé par l'option -val : valeur des variablesValeurs pour des variables entières
Énumérations : a ∈ {4; 5; }Intervalle : i ∈ [0..100] a ∈ [--..--]
Intervalle avec périodicité : i ∈ [2..42]%2,10
Toutes les valeurs de l’intervalle ayant pour reste 2 après division par 10 : 2, 12, 22, 32, 42
Valeurs pour des variables flottantesValeur exacte (3.0) et intervalle ([-1.0..1.0])
Valeurs pour des tableaux et pointeursEnsemble d'adresses sous forme base + offset (en octets)p ∈ {{ &a ; &b ;}}
p ∈ {{ &t + {0; 4; 8; 12;} ; &s + { 0; } ; }}
2011-01-31 Introduction à Frama-C 21
Exemple d'analyse de valeur : démo !
2011-01-31 Introduction à Frama-C 22
Frama-C pour l'analyse de code
frama-c-gui -val value-analysis.c
Permet de faire des vérifications exhaustivesConsidère tous les cas possibles
Notamment très difficilement accessibles au test
Alarmes : bug potentiel !Ajout d'une assertion : continuer l'analyse
Sous hypothèse que l'assertion est vraieParfois donne des sur-approximations
Fausses alarmes. Finesse avec -slevel
2011-01-31 Introduction à Frama-C 23
Normalisation des boucles
Boucle originaleint loop1(void) { int i; for (i=0; i<10; i++){ i = i + 1; } return i;}
Boucle vue par Frama-Cint loop1(void) { int i ; i = 0; while (i < 10) { i ++; i ++; } return (i);}
2011-01-31 Introduction à Frama-C 24
Informations fournies par Frama-C sur les boucles
i = 0
while (i < 10)
i ++
i ++ return (i)
i UNINITIALIZED∈
i {0; 2; 4; 6; 8; ∈ 10; }
i {1; 3; 5; 7; 9; }∈
i {0; 2; 4; 6; 8; 10; }∈
i {10; }∈
i {0; ∈ 2; 4; 6; 8; 10; }
i {0; 2; 4; 6; 8; }∈
i {1; 3; 5; 7; 9; }∈
i {∈ 0; 2; 4; 6; 8; 10; }
2011-01-31 Introduction à Frama-C 25
Alarmes générées
Division et modulo par zéro 10 / y 10 % y
Décalage indéfini (hors de [0..31]) 1 << c
Dépassement en arithmétique non signée ou signéeAvec option -val-signed-overflow-alarms
Valeurs flottantes dangereusesQuand une opération peut rendre une valeur infinie ou NaNUtilisation d'une valeur entière comme flottant
Variables non initialisées et pointeurs sur des variables localesAccès mémoire invalides
Par exemple, débordement de tableauComparaison de pointeurs ou effets de bord dangereux
2011-01-31 Introduction à Frama-C 26
Exemple : valeur absolue (1/2)
2011-01-31 Introduction à Frama-C 27
Exemple valeur absolue (2/2)
frama-c-gui –val –val-signed-overflow-alarms absolute.c
L'analyse de valeur de Frama-CA inféré que la variable x a une valeur dans le domaine [-∞,+∞]En déduit que l'opération « -x » est une erreur pour x = 231
Poursuit l'analyse en supposant que x ≠ -231
Insertion d'une assertionÀ prouver par la suite avec d'autres hypothèsesOu modifier le code (par ex. ajouter un test)
2011-01-31 Introduction à Frama-C 28
Autres exemples
Boucles : démo !Alarmes : démo !
frama-c-gui –val –val-signed-overflow-alarms alarms.c
Division possible par zéro : utilisation de -slevelPrendre en compte au plus n chemins différents lors de l'analyseComparer
frama-c-gui –val possible-zero.cframa-c-gui –val –slevel 2 possible-zero.c
2011-01-31 Introduction à Frama-C 29
Preuve de programme(encore plus fort !)
2011-01-31 Introduction à Frama-C 30
Pourquoi la preuve de programme ?
La vérification abstraite ne permet de vérifier que des classes de propriétésOn veut pouvoir vérifier des propriétés plus larges
Liées au domaine de l'applicationCorrection de bon fonctionnement du programme
=> Utilisation de la preuve de programmeEn utilisant principalement la logique de Hoare
On va en donner des exemples en CExiste aussi pour d'autres langages comme Java
2011-01-31 Introduction à Frama-C 31
Introduction théorique : la logique de Hoare
Logique de Hoare ou triplets de Hoare {P} C {Q}P : Précondition, C : Programme, Q : PostconditionRègles logiques pour raisonner sur la correction d'un programme informatiqueSi P est vraie, alors Q est vraie après exécution de la commande Chttp://fr.wikipedia.org/wiki/Logique_de_Hoare
2011-01-31 Introduction à Frama-C 32
Avantages et limites de la preuve de programme
On peut (parfois) calculer PCalcul de plus faible pré-condition(WP : Weakest Precondition)
Preuves statiquesValables pour toutes les exécutions du programme !
Preuve par rapport à une spécificationSi la spécification est fausse, on prouvera un programme correct mais qui ne fait pas le travail attendu !
Équivalent à la programmation par contrat (Eiffel)
2011-01-31 Introduction à Frama-C 33
En pratique dans Frama-C
Workflow1.Programme original en C, annoté en ACSL
ACSL : ANSI C Specification Language2.Génération des obligations de preuves avec le plugin
Jessie3.Génération des obligations de preuves pour un
prouveur particulier avec Why + Visualisation (gWhy)4.Preuve des obligations de preuve
Prouveurs automatiques : Alt-Ergo, CVC3, …Prouveurs manuels : Coq, Isabelle, …
Généralement des erreurs donc on reboucle sur 1.
2011-01-31 Introduction à Frama-C 34
Un exemple de preuve
Calcul de a + bTrois versions
StandardAvec vérificationAvec spécification
Impact sur la preuve ?Démo !frama-c -jessie sum.c
Impact sur l'efficacité ?3e version : pas de tests !
2011-01-31 Introduction à Frama-C 35
Résultat de la preuve
2011-01-31 Introduction à Frama-C 36
Parenthèse : notion d'invariant
Un invariant : propriété toujours vraieDépend de la définition de « toujours »
Dans Frama-C : utilisé pour les bouclesPropriétés toujours vraies dans une boucle
Également avant d'entrer dans le boucleÉgalement en sortie de boucle
On peut aussi spécifier des invariants sur des variables globalesPar opposition, un variant : décroit strictement
Borné par 0, pour prouver la terminaison des boucles
2011-01-31 Introduction à Frama-C 37
Un exemple plus complet : recherche sur un tableau trié
Exemplearchi-classiquetableau t trié,de longeur nRecherche pardichotomie d'une valeur vDeux bornesl : loweru : upperm = (l+u)/2
2011-01-31 Introduction à Frama-C 38
Première spécification fonctionnelle en ACSL
#pragma JessieIntegerModel(math)
#pragma JessieTerminationPolicy(user)
/*@ requires n >= 0 && \valid_range(t, 0, n-1);
behavior success:
assumes \forall integer k1, k2; 0 <= k1 <= k2 <= n-1
==> t[k1] <= t[k2];
assumes \exists integer k; 0 <= k <= n-1 && t[k] == v;
ensures 0 <= \result <= n-1;
behavior failure:
assumes \forall integer k; 0 <= k <= n-1 ==> t[k] != v;
ensures \result == -1;
*/
2011-01-31 Introduction à Frama-C 39
Premier résultat : pas beaucoup de preuve ! :-(
2011-01-31 Introduction à Frama-C 40
Problème des boucles « opaques »
Le problème : la boucle est « opaque »Solution : ajouter un invariant de boucle
Construire progressivement la propriété que l'on veut obtenirÉtape difficile !
En profiter pour ajouter un variant de boucleProuver la terminaison
2011-01-31 Introduction à Frama-C 41
Invariant de boucle
Construireprogressi-vementla propriétérecherchée\forall int k ;0≤k<n &&t[k] == v=>l ≤ k ≤ u
2011-01-31 Introduction à Frama-C 42
Preuves fonctionnelles : nettement mieux !
Toutes les obligations de preuves sont prouvéesAutomatiquement par Alt-Ergo !
2011-01-31 Introduction à Frama-C 43
Spécification plus complète : arithmétique habituelle
2011-01-31 Introduction à Frama-C 44
Corriger l'erreur !
Erreur habituelle d'overflow !Correction : m = l + (u – l) / 2;
Toutes les preuves sont faitesToujours automatiquement !En toutegénéralité !
Quelles quesoient lesentrées/sortiesdu programme
2011-01-31 Introduction à Frama-C 45
Pour aller plus loin...
Spécification des pointeurs et des tableauxCrucial en langage CParfois difficile
Spécification algébriquePour exprimer des choses plus complexes
Par exemple, spécification et preuve d'un algorithme de tri
2011-01-31 Introduction à Frama-C 46
Pour finir...
2011-01-31 Introduction à Frama-C 47
Limites de Frama-C
Analyse statiqueDonne des résultats exhaustifs mais......problème des approximations... temps de calculs
PreuveMoins simple à utiliserParfois difficile d'établir les annotations
Outil en développementChange régulièrement => suivre les évolutions
2011-01-31 Introduction à Frama-C 48
Conclusion
Frama-C + Why + Alt-ErgoSolution libre complète pour l'analyse et la preuve de code C
Analyse de sécurité basique (overflow, …)Preuves plus élaborées
Fonctionnement correct par rapport à une spécification
Technologie loin d'être parfaite, parfois difficileMais ce n'est pas une raison pour ne pas l'utiliser ! ;-)
2011-01-31 Introduction à Frama-C 49
Pour aller plus loin
Documentation de Frama-C sur son site webDocumentations spécifiques de l'Analyse de valeur et de JessieNotamment http://frama-c.com/training_berlin_2010.html
Voir « Tutorial ACSL by Example », projet DEVICE-SOFT de Fraunhofer First
Formalisation et preuve d'une bibliothèque de structures de données en C