Formal specification and verification using JML
Formal specification and verification using JML
[http://www.cs.ru.nl/~erikpoll/Teaching/CSIS/opdracht.html]
Hand in exercise 1 & 2 & 3 - ie. your cumulative result after exercise 3 -
by email to Richard, unless this was signed off on Thursday afternoon already.
Provide your answer as a single attachment entitled TaxpayerYOURFULLNAME.java,
and don't zip, tar, ... it.
Goal of this exercise are to experience
- how many constraints - implicit or explicit constraints - there may be even
in a simple scenario;
- how these can be formalised in a formal specification language;
- how they can then be used by a tool for verification.
The formal specification language we use is JML,
which allows us to express contraints in propositional and predicate logic about
Java programs.
The tool we use is the verification tool
ESC/Java2,
which is an automated program verification tool for Java programs.
Running ESC/Java2
ESC/Java2 is available on the central UNIX machines (e.g. solost)
and on the Windows PCs in the terminal rooms. You can also download it
on your own machine. Instructions for this:
- central UNIX machines
ESC/Java2 is installed in /vol/practica/softwaresecurity.
To run the tool on some file Taxpayer.java, give the command
/vol/practica/softwaresecurity/ESCJava/escjava2 Taxpayer.java
- Windows PCs in terminal rooms
ESC/Java2 is installed in T:\softwaresecurity.
To run the tool on some file A.java, open a command window
by selecting
Start -> Programs -> Accessories -> Command Prompt
then go to the directory where Taxpayer.java is (using cd)
and type in the command
T:\softwaresecurity\ESC\escj.bat Taxpayer.java
- Installing on your own machine
If you prefer running the tool on your own computer,
ESC/Java2 can be downloaded
here.
(Don't be scared to give your email address; we won't use it to spam you.)
You should get the latest version, 2.0a9, and it is probably easiest
to get the binary zip file, i.e. ESCJava-2.0a9-01-10-05-binary.zip.
The tool runs on just about any platform: Windows, Mac, Linux and UNIX.
NB ESC/Java2 only runs under Java 1.4, and not under Java 1.5.
So you might have to download Java 1.4 here.
If you're using Windows, you will have to edit escj.bat to provide the correct path names:
the last line of escj.bat should be
"C:\j2sdk1.4.2_12\bin\Java.exe" -Dsimplify="C:\ESCJava 2\Simplify-1.5.4.exe"
-classpath "C:\ESCJava 2\esctools2.jar" escjava.Main -classpath
"C:\ESCJava 2\jmlspecs.jar" -classpath . %ESCJ_STDARGS% %ESCJ_ARGS%
if you installed ESC/Java2 in "C:\ESCJava 2" and Java in "C:\j2sdk1.4.2_12"
If you're using Linux or MacOS, use the script escjava2 to run
the tool.
I would warn against using any Eclipse plugins for ESC/Java2 you might
find on the web, as these
are not really stable.
The assignment, part 1
For the assignment, download the file Taxpayer.java.
This class is used in an information system at the tax office
to record information about persons.
The tax office want to ensure that the following properties hold:
- Persons are either male or female.
- Persons can marry to people of the opposite sex. (A bit outdated
maybe, but makes for interesting properties to specify).
- A very obvious constraint, but easy to overlook:
if person x is married to person y, then person should of
course also be married, and to person x.
Your assignment is to
- add invariants to the code below to express the constraints mentioned
above, in JML syntax, plus any other sensible constraints you can
think of;
- use ESC/Java2 to detect possible violations, which are reported as warnings
- for the Java methods that ESC/Java2 complains about fix this, by
- correcting the code, or
- adding a (sensible) precondition for the
method, using a JML requires clause, or
- sometimes, adding an invariant to record another
constraint can help in verification.
Hints
- Only look at the first warning that ESC/Java2 produces, and ignore the
others, until you've managed to get rid of this first one.
- The code of the methods marry and divorce
in the class Taxpayer is not correct. ESC/Java2
should detect this and complain about these methods once you've
added your invariants, and you will have to add a few lines of
code to fix these methods, and possibly also add a precondition
by means of a requires clause.
-
It is easiest to introduce one constraint at a time, then fix the errors
this brings to light, and only then move on to the next constraint.
-
If the tool produces some warnings, ie. if the tool thinks
that some formal constraint is not satisfied by the code, this
can have several causes:
- There is an error in the code, which results in a violation in
the Java code. For example, an assignment to some field may be missing.
- There is an error in the JML specification. For example,
maybe you have written "and" in a specifcation where you meant "or",
maybe you have written age > 18
when you meant age >= 18 in some constraint
- There may be some contraints missing, which are needed by the
tool for the verification.
Note that the tool does not know any of the things that may be obvious to you
-- for example, that if some person x is married to y then y is also married to x
-- and such properties may be needed for verification.
- In general, a warning might be caused by the fact that some
property is too difficult for the theorem prover to proof:
an automated theorem prover can only ever prove properties of
a certain, limited complexity. However, for the exercises here
you should not run into this problem.
To stop the tool from complaining, you can
- correct the Java program; here this should only involve
adding some simple assignments to the offending method;
- correct the JML specification;
- add some additional constraints, either as a JML invariant
or as JML precondition aka requires clause.
In the end, ESC/Java2 should run without any complaints on the annotated
code, meaning that it has succeeded in verifying that the code meets
the formal specification.
JML syntax
Below the syntax for Java and JML logical connectives, in order
of decreasing precedence:
| logical connective |
Java/JML syntax |
| not |
! |
| equality |
== |
| inquality |
!= |
| conjunction (and) |
&& |
| disjunction (or) |
|| |
| implication |
==> , <== |
| (in)equivalence |
<==> , <=!=> |
In addition to this, you can use standard Java syntax,
so you can say things such as
this.spouse != null ==> (this.spouse.spouse.isFemale ==> this.isFemale)
Of course, you can write spouse instead of this.spouse,
leaving this implicit.
Note that in Java, as in most programming languages, references
such as the spouse field, can be null. Often
fields should not be null under certain circumstances,
which can be expressed by an invariant of the form
//@ invariant .... ==> spouse !=null;
Often arguments of method should not be null, which can
be expressed by a precondition of the form
//@ requires new_spouse != null;
void marry (Taxpayer new_spouse) {
The assignment, part 2
The tax system uses a income tax allowance (belastingvrije voet):
- Every person has an income tax allowance, over which
means they do not have to pay tax over the first part of their
income. There is a default tax allowance of 5000.
- Married persons can pool their tax allowance, as long as the sum
of their tax allowances remains the same. For example, the wife could
have a tax allowance of 10000, and the husband a tax allowance of 0.
Add invariants that express these constraints,
and if necessary fix/improve the code to ensure that they are not violated.
The assignment, part 3
The new government introduces a measure that people aged 65 and over
have a higher tax allowance, of 7000. The rules for pooling tax
allowances remain the same.
Add invariants that express these constraints,
and if necessary fix/improve the code to ensure that they are not violated.
The assignment, part 4
WARNING: things may get a bit hairy here, so don't be too depressed if you
don't manage to finish this.
The minister for Jeugd en Gezin, André Rouvoet, introduces a new tax measure
giving anyone with underage children an additional tax allowance of 1000 euro.
The taxpayer class is extended with an additional field to keep track
of the youngest child
Taxpayer youngestChild; // youngest child of this person
and the two following lines are added to the constructor
Taxpayer(boolean jongetje, Taxpayer ma, Taxpayer pa) {
...
youngestChild = null; // NEW
ma.youngestChild = this; // NEW
pa.youngestChild = this; // NEW
}
Add the three lines above to your code, add invariant(s) to express
the new government policy above, and re-run ESC/Java2 and fix the code
to ensure that it is not violated.
General hints
Some hints to keep you out of trouble with the tool:
Reflection
Some questions to consider
- In the end, do you think that you found all problems?
Are you certain now that the code is correct?
- Can you think of ways in which the tool or the specification
language could be improved?
- Can you think of other situations where a similar kind of tool support
could be useful?
- Instead of the tool we used, can you think of other ways (formal or informal,
tool-supported or not) to find the problems that the tool found? If so,
would these alternatives
-
find fewer of the problems, the same, or more?
-
find problems sooner or later than the current approach?
-
require more work or less work?
-
provide you with more confidence or less
confidence that the code is correct?