Code Contracts : What, Why and How?
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
Is this program correct?
/* Write a program that prints the first
5 prime numbers */
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
Is this program correct?
History
Robert W Floyd
Sir Tony Hoare
Floyd-Hoare Logic
1967-1969
* Images are taken from Wikipedia
About inventing NULL reference, "I call it my billion dollar mistake."
History
- Owiki-Gries 1976 : Rely-Guarantee for concurrent programs
- O'hearn-Reynolds 2001 : Separation Logic for heap manipulating programs
Code Contracts : Formal description of sets of states (or behaviors) of program or a program fragment that defines correctness of the said program or a program fragment at given program points (or for given program traces/executions) .
“Our field needs more formality, but the profession has not realized it yet.” --Bertrand Meyer (Creator of Eiffel)
We have been using code contracts since long...
We have been using code contracts since long...
void add_to_node(node_t* n,int val)
{
assert(n!=nullptr);
n->val += val;
}
Program State
Values of all the program variables at a given instant
int x;
\(2^{32}\) possible states for a 32-bit int
int a[100];
\(2^{3200}\) possible states for a 32-bit int
Program as a state transformer
int x;
x=x+1;
x==INT_MIN
x==0
x==INT_MAX
...
x==INT_MIN+1
x==INT_MIN
x==1
?
...
...
...
x=x+1
x=x+1
x=x+1
Program as a state transformer
int x;
x=x+1;
x==INT_MIN
x==0
x==INT_MAX
...
x==INT_MIN+1
x==INT_MIN
x==1
Undefined
...
...
...
x=x+1
Program as a state transformer
int x;
x=x+1;
x==INT_MAX
Undefined
x=x+1
x<INT_MAX
x=x+1
x>INT_MIN
Program as a state transformer
int x;
x=x+1;
x==INT_MAX
Undefined
x=x+1
x<INT_MAX
x=x+1
x==old_x+1
Program as a state transformer
int x;
x=x+1;
x==INT_MAX
Undefined
x=x+1
x<INT_MAX
x=x+1
x==old_x+1
precondition
postcondition
Program as a state transformer
int x;
x=x+1;
x==INT_MAX
Undefined
x=x+1
x<INT_MAX
x=x+1
x==old_x+1
precondition
postcondition
Even a million tests has less than 1 in 4096 chance of finding the bug
int foo(int x)
{
int tmp=x;
x=x+1;
if(x<tmp)
{
launch_nukes_and_destroy_the_world();
}
return x;
}
int64_t foo(int64_t x)
{
int64_t tmp=x;
x=x+1;
if(x<tmp)
{
launch_nukes_and_destroy_the_world();
}
return x;
}
Even with a billion tests, the probability of finding the bug is less than 1 in 16 billion
- Ariane 5 : 64-bit FP to 16-bit Short
- Mariner 1 1962: A missing hyphen
- Vancouver stock exchange : Floating point truncation bug
- Nest thermostat bug 2016: Software bug causing battery drain
- Therac-25 : Fatal exposure to radiation to patients
Disasters caused by software
- https://spectrum.ieee.org/how-the-boeing-737-max-disaster-looks-to-a-software-developer
Testing
Testing
Testing
Testing
Testing
Testing
Testing
Absence of failure during testing does not mean absence of bugs.
What ideally we want..
What ideally we want..
Undecidable : There are programs for which computing exact set of reachable sets is impossible.
What ideally we want..
Undecidable : There are programs for which computing exact set of reachable sets is impossible.
... but we are engineers. Do it for programs for which it is possible.
Static Reachability Analysis
Instead of computing exact sets, compute overapproximate sets.
Static Reachability Analysis
Instead of computing exact sets, compute overapproximate sets.
Static Reachability Analysis
Static Reachability Analysis
False positive
Testing
- Scales well
- Easy to understand
- Does not guarantee safety
Static Reachability
- Does not scale well
- Requires expertise
- Can guarantee safety
Static Contract Checking
cond(var1)
cond1(var1,old_var1)
var1=f(old_var1)
cond2(var2)
cond3(var2,old_var2)
var2=f2(old_var2)
Static Contract Checking
cond(var1)
cond1(var1,old_var1)
var1=f(old_var1)
cond2(var2)
cond3(var2,old_var2)
var2=f2(old_var2)
Static Contract Checking
- In practice, for checkers, it is easier to check for contracts rather than synthesizing them
- Contract checking for smaller program fragments is easier than larger fragments
Static Checkers
Dynamic contract checking
Dynamic contract checking
- Absence of bugs are not guaranteed
- Formal and unambiguous in-source documentation
- Self-documenting code: kind of enforces contract update upon code that changes pre/post conditions
- Fault localization
“It is absurd to make elaborate security checks on debugging runs, when no trust is put in the results, and then remove them in production runs, when an erroneous result could be expensive or disastrous. What would we think of a sailing enthusiast who wears his life-jacket when training on dry land but takes it off as soon as he goes to sea?” -- Sir Tony Hoare [1973]
References
- Boost Contract Library
- References to C++ contract draft proposals
- Hoare '69 paper : An Axiomatic Basis for Computer Programming
- Owicki-Gries Rely Guarantee : An Axiomatic Proof Technique for Parallel Programs
- Reynolds paper on heap manipulating programs and it's correctness: Separation Logic: A Logic for Shared Mutable Data Structures
Code Contracts
By Saurabh Joshi
Code Contracts
- 833