Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
44d32d7
building declarations
mira-alford Apr 20, 2026
da5ae8b
Several fixes to smt + expr_smt
mira-alford Apr 20, 2026
7fe70e9
cleanup
mira-alford Apr 20, 2026
f137fe1
strongest postcondition start
mira-alford Apr 21, 2026
15f4fae
the most important thing: comments
mira-alford Apr 21, 2026
cd5cfbe
z3 fix? kinda hacky
mira-alford Apr 21, 2026
1ded011
merged
mira-alford Apr 22, 2026
ad78f89
fixed a boogie backend bug found by the ensures generation
mira-alford Apr 22, 2026
b760370
removed some debbugging
mira-alford Apr 22, 2026
7973adc
confusingly working towards substitution for interproc sp
mira-alford Apr 27, 2026
ee80448
fix to lambda attribute pretty printing
mira-alford Apr 27, 2026
d9fddd1
please why is it not working
mira-alford Apr 28, 2026
d93f9b5
SP Working, test case written
mira-alford Apr 29, 2026
bf85d6b
last minute cleanup
mira-alford Apr 29, 2026
ba893b0
fixed function summaries using cur_req instead of cur_ens
mira-alford Apr 29, 2026
7d4c3c5
fix to incorrect calls
mira-alford Apr 29, 2026
482f826
cleanup
mira-alford Apr 29, 2026
da60ff6
PR review improvements
mira-alford May 5, 2026
5eb8ede
an unrelated memory test :)
mira-alford May 5, 2026
ffe1f7c
an unrelated memory test :)
mira-alford May 5, 2026
4a5df59
an unrelated memory test :)
mira-alford May 5, 2026
f609ab1
Gave in to the demands of the formatter
mira-alford May 5, 2026
84e1551
added vertex to init
mira-alford May 5, 2026
fe9e2e2
added vertex to init
mira-alford May 5, 2026
f255c88
limit on max generated predicate size
mira-alford May 5, 2026
96858c0
fix to transfer phi
mira-alford May 5, 2026
0c5b32b
Formatter got me again :(
mira-alford May 5, 2026
9519a9f
interproc memory testcase
mira-alford May 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions examples/memory/memory_interproc.il
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
memory shared $mem : (bv64 -> bv8);
memory $stack : (bv64 -> bv8);

prog entry @main;

proc @malloc(R0_in:bv64) -> (R0_out:bv64);
proc @free(R0_in:bv64) -> ();

// In future, realloc should actually copy the byte accross.
// For now that is ommitted from this test as the store expression
// locks up the interprocedural redundancy check forever.
proc @realloc(ptr_in:bv64) -> (ptr_out:bv64)
[
block %realloc [
// var x:bv8 := load le $mem ptr_in 8;
call @free(ptr_in);
var size: bv64 := 1:bv64;
var (ptr_out:bv64) := call @malloc(size);
// store le $mem ptr_out x 8;
goto(%realloc_return);
];
block %realloc_return [
return;
];
];

proc @main () -> ()
[
block %main_entry [
var size: bv64 := 1:bv64;
var (addr:bv64) := call @malloc(size);
var (addr_2:bv64) := call @realloc(addr);
goto(%main_return);
];
block %main_return [
assert neq(addr, addr_2);
call @free(addr_2);
return;
];
];
121 changes: 121 additions & 0 deletions examples/memory/memory_safety.il
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
memory shared $mem : (bv64 -> bv8);
memory $stack : (bv64 -> bv8);

prog entry @main;

// Unspecified malloc/free procedures. Specified by
// memory specification + encoding transform.
proc @malloc(R0_in:bv64) -> (R0_out:bv64);
proc @free(R0_in:bv64) -> ();

// Valid memory operations. Allocates 2 bytes,
// stores/loads to the allocated space, and frees.
proc @main () -> () { .entrypoint=true; }
[
block %main_entry [
var size:bv64 := 2:bv64;
var (addr:bv64) := call @malloc(size);

store le $mem bvadd(addr,0:bv64) 0xff:bv8 8;
var temp:bv8 := load le $mem bvadd(addr,0:bv64) 8;

call @free(addr);

goto(%main_return);
];
block %main_return [
return ();
];
];

// Double free example. Calls free on address twice.
proc @double_free () -> () { .entrypoint=true; }
[
block %main_entry [
var size:bv64 := 2:bv64;
var (addr:bv64) := call @malloc(size);

store le $mem bvadd(addr,0:bv64) 0xff:bv8 8;
var temp:bv8 := load le $mem bvadd(addr,0:bv64) 8;

call @free(addr);
call @free(addr);

goto(%main_return);
];
block %main_return [
return ();
];
];

// Example of freeing a valid address which is not at the
// base of an allocation.
proc @invalid_free () -> () { .entrypoint=true; }
[
block %main_entry [
var size:bv64 := 2:bv64;
var (addr:bv64) := call @malloc(size);

call @free(bvadd(addr,1:bv64));

goto(%main_return);
];
block %main_return [
return ();
];
];

// Example of loading memory after free.
proc @use_after_free () -> () { .entrypoint=true; }
[
block %main_entry [
var size:bv64 := 2:bv64;
var (addr:bv64) := call @malloc(size);

store le $mem bvadd(addr,0:bv64) 0xff:bv8 8;
call @free(addr);
var temp:bv8 := load le $mem bvadd(addr,0:bv64) 8;

goto(%main_return);
];
block %main_return [
return ();
];
];

// Example reading at offset 4 of a 2 byte allocation.
proc @out_of_bounds () -> () { .entrypoint=true; }
[
block %main_entry [
var size:bv64 := 2:bv64;
var (addr:bv64) := call @malloc(size);

store le $mem bvadd(addr,4:bv64) 0xff:bv8 8;
var temp:bv8 := load le $mem bvadd(addr,4:bv64) 8;

call @free(addr);

goto(%main_return);
];
block %main_return [
return ();
];
];

// Example of catching a memory leak (unfreed addr).
proc @memory_leak () -> () { .entrypoint=true; }
[
block %main_entry [
var size:bv64 := 2:bv64;
var (addr:bv64) := call @malloc(size);

store le $mem bvadd(addr,0:bv64) 0xff:bv8 8;
var temp:bv8 := load le $mem bvadd(addr,0:bv64) 8;

goto(%main_return);
];
block %main_return [
return ();
];
];

10 changes: 8 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,14 @@

devShells = {
default = self.devShells.fp;
fp = fpOcamlPackages.callPackage ./nix/shell.nix { inherit bnfc-treesitter; };
no-fp = selfOcamlPackages.callPackage ./nix/shell.nix { inherit bnfc-treesitter; };
fp = fpOcamlPackages.callPackage ./nix/shell.nix {
inherit bnfc-treesitter;
z3 = pkgs.z3.out;
};
no-fp = selfOcamlPackages.callPackage ./nix/shell.nix {
inherit bnfc-treesitter;
z3 = pkgs.z3.out;
};
};
};
};
Expand Down
2 changes: 1 addition & 1 deletion lib/analysis/dataflow_graph.ml
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ struct

include SV

let init p =
let init ?(vertex = None) p =
let vs = Lang.Procedure.formal_in_params p |> StringMap.values in
vs
|> Iter.map (fun v -> (v, top_val))
Expand Down
1 change: 1 addition & 0 deletions lib/analysis/dune
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
tnum_wint_reduced_product
known_bits
wp_dual
sp
sva)
(libraries
intPQueue
Expand Down
2 changes: 1 addition & 1 deletion lib/analysis/gamma_domain.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module Domain = struct

let name = "Gamma domain"

let init proc =
let init ?(vertex = None) proc =
Procedure.formal_in_params proc
|> StringMap.values
|> Iter.append
Expand Down
2 changes: 1 addition & 1 deletion lib/analysis/intra_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ module Forwards (D : IntraDomain) = struct
Procedure.graph p
|> Option.map (fun g ->
A.recurse g (Procedure.topo_fwd p)
(fun v -> D.init p)
(fun v -> D.init ~vertex:(Some v) p)
widening_set widening_delay))
|> Option.get_or ~default:A.M.empty

Expand Down
2 changes: 1 addition & 1 deletion lib/analysis/known_bits.ml
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ module Domain = struct

include StateAbstraction

let init p =
let init ?(vertex = None) p =
let vs = Lang.Procedure.formal_in_params p |> StringMap.values in
vs
|> Iter.map (fun v -> (v, top_val))
Expand Down
4 changes: 2 additions & 2 deletions lib/analysis/lattice_types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ end
module type StateDomain = sig
include StateAbstraction

val init : Program.proc -> t
val init : ?vertex:Procedure.Vert.t Option.t -> Program.proc -> t
val transfer_state : (Var.t -> V.t) -> Program.stmt -> (Var.t * V.t) Iter.t
end

module type Domain = sig
include Lattice

val transfer : t -> Program.stmt -> t
val init : Program.proc -> t
val init : ?vertex:Procedure.Vert.t Option.t -> Program.proc -> t
end

module FlatLattice (L : sig
Expand Down
Loading
Loading