OCP Analysis and Adaptation Results Rockwell Collins ATC Iowa State University May, 2003 Overview Issues list Pattern catalog Tool support OCP results Plans May 03 / SLIDE 2 Issues list Identifies 83 issues related to software for high assurance systems based on: — Handbook for Object-Oriented Technology in Aviation (OOTiA), Proceedings of FAA/NASA Workshops 1 & 2 on Object-Oriented Technology in Aviation, 2003 — Guide to the Certification of Systems with Embedded Object-Oriented Software, Aerospace Vehicle Systems Institute (AVSI), 2001 — Gary Daugherty, Certifiability of CORBA, Rockwell Collins Technical Report, 2001 — “Object-Oriented Technology (OOT) In Civil Aviation Projects: Certification Concerns”, CAST-4, January 2000, http://av-info.faa.gov/software — Leanna K. Rierson. Object-Oriented Technology (OOT) in Civil Aviation Projects: Certification Concerns, Federal Aviation Administration, Washington, D.C. — Ye Wu and Jeff Offutt. Maintaining Evolving Component-Based Software with UML, George Mason University Technical Report, 2002 — Barbara Liskov and Jeanette Wing. “A Behavioral Notion of Subtyping”, ACM Transactions on Programming Languages and Systems, 16(6): 1811-1841, November 1994. May 03 / SLIDE 3 Issues list Includes both design level and language level issues: — Bertrand Meyer. “Applying design by contract.” IEEE Computer 25(10):40-51, October 1992. — Guide to the use of the Ada Programming Language in high integrity systems, ISO/IEC TR 15942, 2000 — John Barnes. High Integrity Ada: The SPARK Approach, Addison-Wesley, Harlow, England, ISBN 0-201-17517-7, 1997 — Use of the C++ Programming Language, Certification Authorities Software Team (CAST), position paper, CAST-8, January, 2002 — David W. Binkley. C++ in Safety Critical Systems, NIST, November 1995 — Boeing, BCA Technical Standard for the Use of C++ in Airborne Software, D6-82801, 2002 — Scott Meyers. Effective C++, 2nd edition, Addison-Wesley, Reading, MA, 1998 — Scott Meyers. More Effective C++, Addison-Wesley, Reading, MA, 1996 — Ian Joyner. C++??: A critique of C++ and Programming Language Trends of the 1990s, 1996 — Marshall P. Cline and Greg A. Lamow. C++ FAQs, Addison-Wesley, Reading, MA, 1995. May 03 / SLIDE 4 Issues list And issues related to verification and testing: — Jeff Offutt, et al. A Fault Model for Subtype Inheritance and Polymorphism, Twelfth IEEE International Symposium on Software Reliability Engineering (ISSEE ’01), 2001 — Robert T. Alexander et al. Fault Detection Capabilities of Coupling-based OO Testing, Colorado State University Technical Report, 2001 — Robert V. Binder. Testing Object-Oriented Systems: Models, Patterns, and Tools, Addison-Wesley, Reading, MA, 2000. — Robert T. Alexander and Jeff Offutt. Analysis Techniques for Testing Polymorphic Relationships, In Thirteenth International Conference on Technology of Object-Oriented Languages and Systems (TOOLS30), 1999. May 03 / SLIDE 5 Pattern catalog Forty two design patterns intended to address the most significant issues Ten of these are abstract (define the problem) Thirty two are concrete (provide specific/alternative solutions) Specified in “Gang of Four” format With formal specifications (to support automation) in XPSL/XML And well defined relationships between patterns (extends, requires, excludes, etc.) Developed incrementally May 03 / SLIDE 6 Pattern catalog Increment one — Development of eXtensible Pattern Specification Language (XPSL/XML) — Development of patterns for: Control flow, Data integrity, Pointer integrity, Unintended side effects, Multiple inheritance May 03 / SLIDE 7 Pattern catalog Increment two — Extension of XPSL (in terms of specific queries/views/transformations) — Development of patterns for: Contracts and subtyping, Coupling and cohesion, OO metrics, Dynamic resource allocation, Safety critical language subsets May 03 / SLIDE 8 Tool support For 8 patterns addressing 10 issues Implementation based on ISU’s KCS toolset Programs represented in eXtensible Common Intermediate Language (XCIL/XML) Framework to support XPSL queries, views and transformations Developed incrementally May 03 / SLIDE 9 Tool support Increment one — Development of XCIL — Translation of C++ to XCIL, — Verification of translation, — Analysis framework (queries and views), — Analysis support for selected increment one patterns, — Focus on “local” patterns, affecting individual OCP components May 03 / SLIDE 10 Tool support Increment two — Adaptation framework (transformations), — Adaptation support for selected increment one patterns, — Analysis support for selected increment two patterns, — Focus on “global” patterns, requiring an analysis of the entire OCP May 03 / SLIDE 11 Technical issues Size of the OCP Manual nature of the review process Lack of tool support for HA analysis and transformation Lack of user control (user defined patterns) Regression testing (first do no harm) Need to integrate with other tools May 03 / SLIDE 12 Technical Approach Modeling tools (GME, Rose, etc.) HA Models Models XML/XMI models KCS toolset SW (for translation, analysis, and adaptation) Adapted XML/XMI models HA SW Adapted OCP, and other software source (in C++, Java, other languages.) OCP and other software source (in C++, Java, other languages) Patterns in XML/XMI Issues List Catalog Developer of patterns for high assurance software Review/edit T-VEC formal specs T-VEC Regression testing May 03 / SLIDE 13 OCP results OCP 2.2 http://dirac.ee.iastate.edu/ocp/ Issues Patterns Matches Adaptations May 03 / SLIDE 14 Classification of problems Hard run time error — Lurking run time error — A problem that may fall into one of the run time error categories – although we don’t know which. Obstacle to analysis — A hard run time error may result if additional correct code is introduced. Potential run time error — An error appears in the current code. A fault may occur when the erroneous code is executed. The code cannot be analyzed in some manner typically required for “certification” (potentially masking/hiding run time errors). Maintenance risk — The code is correct, but subsequent changes are likely to introduce errors. May 03 / SLIDE 15 Increment one Addresses issues related to — Implicit type conversion — Violations of strong typing — Control flow — Compiler generated constructors, operators — Pointer integrity May 03 / SLIDE 16 Issue 4: Implicit type conversion Implicit type conversion may involve a potential loss of data or precision — “Type conversions shall not be made from a longer to a shorter (number of bits) type” “Type conversion shall not be made from an unsigned type to a signed type of the same size” “Type casting shall be explicitly coded with use of the keywords const_cast, static_cast and reinterpret cast, and shall not be left as an operation only implied by the code (e.g., an assignment statement)” Boeing. BCA Technical Standard for the Use of C++ in Airborne Software, D6-82801 — “Loss of information rule. To help ensure correctness, any conversions that may result in loss of data or data accuracy and precision should be explicit, should be conspicuously marked (identified) in the program source code, and should only be permitted after thorough review and analysis of potential adverse effects.” [OOTiA Position Paper on Type Conversion] May 03 / SLIDE 17 Issue 4: Implicit type conversion Implicit type conversion between logically unrelated types (e.g., integer and boolean, character and integer) may violate the principles of strong typing — “Unchecked conversion rule. To help ensure type safety and verification, all unchecked conversions should be explicit, be conspicuously marked (identified) in the program source code, and be permitted only after thorough review and analysis of potential adverse effects.” [OOTiA Position Paper on Type Conversion] — “Scalar type rule. Implicit conversions between scalar types should only be permitted when the new type defines a set of operations that is logically a subset of those defined by the old type.” [OOTiA Position Paper on Type Conversion] — “Supertype rule. To help ensure type safety and verification, all implicit type conversions involving references to class instances should only represent a conversion from a subtype to one of its supertypes.” [OOTiA Position Paper on Type Conversion] May 03 / SLIDE 18 Issue 4: Implicit type conversion Implicit type conversion may incur a significant, hidden overhead (e.g., due to implicit constructor calls) — “Low overhead rule. To ensure that the developer does not introduce significant hidden overhead and performance issues, implicit type conversions should only be used for predefined scalar types and references to structured types.” [OOTiA Position Paper on Type Conversion] Very hot to Hot, rank = 3 May 03 / SLIDE 19 Pattern: Safe Type Conversion Restricts implicit conversions to those that are type safe, low overhead, and guarantee no loss of data or precision, i.e. — Conversion of a smaller integer type to larger integer type whose range subsumes the original, with sign extension of two’s complement values — Conversion from a smaller IEEE 754 floating point type to a larger IEEE 754 floating point type — Conversion from a reference type S to a reference type T, provided S is a subtype (subclass or subinterface) of T — Conversion from an Array/Vector whose element type is a reference type SC to an Array/Vector whose element type is a reference type TC, provided that SC is a subtype of TC — Conversion from a general collection type whose element type is a reference type to a collection of the same type whose element type is a reference type TC, provided that SC is a subtype of TC May 03 / SLIDE 20 Pattern: Safe Type Conversion Specifies that type conversions between logically unrelated types (e.g., integer and boolean, character and integer) must be explicit Specifies that type conversions that may incur a significant overhead (e.g., that use constructors or conversion operators to perform type conversion) must be explicit Specifies that supertype to subtype conversions (down casts) must either be proven to be correct (by means of analysis) or must be guarded by a run time check May 03 / SLIDE 21 Matches No implicit conversions between integer and float 58,675 implicit conversions of a larger value to a smaller value 352 implicit conversions of a signed value to an unsigned value 87 implicit conversions of an unsigned value to a signed value Matches represent potential run time errors May 03 / SLIDE 22 Adaptations Subject to review Need to consider which implicit conversions are “high overhead” Need report on types converted from/to Need report on all writes to variables involved in conversions Need to consider whether the actual range of values of the source type fits within the range of values permitted by the destination type Need to consider whether the converted values are treated as numeric values (whether signed/unsigned matters) Introduce user defined types or typedefs Use bool instead of integer type Use single size, avoid conversions Use explicit conversions Introduce run-time range checks (when not performed by C++) May 03 / SLIDE 23 To do Identify “low overhead” vs. ”high overhead” implicit conversions Provide the suggested reports as an aid to the review process Provide for feedback (annotations) to feed the toolset information derived from reviews Look for all conversions between logically unrelated types (not just integer/float) Look for explicit conversions that involve a potential loss of data or precision Look for down casts (supertype to subtype conversions) Look for definitions of implicit conversion operations See pattern for details May 03 / SLIDE 24 Issue 17: Break in switch Error prone, especially when cases are later added or removed — “Each case in a switch, which contains any executable code, shall be terminated with a break.” “This eliminates the dubious practice of falling through a case to use code in a succeeding case for common processing. It is too easy to lose track of the correct program flow in code maintenance.” Mandatory for DO-178B software levels A through D Boeing. BCA Technical Standard for the Use of C++ in Airborne Software, D6-82801 Hot, Rank = 4 May 03 / SLIDE 25 Pattern: Fall through switch case Multiple cases may be associated with the same code However, each block of code associated with a case must end in a ‘break’ This includes the last case of the switch statement (in case other cases are later added after it) May 03 / SLIDE 26 Matches 461 fall through cases Matches represent maintenance risks May 03 / SLIDE 27 Adaptations Refactor code to either: — introduce a method called by both cases (when the shared code is cohesive) — introduce an inlined call (when the shared code is short and cohesive) — introduce a conditional (if statement or nested case) when the shared code is not cohesive — introduce replicated code (when the shared code is short but not cohesive) May 03 / SLIDE 28 To do Support one or more of the suggested adaptations Support user selection of the adaptation to be applied May 03 / SLIDE 29 Issue 19: Use of goto’s Complicates analysis — The use of goto should be excluded because it complicates flow analysis (FA), symbolic analysis (SA), timing analysis (TA), and structural testing (ST). The use of goto is regarded as both unnecessary, and undesirable compared to the use of other control structures. It should not appear in well written code. Guide for the Use of the Ada Programming Language in High Integrity Systems, ISO/IEC TR 15942 R. Chapman. SPARK – A state-of-the-practice approach to the Common Criteria implementation requirements, Praxis Critical Systems Hot, Rank = 4 May 03 / SLIDE 30 Pattern: Goto-free execution The pattern forbids all explicit goto’s But does not forbid implicit goto’s (such as those implied by the use of if statements, switch statements, loops, or exception throws) May 03 / SLIDE 31 Matches 1,744 explicit gotos Matches represent false positives if the goto’s are generated by macros as a substitute for exception throws (as many apparently are) These should be OK, assuming exception handling/error handling jumps are themselves allowed Otherwise matches represent maintenance risks, obstacles to analysis, and potential run time errors May 03 / SLIDE 32 Adaptations Subject to review Unless used as a substitute for exceptions, refactor code to: — replace goto with structured control flow (conditional, loop, break, continue, error return, other common forms) If used as a substitute for exceptions, apply exception/error handling patterns: — Enforcing the disciplined use of exceptions (per Bertrand Meyer) — Ensuring all reported errors (thrown exceptions) have handlers – as in Java — Eliminate macros in favor of pattern substitution, allowing a variety of error reporting/error handling strategies May 03 / SLIDE 33 To do Provide support to for “macro recognition” Develop/apply error handling patterns, replacing the use of macros for this purpose May 03 / SLIDE 34 Other related patterns from the catalog Jump-free execution No user thrown exceptions Top level handler for predefined exceptions May 03 / SLIDE 35 Issue 25: Compiler generated operations Compiler generated operations have default meanings that may be inappropriate for a given class. — Since the default constructor, copy constructor, destructor, and the operators operator=, operator&, and operator, (i.e., operator<comma>) all have default meanings; they should be explicitly defined in every class. To avoid unwanted implicit calls to these constructors and operators, declare them private. – [Binkley, C++ in Safety Critical Systems] — Law of The Big Three: “If a class needs a destructor, or a copy constructor, or an assignment operator, it needs them all” … “During code reviews and debugging sessions, we have traced many core dumps back to violations of The Law” [Cline and Lomow, C++ FAQs] — “Declare a copy constructor and an assignment operator for classes with dynamically allocated memory” [Scott Meyers, Effective C++, 2nd edition, item 11] — Declare a constructor for all classes with an user defined invariant – Based on the FAA/NASA OOTiA Handbook complete initialization rule, invariant rule and invariant assertion rule Hot, Rank = 4 May 03 / SLIDE 36 Pattern: Compiler generated operations Constructor rule — If we have a user defined invariant, we need a user defined constructor — All fields without initial values must be set by a user defined constructor Copy constructor rule — Assignment rule — If the class has dynamically allocated components, we need a user defined assignment operator Destructor rule — If the class has dynamically allocated components, we need a user defined copy constructor If the class has dynamically allocated components, we need a user defined destructor Consistency rule — If the class has a user overrides the default behavior of its destructor, copy constructor, or assignment operator, then it should override the behavior of all three May 03 / SLIDE 37 Matches 1,451 classes with compiler generated default constructors 2,078 classes with compiler generated copy constructors 2,100 classes with compiler generated “=” operators 2,218 classes with compiler generated “&” operators Matches are subject to application of the previous rules Violations of the rules represent likely run time errors or lurking run time errors May 03 / SLIDE 38 Adaptations The user is responsible for introducing the necessary operations, while the tool is responsible for checking the user supplied code In addition the tool may introduce run-times checks of constructor postconditions, to ensure the class invariant is established Checks of user supplied constructor — Run time check of invariant as postcondition — Check that all fields are initialized Checks of user supplied copy constructor — Run time check of invariant as postcondition — Check that all dynamically allocated components are replicated (deep copy) Check of user supplied assignment operator — Check that all dynamically allocated components are replicated (deep copy) Check of user supplied destructor — Check that all dynamically allocated components are deallocated May 03 / SLIDE 39 To do Provide tool support for associated rules Support the selective insertion of code to check constructor postconditions (class invariants) May 03 / SLIDE 40 Issue 30: Pointer arithmetic Use of pointer arithmetic Bounds checks and invalid pointer values — “Operational software shall not include pointer arithmetic.” “In general, there is little justification for going to the effort of designing code to do pointer arithmetic. The performance gained by doing pointer arithmetic is seldom worth the increased risk of error.” Explicit pointer value calculation is prohibited for DO-178B software levels A through D Boeing. BCA Technical Standard for the Use of C++ in Airborne Software, D6-82801 — “Direct manipulation of pointer values (pointer arithmetic) should be prohibited … Java and C# can be used as a guide. What cannot be done is these languages generally should not be allowed. ” [Daugherty, Certifiability of CORBA] Obstacle to analysis Hot, Rank = 5 May 03 / SLIDE 41 Pattern: No pointer arithmetic A pointer can be used only as a substitute for an opaque reference, i.e., in XCIL: — On the left hand side of an assignment — In a reference to the value of an attribute — In a reference to the value of an array element — In a reference to the length of an array — In reference to the run time type of an object — As the target of a dispatching call — As an argument to a call — As a value returned by a method — As the thrown value of an exception — In a reference to an object to be locked/unlocked May 03 / SLIDE 42 Matches 470 instances of pointer arithmetic Matches represent potential run time errors and obstacles to analysis May 03 / SLIDE 43 Adaptations Replace each array element pointer with an array base pointer and index, performing all arithmetic on indices rather than pointer values Selectively introduce run-time bounds checks (typically not performed by C++ compilers) Restrict other uses of pointers in XCIL to the cases given (in which the use of a pointer is compatible with the use of an opaque reference), requiring the user to make associated changes May 03 / SLIDE 44 To do Complete tools-related work on transformations to eliminate arithmetic involving array pointers Develop strategy for incremental introduction of changes — For examnple, support a conversion from array pointer types to a type representing an array reference + index (class ArrayReference) — Explicitly apply this conversion to all parameters passed into/out of the portion of the software to be changed — Incrementally adapt the entire OCP and its support libraries May 03 / SLIDE 45 Issue 47: Use of union (untagged variant records) Can lead to errors that cannot be caught by the compiler and violations of strong typing — “The type union should not be used” “union is an untagged type. Its use can lead to data type errors that cannot be trapped by the compiler” Prohibited for DO-178B software levels A through D Boeing. BCA Technical Standard for the Use of C++ in Airborne Software, D6-82801 — “Use a class hierarchy with virtual functions in place of a union as it provides type checking of the data stored in the union” [Binkley, C++ in Safety Critical Systems] Hot, Rank = 6 May 17 April 03 /03 SLIDE / SLIDE 46 46 Pattern: Non-discriminated union The pattern forbids all untagged (non-discriminated) unions May 03 / SLIDE 47 Matches 9 declarations of untagged union types Matches represent maintenance risks, obstacles to analysis, and potential run time errors May 03 / SLIDE 48 Adaptations Replace untagged union with — class-subclass — class-state = tagged union (discriminated record) May 03 / SLIDE 49 To do Add abstract pattern and two concrete subpatterns (for conversion to classsubclass and class-state) to catalog Develop tool support for the associated transformations (giving the user a choice of which to apply) May 03 / SLIDE 50 Issue 56: Implicit method return Without an explicit return statement, the developer’s intent may be unclear, control flow may be more difficult to follow, and it may be unclear what values may be returned by a given method — “Return from a function shall be accomplished only by an explicit return statement, i.e., the code shall not use a default or implicit return.” “Not writing return in a function relies on the default return. Explicit return in every branch that terminates has two benefits. It simplifies the maintenance task of understanding the flow of control, and makes it completely clear the possible values that are returned.” Mandatory for DO-178B software levels A through D Boeing. BCA Technical Standard for the Use of C++ in Airborne Software, D6-82801 Other, Rank = 9 May 03 / SLIDE 51 Pattern: No implicit method value return All execution paths associated with a method that returns a value must end with an explicit return May 03 / SLIDE 52 Matches None found May 03 / SLIDE 53 Unimplemented local patterns Enforce invariant (Issue 13) Closed argument list (Issue 15) No dangling pointers to local variables No assignment statement arguments (Issue 40) Loop termination (Issue 44) No user thrown exceptions (Issue 49) Top level handler for predefined exceptions (Issue 49) May 03 / SLIDE 54 Unspecified local patterns Undefined and implementation defined behavior (Issue 2) Incomplete construction (Issue 12) Use/overriding of default parameter values (Issue 16) Accidental mismatch of software and processor (or compiler), e.g. with respect to desired precision and accuracy (Issue 27) Overloading and implicit type conversion involving calls to overloaded methods (Issue 28) Side effects in expressions and arguments (Issue 50) Side effects in functions that return a result (other than an error code) (Issue 51) Template verification (Issue 52) Verification of inlined methods (Issue 53) Class cohesion (Issue 66) May 03 / SLIDE 55 Increment two Addresses issues related to — Lack of precise requirements/interface specifications — Integration errors at class boundaries — Supertype/subtype compatibility — Use of dynamic dispatch — Dynamic dispatch during object construction — Safety critical language subsets May 03 / SLIDE 56 Issue 1: Precise requirements/interface specifications Lack of precise requirements/interface specifications — “If we don’t state what a module should do, there is little likelihood that it will do it (The law of excluded miracles)” – Bertrand Meyer — Programming by contract: “The relationship between a class and its clients [can be] viewed as a formal agreement [contract]. Only through such a precise definition of every module’s claims and responsibilities can we hope to attain a significant degree of trust in large software systems” [Bertrand Meyer, Object-oriented Software Construction] Integration errors at class interface boundaries — — “The compositional relationships of inheritance and aggregation, especially when combined with polymorphism, introduce new kinds of integration faults” and “increase the difficulty of the detection of faults that result from the integration of components” – Roger T. Alexander In OO systems, “complexity is relocated to the connections among components” and “there is less static determinism (many faults can now only be detected at runtime)” Offutt Very hot, Rank = 1 May 03 / SLIDE 57 Issue 6: Supertype/subtype compatibility “The single largest source of design errors is improper inheritance” [C++ FAQs, Issue 119] Faulty intuition — Intuition with regard to classification can lead to superclass-subclass relationships that violate the Liskov Substitution Principle (a.k.a. “Square peg in a round hole”) [Binder, Testing Object-Oriented Systems] Failure to implement to inherited specifications — A subclass may fail to follow the Liskov substitution principle, breaking the promises to clients made by superclasses (a.k.a. “Naughty children”) [Binder, Testing ObjectOriented Systems, p. 503] — Subclass methods may fail to act on superclass attributes that are modified by methods they override (a.k.a. “State Definition Anomaly (SDA)”) or may assign them inconsistent values (a.k.a. “State Defined Incorrectly (SDI)”) – Offutt — A method may call other overridden (possibly private or protected) methods that break the promises made by their parent methods (a.k.a. “Indirect Inconsistent State Definition (IISD)” or “State Visibility Anomaly (SVA)”) - Offutt May 03 / SLIDE 58 Issue 6: Supertype/subtype compatibility Failure to implement to inherited specifications — “Revoking an inherited public service is evil” [C++ FAQs, Issue 122] — “It’s legal for an overridden method to do nothing if, and only if, the specification of the service in the base class tells users that it might do nothing. Without such an adaptable specification in the base class, doing nothing is like false advertising.” [C++ FAQs, Issue 127] Misuse of inheritance to share code/data — Inheritance can be misused to support code sharing without consideration of substitutability and the rules for behavioral subtyping (i.e., LSP) Programmer specified optimizations — Some languages make it easy to break the inheritance and subtyping guidelines in order to perform programmer specified optimizations (e.g., by omitting the C++ “virtual” keyword to avoid the overhead of dynamic dispatch). May 03 / SLIDE 59 Issue 6: Supertype/subtype compatibility Accidental overriding/hiding — It is important that the overriding of one operation by another always be intentional rather than accidental (a.k.a. “Accidental override”) [Binder, Testing Object-Oriented Systems] — The overriding of an attribute in a subclass can hide a superclass attribute with the same name resulting in an inconsistent state when a sequence of superclass and subclass methods are called (a.k.a. “State Definition Inconsistency (SDIH)”) - Offutt Missing override — Failure to override a method, e.g., in order to maintain a stronger subclass invariant, will not be detected by compilers, leading to undetected errors (a.k.a. “Missing override”) [Binder, Testing Object-Oriented Systems, p. 502] — As a result, superclass methods may put a subclass in a state inconsistent with the subclass invariant (a.k.a. “Inconsistent Type Use (ITU)”) – Offutt Hot, Rank = 4 May 03 / SLIDE 60 Issue 23: Use of dynamic dispatch Dynamic dispatch raises potential issues with respect to flow analysis, timing analysis, structural coverage, and the reuse of test results — “Data flow analysis and control flow analysis are complicated by dynamic dispatch, because it may be unclear which method in the inheritance hierarchy is going to be called.” [FAA/NASA Handbook for Object-Oriented Technology in Aviation (OOTiA)] — “Structural coverage analysis is complicated by dynamic dispatch because structural coverage changes when going from subclass to superclass. A closely related issue is that inheritance and polymorphism may cause difficulty in obtaining structural coverage (both modified condition/decision coverage (MC/DC) and decision coverage). ” [FAA/NASA Handbook for Object-Oriented Technology in Aviation (OOTiA)] — “Requirements-based testing is complicated by dynamic dispatch, because it may be difficult to determine how much superclass verification activity can be reused for its subclasses.” [FAA/NASA Handbook for Object-Oriented Technology in Aviation (OOTiA)] Hot, Rank = 4 May 03 / SLIDE 61 Issue 5: Dynamic dispatch during object construction Need to ensure subclass methods are not called before subclass data has been initialized, establishing the subclass invariant — “Dynamic dispatch can introduce problems related to initialization (i.e., especially with regard to deep class hierarchies)” [Binder] — Use of dynamic dispatch by a superclass constructor (or by a method in the transitive closure of this constructor) can lead to the use of subclass attributes before they have been initialized (a.k.a. “Anomalous Construction Behavior (ACB1)”) - Offutt — Use of dynamic dispatch by a superclass constructor (or by a method in the transitive closure of this constructor) can lead to the use of superclass attributes before they have been initialized (a.k.a. “Anomalous Construction Behavior (ACB2)”) - Offutt Hot, Rank = 4 May 03 / SLIDE 62 Pattern: Formal interfaces Addresses Issue 1: Lack of precise requirements/interface specifications — “If we don’t state what a module should do, there is little likelihood that it will do it (The law of excluded miracles)” – Bertrand Meyer — Programming by contract: “The relationship between a class and its clients [can be] viewed as a formal agreement [contract]. Only through such a precise definition of every module’s claims and responsibilities can we hope to attain a significant degree of trust in large software systems” [Bertrand Meyer, Object-oriented Software Construction] — MC/DC test coverage criteria [DO-178B] Matches — All class interfaces See SEC Catalog for details Use of Daikon tool from MIT [Ernst] may allow pre/postconditions to be generated semi-automatically from code May 03 / SLIDE 63 To do Initially formal interfaces will be developed in terms of T-VEC pre/postconditions with no support from the KCS toolset Subsequently pre/post specifications will be imported/exported by the KCS toolset in order to: — Support the checks specified by the Formal Interface pattern — Permit the selective use of pre/post and invariant specifications as the basis for the generation of run-time checks (as in Eiffel) — Support the types of analysis/adaptation suggested by the Formal Subtyping pattern Initially this will involve a conversion to/from the T-VEC file format Eventually it should be possible to import/export this information from UML requirements and design models And to provide assistance to the user in the generation of formal specifications from existing code (e.g., using Daikon or similar tools) May 03 / SLIDE 64 The importing of T-VEC pre/post specifications Extended UML UML XMI XCIL map/ merge Action Semantics JVM MS-IL XCIL (1.3g) C++ (EDG AST) XCIL map T-VEC specs XCIL map/ merge May 20 Mar 03 03 / SLIDE / SLIDE 6565 The exporting of pre/post specifications to T-VEC Extended UML UML XMI XCIL extract/ map Action Semantics JVM MS-IL XCIL (1.3g) C++ source line mapping XCIL map T-VEC specs XCIL extract/ map May 20 Mar 03 03 / SLIDE / SLIDE 6666 Pattern: Inheritance with overriding Simple overriding rule Accidental override rule Simple dispatch rule Complete initialization rule Initialization dispatch rule May 03 / SLIDE 67 Pattern: Method extension Method extension rule Sole exception to the simple dispatch rule imposed by the Inheritance with overriding pattern See SEC Catalog for details May 03 / SLIDE 68 Patterns: Formal subtyping Addresses — Issue 6: Supertype/subtype compatibility — Issue 23: Use of dynamic dispatch Issue 5: Dynamic dispatch during object construction — In particular — “The single largest source of design errors is improper inheritance” [C++ FAQs, Issue 119] Errors may result from — — — — — — Faulty intuition Failure to implement to inherited specifications Misuse of inheritance to share code/data Programmer specified optimizations Accidental overriding/hiding Missing override May 03 / SLIDE 69 Pattern: Formal subtyping Analysis results — 938 subtyping relationships — 1,392 cases in which an operation is implemented by multiple methods (OMM pointcut) — 3,112 instances of “true dynamic dispatch” (TDD pointcut) — Interested in subsets (OMM incompatibilities) and intersections (OMM incompatibilities with TDD) to separate hard run-time errors from lurking errors Review results (sample of ~40 subtyping relationships) — 24 violations of subtyping rules/LSP (including conflicting postconditions, less visible subclass operations, disabled methods, null method implementations, and weaker postconditions) Violations represent either lurking or hard run time errors See SEC Catalog and OCP Subtyping Relationships for details/adaptations May 03 / SLIDE 70 Matches 938 subtyping relationships 1,392 instances of operations implemented by more than one method (OMM) 3,112 instances of true dynamic dispatch (TDD) May 03 / SLIDE 71 OMM checks Check OMM for violations of LSP — Tool can identify all instances of OMM — Violations of LSP are associated with relationships (between an operation and an implementing method, or between a method and an overriding method) — Tools can identify certain simple violations — Others can be found in manual reviews MethodA1 Relationships between overriding methods must comply with LSP, or be marked as an error OperationA Relationships between the operation and its implementing methods must comply with LSP, or be marked as an error MethodA2 MethodA3 Represents either a hard run time error or a lurking error May 03 / SLIDE 72 TDD checks Problematic call occurs when LSP violation in TDD operation-method set — Considering only the operation and the methods that could be invoked as a result of the call (i.e., those defined by subtypes of the declared type of the target object) — There is an LSP violation in this set (between the operation and one of the methods, or between a method and an overriding method) Call to target.operationA () OperationA MethodA2 The call is OK as long as all these relationships comply with LSP MethodA3 Represents a hard run time error if the client depends on the erroneous relationship Or a lurking error otherwise May 03 / SLIDE 73 Review results 24 violations of subtyping rules/LSP found in a manual review of a sample of ~40 subtyping relationships, including: — conflicting postconditions (CPOST), — less visible subclass operations (LVO), — disabled methods (DISM), — null method implementations (NMI), — weaker postconditions (WPOST) See the OCP Subtyping Relationships report for further details May 03 / SLIDE 74 To do Include checks for the most common LSP and specification errors that can be found by tools (LVO, DISM, INVI, NMI, UNERR, OVER, UNDER) Allow user specification of additional LSP violations (CPOST, INVI, MINV, OVER, UNDER, WPOST, etc.) detected in reviews Have the toolset track which LSP relationships have not been checked (all OMM relationships should be reviewed) Determine which instances of TDD represent “problematic” calls Introduce related transformations (as suggested in the slides that follow) Provide tool support for checking the simple dispatch rule (Inheritance with overriding pattern) and the method extension rule (Method extension pattern) Extend tool support to include all pointcuts, views, and transformations defined by the Formal Subtyping pattern and the “inheritance” of pre/postconditions May 03 / SLIDE 75 Less visible operation (LVO) An inherited operation is made less visible in a subclass Revoking an inherited public service is evil” [C++ FAQs, Issue 122] And a fundamental violation of LSP And a violation of the rules defined by the Inheritance with overriding pattern Easily detectable by toolset One instance found in manual review of ~40 OCP subclasses Can refactor the class to introduce a precondition and query to make the operation optional Or refactor the class hierarchy May 03 / SLIDE 76 Unexpected error (UNERR) An overriding operation/method reports an error not specified in its supertype/superclass A fundamental violation of LSP And a violation of the rules defined by the Inheritance with overriding pattern Potentially detectable by toolset, given a formally stated postcondition Two instances found in manual review of ~40 OCP subclasses (one representing DISM) Can respecify parent operation to allow reporting of the error Or treat it as a case of NMI if the error corresponds to this May 03 / SLIDE 77 Disabled method (DISM) An existing method is overridden in a subclass by method that asserts that the method is disabled A special case of UNERR and a fundamental violation of LSP And a violation of the rules defined by the Formal subtyping pattern Detectable by toolset, given the possible forms a disabled method may take One instance found in manual review of ~40 OCP subclasses Can refactor the class to introduce a precondition and query to make the operation optional Or refactor the class hierarchy May 03 / SLIDE 78 Invalid or incomplete implementation (INVI) The execution of the method does not deliver on the promises made by the operation/method’s description/postcondition (whether inherited or defined by the class) A violation of LSP And a violation of the rules defined by the Formal subtyping pattern Most easily detected by review But some cases can be caught by toolset given a formally stated postcondition Or by looking at special cases (such as NMI) 14 instances found in manual review of ~40 OCP subclasses (12 of them instances of NMI) May 03 / SLIDE 79 Null method implementation (NMI) A method of a concrete class defines a null implementation of an operation that conflicts with its description (whether inherited or defined by the class). A special case of INVI, and a violation of [C++ FAQs, Issue 127]. “It’s legal for an overridden method to do nothing if, and only if, the specification of the service in the base class tells users that it might do nothing. Without such an adaptable specification in the base class, doing nothing is like false advertising.” [C++ FAQs, Issue 127] Detectable in most cases by toolset, given given the possible forms a null method may take 12 instances found in manual review of ~40 OCP subclasses Can specify a precondition to make the operation optional, or qualify the postcondition to specify that the operation may do nothing If all operations of the class are null, then it is preferable to address this as a case of NSCI May 03 / SLIDE 80 Null subclass implementation (NSCI) NMI for all methods of subclass Suggested by NullObject pattern Problematic in high assurance systems — Unless it is a null implementation is always OK, for all clients under all circumstances — And the class name/contract defined by the superclass makes this clear Should be replaced by HA version of the pattern, which: — Ensures any optional null behavior is defined by each superclass operation’s pre/post specification, i.e., the postcondition is of the form “true or optional-result” — Names the superclass to make it clear that it’s implementation may be null — Defines a subclass that represents the root of all non-null implementations (so that clients that require a non-null implementation can use strong typing to guarantee this) Or (less desirable) refactor the base class to introduce postconditions and the query isNull to make all results explicitly optional May 03 / SLIDE 81 Null subclass implementation (NSCI) For example, replace Lock, NullLock, LockImpA, LockImpB Lock NullLock LockImpA LockImpB With OptionalLock, NullLock, Lock, LockImpA, LockImpB postcondition indicates result is optional OptionalLock NullLock postcondition indicates result is guaranteed Lock LockImpA LockImpB May 03 / SLIDE 82 Null subclass implementation (NSCI) Or (less desirable), refactor the Lock class to introduce postconditions and query isNull to make all results explicitly optional Refactor to introduce postconditions and query isNull to make all results explicitly optional Lock NullLock isNull returns true LockImpA LockImpB isNull returns falae May 03 / SLIDE 83 Overspecified operation (OVER) An operation is overspecified by its description Usually as a consequence of specifying implementation details rather than just the result, from the client’s perspective A violation of the OOTiA Coupling pattern Can be detected by tools, given formally specified pre/postconditions Neither the pre or post should contain references to features of the class that are less visible than the operation being specified One instance found in manual review of ~40 OCP subclasses May 03 / SLIDE 84 Underspecified operation (UNDER) An operation is underspecified by its description, e.g., by failing to specify how errors are reported (UNDER-ERR) See the Formal interface pattern Errors of omission are detectable by toolset, given a formally specified postcondition The tool can, for example, determine when a change to a public property of the class fails to appear in the postcondition 7 instances found in manual review of ~40 OCP subclasses May 03 / SLIDE 85 Other violations of LSP To detect other violations of LSP we can structure the pre/postconditions to make the relationships between them obvious (as in Eiffel) To ensure the precondition is weaker or the same in a redefined operation, for instance, we can assume the parent precondition is “inherited”, and only allow it to be extended by or’ing it with an additional clause And to ensure the postcondition is stronger or the same in a redefined operation, we can assume the parent postcondition is “inherited”, and only allow it to be extended by and’ing it with an additional clause Always specifying pre/postconditions in this way makes them easy to verify (using tools such as T-VEC that generate test cases from pre/postconditions) See the Formal subtyping pattern in SEC Catalog May 03 / SLIDE 86 Pattern: Subtyping tests generated from formal interfaces Minimum compatibility rule LSP compliance rule Redefined/implementing precondition rule Redefined/implementing postcondition rule Subtype invariant rule Inherited test case rule Separate context rule May 03 / SLIDE 87 Pattern: Subtyping tests generated from formal interfaces Assumes contracts can be written after the fact — “Contracts are inherent in library design; if not explicitly stated, they are lurking anyway under the cover, either suppressed or replaced by comments in the program, explanations in the documentation, exceptions and other ersatz techniques.” – Bertrand Meyer Assumes tool support for test case generation from pre/postconditions — Using T-VEC May 03 / SLIDE 88 To do Generate T-VEC specs (by hand) for all modules we plan to change Follow the Formal subtyping pattern with respect to the rules for the “inheritance” of pre/postconditions and compliance with LSP Introduce KCS tool support for the importing/exporting of T-VEC specs Provide tool support for the “inheritance” of pre/postconditions in accordance with the pattern Explore the use of tools such as Daikon to generate pre/post specifications from code May 03 / SLIDE 89 Pattern: Multiple implementation inheritance Addresses issue 8: Ambiguity resulting from the use of multiple implementation inheritance Multiple inheritance session of OOTiA workshop unattended because no one thought MII appropriate for high assurance applications Review results (sample of ~40 subtyping relationships) — 4 instances of multiple implementation inheritance Matches represent maintenance risks and potential run time errors Rules — Replace with delegation for DO-178B levels A through C See SEC Catalog for details/adaptations May 03 / SLIDE 90 To do Provide tool support for the identification of cases of multiple implementation inheritance and the pointcuts associated with the pattern Provide tool support for the replacement of multiple implementation inheritance with delegation May 03 / SLIDE 91 Issue 71: Obstacles to level A static analysis Need for level A static analysis, including data/control flow analysis Need for formally defined semantics Need for an analyzable, precisely defined language subset for safety-critical applications Hot, Rank = 4 May 03 / SLIDE 92 Pattern: Safety critical formal language subset Limit XCIL actions and predefined types to those that map to the UML Action Semantics or the JVM While permitting the use of structural elements from UML (classes, interfaces, components, operations, methods, etc.) to organize them Impose additional restrictions based on the ISO High Assurance Ada standard and SPARK, including those defined by other patterns in the catalog See the SEC Catalog for details May 03 / SLIDE 93 To do Provide tool support to identify actions that do not map to the JVM instruction set Provide tool support for the identification of functions with side effects and other restrictions mentioned by the pattern Provide tool support for other SPARK-like patterns called for by this pattern (which have not already been implemented) Formally define this pattern in XPSL May 03 / SLIDE 94 Lessons learned Tool support has been invaluable in identifying potential problems — — More effective in terms of hours spent, accuracy, and counts of problems found Necessary due to size of OCP Need to be able to interactively refine problem description, tune patterns May 03 / SLIDE 95 Lessons learned A broad, automated problem analysis is needed to find likely problems — Given size of the OCP — And number of issues Results of analysis should dictate which patterns to develop further — Need to consider both ranking and probability of occurrence — Need to support interactive exploratory analysis — Need to refine problem analysis to include discriminators Need to support a progression from manual, to interactive, to fully automated transformation — Most important transformations require developer in the loop — Need to support use of tool as an assistant — Need to support critics/review process May 03 / SLIDE 96 Lessons learned Need automated support for the evolution of meta-models (XCIL, XPSL) — Need automated checking of translation results — These change frequently Well formedness rules Need to support import/export from multiple tools (e.g., UML, C++, T-VEC) — Need to merge inputs from different tools into common XCIL model — Need to extract XCIL and map to multiple representations (XMI, T-VEC pre/post, C++) Reliance on XML comes at a price — Supports rapid tool development — But need lots of processing power/space — Can optimize toolset itself (using patterns) after the fact Target language independence works May 03 / SLIDE 97 Unimplemented global patterns Synchronization (Issue 3) Multiple interface inheritance (Issue 7) Replacement of multiple implementation inheritance with delegation (Issue 8) No dynamic allocation after initialization (Issue 9) Initialization before use (Issue 12) Class coupling (Issues 13, 67, 68) Dynamic dispatch test coverage Method extension Deep hierarchy May 03 / SLIDE 98 Unspecified global patterns Checking of inputs and outputs at partition boundaries (Issue 1) Concurrency (Issue 3) Aliasing, involving pointers or arguments (Issue 11) Enforcement of safety invariants (Issue 14) Re-entrant function execution (Issue 18) Enforcement of architectural layering/partitioning rules (Issue 24) Initialization dependencies between classes/modules (Issue 46) Unreachable deactivated code (Issue 57) May 03 / SLIDE 99
© Copyright 2026 Paperzz