This is the starting point for the RSE project.
In case of changes to the project description, we will communicate them via this Moodle thread. Please check both this thread and also other threads on Moodle regularly.
Imagine you are in charge of the deliveries for a chain of grocery stores. You will organize deliveries of products to stores, where the delivery will be moved with a trolley to the reserve where it is stored. As you write up a program to record planned deliveries, you want to make sure that there are no errors: a delivery should always deliver a positive amount of product, should not be bigger than the trolley size of the store, and the total amount received by a store should not be bigger than the size of its reserve. To verify your tentative programs, you decide to apply program analysis as taught in RSE.
Consider the following class Store
:
/**
* We are verifying calls into this class
*
*/
public final class Store {
// Trolley and reserve size for the store
private final int trolley_size, reserve_size;
// Amount of product received so far
int received_amount;
public Store(int trolley_size, int reserve_size) {
this.trolley_size = trolley_size;
this.reserve_size = reserve_size;
this.received_amount = 0;
}
public void get_delivery(int volume) {
// check NON_NEGATIVE
assert 0 <= volume;
// check FITS_IN_TROLLEY
assert volume <= this.trolley_size;
this.received_amount += volume;
// check FITS_IN_RESERVE
assert this.received_amount <= this.reserve_size;
}
}
The goal of the project is to implement a program analyzer that takes as input a
Java program which makes use of the Store
class. The program analyzer then
verifies that the following conditions hold for this program:
Property NON_NEGATIVE:
- For any reachable invocation of
get_delivery(v)
on an objecto
of classStore
,v >= 0
.
Property FITS_IN_TROLLEY:
- For any reachable invocation of
get_delivery(v)
on an objecto
of classStore
,v <= o.trolley_size
.
Property FITS_IN_RESERVE:
- For any reachable invocation of
get_delivery(v)
on an objecto
of classStore
, after the call is executed we have thato.received_amount <= o.reserve_size
.
These properties should be viewed as independent: for example, FITS_IN_TROLLEY
may be SAFE
even if NON_NEGATIVE
is UNSAFE
. In particular, you may
assume that only one assertion is checked at a time, and that violations of
other assertions are ignored.
Your program analyzer (see skeleton below) must take as input a TEST_CLASS
and
a VerificationProperty
(e.g., NON_NEGATIVE
), and return true (called SAFE
)
if the property is guaranteed to hold, and false (called UNSAFE
) if the
property cannot be proven.
// expected results:
// NON_NEGATIVE SAFE
// FITS_IN_TROLLEY SAFE
// FITS_IN_RESERVE SAFE
public class Basic_Test_Safe {
public static void m1() {
Store s = new Store(2, 4);
s.get_delivery(2);
s.get_delivery(1);
Store s2 = new Store(4, 4);
s2.get_delivery(4);
}
}
// expected results:
// NON_NEGATIVE UNSAFE
// FITS_IN_TROLLEY UNSAFE
// FITS_IN_RESERVE UNSAFE
public class Basic_Test_Unsafe {
public void m2(int j) {
Store s = new Store(1, 2);
if(-1 <= j && j <= 3)
s.get_delivery(j);
}
}
For each group, we have set up a repository with a skeleton for your solution, which you should see at https://gitlab.inf.ethz.ch/dashboard/projects. After reading this project description, you should read and follow the README.md file. It contains instructions on how to set up the project and run it.
The output of the skeleton is initially always SAFE
, which is unsound. The
goal of the project is to follow the comments in the code (check for FILL THIS OUT
), such that the project only reports SAFE
for test classes where we can
guarantee it (but as often as possible). Feel free to change any part of the
skeleton (even parts not marked with FILL THIS OUT
), and to create new files,
as long as you do not change files which tell you DO NOT MODIFY THIS FILE
.
For your analysis, you will use the two libraries APRON and Soot. Part of your assignment is understanding these libraries sufficiently to leverage them for program analysis. In addition to the resources provided below, you may also consult
- The course lectures on abstract interpretation and pointer analysis.
- The language fragment of Soot to handle (see below).
- The documentation for APRON and Soot (including documentation of methods and classes), which is available in Visual Studio Code after setting up the project (see README.md file).
APRON is a library for numerical abstract domains. An example file of using APRON exists here - it should demonstrate everything you need to know about APRON.
If you require more resources (which should not be necessary), you can also find documentation about the APRON framework here, and more extensive usage examples here.
Your program analyzer is built using Soot, a framework for analyzing Java programs. You can learn more about Soot by reading its tutorial, survivor guide, and javadoc. If you require more resources (which should not be necessary), you can find additional tutorials here.
Your program analyzer will use Soot's pointer analysis to determine which
variables may point to Store
objects (see the
Verifier.java file
in your skeleton).
For this project, you will analyse a fragment of Jimple. This language contains
only local integer variables and Store
objects. Note that the type of
integer variables can be int, byte, short, or bool (e.g., int i = 10;
is
represented as byte, see also
SootHelper.java ->
isIntValue
).
- Details about the Jimple language can be found here
- The language fragment to handle is:
Jimple Construct | Meaning |
---|---|
DefinitionStmt | Definition Statement: here, you only need to handle integer assignments to a local variable. That is, x = y , or x = 5 or x = EXPR , where EXPR is one of the three binary expressions below. That is, you need to be able to handle: y = x + 5 or y = x * z . |
JMulExpr | Multiplication |
JSubExpr | Subtraction |
JAddExpr | Addition |
JIfStmt | Conditional Statement. You need to handle conditionals where the condition can be any of the binary boolean expressions below. These conditions can again only mention integer local variables or constants, for example: if (x > y) or if (x <= 4) , etc. |
JEqExpr | == |
JGeExpr | >= |
JGtExpr | > |
JLeExpr | <= |
JLtExpr | < |
JNeExpr | != |
IntConstant | Integer constant |
JimpleLocal | Local variable |
ParameterRef | Method parameter |
JInvokeStmt | Call to get_delivery (cp. JVirtualInvokeExpr) or initializer for new Store object (cp. JSpecialInvokeExpr) |
JReturnVoidStmt | Return from function |
JGotoStmt | Goto statement |
- Loops are also allowed in the programs.
- Assignments of pointers of type
Store
are possible, e.g.e = f
wheree
andf
are of typeStore
. However, those are handled by the pointer analysis.
- You may assume the class you analyze only has a single method in addition to
its constructor (called
<init>
in Soot). You may assume that the constructor is empty. - You can assume the constructor
Store
takes as arguments (trolley_size
,reserve_size
) only integer constants (never local variables). However, the methodget_delivery
can be called with any element of the language fragment detailed above. - You can assume all analyzed methods only have integer parameters (in
particular, they cannot have
Store
parameters). - The analyzed code may contain loops and branches.
- You will need to apply widening. Do this after
WIDENING_THRESHOLD
steps (see NumericalAnalysis.java -> WIDENING_THRESHOLD). Our grading will ensure that increasingWIDENING_THRESHOLD
does not increase your score. - Only local variables need to be tracked for the numerical analysis (no global variables), but for the heap you need to use the existing pointer analysis of Soot. The skeleton already contains the invocation of the pointer analysis. You can then leverage the result of this pointer analysis for your numerical analysis.
- You can assume the analyzed code never throws exceptions, such as
null
dereferences, or division by zero. - You may ignore overflows in your implementation (in other words, you may assume that APRON captures Java semantics correctly)
- It is enough to use the polyhedra domain that APRON provides (Polka) to analyze relations over the local integer variables.
- If you see an operation for which you are not precise - do not crash, but be less precise or go to top instead so that you remain sound. This is useful in case of misunderstandings on the project description.
- The three properties to check are ordered by difficulty. We recommend you work on them in the order NON_NEGATIVE, FITS_IN_TROLLEY, FITS_IN_RESERVE. The last property is meant as a challenge for stronger groups (but solving it is necessary for full points).
- We strongly recommend you to test your implementation on many examples (you should come up with your own examples).
- The project deadline is Wednesday, June 7th, 3, 17:00 (Zurich time)!
- We may decline to answer project questions after Monday, June 5th, 2023, 17:00. This avoids last-minute revelations that cannot be incorporated by all groups.
- Commit and push your project to the master branch of your GitLab repository (that originally contained the skeleton) before the project deadline. Please do not update your repository (commit, revert, etc.) after the deadline - we will flag groups that try this.
- If you cannot access your GitLab repository, contact [email protected].
- We will evaluate your tool on our own set of programs for which we know if they are valid or not.
- Your project must use the setup of the provided skeleton. In particular, you cannot use libraries other than those provided in analysis/pom.xml.
- We will evaluate you depending on the correctness of your program and the precision of your solution. You will not get points if your program does not satisfy the requirements. If your solution is unsound (i.e. says that an unsafe code is safe), or imprecise (i.e. says that a safe code is unsafe) we will penalize it.
- We will penalize unsoundness much more than imprecision.
- There will be a time limit of 10 seconds and 1GB of RAM to verify an application. Use this script if you want to ensure your solution adheres to these limits. Because the performance of a given solution is sometimes hard to predict, this limit is chosen generously.
- We will award additional points for groups that achieve a test instruction
coverage of
>=75%
(achieving coverage>75%
does not yield more points than achieving75%
). If some of your tests fail, we will not award any additional points. - Your solution must use abstract interpretation. Do not use other techniques like symbolic execution, testing, brute force, random guessing, machine learning, etc.
- Do not try to cheat (e.g., by reading the solutions from the test file)!
- Only submit solutions that you have written yourself and that you have understood. Cross-team implementation and copy paste (except from the project skeleton itself) is not permitted.
In case you are unsure if you are expected to be precise on a given program, you may query the master solution here to gauge the precision we expect from a top-graded project (you need to provide your nethz username and password).
For questions about the project, please consult, in this order:
- This project description
- The skeleton in your GitLab repository (in particular the README file)
- The documentation of libraries&frameworks, in particular APRON and Soot discussed above
- The Moodle page. All students will see and are encouraged to reply to the questions about the project.
- The project TA at [email protected] (only when Moodle is not possible)