introduction to spark reference: “high integrity ada” john barnes

31
Introduction to SPARK Reference: “High integrity Ada” John Barnes

Upload: willa-fisher

Post on 17-Dec-2015

227 views

Category:

Documents


2 download

TRANSCRIPT

Introduction to SPARK

Reference:“High integrity Ada”John Barnes

SPARK

Is (formally) a subset of Ada, in that any correct SPARK program is also a correct Ada program.

But this is misleading, because the annotations are really a major language feature.

SPARK Basic Structure

Take AdaRemove features to get a small subsetDefine a set of annotationsAnnotations are from Ada’s point of view

comments lexically (they start with --#)But they are syntactic elements of SPARKSo SPARK is a separate language

What to Leave Out of Ada

Things that make certification and formal reasoning (e.g. verification) harder: Tasks Exceptions Generics Access types Gotos

Why no tasks?

Because tasking programs are inherently more complex than simple sequential programs.

The state of a tasking program is a much more complex object

Task interactions are complexNon-determinacy is a concern

Why no Exceptions?

Because exceptions make the control flow of a program much more complex

Certifiable programs cannot have unexpected exceptions anyway

Exception handlers lead to deactivated code which is problematic for certification.

Why no Generics

Generics are a short hand for repeated instantiations, so do not provide any fundamental expressive power

But proving properties is more complex because we have to quantify over types.

If we have to prove separate instantiations we may as well write them.

Why no Access Types

Access types only make sense in connection with dynamic storage allocate.

But dynamic allocation is a real problem, since it is hard to prove that storage is never exhausted.

Why no Gotos

Not really needed in most programming

At best only a minor convenienceBut they complicate formal analysis

Because the effect of a sequence of code can no longer be represented as the composition of the effects of its sequential components.

What Else to Leave Out?

Ada favors the reader heavily over the writer in its design.

SPARK carries this principle to further extremes. Why, because the reader may be a formal tool.

Furthermore, writing code takes a fraction of the time it takes to certify.

Other Things Left Out

Dynamically sized arrays Eases reasoning about range

correctnessOverloadingImplicit operations (e.g. sliding)Implicit subtypes

X : Integer range 1 .. 10; -- not allowed Must declare separate subtype

The Annotation Language

All statements start with --#, but they are not comments, they are strict elements of the SPARK syntax.

Global Definitions Declare use of global variables

Dependency Relations Specify information flow (what outputs

depend on what inputs)

Oher types of annotations

Access of Variables in Packages The idea is to restrict visibility

Inherit clauses Control visibility of package names

Own variable clauses Control access to package variables

Initialization Indicate initialization of own variables

Purpose of Annotations

Make code clearer at spec levelIntroduce redundancy, compiler can

checkAllow error checks to be madeSupport verification

The SPARK tools

SPARK Examiner processes SPARK programs Checks syntactic validity

Including checking annotations for consistency and correctness

Generates useful warnings Generates auxiliary information helpful

in analysis and certification

Annotations in Action

Procedure Sly (V : in vector)--# global in out A;--# derives A from A, V;is begin

A (1) := V (1) + V (1);A (1) := V (1) + V (1);

end Sly;…A (1) := 1.0;

Sly (A); -- error, param overlaps global variable

An example: Exchange

Procedure Exchange (X, Y : in out Float)--# global T;--# derives X from Y & Y from Xis begin

T := X; X := Y; Y := T;end;

This is illegal because it modifies T, and the annotations do not make this clear

Exchange (attempt 2)

Procedure Exchange (X, Y : in out Float)--# global T;--# derives X from Y & Y from Xis

T : Floatbegin

T := X; X := Y; Y := X;end;

This generates 4 (!) fatal errors

Errors in attempt 2

T := X is an ineffective statementImportation of initial value of X

ineffectiveVariable T is not referenced or exportedImported value of X not used in

deriving the value of YImported value of Y may be used in the

derivation of Y

Path Functions

Compute all possible paths through program and provide explicit information about possible paths

List conditions for each pathCheck consistency of conditions

Check Path Consistency

if X > Y then … if X < Y then … end if;end if;

Path 2 traversal conditions1. X > y2. X < Y

Path 2: path eliminated (contradictory conditions)

Verification Conditions

procedure Exchange (X, Y : in out Float)-- #derives X from Y & Y from X-- #post X = Y~ & Y = X~is

T : Float;begin

T := X; X := Y; Y := T;end;

Verification Conditions

H1: true .->

C1: y = y .C2: x = x .

Meaning is H1 => C1 and C2Obvious in this case

The Simplifier

Attempts to simplify the verification conditions generated by the examiner

For example previous set of conditions simplifies to *** true .

Another Example

Type T is range -128 .. + 128; procedure Inc (X : in out T)

--# derives X from Xis begin

X := X + 1;end;

Verification Conditions

After simplification we get the conditions:

H1: x >= -128 .H2: x <= 128 .

->C1: x <= 127 .

This last conclusion cannot be proved

An Improved Inc procedure

procedure Inc (X : in out T)--# derives X from X;--# pre X < T’Lastis begin

X := X + 1;end;

Now proof obligation shifts to call site

The Proof Checker

The simplifier does a lot, but it is after all a simplifier, it does not prove complex theorems.

Proof of complex theorems may be needed

The proof checker is in charge of making sure these proofs are correct.

Is SPARK really usable

In real life, there are complex external gizmos like external sensors with weird data.

Devices with inherently non-determistic behavior

Computations that require low level messing around

One more feature:

-- #hideAllows arbitrary use of full Ada (or

anything else for that matter)Hidden from examiner. For example,

we can give a procedure spec with full annotatations.

And then completely hide the bodyAnd use other means to verify the body

How is SPARK Used

SPARK program is writtenExamined with examinerOtherwise examined by various

techniques and testsMight include formal proof

for example at least freedom from exceptionsThen result is compiled with Ada compilerThe object code is verified