Lecture 5: Code Red, Ariane 5, and Gambling CS201j: Engineering Software University of Virginia Computer Science David Evans http://www.cs.virginia.edu/~evans Menu • No checking, run-time checking, static checking • Implementing Data Abstractions • Checking Invariants • Rep Exposure • PS2 Comments 12 September 2002 CS 201J Fall 2002 2 Handling Mistakes • No checking – Assume programmers know what they are doing • Run-time checking – Check for anomalous behavior during program execution • Static checking – Check at compile-time – Know properties of all possible executions before executing code 12 September 2002 CS 201J Fall 2002 3 Example: Array Bounds What should happen when the program writes beyond the bounds of an array? int a[10]; a[10] = 17; 12 September 2002 CS 201J Fall 2002 4 C/C++ Answer • Checking is just a waste of execution time, we should trust the programmer not to make mistakes. # include <iostream.h> int main (void) { int x = 9; char s[4]; } 12 September 2002 cin >> s; cout << "s is: " << s << endl; cout << "x is: " << x << endl; CS 201J Fall 2002 5 C/C++ Bounds NonChecking # include <iostream.h> int main (void) { int x = 9; char s[4]; } cin >> s; cout << "s is: " << s << endl; cout << "x is: " << x << endl; 12 September 2002 > g++ -o bounds bounds.cc > bounds cs (User input) s is: cs x is: 9 > bounds cs201 s is: cs201 x is: 49 > bounds cs201j s is: cs201j x is: 27185 > bounds aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa s is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa x is: 1633771873 Segmentation fault (core dumped) CS 201J Fall 2002 6 s ‘c’ ‘s’ ‘2’ What’s going on?!! # include <iostream.h> int main (void) { int x = 9; char s[4]; ‘0’ x ‘1’ = 9 49 } cin >> s; cout << "s is: " << s << endl; cout << "x is: " << x << endl; > bounds cs201 s is: cs201 x is: 49 12 September 2002 CS 201J Fall 2002 7 s ‘c’ ‘s’ ‘2’ What’s going on?!! # include <iostream.h> int main (void) { int x = 9; char s[4]; ‘0’ x ‘1’ = 9 49 } cin >> s; cout << "s is: " << s << endl; cout << "x is: " << x << endl; ‘j’ = 106 In C/C++, space for int is enough to hold 4 chars. 12 September 2002 > bounds cs201j s is: cs201j x is: 27185 CS 201J Fall 2002 8 # include <iostream.h> s ‘a’ ‘a’ int main (void) { int x = 9; char s[4]; ‘a’ ‘a’ x ‘a’ 9 ‘a’ ‘a’ 9 ‘a’ return address 12 September 2002 ‘a’ } cin >> s; cout << "s is: " << s << endl; cout << "x is: " << x << endl; > bounds aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa s is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa x is: 1633771873 Segmentation fault (core dumped) When main returns, execution jumps to the return address stored on the stack. But, the input overwrote that return address! CS 201J Fall 2002 9 When things go really bad… • If person entering input is clever, they can put what they want in the return address, and their own code after that to jump to! • “Buffer Overflow Attack” • “Stack Smashing” 12 September 2002 CS 201J Fall 2002 10 Code Red 12 September 2002 CS 201J Fall 2002 11 Buffer Overflows • Code Red: exploited buffer overflow in Microsoft’s IIS (web server) • Attacker sends excessively long request to web server, overflows buffer and puts virus code on stack • About ½ of all security problems are due to buffer overflows! 12 September 2002 CS 201J Fall 2002 12 Array Bounds in Java public class AverageLength { public static void main (/*@non_null@*/ String args[]) { String filename = args[0]; … } } > javac AverageLength.java > java AverageLength Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException at AverageLength.main(AverageLength.java:7) 12 September 2002 CS 201J Fall 2002 13 Array Bounds with ESC/Java public class AverageLength { public static void main (/*@non_null@*/ String args[]) { String filename = args[0]; … } } > escjava AverageLength.java AverageLength.java:7: Warning: Array index possibly too large (IndexTooBig) String filename = args[0]; ^ 12 September 2002 CS 201J Fall 2002 14 Array Bounds Checking • C/C++: No checking + No execution cost ? Lower Development cost? (if you don’t care about robustness) - Really, really bad things can happen (and do often for typical programs) 12 September 2002 CS 201J Fall 2002 15 Array Bounds Checking • Java: Run-time checking – Performance cost: virtual machine needs to check array indexes are in bounds + Get a run-time error, instead of Code Red But, sometimes run-time errors can be really, really bad too! 12 September 2002 CS 201J Fall 2002 16 Run-Time Exceptions Before Run-Time Exception After Run-Time Exception Rubble, $0B Ariane V (European) rocket, $5B Rocket exploded because of Run-Time Exception (1996) (not array bounds, value out of range – one bad line of code) 12 September 2002 CS 201J Fall 2002 17 Array Bounds Checking • ESC/Java: static checking + Check at compile-time: know there will not be an array bounds error on any possible execution ? If you trust the compile time checking, can turn off run-time checking (no performance penalty) ? More apparent effort to develop code (but is there really?) 12 September 2002 CS 201J Fall 2002 18 Implementing Data Abstractions Undirected Graph: B D A E C 12 September 2002 CS 201J Fall 2002 19 Specifying Graph public class Graph { // OVERVIEW: // A Graph is a mutable type that // represents an undirected // graph. It consists of nodes that are // named by Strings, and edges that // connect a pair of nodes. Do all nodes have to be connected? Can there be more than one edge between the same two nodes? 12 September 2002 CS 201J Fall 2002 20 Abstract Notation // // // // // // // A typical Graph is: < Nodes, Edges > where Nodes = { n1, n2, …, nm } and Edges = { {from_1, to_1}, …, {from_n, to_n} } 12 September 2002 CS 201J Fall 2002 21 Operations • Creator public Graph () // EFFECTS: Initializes this to a graph // with no nodes or edges: < {}, {} >. 12 September 2002 CS 201J Fall 2002 22 Mutators void addNode (String name) // REQUIRES: name is not the name of a node in this // MODIFIES: this // EFFECTS: adds a node named name to this: // this_post = < this_pre.nodes U { name }, this_pre.edges > void addEdge (String fnode, String tnode) // REQUIRES: fnode and tnode are names of nodes What if there is already an edge there? // in this. Can nodes have edges to themselves? // MODIFIES: this // EFFECTS: Adds an edge from fnode to tnode to this: // this_post = < this_pre.nodes, // this_pre.edges U { {fnode, tnode} } > 12 September 2002 CS 201J Fall 2002 23 Observers boolean hasNode (String node) // EFFECTS: Returns true iff node is // a node in this. 12 September 2002 CS 201J Fall 2002 24 Observers StringIterator nodes () // EFFECTS: Returns the StringIterator that // yields all nodes in this in arbitrary // order. 12 September 2002 CS 201J Fall 2002 25 Observers StringIterator neighbors (String node) // REQUIRES: node is a node in this // EFFECTS: Returns the StringIterator that // yields all nodes in this that are // directly connected to node: // \result = // { n | {node, n} is in this.edges } 12 September 2002 CS 201J Fall 2002 26 Implementing Graph • Choose a rep – Think about implementing addEdge, addNode and getNeighbors • Next time: come to class Tuesday with at least one idea for a rep to implement Graph 12 September 2002 CS 201J Fall 2002 27 PS2 12 September 2002 CS 201J Fall 2002 28 Specifications • Describe what it does that a caller can see, not how it does it. – Specifications should never mention local variables: caller can’t see them – Language like “calculates”, “reads”, “goes through”, etc. are a bad sign: these are not actions that are visible to the caller • Use requires clause to eliminate inputs from consideration (that you don’t describe in your effects) 12 September 2002 CS 201J Fall 2002 29 Specifying AverageLength public class AverageLength { public static void main (String args[]) // REQUIRES: } After you fixed the code, do we need to require args has at least one element? No, we can specify in EFFECTS what happens when args has no elements. Only need to use REQUIRES to eliminate inputs where the behavior is not known. 12 September 2002 CS 201J Fall 2002 30 Specifying AverageLength public class AverageLength { public static void main (String args[]) // REQUIRES: } Anything needed in REQUIRES? String filename = args[0]; … FileInputStream infile = new FileInputStream (filename); StringTable names = new StringTable (infile); We need to satisfy the require clauses of all methods called in implementation! 12 September 2002 CS 201J Fall 2002 31 public StringTable (java.io.InputStream instream) // requires: The stream instream is a names file containing lines of the form // <name>: <rate> // where the name is a string of non-space characters and the rate is // a floating point number. // modifies: instream // effects: Initializes this as a names table using the data from instream. public class AverageLength { public static void main (/*@non_null@*/ String args[]) // REQUIRES: args is not null, and if args has at least one // element, and args[0] is the name of a readable file, the // file named by args[0] must contain lines of the form // <name>: <rate> // where the name is a string of non-space characters and // the rate is a floating point number. 12 September 2002 CS 201J Fall 2002 32 AverageLength Modifies • Should we also take the modifies clause from StringTable (FileInputStream)? public StringTable (java.io.InputStream instream) // modifies: instream // effects: Initializes this as a names table using the data from instream. No: the stream passed to StringTable (FileInputStream) is a local variable. Although it is modified, this modification is not visible to the caller. How do we know the file associate with the stream is not modified? • AverageLength does modify System.out by printing MODIFIES: System.out 12 September 2002 CS 201J Fall 2002 33 AverageLength Effects public class AverageLength { public static void main (/*@non_null@*/ String args[]) // REQUIRES: If args has at least one element, and args[0] // is the name of a readable file, the file named by args[0] // must contain lines of the form <name>: <rate> where // the name is a string of non-space characters and the rate // is a floating point number. // MODIFIES: System.out // EFFECTS: If args is an empty array, prints a warning and // exits. If args[0] is not the name of a readable file, // prints a warning and exits. If the file named by args[0] // is empty, prints a warning an exits. Otherwise, prints a // message that indicates the average length of the names in // the names file named by args[0]. 12 September 2002 CS 201J Fall 2002 34 Black Box/Glass Box Testing • Black Box testing: consider specification only – Paths through specification • Glass Box testing: consider code – Paths through the code 12 September 2002 CS 201J Fall 2002 35 Black Box Tests public class AverageLength { public static void main (/*@non_null@*/ String args[]) // REQUIRES: If args has at least one element, and args[0] // is the name of a readable file, the file named by args[0] // must contain lines of the form <name>: <rate> where // the name is a string of non-space characters and the rate // is a floating point number. // MODIFIES: System.out // EFFECTS: If args is an empty array, prints a warning and // exits. If args[0] is not the name of a readable file, // prints a warning and exits. If the file named by args[0] // is empty, prints a warning an exits. Otherwise, prints a // message that indicates the average length of the names in // the names file named by args[0]. Obvious paths: 1. args is an empty array (run java AverageLength) 2. args[0] is an empty file 3. otherwise (note: args[0] file must satisfy requires clause) Should try files with one entry and many entries 12 September 2002 CS 201J Fall 2002 36 Glass Box Tests • Devise test cases that exercise interesting paths through code: – Both branches of an if – Zero, one, many iterations of a loop • For straightforward implementations, often there are no new tests (beyond Black Box) • For complex procedures (like most of your NameTrends), there may be many new tests 12 September 2002 CS 201J Fall 2002 37 Wagering Strategy • How did you decide what to wager? • How should you have decided what to wager? 12 September 2002 CS 201J Fall 2002 38 Commerce School Strategy If p is the probability your code is correct, Expected Return = wp – 2w (1-p) = 3wp - 2w If p < 2/3, maximize with w = 0. If p = 2/3, expected return is 0 regardless of wager. If p > 2/3, expected return increases with w, bet maximum. 12 September 2002 CS 201J Fall 2002 39 Psychological Strategies • Expected return is a bad model, since the value is non-linear – If my ps was worth 90 without wager, 1/3 change of getting a 50 is not worth 2/3 chance of getting 110. • Dave is probably crazy for asking such a question, so I have no clue how this will be graded 12 September 2002 CS 201J Fall 2002 40 Why Confidence Matters? • Incorrect code, no confidence – Worthless, no one can use it (but if they do, they get what they deserve) • Correct code, no confidence – Worthless, no one can use it (but if they do, they get lucky) • Incorrect code, high confidence – Dangerous! • Correct code, high confidence – Valuable 12 September 2002 CS 201J Fall 2002 41 PS2 Wagering • Hard to grade because of vague specs – If I was super strict, everyone would have lost their wager. • PS3: wagering question will be judged by testing your program against a (secret) test suite that I design 12 September 2002 CS 201J Fall 2002 42 Easy way to get 100 on PS 2: • Get full credit for questions 1-4 • Answer question 5 (specify name trends) badly (0): static public void main (String args[]) // REQUIRES: false // EFFECTS: Prints out a correct proof of // P = NP. 12 September 2002 CS 201J Fall 2002 43 Remaining Answers 6. Implement program that satisfies spec: static public void main (String args[]) { // REQUIRES: false // EFFECTS: Prints out a correct proof of P = NP. System.err.println (“Ha ha ha!”) } 7. Testing Strategy • No testing necessary, no way to satisfy requires 8. Bet: 20 12 September 2002 Note: I didn’t actually want you to do this! CS 201J Fall 2002 44 Charge • Next class: implementing Graph – Choose a rep, abstraction function and rep invariant – Implement the methods • Before class: think about your rep • PS3: due next Thursday 12 September 2002 CS 201J Fall 2002 45