Computergestützte Verifikation 18.6.2002 1 Zusammenfassung Abstraktion zentral: Simulation/Bisimulation Simulation ACTL* Bisimulation CTL* Jede Menge abstrakter Zustände kann zu Simulation fortgesetzt werden, aber nicht immer zu einer Bisimulation Die meisten Reduktionstechniken sind Abstraktionen 2 Allgemeine Abstraktionsverfeinerung Spaltung eines abstrakten Zustandes kann weitere Spaltungen notwendig machen Propagation nach rückwärts... ... bis sich nix mehr ändert 3 Scheingegenbeispiele erfüllbare Pfadformel nicht erfüllbare Pfadformel dead end state = erreichbar von einem konkreten Zustand im ersten abstrakten Zustand bad state = hat Nachfolger Verfeinerung = trenne dead end und bad states 4 Lasso-Gegenbeispiele Realisierbar im konkreten System? Schlaufe im konkreten System kann länger sein als im abstrakten System Satz: Wenn abstrakte Schleife überhaupt konkret realisierbar ist, so auch eine der Länge k x A A – Länge der abstrakten Schlaufe k – Anzahl der konkreten Zustände im “kleinsten” abstrakten 5 Zustand Zusammenfassung Abstraktionsverfeinerung a) allgemein: lokale Realisierung der Bisimulationskritierien werden durch das gesamte Transitionssystem propagiert. Wichtig: Umkehrbarkeit der Übergangsrelation b) gegenbeispielgesteuert: Wichtig: 1. Realisierbarkeit abstrakter Pfade im konkreten System muß überprüfbar sein 2. geeignete Heuristiken für Trennung von dead ends und bad states 6 8. Softwareverifikation 8.1 Predicate Abstraction 8.2 Abstract Interpretation 8.3 Slicing 8.4 ... --- Vorsicht Baustelle --7 Probleme bei der Softwareverifikation 1. komplexe Datentypen und Expressions 2. Pointer und dynamische Datenstrukturen 3. Prozeduren und Rekursion 4. Bibliotheken 8 8.1 Predicate Abstraction Basis: n boolesche Prädikate auf Programmvariablen z.B. p = NULL x > y +1 Jedem Prädikat fi wird eine boolesche Variable bi zugeordnet konkreter Zustand = Belegung der Programmvariablen abstrakter Zustand = Formel über den bi Abstraktionsrelation r: c r a gdw. [f1(c), ...., fn(c)] a Halbordnung “impliziert” auf den abstrakten Zuständen pc wird fast immer explizit repräsentiert 9 Abstrakte Zustände c¬d ¬ c d a b ¬ a b (¬ b ¬ d)(¬ a ¬ c¬ ¬ a¬ b a¬ b c d ¬ c¬ d Praxis: z.B. Repräsentation abstrakter Zustände als BDD oder: Restriktion auf einfache Konjunktionen (im Beispiel: ¬ d) 10 Wo kommen Prädikate her? a) nutzerdefiniert b) automatisch - Bedingungen in IF, WHILE, .... - elementare Aussagen in Formel 11 Abstrakter Nachfolger geg.: Abstrakter Zustand a, guarded command g: g x1..n:=T1..n ges.: a’ so daß - jeder konkrete Zustand, der von einem von a repr. Zustand aus per g entsteht, von a’ repr. wird - a’ mglst. stark Berechnung von a’ im allg. schwer, für Konjunktionen leichter: a’: - false, n - j=1 falls a[bifi]i=1..n ¬ g bj falls a[bifi]i=1..n g fj [ xiTi]i=1..n ¬bj falls a[bifi]i=1..n g ¬fj [ xiTi]i=1..n true, sonst Theorembeweiser 12 Beziehung zu Dijkstras Weakest Preconditions geg: Statement s, Zustandseigenschaft f spost(s,f) = die stärkste Eigenschaft f’, so daß jeder Zustand, der vor Ausführung von s f erfüllt, nach s f’ erfüllt. wpre(s,f) = die schwächste Eigenschaft f’, so daß jeder Zustand, der nach Ausführung von s f erfüllt, vor s f’ erfüllt hat. Für Zuweisungen: wpre(x := E, f) = f[x E] Satz: (spost(s,f) f’ ) (f wpre(s,f’) ) exakter abstrakter Nachfolger von a mit command g: spost(g,a) 13 Theorembeweiser Eingabe: prädikatenlog. Formel, nicht immer Stufe 1 1. Formel aus entscheidbarer Theorie Entscheidungsalg. - SAT-Checker - Pressburger Arithmetik - Bitvektor-Arithmetik - Model Checker .... 2. Rewriting - Regeln (z.B. Schlussregeln) Termersetzung, Unifikation - Ziel: Rückführung auf Axiome - erweiterbare Regelbasis - Taktiken 14 Abstraktionsverfeinerung = Hinzunahme weiterer Prädikate 15 typedef struct cell{ int val; struct cell* next; } * list; void partition() { bool b1,b2,b3,b4; Beispiel b1 = unknown(); b3 = unknown(); b2 = true; b4 = unknown(); list partition(list *l, int v) { skip; list curr, prev, newl, nextCurr; while(*) { assume(!b1); curr = * l; skip; prev = NULL; if(*) { newl = NULL; assume(b3) while( curr != NULL) { if(*) { nextCurr = curr -> next; assume(!b2); if(curr -> val > v) { skip; if(prev != NULL) { } prev -> next = nextCurr; if(*) { } skip; if(curr == *l) { } *l = nextCurr; skip; } L: skip; curr -> next = newl; } else { L: newl = curr; b1: curr==NULL assume(!b3); } else { b2: prev==NULL b2 = b1; prev = curr; b3: curr->val>v b4 = b3; } b4: prev->val>v } curr = nextCurr; b1 = unknown(); } b3 = unknown(); return newl; AG(@L curr!=NULL AND curr->val>v } AND (prev->val<=v OR prev=NULL)) 16 } assume(b1); AG(@L !b1 AND b2 AND (!b3 OR b4)) } Pointer bisher: wpre(x := E,f) = f[ x E] stimmt nicht, wenn Pointer beteiligt sind: Beispiel: Sei p = & x; wpre(x = 3, *p > 5) != *p > 5 (für einen potentiellen Alias y) wpre(x := E, f) = ( ( &x = &y f[y E]) ( &x != &y f) ) Nichtdeterminismus, es sei denn, Alias-Analyse kann eine Alternative ausschließen: “may point to”, “may not point17to” Bedingungen IF B THEN T ELSE E END IF * THEN assume(X); T ELSE assume(Y); END X: das stärkste Prädikat (über den gegebenen Prädikaten) das von B impliziert wird Y: das stärkste Prädikat (über den gegebenen Prädikaten) das von ¬B impliziert wird zwischen X und Y kann Lücke klaffen Nichtdet. 18 Prozeduren einfach: Inlining (mit Tiefenrestriktion bei Rekursion) schwierig: Fixpunktberechnung 19 Übung main() { int x,y,z; x = 3; y = x + 1; while(y > 3) { z = 0; if(x == z) { x = x + 1; z = 3; } else { y = x - 1; y++; } y = 2 * y; } x = foo(y,z); Transformiere folgendes C-Programm in ein boolesches Programm, basierend auf den Prädikaten x > 0, y = x und y != 0 } 20