Skip to content

Commit c767615

Browse files
committed
New release with several bugfixes.
1 parent 9bb531e commit c767615

File tree

101 files changed

+8780
-751
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+8780
-751
lines changed

CONTRIBUTORS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
| Pramod Subramanyan | [email protected] |
66
| Sanjit Seshia | [email protected] |
77
| Rohit Sinha | [email protected] |
8+
| Kevin Cheang | [email protected] |
9+
| Cameron Rasmussen | [email protected] |
810

911
## Other Contributors
1012

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
The [tutorial](https://github.com/uclid-org/uclid/blob/master/tutorial/tutorial.pdf) has a gentle introduction to using uclid5.
66

7-
If you use uclid5 in your own research, it is suggested that you cite the following MEMOCODE 2018 paper.
7+
If you use uclid5 in your work, please cite the following MEMOCODE 2018 paper:
88

99
Sanjit A. Seshia and Pramod Subramanyan. <font color="blue">UCLID5: Integrating Modeling, Verification, Synthesis and Learning.</font>
1010
[\[PDF\]](https://cse.iitk.ac.in/users/spramod/papers/memocode18.pdf)
@@ -18,6 +18,17 @@ You will need the [Z3 SMT solver](https://github.com/Z3Prover/z3) to be installe
1818

1919
uclid5 requires that the Z3 dynamic link library (libz3.so on Unix-like platforms) as well as the dynamic link library for the Z3/Java API (libz3java.so on Unix-like platforms) be in your dynamic library path (`$LD_LIBRARY_PATH` on Unix-like platforms; just `PATH` on Windows).
2020

21+
### Mac OS X El Capitan or up
22+
System Integrity Protection is a feature introduced by Apple in OS X El Capitan; it prevents the modifications of system-owned files and directories by any process without a specific ‘entitlement’, even when executed by a root user or a user with root privileges. Since Java is a SIP protected executable, it ignores the user set DYLD_LIBRARY_PATH, which prevents the system from recognizing the Z3 Dynamic Library.
23+
24+
To fix this issue, put:
25+
- JNI dynamic link libraries (e.g libz3java.dylib) in: /Library/Java/Extensions
26+
- non-JNI dynamic link libraries (e.g libz3.dylib) in: /usr/local/lib
27+
28+
For more information on the resolution of this issue, please refer to:
29+
https://github.com/Z3Prover/z3/issues/294
30+
31+
2132
## Download Pre-Built Binaries
2233

2334
Download the latest stable pre-built package from [releases tab](https://github.com/uclid-org/uclid/releases).
@@ -40,7 +51,7 @@ If compilation and tests pass, you can build a universal package.
4051

4152
This will create uclid/target/universal/uclid-0.8.zip, which contains the uclid binary in the bin/ subdirectory. Unzip this file, and add it to your path.
4253

43-
## Installing uclid5
54+
## Installing and Running uclid5
4455

4556
$ unzip uclid-0.9.5.zip
4657
$ cd uclid-0.9.5

build.sbt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
name := "uclid"
22
version := "0.9.5"
3-
scalaVersion := "2.12.6"
3+
maintainer := "[email protected]"
4+
scalaVersion := "2.12.7"
45

56
scalacOptions += "-feature"
67
scalacOptions += "-unchecked"
78
scalacOptions += "-deprecation"
89

910
resolvers += "Artima Maven Repository" at "http://repo.artima.com/releases"
1011

11-
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.8.0"
12+
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.0"
1213
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
13-
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.6" withSources()
14-
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.1"
15-
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
14+
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.1" withSources()
15+
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.5"
16+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test"
1617
libraryDependencies += "com.github.scopt" %% "scopt" % "3.7.0"
1718

1819
enablePlugins(JavaAppPackaging)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
module main {
2+
3+
var fork_taken : [bv2]boolean;
4+
var num_forks : [bv2]bv2;
5+
var eaten : [bv2]boolean;
6+
7+
8+
var got_forks_left : [bv2]boolean;
9+
var got_forks_right : [bv2]boolean;
10+
11+
12+
init {
13+
fork_taken = const(false, [bv2]boolean);
14+
num_forks = const(0bv2, [bv2]bv2);
15+
eaten = const(false, [bv2]boolean);
16+
got_forks_left = const(false, [bv2]boolean);
17+
got_forks_right = const(false, [bv2]boolean);
18+
}
19+
20+
21+
procedure acquire_left(i: bv2)
22+
returns (success: boolean)
23+
modifies fork_taken;
24+
{
25+
success = false;
26+
if (fork_taken[i - 1bv2] == false) {
27+
fork_taken[i - 1bv2] = true;
28+
success = true;
29+
}
30+
}
31+
32+
33+
procedure acquire_right(i: bv2)
34+
returns (success: boolean)
35+
modifies fork_taken;
36+
{
37+
success = false;
38+
if (fork_taken[i] == false) {
39+
fork_taken[i] = true;
40+
success = true;
41+
}
42+
}
43+
44+
input i: bv2;
45+
input tryLeft : boolean;
46+
input tryRight: boolean;
47+
48+
procedure get_forks(i: bv2)
49+
modifies fork_taken, num_forks, got_forks_left, got_forks_right;
50+
{
51+
var got_fork : boolean;
52+
53+
// each philosopher tries to acquire left fork first and then right fork
54+
55+
if (tryLeft && !got_forks_left[i]) {
56+
call (got_fork) = acquire_left(i);
57+
if (got_fork) {
58+
num_forks[i] = num_forks[i] + 1bv2;
59+
got_forks_left[i] = true;
60+
}
61+
}
62+
63+
if (tryRight && got_forks_left[i] && !got_forks_right[i]) {
64+
call (got_fork) = acquire_right(i);
65+
if (got_fork) {
66+
num_forks[i] = num_forks[i] + 1bv2;
67+
got_forks_right[i] = true;
68+
}
69+
}
70+
}
71+
72+
procedure release_forks(i: bv2)
73+
modifies num_forks, fork_taken, got_forks_left, got_forks_right;
74+
{
75+
// releases the forks after philosopher has eaten once
76+
// and again competes to acquire the forks
77+
num_forks[i] = 0bv2;
78+
fork_taken[i] = false;
79+
fork_taken[i - 1bv2] = false;
80+
got_forks_right[i] = false;
81+
got_forks_left[i] = false;
82+
}
83+
84+
next {
85+
86+
if (eaten[i] == false) {
87+
// try acquiring two forks
88+
call get_forks(i);
89+
if (num_forks[i] == 2bv2) { eaten' = eaten[i -> true]; }
90+
}
91+
else {
92+
call release_forks(i);
93+
eaten' = eaten[i -> false];
94+
}
95+
}
96+
97+
// Given all resource has been consumed and all users have tried,
98+
// then atleast one philosopher has succeed
99+
// (i.e. no deadlock, however starvation is possible)
100+
property[LTL] someone_eats:
101+
102+
G ( F(i == 0bv2) && F ((i == 1bv2)) && F(i == 2bv2) && F(i == 3bv2) &&
103+
F(fork_taken[0bv2] == true) && F(fork_taken[1bv2] == true) &&
104+
F(fork_taken[2bv2] == true) && F(fork_taken[3bv2] == true))
105+
==> F(eaten[0bv2] || eaten[1bv2] || eaten[2bv2] || eaten[3bv2]);
106+
107+
108+
109+
control {
110+
v = bmc(8);
111+
check;
112+
print_results;
113+
v.print_cex(i, tryLeft, tryRight, got_forks_left, got_forks_right, fork_taken, num_forks, eaten);
114+
}
115+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
module main {
2+
3+
var fork_taken : [bv2]boolean;
4+
var num_forks : [bv2]bv2;
5+
var eaten : [bv2]boolean;
6+
7+
8+
var got_forks_left : [bv2]boolean;
9+
var got_forks_right : [bv2]boolean;
10+
11+
12+
init {
13+
fork_taken = const(false, [bv2]boolean);
14+
num_forks = const(0bv2, [bv2]bv2);
15+
eaten = const(false, [bv2]boolean);
16+
got_forks_left = const(false, [bv2]boolean);
17+
got_forks_right = const(false, [bv2]boolean);
18+
}
19+
20+
21+
procedure acquire_left(i: bv2)
22+
returns (success: boolean)
23+
modifies fork_taken;
24+
{
25+
success = false;
26+
if (fork_taken[i - 1bv2] == false) {
27+
fork_taken[i - 1bv2] = true;
28+
success = true;
29+
}
30+
}
31+
32+
33+
procedure acquire_right(i: bv2)
34+
returns (success: boolean)
35+
modifies fork_taken;
36+
{
37+
success = false;
38+
if (fork_taken[i] == false) {
39+
fork_taken[i] = true;
40+
success = true;
41+
}
42+
}
43+
44+
input i: bv2;
45+
input tryLeft : boolean;
46+
input tryRight: boolean;
47+
48+
procedure get_forks(i: bv2)
49+
modifies fork_taken, num_forks, got_forks_left, got_forks_right;
50+
{
51+
var got_fork : boolean;
52+
53+
// Philosophers either gets both forks or none
54+
55+
if (tryLeft && tryRight && !fork_taken[i-1bv2] && !fork_taken[i]) {
56+
num_forks[i] = num_forks[i] + 2bv2;
57+
got_forks_left[i] = true;
58+
got_forks_right[i] = true;
59+
}
60+
}
61+
62+
procedure release_forks(i: bv2)
63+
modifies num_forks, fork_taken, got_forks_left, got_forks_right;
64+
{
65+
// releases the forks after philosopher has eaten once
66+
// and again competes to acquire the forks
67+
num_forks[i] = 0bv2;
68+
fork_taken[i] = false;
69+
fork_taken[i - 1bv2] = false;
70+
got_forks_right[i] = false;
71+
got_forks_left[i] = false;
72+
}
73+
74+
next {
75+
76+
if (eaten[i] == false) {
77+
// try acquiring two forks
78+
call get_forks(i);
79+
80+
if (num_forks[i] == 2bv2) { eaten' = eaten[i -> true]; }
81+
} else {
82+
call release_forks(i);
83+
eaten' = eaten[i -> false];
84+
}
85+
}
86+
87+
// Given all resource has been consumed and all users have tried,
88+
// then atleast one philosopher has succeed
89+
// (i.e. no deadlock, however starvation is possible)
90+
property[LTL] someone_eats:
91+
92+
G ( F(i == 0bv2) && F ((i == 1bv2)) && F(i == 2bv2) && F(i == 3bv2) &&
93+
F(fork_taken[0bv2] == true) && F(fork_taken[1bv2] == true) &&
94+
F(fork_taken[2bv2] == true) && F(fork_taken[3bv2] == true))
95+
==> F(eaten[0bv2] || eaten[1bv2] || eaten[2bv2] || eaten[3bv2]);
96+
97+
98+
99+
control {
100+
v = bmc(12);
101+
check;
102+
print_results;
103+
v.print_cex(i, tryLeft, tryRight, fork_taken, num_forks, eaten);
104+
}
105+
}

examples/fib2safety.ucl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module fib
2+
{
3+
var a, b : integer;
4+
5+
init {
6+
assume (a >= 0);
7+
assume (b > 0);
8+
assume (a <= b);
9+
}
10+
11+
next {
12+
a' = b;
13+
b' = a + b;
14+
}
15+
}
16+
17+
module main
18+
{
19+
instance fib1 : fib();
20+
instance fib2 : fib();
21+
22+
init {
23+
assume (fib1.a == fib2.a && fib1.b == fib2.b);
24+
}
25+
26+
next {
27+
next (fib1);
28+
next (fib2);
29+
}
30+
31+
property b_are_eq : fib1.b == fib2.b;
32+
property a_are_eq : fib1.a == fib2.a;
33+
property b_gt_0 : fib1.b > 0 && fib2.b > 0;
34+
property a_ge_0 : fib1.a >= 0 && fib2.a >= 0;
35+
property a_le_b : fib1.a <= fib1.b && fib2.a <= fib2.b;
36+
37+
control {
38+
v = unroll(5);
39+
// v = induction;
40+
check;
41+
print_results;
42+
v.print_cex(fib1.a, fib1.b, fib2.a, fib2.b);
43+
}
44+
}

examples/hash.ucl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
module main
2+
{
3+
function hash(d1 : integer, h1 : integer) : integer;
4+
5+
axiom forall (d1 : integer, d2 : integer, h1 : integer, h2 : integer)
6+
pattern[hash(d1, h1), hash(d2, h2)]
7+
:: (d1 == d2 && h1 == h2) <==> hash(d1, h1) == hash(d2, h2);
8+
9+
var dcopy : [integer]integer;
10+
var data : [integer]integer;
11+
var dhash : integer;
12+
13+
procedure compute_hash(d : [integer]integer)
14+
returns (h : integer)
15+
{
16+
var h1, h2 : integer;
17+
h1 = hash(d[1], d[2]);
18+
h2 = hash(d[3], d[4]);
19+
h = hash(h1, h2);
20+
}
21+
22+
init {
23+
dcopy = data;
24+
call (dhash) = compute_hash(data);
25+
data[0] = dhash;
26+
}
27+
28+
next {
29+
var idx : integer;
30+
var dat : integer;
31+
var arr1 : [integer]integer;
32+
var arrh : integer;
33+
34+
// havoc the index idx with dat.
35+
arr1 = data[idx -> dat];
36+
// update the hash
37+
call (arrh) = compute_hash(arr1);
38+
// store the hash.
39+
data' = arr1[0 -> arrh];
40+
}
41+
42+
invariant init_hash:
43+
dhash == hash(hash(dcopy[1], dcopy[2]), hash(dcopy[3], dcopy[4]));
44+
invariant eq_data :
45+
(data[0] == dhash) ==> (data[1] == dcopy[1] && data[2] == dcopy[2] &&
46+
data[3] == dcopy[3] && data[4] == dcopy[4]);
47+
48+
control {
49+
set_solver_option(":mbqi", false);
50+
v = induction(1);
51+
check;
52+
print_results;
53+
}
54+
}

project/plugins.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// this adds the native packager.
2-
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.1")
2+
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.14")
33
// this helps create eclipse projects.
4-
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.3")
4+
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
55

0 commit comments

Comments
 (0)