Software Verification Graph Model Graph Coverage Four Structures for Modeling Software Graphs Logic Input Space Syntax Applied to Applied to Source Specs Source Specs Design Use cases Applied to FSMs DNF Source Models Integ Input 2 Definition of a Graph • A set N of nodes, N is not empty • A set N0 of initial nodes, N0 is not empty • A set Nf of final nodes, Nf is not empty • A set E of edges, each edge from one node to another – ( ni , nj ), i is predecessor, j is successor 3 Three Example Graphs 0 0 1 2 3 3 1 4 7 2 5 8 0 6 9 1 Not a valid graph 2 3 N0 = { 0 } N0 = { 0, 1, 2 } N0 = { } Nf = { 3 } Nf = { 7, 8, 9 } Nf = { 3 } 4 Paths in Graphs • Path : A sequence of nodes – [n1, n2, …, nM] – Each pair of nodes is an edge • Length : The number of edges – A single node is a path of length 0 • Subpath : A subsequence of nodes in p is a subpath of p • Reach (n) : Subgraph that can be reached from n 0 1 2 A Few Paths [ 0, 3, 7 ] 3 4 5 6 [ 1, 4, 8, 5, 1 ] [ 2, 6, 9 ] 7 8 Reach (0) = { 0, 3, 4, 7, 8, 5, 1, 9 } Reach ({0, 2}) = G Reach([2,6]) = {2, 6, 9} 9 5 Control Flow Graphs • A CFG models all executions of a method by describing control structures • Nodes : Statements or sequences of statements (basic blocks) • Edges : Transfers of control • Basic Block : A sequence of statements such that if the first statement is executed, all statements will be (no branches) • CFGs are sometimes annotated with extra information – branch predicates – defs – uses • Rules for translating statements into graphs … 6 CFG : The if Statement if (x < y) { y = 0; x = x + 1; } else { x = y; } 1 x<y y=0 x=x+1 x >= y 2 3 x=y 4 if (x < y) { y = 0; x = x + 1; } 1 x<y y=0 x=x+1 2 x >= y 3 7 CFG : The if-return Statement if (x < y) { return; } print (x); return; 1 x<y return 2 x >= y 3 print (x) return No edge from node 2 to 3. The return nodes must be distinct. 8 Loops • Loops require “extra” nodes to be added • Nodes that do not represent statements or basic blocks 9 CFG : while and for Loops x = 0; while (x < y) { y = f (x, y); x = x + 1; } x=0 1 dummy node 2 x<y x >= y 3 4 implicitly initializes loop x=0 y =f(x,y) x=x+1 1 2 for (x = 0; x < y; x++) { y = f (x, y); } y = f (x, y) x<y x >= y 3 5 4 x=x+1 implicitly increments loop 10 CFG : do Loop, break and continue x = 0; do { y = f (x, y); x = x + 1; } while (x < y); println (y) x=0 1 2 x >= y y = f (x, y) x = x+1 x<y x = 0; while (x < y) { y = f (x, y); if (y == 0) { break; } else if y < 0) { y = y*2; continue; } x = x + 1; } print (y); 1 x=0 2 3 y =f(x,y) y == 0 4 break 5 y<0 6 7 3 y = y*2 continue x=x+1 8 11 CFG : The Case (switch) Structure read ( c) ; switch ( c ) { case ‘N’: y = 25; break; case ‘Y’: y = 50; break; default: y = 0; break; } print (y); read ( c ); 1 c == ‘N’ c == ‘Y’ default y = 25; break; 2 3 4 y = 50; break; y = 0; break; 5 print (y); 12 Exponentiation Algorithm 1 scanf(“%d %d”,&x, &y); 2 if (y < 0) pow = -y; else pow = y; 1 2 3 z = 1.0; 4 while (pow != 0) { z = z * x; pow = pow - 1; 5 } 6 if (y < 0) z = 1.0 / z; 7 printf (“%f”,z); 3 4 5 6 7 Bubble Sort Algorithm 1 for (j=1; j<N; j++) { last = N - j + 1; 2 for (k=1; k<last; k++) { 3 if (list[k] > list[k+1]) { temp = list[k]; list[k] = list[k+1]; list[k+1] = temp; 4 } 5 } 6} 7 print(“Done\n”); 1 2 3 4 5 6 7 Example Control Flow – Stats public static void computeStats (int [ ] numbers) { int length = numbers.length; double med, var, sd, mean, sum, varsum; sum = 0; for (int i = 0; i < length; i++) { sum += numbers [ i ]; } med = numbers [ length / 2]; mean = sum / (double) length; varsum = 0; for (int i = 0; i < length; i++) { varsum = varsum + ((numbers [ I ] - mean) * (numbers [ I ] - mean)); } var = varsum / ( length - 1.0 ); sd = Math.sqrt ( var ); System.out.println System.out.println System.out.println System.out.println System.out.println ("length: " + length); ("mean: " + mean); ("median: " + med); ("variance: " + var); ("standard deviation: " + sd); } © Ammann & Offutt Control Flow Graph for Stats public static void computeStats (int [ ] numbers) { int length = numbers.length; double med, var, sd, mean, sum, varsum; sum = 0; for (int i = 0; i < length; i++) { sum += numbers [ i ]; } med = numbers [ length / 2]; mean = sum / (double) length; 1 2 3 i=0 i >= length varsum = 0; i < length for (int i = 0; i < length; i++) i++ 4 { varsum = varsum + ((numbers [ I ] - mean) * (numbers [ I ] - mean)); } var = varsum / ( length - 1.0 ); sd = Math.sqrt ( var ); System.out.println System.out.println System.out.println System.out.println System.out.println ("length: " + length); ("mean: " + mean); ("median: " + med); ("variance: " + var); ("standard deviation: " + sd); } © Ammann & Offutt 5 i=0 6 i < length i >= length 7 8 i++ Test Paths and SESEs • Test Path : A path that starts at an initial node and ends at a final node • Test paths represent execution of test cases – Some test paths can be executed by many tests – Some test paths cannot be executed by any tests • SESE graphs : All test paths start at a single node and end at another node – Single-entry, single-exit – N0 and Nf have exactly one node 1 0 4 3 2 6 5 Double-diamond graph Four test paths [ 0, 1, 3, 4, 6 ] [ 0, 1, 3, 5, 6 ] [ 0, 2, 3, 4, 6 ] [ 0, 2, 3, 5, 6 ] 17 Tests and Test Paths test 1 many-to-one Test Path test 2 test 3 Deterministic software – a test always executes the same test path test 1 many-to-many Test Path 1 test 2 Test Path 2 test 3 Test Path 3 Non-deterministic software – a test can execute different test paths 18 Visiting and Touring • Visit : A test path p visits node n if n is in p A test path p visits edge e if e is in p • Tour : A test path p tours subpath q if q is a subpath of p Path [ 0, 1, 3, 4, 6 ] Visits nodes 0, 1, 3, 4, 6 Visits edges (0, 1), (1, 3), (3, 4), (4, 6) Tours subpaths [0, 1, 3], [1, 3, 4], [3, 4, 6], [0, 1, 3, 4], [1, 3, 4, 6] 19 Data Flow Criteria Goal: Try to ensure that values are computed and used correctly • Definition (def) : A location where a value for a variable is stored into memory • Use : A location where a variable’s value is accessed • def (n) or def (e) : The set of variables that are defined by node n or edge e • use (n) or use (e) : The set of variables that are used by node n or edge e X = 42 0 1 3 2 Defs: def (0) = {X} Z = X*2 4 def (4) = {Z} 6 5 Z = X-8 def (5) = {Z} Uses: use (4) = {X} use (5) = {X} 20 Data Flow Coverage for Source • def : a location where a value is stored into memory – x appears on the left side of an assignment (x = 44;) – x is an actual parameter in a call and the method changes its value – x is a formal parameter of a method (implicit def when method starts) – x is an input to a program • use : a location where variable’s value is accessed – x appears on the right side of an assignment – x appears in a conditional test – x is an actual parameter to a method – x is an output of the program – x is an output of a method in a return statement • If a def and a use appear on the same node, then it is only a DU-pair if the def occurs after the use and the node is in a loop DU Pairs and DU Paths • DU pair : A pair of locations (li, lj) such that a variable • • • • • v is defined at li and used at lj Def-clear : A path from li to lj is def-clear with respect to variable v if v is not given another value on any of the nodes or edges in the path Reach : If there is a def-clear path from li to lj with respect to v, the def of v at li reaches the use at lj du-path : A simple subpath that is def-clear with respect to v from a def of v to a use of v du (ni, nj, v) – the set of du-paths from ni to nj du (ni, v) – the set of du-paths that start at ni 22 Def-Use Pairs ... if (...) { x = ... ; ... } y = ... + x + ... ; Def-Use path ... Definition: x gets a value if (...) { x = ... ... y = ... + x + ... ... Use: the value of x is extracted Definition-Clear or Killing x = ... // A: def x q = ... x = y; // B: kill x, def x z = ... y = f(x); // C: use x Path A..C is not definitionclear Path B..C is definition-clear ... A x = ... ... B x=y ... C y = f(x) Definition: x gets a value Definition: x gets a new value, old value is killed Use: the value of x is extracted Touring DU-Paths • A test path p du-tours subpath d with respect to v if p tours d and the subpath taken is def-clear with respect to v • Three criteria – Use every def – Get to every use – Follow all du-paths 25 Data Flow Test Criteria • First, we make sure every def reaches a use All-defs coverage (ADC) : For each set of du-paths S = du (n, v), TR contains at least one path d in S. • Then we make sure that every def reaches all possible uses All-uses coverage (AUC) : For each set of du-paths to uses S = du (ni, nj, v), TR contains at least one path d in S. • Finally, we cover all the paths between defs and uses All-du-paths coverage (ADUPC) : For each set S = du (ni, nj, v), TR contains every path d in S. 26 Data Flow Testing Example Z = X*2 X = 42 0 1 4 3 2 6 5 Z = X-8 All-defs for X All-uses for X All-du-paths for X [ 0, 1, 3, 4 ] [ 0, 1, 3, 4 ] [ 0, 1, 3, 4 ] [ 0, 1, 3, 5 ] [ 0, 2, 3, 4 ] [ 0, 1, 3, 5 ] [ 0, 2, 3, 5 ] 27 Example: Definition and Uses What are the definitions and uses for the program below? 1. 2. 3. 4 read (x, y); z = x + 2; if (z < y) w = x + 1; else 5. y = y + 1; 6. print (x, y, w, z); Example: Definition and Uses Def 1. 2. 3. 4 read (x, y); z = x + 2; if (z < y) w = x + 1; else 5. y = y + 1; 6. print (x, y, w, z); x, y z w y Use x z, y x y x, y, w, z Example Data Flow – Stats public static void computeStats (int [ ] numbers) { int length = numbers.length; double med, var, sd, mean, sum, varsum; sum = 0.0; for (int i = 0; i < length; i++) { sum += numbers [ i ]; } med = numbers [ length / 2 ]; mean = sum / (double) length; varsum = 0.o; for (int i = 0; i < length; i++) { varsum = varsum + ((numbers [ i ] - mean) * (numbers [ i ] - mean)); } var = varsum / ( length - 1 ); sd = Math.sqrt ( var ); System.out.println System.out.println System.out.println System.out.println System.out.println } ("length: " + length); ("mean: " + mean); ("median: " + med); ("variance: " + var); ("standard deviation: " + sd); Control Flow Graph for Stats public static void computeStats (int [ ] numbers) { int length = numbers.length; double med, var, sd, mean, sum, varsum; sum = 0.0; for (int i = 0; i < length; i++) { sum += numbers [ i ]; } med = numbers [ length / 2 ]; mean = sum / (double) length; 1 ( numbers ) sum = 0 length = numbers.length 2 i=0 3 i >= length varsum = 0.o; i < length for (int i = 0; i < length; i++) { varsum = varsum + ((numbers [ i ] - mean) * (numbers [ i ] - mean));5 4 } sum += numbers [ i ] var = varsum / ( length - 1 ); i++ sd = Math.sqrt ( var ); System.out.println System.out.println System.out.println System.out.println System.out.println } ("length: " + length); ("mean: " + mean); ("median: " + med); ("variance: " + var); ("standard deviation: " + sd); varsum = … i++ med = numbers [ length / 2 ] mean = sum / (double) length varsum = 0 i=0 6 i >= length i < length 7 8 var = varsum / ( length - 1.0 ) sd = Math.sqrt ( va ) print (length, mean med, var, sd) CFG for Stats – With Defs & Uses 1 def (1) = { numbers, sum, length } 2 def (2) = { i } 3 use (3, 5) = { i, length } use (3, 4) = { i, length } 4 5 def (5) = { med, mean, varsum, i } use (5) = { numbers, length, sum } def (4) = { sum, i } use (4) = { sum, numbers, i } 6 use (6, 8) = { i, length } use (6, 7) = { i, length } 7 def (7) = { varsum, i } use (7) = { varsum, numbers, i, mean } 8 def (8) = { var, sd } use (8) = { varsum, length, mean, med, var, sd } Defs and Uses Tables for Stats Node 1 2 3 4 5 Def Use { numbers, sum, length } {i} { numbers } { sum, i } { med, mean, varsum, i } { numbers, i, sum } { numbers, length, sum } 8 { varsum, i } { var, sd } Use (1, 2) (2, 3) (3, 4) (4, 3) { i, length } (3, 5) { i, length } (5, 6) 6 7 Edge { varsum, numbers, i, mean } { varsum, length, var, mean, med, var, sd } (6, 7) { i, length } (7, 6) (6, 8) { i, length } DU Pairs for Stats variable DU Pairs defs come before uses, do not count as DU pairs numbers (1, 4) (1, 5) (1, 7) length (1, 5) (1, 8) (1, (3,4)) (1, (3,5)) (1, (6,7)) (1, (6,8)) med var sd mean sum varsum i (5, 8) (8, 8) defs after use in loop, these are valid DU pairs (8, 8) (5, 7) (5, 8) No def-clear path … (1, 4) (1, 5) (4, 4) (4, 5) different scope for i (5, 7) (5, 8) (7, 7) (7, 8) (2, 4) (2, (3,4)) (2, (3,5)) (2, 7) (2, (6,7)) (2, (6,8)) (4, 4) (4, (3,4)) (4, (3,5)) (4, 7) (4, (6,7)) (4, (6,8)) (5, 7) (5, (6,7)) (5, (6,8)) No path through graph from (7, 7) (7, (6,7)) (7, (6,8)) nodes 5 and 7 to 4 or 3 DU Paths for Stats variable numbers length med var sd sum DU Pairs DU Paths (1, 4) (1, 5) (1, 7) [ 1, 2, 3, 4 ] [ 1, 2, 3, 5 ] [ 1, 2, 3, 5, 6, 7 ] (1, 5) (1, 8) (1, (3,4)) (1, (3,5)) (1, (6,7)) (1, (6,8)) [ 1, 2, 3, 5 ] [ 1, 2, 3, 5, 6, 8 ] [ 1, 2, 3, 4 ] [ 1, 2, 3, 5 ] [ 1, 2, 3, 5, 6, 7 ] [ 1, 2, 3, 5, 6, 8 ] (5, 8) (8, 8) (8, 8) (1, 4) (1, 5) (4, 4) (4, 5) [ 5, 6, 8 ] No path needed No path needed [ 1, 2, 3, 4 ] [ 1, 2, 3, 5 ] [ 4, 3, 4 ] [ 4, 3, 5 ] variable mean DU Pairs (5, 7) (5, 8) DU Paths [ 5, 6, 7 ] [ 5, 6, 8 ] varsum (5, 7) (5, 8) (7, 7) (7, 8) [ 5, 6, 7 ] [ 5, 6, 8 ] [ 7, 6, 7 ] [ 7, 6, 8 ] i (2, 4) (2, (3,4)) (2, (3,5)) (4, 4) (4, (3,4)) (4, (3,5)) (5, 7) (5, (6,7)) (5, (6,8)) (7, 7) (7, (6,7)) (7, (6,8)) [ 2, 3, 4 ] [ 2, 3, 4 ] [ 2, 3, 5 ] [ 4, 3, 4 ] [ 4, 3, 4 ] [ 4, 3, 5 ] [ 5, 6, 7 ] [ 5, 6, 7 ] [ 5, 6, 8 ] [ 7, 6, 7 ] [ 7, 6, 7 ] [ 7, 6, 8 ] DU Paths for Stats – No Duplicates There are 38 DU paths for Stats, but only 12 unique [ 1, 2, 3, 4 ] [ 1, 2, 3, 5 ] [ 1, 2, 3, 5, 6, 7 ] [ 1, 2, 3, 5, 6, 8 ] [ 2, 3, 4 ] [ 2, 3, 5 ] [ 4, 3, 4 ] [ 4, 3, 5 ] [ 5, 6, 7 ] [ 5, 6, 8 ] [ 7, 6, 7 ] [ 7, 6, 8 ] 4 expect a loop not to be “entered” 6 require at least one iteration of a loop 2 require at least two iterations of a loop Test Cases and Test Paths Test Case : numbers = (44) ; length = 1 Test Path : [ 1, 2, 3, 4, 3, 5, 6, 7, 6, 8 ] Additional DU Paths covered (no sidetrips) [ 1, 2, 3, 4 ] [ 2, 3, 4 ] [ 4, 3, 5 ] [ 5, 6, 7 ] [ 7, 6, 8 ] The five stars that require at least one iteration of a loop Test Case : numbers = (2, 10, 15) ; length = 3 Test Path : [ 1, 2, 3, 4, 3, 4, 3, 4, 3, 5, 6, 7, 6, 7, 6, 7, 6, 8 ] DU Paths covered (no sidetrips) [ 4, 3, 4 ] [ 7, 6, 7 ] The two stars that require at least two iterations of a loop Other DU paths require arrays with length 0 to skip loops But the method fails with index out of bounds exception… med = numbers [length / 2]; A fault was found Example: Def-Use Associations def-use associations for variable z. read (z) x = 0 y = 0 if (z 0) { x = sqrt (z) if (0 x && x 5) y = f (x) else y = h (z) } y = g (x, y) print (y) Example: Def-Use Associations read (z) def-use associations for x = 0 variable x. y = 0 if (z 0) { x = sqrt (z) if (0 x && x 5) else } y = g (x, y) print (y) y = f (x) y = h (z) Example: Def-Use Associations read (z) def-use associations for variable x = 0 y. y = 0 if (z 0) { x = sqrt (z) if (0 x && x 5) y = f (x) else y = h (z) } y=g (x, y) print (y) Using Control-flow Testing to Test Function ABS • Consider the following function: /* ABS This program function returns the absolute value of the integer passed to the function as a parameter. INPUT: An integer. OUTPUT: The absolute value if the input integer. */ 1 int ABS(int x) 2 { 3 if (x < 0) 4 x = -x; 5 return x; 6 } The Flowgraph for ABS /* ABS This program function returns the absolute value of the integer passed to the function as a parameter. INPUT: An integer. OUTPUT: The absolute value if the input integer. */ 1 int ABS(int x) 2 { 3 if (x < 0) 4 x = -x; 5 return x; 6 } 1 3 5 6 Example: Using Control-flow Testing to Test Program COUNT • Consider the following program: /* COUNT This program counts the number of characters and lines in a text file. INPUT: Text File OUTPUT: Number of characters and number of lines. */ 1 main(int argc, char *argv[]) 2 { 3 int numChars = 0; 4 int numLines = 0; 5 char chr; 6 FILE *fp = NULL; 7 Program COUNT (Cont’d) 8 if (argc < 2) 9 { 10 printf(“\nUsage: %s <filename>”, argv[0]); 11 return (-1); 12 } 13 fp = fopen(argv[1], “r”); 14 if (fp == NULL) 15 { 16 perror(argv[1]); 17 return (-2); 18 } /* display error message */ Program COUNT (Cont’d) 19 while (!feof(fp)) 20 { 21 chr = getc(fp); /* read character */ 22 if (chr == ‘\n’) /* if carriage return */ 23 ++numLines; 24 else 25 ++numChars; 26 } 27 printf(“\nNumber of characters = %d”, numChars); 28 printf(“\nNumber of lines = %d”, numLines); 29 } The Flowgraph for COUNT 1 8 11 14 17 19 22 23 24 26 • The junction at line 12 and line 18 are not needed because if you are at these lines then you must also be at line 14 and 19 respectively. 29 An example: All-du-paths What are all the du-paths in the following program ? read (x,y); for (i = 1; i <= 2; i++) print (“hello”); if (y < 0) print (x); Example: pow(x,y) /* pow(x,y) This program computes x to the power of y, where x and y are integers. INPUT: The x and y values. OUTPUT: x raised to the power of y is printed to stdout. */ 1 void pow (int x, y) 2 { 3 float z; 4 int p; 5 if (y < 0) 6 p = 0 – y; 7 else p = y; 8 z = 1.0; 9 while (p != 0) 10 { 11 z = z * x; 12 p = p – 1; 13 } 14 if (y < 0) 15 z = 1.0 / z; 16 printf(z); 17 } Def-Use Pairs (3) /** Euclid's algorithm */ public class GCD { public int gcd(int x, int y) { int tmp; // A: def x, y, tmp while (y != 0) { // B: use y tmp = x % y; // C: def tmp; use x, y x = y; // D: def x; use y y = tmp; // E: def y; use tmp } return x; // F: use x } Find all DU for x and y Public int gcd (int x, int y) { int tmp; While (y!= 0) { tmp= x % y; x = y; y = tmp; } return x; } 50