Fixing Software Before It Breaks SIGAda 2001 S. Tucker Taft CTO AverCom Corp., a Titan Company October 3, 2001 Bloomington, MN.

Slides:



Advertisements
Similar presentations
Programming Languages and Paradigms
Advertisements

Names and Bindings.
1 Copyright © 1998 by Addison Wesley Longman, Inc. Chapter 13 In a language without exception handling: When an exception occurs, control goes to the operating.
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
Chapter 10 Introduction to Arrays
Abstract Data Types Data abstraction, or abstract data types, is a programming methodology where one defines not only the data structure to be used, but.
Inheritance Inheritance Reserved word protected Reserved word super
CSI 3120, Exception handling, page 1 Exception and Event Handling Credits Robert W. Sebesta, Concepts of Programming Languages, 8 th ed., 2007 Dr. Nathalie.
CS 330 Programming Languages 10 / 16 / 2008 Instructor: Michael Eckmann.
1 Chapter 4 Language Fundamentals. 2 Identifiers Program parts such as packages, classes, and class members have names, which are formally known as identifiers.
Software Testing and Quality Assurance
ISBN Chapter 5 Names, Bindings, Type Checking, and Scopes Names Variables The Concept of Binding Type Checking Strong Typing Type Compatibility.
C#.NET C# language. C# A modern, general-purpose object-oriented language Part of the.NET family of languages ECMA standard Based on C and C++
CS 330 Programming Languages 09 / 18 / 2007 Instructor: Michael Eckmann.
Aalborg Media Lab 23-Jun-15 Inheritance Lecture 10 Chapter 8.
OOP #10: Correctness Fritz Henglein. Wrap-up: Types A type is a collection of objects with common behavior (operations and properties). (Abstract) types.
Exceptions Problems with error reporting so far –Either ignored exceptions or terminated program on first error. –Error handling and regular code mixed.
CS 330 Programming Languages 09 / 16 / 2008 Instructor: Michael Eckmann.
Examining the Code [Reading assignment: Chapter 6, pp ]
1 Exception and Event Handling (Based on:Concepts of Programming Languages, 8 th edition, by Robert W. Sebesta, 2007)
Exceptions. Many problems in code are handled when the code is compiled, but not all Some are impossible to catch before the program is run  Must run.
© 2003 G. Drew Kessler and William M. Pottenger1 Subroutines (Part 1) CSE 262, Spring 2003.
Ranga Rodrigo. Class is central to object oriented programming.
Language Evaluation Criteria
1 Exception Handling Introduction to Exception Handling Exception Handling in PLs –Ada –C++ –Java Sebesta Chapter 14.
CS 363 Comparative Programming Languages Expressions and Assignment Statements.
Type Equivalence Rules Ada –Strict name equivalence except for almost everything Unique array constructors give rise to unique types Subtypes can create.
1 Debugging and Testing Overview Defensive Programming The goal is to prevent failures Debugging The goal is to find cause of failures and fix it Testing.
EE4E. C++ Programming Lecture 1 From C to C++. Contents Introduction Introduction Variables Variables Pointers and references Pointers and references.
CSC3315 (Spring 2009)1 CSC 3315 Programming Languages Hamid Harroud School of Science and Engineering, Akhawayn University
Names Variables Type Checking Strong Typing Type Compatibility 1.
5-1 Chapter 5: Names, Bindings, Type Checking, and Scopes Variables The Concept of Binding Type Checking Strong Typing Type Compatibility Scope and Lifetime.
March 12, ICE 1341 – Programming Languages (Lecture #6) In-Young Ko Programming Languages (ICE 1341) Lecture #6 Programming Languages (ICE 1341)
07 Coding Conventions. 2 Demonstrate Developing Local Variables Describe Separating Public and Private Members during Declaration Explore Using System.exit.
SWE 619 © Paul Ammann Procedural Abstraction and Design by Contract Paul Ammann Information & Software Engineering SWE 619 Software Construction cs.gmu.edu/~pammann/
Hello.java Program Output 1 public class Hello { 2 public static void main( String [] args ) 3 { 4 System.out.println( “Hello!" ); 5 } // end method main.
Arrays An array is a data structure that consists of an ordered collection of similar items (where “similar items” means items of the same type.) An array.
Question of the Day  On a game show you’re given the choice of three doors: Behind one door is a car; behind the others, goats. After you pick a door,
Low-Level Detailed Design SAD (Soft Arch Design) Mid-level Detailed Design Low-Level Detailed Design Design Finalization Design Document.
Testing. 2 Overview Testing and debugging are important activities in software development. Techniques and tools are introduced. Material borrowed here.
Slide: 1 Copyright © AdaCore Subprograms Presented by Quentin Ochem university.adacore.com.
1 Type Checking Type checking ensures that the operands and the operator are of compatible types Generalized to include subprograms and assignments Compatible.
C++ History C++ was designed at AT&T Bell Labs by Bjarne Stroustrup in the early 80's Based on the ‘C’ programming language C++ language standardised in.
CSE 425: Data Types I Data and Data Types Data may be more abstract than their representation –E.g., integer (unbounded) vs. 64-bit int (bounded) A language.
Programming Languages and Paradigms Imperative Programming.
Arithmetic Expressions
MCS 270 Spring 2014 Object-Oriented Software Development.
Interfaces About Interfaces Interfaces and abstract classes provide more structured way to separate interface from implementation
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
How to execute Program structure Variables name, keywords, binding, scope, lifetime Data types – type system – primitives, strings, arrays, hashes – pointers/references.
1 Structure of Compilers Lexical Analyzer (scanner) Modified Source Program Parser Tokens Semantic Analysis Syntactic Structure Optimizer Code Generator.
PROGRAMMING TESTING B MODULE 2: SOFTWARE SYSTEMS 22 NOVEMBER 2013.
Refactoring Agile Development Project. Lecture roadmap Refactoring Some issues to address when coding.
Java How to Program, 9/e © Copyright by Pearson Education, Inc. All Rights Reserved.
Exceptions Lecture 11 COMP 401, Fall /25/2014.
Terms and Rules II Professor Evan Korth New York University (All rights reserved)
Chapter 1: Preliminaries Lecture # 2. Chapter 1: Preliminaries Reasons for Studying Concepts of Programming Languages Programming Domains Language Evaluation.
(C) 2010 Pearson Education, Inc. All rights reserved. Java How to Program, 8/e.
ISBN Chapter 12 Support for Object-Oriented Programming.
UMass Lowell Computer Science Java and Distributed Computing Prof. Karen Daniels Fall, 2000 Lecture 10 Java Fundamentals Objects/ClassesMethods.
Dr. M. Al-Mulhem Introduction 1 Chapter 6 Type Systems.
Type Checking, and Scopes
Java Primer 1: Types, Classes and Operators
Input Space Partition Testing CS 4501 / 6501 Software Testing
Exception Handling and Event Handling
Arithmetic Expressions
Java Programming Language
Covering CWE with Programming Languages and Tools
Java Programming Language
Assertions References: internet notes; Bertrand Meyer, Object-Oriented Software Construction; 4/25/2019.
Presentation transcript:

Fixing Software Before It Breaks SIGAda 2001 S. Tucker Taft CTO AverCom Corp., a Titan Company October 3, 2001 Bloomington, MN

Outline  Why Static Analysis?  Comparison of Static Error Detection in Current Ada versus C-based Languages  How Far Can Static Analysis Go?  Possible New (Annotation) Language Features to Enhance Static Error Detection  Conclusion  Acknowledgements: These ideas have been freely stolen from SPARK, Eiffel, Cyclone, Hermes/NIL,... and further developed in conjunction with Bob Duff

Why Static Analysis?  Full Run-Time Coverage Testing is Very Expensive  If Run-Time Exceptions are Possible, Coverage Testing Becomes That Much Harder  Tasking Creates A Potentially Intractable Number of Distinct Cases to Test  Generics Can Only Be Tested At Run-Time for Specific Instantiations -- Testing in General At Run-Time Is Not Defined.

Comparing Current Ada with C-Based Languages  Array Checking  Ada: Must be correct index type  C/C++/Java: Any integer type may index any array; Java checks out-of-range at run-time  Enumeration Types  Ada: No implicit conversion to/from an enumeration type  C: Freely interconvertible with any integer type  C++: Freely convertible to integer, but not back  Java: No enumeration types, must use ints with named constants

Comparing Current Ada with C-Based Languages (cont’d)  Generic Templates  Ada: Compile-time checks that generic body uses parameters appropriately  C++: No checking of generic template until instantiated  Synchronized/Protected Operations  Ada: All operations with access to protected data components lock during call  Java: May always add operation that doesn’t lock, either in same class or a subclass

Comparing Current Ada with C-Based Languages (cont’d)  Reading Uninitialized Variables  Ada: Bounded error to reference  Java: Disallowed at Compile-Time  Exceptions Handled  Ada: Unhandled exceptions propagated  Java: Unhandled exceptions disallowed at compile-time unless in “throws” clause (or “unchecked” exception)

How Far Can Static Analysis Go?  My Claim:  All situations that might result in failures of language-defined checks, or in bounded error or erroneous execution, can be eliminated at compile-time  My Concern:  How conservative, burdensome, or restrictive would the compile-time checks become?  SPARK-Ada95 is example of fairly restrictive subset, though it has grown into a highly usable system.

How Far Can Static Analysis Go? (cont’d)  My Belief:  Careful (annotation) language design can produce a highly flexible and usable language which nevertheless has no language-defined run-time failure conditions.  Many Higher-level or Application-specific failure conditions or inconsistencies can also be eliminated at compile-time using a “programmable” annotation language  Physical Units Checking is an example  Need to Study:  What are Typical Sources of (Human) Error

Typical Mistakes  Sin of Omission  Uninitialized Variables  Missing case in switch/case statement  Missing token/character (e.g. “break;”, “=“, “&”)  Missing return statement  Missing “increment” step in loop  Sin of Confusion  Swapping the parameters to “strcpy”  Confusing 1 = success vs. 0 = success  Forgetting about implicit effects or precedence

Typical Mistakes (cont’d)  Sin of Short-Sightedness (aka Laziness)  Fixed size buffer (the famous “gets” hole in “sendmail”)  Fixed size table (annoying “too many revisions” in RCS)  Well (Human) Engineered Language can:  Minimize Occurrence of These, or...  Catch These Mistakes at Compile-Time Well Human Engineered

Blaming the Worker for C’s Poor Human Engineering  A Software Fault Prevention Approach in Coding and Root Cause Analysis  Weider D. Yu, Bell Labs Technical Journal, April-June 1998  The top three root causes of the faults were:  execution/oversight (38%),  Inadequate attention to details (75%) and inadequate considerations to all relevant issues (11%);  resource/planning (19%),  Not enough engineer time (76%) and not enough internal support (4%);  education and training (15%).  Area of technical responsibility (68%) and programming language usage (15%).

Lucent 5ESS Software Fault Root Cause Analysis No Mention of Defective Material (i.e. the C Language) -- Only Defective Workmanship!

Lucent 5ESS C Programmer Advisories  Initialize all variables before use  Control flow of break and continue statements  Check C operator associativity and precedence for correct usage  Ensure loop boundaries are correct  Do not over-index arrays  Ensure value of variables is not truncated  Reference pointer variables correctly  Check pointer increments/decrements  Ensure logical OR and AND tests are correct

Lucent 5ESS C Programmer Advisories (cont’d)  Use all assignment and equal operators as intended  Ensure bit field data types are either unsigned or enum  Use logical AND and mask operators as intended  Check preprocessor conditionals  Check comment delimiters  Test unsigned variables for == 0 or != 0 only  Use cast cautiously Such Advisories are a sure sign of Poor Human Engineering and/or Defective Materials

The Big Trick to Catching Errors Early  Redundancy  Force the programmer to follow the writing- teacher’s rule:  Tell you what they are going to say  Tell you  Tell you what they said  Kinds of Redundancy:  Type Declarations  Subrange Declarations  var vs. const, in vs. out specification  Assertions, Pre/Post Conditions  Separation of Interface and Implementation  Tools should check for consistency

The Second Big Trick  Compartmentalization  Create many different specialized types  Any one type may only be used in appropriate places  Examples of Compartmentalization:  Use Uniquely shaped plugs and sockets  Define Appropriate Enumeration Types  Disallow Implicit Numeric Conversions, Allow usage- specific numeric types (“age”, “length”)  Specify Minimal Subrange for each variable  Require Boolean inside a conditional test  Avoid “if (func_name) { …”  Create a “gauntlet” for the program to pass  Lot’s of little, picky, tests on every line (like a slalom)

The Third Big Trick  Require Completeness  Don’t Fill in the blanks without explicit direction (e.g. explicit and local specification of default)  Examples of Completeness Requirements:  Case statement must cover all possible values of expression  Initializer must provide value for all components  Implementation Module must provide code for every (non-abstract) function appearing in Interface Module; every abstract function must be overridden  All Local Variables must be Explicitly Initialized on all paths prior to use  Every path out of function requires a “return” or “raise”

The Last Big Trick  Require Explicitness  aka: “Say it at least once!”  Favor the reader over the writer  Minimize implicit/side effects  Keep semantics obvious  Disallow possibly ambiguous cases  E.g., don’t create elaborate preference rules or implicit conversion rules  Make sure any defaults are safe and benign  Make sure the simple thing to do is the safest and easiest to maintain  Make sure unsafe programming constructs are highly visible, and require extra and explicit work at each use X

Examples of Areas for Enhanced Static Analysis for Ada  Uninitialized Variables  Null Checks  Erroneous Concurrent Access  Access-Before Elaboration  Physical Units Checking  Programmable Static Analysis

Basic Principles  All Run-Time Checks become Compile-Time Checks based on possibility of failure using “basic” flow analysis  Should support “simple” conditional/variant code  E.g.: if cond then X := 3; end if; …. If cond then Y := X; end if;  Explicit Checks coded by programmer will be recognized  E.g.: if X /= null then...  Annotations added to Spec to “Pass” PreConditions/PostConditions to Caller  This process can be automated

Uninitialized Variables  Add in/out/in-out/uninit annotation for global variables to spec  Add init/uninit annotations for exception propagation (if exceptions allowed)  Add default init/uninit annotations for access/comp/priv types (normal default is init)  Require initialization for:  Elementary value usage  RHS of composite assignment  “in”, “in out” params/globals at call (including ops)  Expr or “out” param/global at return

Null Checks  Very similar to Uninitialized variables  Add “not-null” annotation (or subtype constraint) for params, globals, func-result  Add “not-null” annotation for components  Require not null value upon:  Dereference (implicit or explicit)  Pass/Assign to not-null param/object  Return with not-null result, “out” param/global

Erroneous Concurrent Access  Add “task_safe” annotation for subprograms, packages, tasks  Task_safe subprograms may only refer to globals that are atomic or protected.  Task_safe tasks/subps may only have nested task_safe tasks, and call non-local subprograms only if they are task_safe.  “Task_safe” on a package implies all nested tasks, and all visible task types and subps are task_safe, and has task_safe elaboration

Access Before Elaboration  Add pragma which requires static elaboration checks  Complain at link-time if statically-safe elaboration order not determinable  Analysis shows this imposes very few restrictions on “real” programs

Physical Units Checking  Add pragma/attribute/annotation of units for scalar subtypes  Add subp annotations that require unit relationships, or compute units of result/out params based on units of other params  Compute and check unit relationships at compile-time or instantiation time.

Programmable Static Analysis  Allow declaration of “compile-time” attributes for instances of types, instances of generic, etc.  Allow annotations / preconditions / postconditions to use compile-time attributes.  Propagate annotations along with other information through flow analysis

Conclusion  Proving correctness is extremely hard  Proving “reasonableness,” consistency, etc. is feasible at compile-time  Pushing all of Ada’s current exception, bounded-error, and erroneous conditions to compile-time checks is possible, without creating excessive constraints  Adding programmable static analysis can allow compile-time checking to check application-specific “reasonableness.”