Une introduction à Frama-C - Linux-Francedmentre/gulliver/presentations/expose-frama-c... ·...

Post on 17-May-2020

13 views 0 download

Transcript of Une introduction à Frama-C - Linux-Francedmentre/gulliver/presentations/expose-frama-c... ·...

David MentréDavid Mentré

dmentre@linux-france.orgdmentre@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