Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for inline assembler & goto instructions in inline assembler #1326

Open
wants to merge 72 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
ecda994
test
Nov 17, 2023
8c6531d
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Nov 17, 2023
33a8539
tiny commit so someone else doesn't have to fix compareAST
Nov 22, 2023
50901d1
cfg done; indentation complaints but I don't want to fix right now
Nov 22, 2023
43e50df
only added event type
Nov 25, 2023
5b09bbe
access analysis now emits invalidates
Nov 25, 2023
343f516
varEq analysis; invalidation tested
Nov 29, 2023
e797b87
deadlock done; indentation complaints even after I ran ocp-indent???
Nov 30, 2023
834b50f
mutexAnalysis done; fileUse buggy but commiting to try earlier commit
Dec 6, 2023
0605f4c
use queries
Dec 13, 2023
ccb8b05
warnings + expsplit (todo: ask supervisor about maylocks)
Dec 14, 2023
16ca052
this is only there to revert in case the warnings are needed (likely …
Dec 14, 2023
26c3dc6
ups
Dec 14, 2023
22276ad
mallocFresh
Dec 14, 2023
6925cbc
memLeak; ask supervisor about Multiple query
Dec 20, 2023
9ccd213
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Dec 20, 2023
7f63076
Revert "mallocFresh" => revert the revert when it compiles pls
Dec 20, 2023
d45791b
should have done base earlier; lots of analyses solve themselves
Dec 21, 2023
08a7156
malloc Fresh
Dec 21, 2023
4bc2e67
region-analysis
Jan 8, 2024
eb1650b
i add event function to region and useAfterfree analysis but it doesn…
Jan 9, 2024
2084173
Modifes Taint jmpbufs to store if potentially invalid.
N0W0RK Jan 11, 2024
e5cbbbc
Revert commit that doesn't compile so that we can test
Jan 11, 2024
6834957
Revert "region-analysis" (doesn't compile)
Jan 11, 2024
bcfb172
changes in region, useAfterFree and taintPartialContexts
Jan 11, 2024
31952ef
my stuff
Jan 11, 2024
be7ce58
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Jan 11, 2024
d831e1f
init function on malloc_null is never called????????????/
Jan 11, 2024
bb71066
my tests, TODO: add annotations
Jan 11, 2024
e22323c
bugfix
Jan 11, 2024
bb9582b
bugfix
Jan 11, 2024
134b032
Modifications of Variables by assembly between setjmp and longjmp are…
N0W0RK Jan 12, 2024
f137824
CondVar assumptions about lvals are dropped after clobber by asm.
N0W0RK Jan 12, 2024
5f7a314
CondVar assumptions about lvals are dropped after clobber by asm.
N0W0RK Jan 12, 2024
6b9f3e9
Merge branch 'master' of github.com:goblint/analyzer
Jan 12, 2024
b612b83
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Jan 12, 2024
91d85f3
moved invalidate emit to base
Jan 12, 2024
d2d9474
maybe like this?
Jan 12, 2024
9375176
I am retarded
Jan 12, 2024
eb41513
followed orders
Jan 12, 2024
90946cd
can one also point to latest commit?
Jan 14, 2024
b55366c
maybe
Jan 15, 2024
a75b931
forgot to pull
Jan 17, 2024
cb09957
todo: starting at valueDomain.ml (email), wtf should I do in cfgtools
Jan 17, 2024
2570bc6
went through everything
Jan 17, 2024
f3e582b
Adds initial regression tests
N0W0RK Jan 23, 2024
f6df1c5
to pull
Jan 25, 2024
c1fa1f5
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Jan 25, 2024
a3bd48a
tests
Jan 25, 2024
7b95fcd
expsplit-test
Jan 25, 2024
258ed14
ups
Jan 25, 2024
c7b4256
use-after-free-test
Jan 25, 2024
a1caa65
our tests pass make test (random tests fail though for some reason)
Jan 25, 2024
7030715
mod-since-setjmp-test
Jan 25, 2024
9868949
merge master to see if tests pass now
Jan 25, 2024
e2e2bec
test
Jan 25, 2024
ae41a07
Removes merge annotation
N0W0RK Jan 25, 2024
78e3c5d
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Jan 25, 2024
2b62fcf
Fixes Build Error after changes to ctx
N0W0RK Jan 25, 2024
f0dcc97
var-eq-test
Jan 25, 2024
52c8e95
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Jan 25, 2024
01cf846
uninit-test
Jan 25, 2024
2741b32
ups
Jan 25, 2024
efdb7ff
big ups
Jan 25, 2024
cd1c365
bugfixes; mutex-test
Feb 1, 2024
cdb6a3e
asm tests
Feb 2, 2024
83b5a7c
adding outs ins params makes goblint segfault every time (compiles)
Feb 5, 2024
8abe7a6
wtf
Feb 6, 2024
7edfff0
found bug :) why did ocaml no give a warning?
Feb 6, 2024
802271c
Merge branch 'master' of github.com:N0W0RK/goblint-analyzer
Feb 6, 2024
a7b830d
bugfix
Feb 7, 2024
626b8e1
Refactores regression tests.
N0W0RK Feb 9, 2024
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
4 changes: 4 additions & 0 deletions goblint.opam.locked
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ post-messages: [
]
# TODO: manually reordered to avoid opam pin crash: https://github.com/ocaml/opam/issues/4936
pin-depends: [
[
"goblint-cil.2.0.3"
"git+https://github.com/N0W0RK/goblint-cil.git#second_try"
]
[
"ppx_deriving.5.2.1"
"git+https://github.com/ocaml-ppx/ppx_deriving.git#0a89b619f94cbbfc3b0fb3255ab4fe5bc77d32d6"
Expand Down
13 changes: 13 additions & 0 deletions src/analyses/accessAnalysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ struct

let collect_local = ref false
let emit_single_threaded = ref false
let ignore_asm = ref true

let init _ =
ignore_asm := get_bool "asm_is_nop";
collect_local := get_bool "witness.yaml.enabled" && get_bool "witness.invariant.accessed";
let activated = get_string_list "ana.activated" in
emit_single_threaded := List.mem (ModifiedSinceSetjmp.Spec.name ()) activated || List.mem (PoisonVariables.Spec.name ()) activated
Expand Down Expand Up @@ -73,6 +75,17 @@ struct
ctx.local
end

let asm ctx outs ins =
if not !ignore_asm then begin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the asm_is_top flag impact all analyses? If this check be moved into the mCP, so that it only needs to be done once?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it probably should be at the FromSpec level even. And the top-level asm_is_nop option should probably be replaced with something more organized like sem.asm.nop.

let handle_in exp = access_one_top ctx Read false exp in
List.iter handle_in ins;
(* deref needs to be set to true because we have to use AddrOf *)
let handle_out lval = access_one_top ~deref:true ctx Write false (AddrOf lval) in
List.iter handle_out outs;
end;
ctx.local


let branch ctx exp tv : D.t =
access_one_top ctx Read false exp;
ctx.local
Expand Down
16 changes: 14 additions & 2 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ struct
let name () = "base"
let startstate v: store = { cpa = CPA.bot (); deps = Dep.bot (); weak = WeakUpdates.bot (); priv = Priv.startstate ()}
let exitstate v: store = { cpa = CPA.bot (); deps = Dep.bot (); weak = WeakUpdates.bot (); priv = Priv.startstate ()}
let ignore_asm = ref true

(**************************************************************************
* Helpers
Expand Down Expand Up @@ -160,6 +161,7 @@ struct
end;
return_varstore := Cilfacade.create_var @@ makeVarinfo false "RETURN" voidType;
longjmp_return := Cilfacade.create_var @@ makeVarinfo false "LONGJMP_RETURN" intType;
ignore_asm := get_bool "asm_is_nop";
Priv.init ()

let finalize () =
Expand Down Expand Up @@ -1240,9 +1242,11 @@ struct
if AD.mem Addr.UnknownPtr jmp_buf then
M.warn ~category:Imprecise "Jump buffer %a may contain unknown pointers." d_exp e;
begin match get ~ctx ~top:(VD.bot ()) ctx.local jmp_buf None with
| JmpBuf (x, copied) ->
| JmpBuf (x, copied, invalid) ->
if copied then
M.warn ~category:(Behavior (Undefined Other)) "The jump buffer %a contains values that were copied here instead of being set by setjmp. This is Undefined Behavior." d_exp e;
if invalid then
M.warn ~category:(Behavior (Undefined Other)) "The jump buffer %a was modified by inline assembly. This is may lead to Undefined Behavior." d_exp e;
x
| Top
| Bot ->
Expand Down Expand Up @@ -2582,7 +2586,7 @@ struct
| Setjmp { env }, _ ->
let st' = match eval_rv ~ctx st env with
| Address jmp_buf ->
let value = VD.JmpBuf (ValueDomain.JmpBufs.Bufs.singleton (Target (ctx.prev_node, ctx.control_context ())), false) in
let value = VD.JmpBuf (ValueDomain.JmpBufs.Bufs.singleton (Target (ctx.prev_node, ctx.control_context ())), false, false) in
let r = set ~ctx st jmp_buf (Cilfacade.typeOf env) value in
if M.tracing then M.tracel "setjmp" "setting setjmp %a on %a -> %a\n" d_exp env D.pretty st D.pretty r;
r
Expand Down Expand Up @@ -2898,6 +2902,11 @@ struct
in
D.join ctx.local e_d'

let asm ctx outs ins =
if not !ignore_asm then
ctx.emit (Events.Invalidate {lvals=outs});
ctx.local

let event ctx e octx =
let ask = Analyses.ask_of_ctx ctx in
let st: store = ctx.local in
Expand Down Expand Up @@ -2929,6 +2938,9 @@ struct
{st' with cpa = CPA.remove !longjmp_return st'.cpa}
| None -> ctx.local
end
| Events.Invalidate {lvals} ->
let exps = List.map Cil.mkAddrOrStartOf lvals in
invalidate ~ctx st exps
| _ ->
ctx.local
end
Expand Down
9 changes: 9 additions & 0 deletions src/analyses/condVars.ml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ struct
of_expr true e >? of_lval >? of_clval |? Queries.Result.top q
| _ -> Queries.Result.top q

let event ctx event octx =
match event with
| Events.Invalidate {lvals} ->
let mpts = List.map (fun lval -> mayPointTo ctx (AddrOf lval)) lvals in
let remove_mpt d mpt =
List.fold_left (fun d (v,o as k) -> D.remove k d |> D.remove_var v) d mpt in
List.fold_left remove_mpt ctx.local mpts
| _ -> ctx.local

(* transfer functions *)
let assign ctx (lval:lval) (rval:exp) : D.t =
(* remove all keys lval may point to, and all exprs that contain the variables (TODO precision) *)
Expand Down
1 change: 1 addition & 0 deletions src/analyses/deadlock.ml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct
let remove ctx l =
let inLockAddrs (e, _, _) = Lock.equal l e in
D.filter (neg inLockAddrs) ctx.local

end

include LocksetAnalysis.MakeMay (Arg)
Expand Down
9 changes: 9 additions & 0 deletions src/analyses/expsplit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ struct
D.add exp value ctx.local
| Longjmped _ ->
emit_splits_ctx ctx
| Invalidate {lvals} ->
let handle_lval local lval =
let exp = Lval lval in
if D.mem exp local then
D.remove exp local
else
local
in
List.fold handle_lval ctx.local lvals
| _ ->
ctx.local
end
Expand Down
23 changes: 23 additions & 0 deletions src/analyses/locksetAnalysis.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(** Basic lockset analyses. *)

open Analyses
open GoblintCil


module type DS =
Expand Down Expand Up @@ -33,6 +34,20 @@ sig
val remove: (D.t, G.t, D.t, V.t) ctx -> ValueDomain.Addr.t -> D.t
end

let addr_set_of_lval (a: Queries.ask) lval =
let exp = Cil.mkAddrOrStartOf lval in
let addr_set = a.f (Queries.MayPointTo exp) in
addr_set

let locks_of_lvals ctx lvals =
let ask = Analyses.ask_of_ctx ctx in
let collect_addr_sets locks lval =
let addr_set = addr_set_of_lval ask lval in
ValueDomain.AD.union locks addr_set
in
let addr_set = List.fold_left collect_addr_sets (ValueDomain.AD.empty ()) lvals in
ValueDomain.AD.elements addr_set

module MakeMay (Arg: MayArg) =
struct
include Make (Arg.D)
Expand Down Expand Up @@ -60,6 +75,7 @@ module type MustArg =
sig
include MayArg
val remove_all: (D.t, _, D.t, _) ctx -> D.t
val is_held: (D.t, G.t, D.t, V.t) ctx -> ValueDomain.Addr.t -> bool
end

module MakeMust (Arg: MustArg) =
Expand All @@ -82,6 +98,13 @@ struct
Arg.remove_all ctx (* remove all locks *)
| Events.Unlock l ->
Arg.remove ctx l (* remove definite lock or all in parallel if ambiguous (blob lock is never added) *)
| Events.Invalidate {lvals} ->
let locks = locks_of_lvals ctx lvals in
let is_held lock = Arg.is_held ctx lock in
let locks = List.filter is_held locks in
let remove_lock ctx lock = {ctx with local = Arg.remove ctx lock} in
let ctx = List.fold_left remove_lock ctx locks in
ctx.local
| _ ->
ctx.local
end
4 changes: 2 additions & 2 deletions src/analyses/mCP.ml
Original file line number Diff line number Diff line change
Expand Up @@ -428,15 +428,15 @@ struct
if q then raise Deadcode else d


let asm (ctx:(D.t, G.t, C.t, V.t) ctx) =
let asm (ctx:(D.t, G.t, C.t, V.t) ctx) outs ins =
let spawns = ref [] in
let splits = ref [] in
let sides = ref [] in
let emits = ref [] in
let ctx'' = outer_ctx "asm" ~spawns ~sides ~emits ctx in
let f post_all (n,(module S:MCPSpec),d) =
let ctx' : (S.D.t, S.G.t, S.C.t, S.V.t) ctx = inner_ctx "asm" ~splits ~post_all ctx'' n d in
n, repr @@ S.asm ctx'
n, repr @@ S.asm ctx' outs ins
in
let d, q = map_deadcode f @@ spec_list ctx.local in
do_sideg ctx !sides;
Expand Down
8 changes: 8 additions & 0 deletions src/analyses/mallocFresh.ml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ struct
let assign ctx lval rval =
assign_lval (Analyses.ask_of_ctx ctx) lval ctx.local

let event ctx e octx =
match e with
| Events.Invalidate {lvals} ->
let ask = Analyses.ask_of_ctx ctx in
let handle_lval local lval = assign_lval ask lval local in
List.fold_left handle_lval ctx.local lvals
| _ -> ctx.local

let combine_env ctx lval fexp f args fc au f_ask =
ctx.local (* keep local as opposed to IdentitySpec *)

Expand Down
37 changes: 25 additions & 12 deletions src/analyses/malloc_null.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Offs = ValueDomain.Offs

open GoblintCil
open Analyses
open GobConfig

module Spec =
struct
Expand All @@ -16,6 +17,21 @@ struct
module C = ValueDomain.AddrSetDomain
module P = IdentityP (D)

let name () = "malloc_null"

let return_addr_ = ref Addr.NullPtr
let return_addr () = !return_addr_

let startstate v = D.empty ()
let threadenter ctx ~multiple lval f args = [D.empty ()]
let threadspawn ctx ~multiple lval f args fctx = ctx.local
let exitstate v = D.empty ()
let ignore_asm = ref true

let init marshal =
return_addr_ := Addr.of_var (Cilfacade.create_var @@ makeVarinfo false "RETURN" voidType);
ignore_asm := get_bool "asm_is_nop"

(*
Addr set functions:
*)
Expand Down Expand Up @@ -153,16 +169,22 @@ struct
D.add (Addr.of_mval mval) ctx.local
| _ -> ctx.local

let asm ctx outs ins =
if not !ignore_asm then begin
let handle_in exp = warn_deref_exp (Analyses.ask_of_ctx ctx) ctx.local exp in
List.iter handle_in ins;
let handle_out lval = warn_deref_exp (Analyses.ask_of_ctx ctx) ctx.local (Lval lval) in
List.iter handle_out outs;
end;
ctx.local

let branch ctx (exp:exp) (tv:bool) : D.t =
warn_deref_exp (Analyses.ask_of_ctx ctx) ctx.local exp;
ctx.local

let body ctx (f:fundec) : D.t =
ctx.local

let return_addr_ = ref Addr.NullPtr
let return_addr () = !return_addr_

let return ctx (exp:exp option) (f:fundec) : D.t =
let remove_var x v = List.fold_right D.remove (to_addrs v) x in
let nst = List.fold_left remove_var ctx.local (f.slocals @ f.sformals) in
Expand Down Expand Up @@ -212,15 +234,6 @@ struct
end
| _ -> ctx.local

let name () = "malloc_null"

let startstate v = D.empty ()
let threadenter ctx ~multiple lval f args = [D.empty ()]
let threadspawn ctx ~multiple lval f args fctx = ctx.local
let exitstate v = D.empty ()

let init marshal =
return_addr_ := Addr.of_var (Cilfacade.create_var @@ makeVarinfo false "RETURN" voidType)
end

let _ =
Expand Down
5 changes: 2 additions & 3 deletions src/analyses/memLeak.ml
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,8 @@ struct
| ad when (not (Queries.AD.is_top ad)) && Queries.AD.cardinal ad = 1 ->
(* Note: Need to always set "ana.malloc.unique_address_count" to a value > 0 *)
begin match Queries.AD.choose ad with
| Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) ->
ToppedVarInfoSet.remove v ctx.local
| _ -> ctx.local
| Queries.AD.Addr.Addr (v,_) when ctx.ask (Queries.IsAllocVar v) && ctx.ask (Queries.IsHeapVar v) && not @@ ctx.ask (Queries.IsMultiple v) -> ToppedVarInfoSet.remove v state
| _ -> state
end
michael-schwarz marked this conversation as resolved.
Show resolved Hide resolved
| _ -> ctx.local
end
Expand Down
6 changes: 5 additions & 1 deletion src/analyses/mutexAnalysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,14 @@ struct
(s', Multiplicity.increment (fst l) m)
| _ -> (s', m)

let is_held ctx l =
let s, _ = ctx.local in
Lockset.mem (l, true) s || Lockset.mem(l, false) s

let remove' ctx ~warn l =
let s, m = ctx.local in
let rm s = Lockset.remove (l, true) (Lockset.remove (l, false) s) in
if warn && (not (Lockset.mem (l,true) s || Lockset.mem (l,false) s)) then M.warn "unlocking mutex (%a) which may not be held" Addr.pretty l;
if warn && (not (Lockset.mem (l,true) s || Lockset.mem (l,false) s)) then M.warn "unlocking mutex (%a) which may not be held" Addr.pretty l;
match Addr.to_mval l with
| Some mval when MutexTypeAnalysis.must_be_recursive ctx mval ->
let m',rmed = Multiplicity.decrement l m in
Expand Down
23 changes: 23 additions & 0 deletions src/analyses/region.ml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,29 @@ struct
| Some r when Lvals.is_empty r -> false
| _ -> true
end

let event ctx e octx =
match e with
| Events.Invalidate {lvals} ->
begin
match ctx.local with
| `Lifted reg ->
let old_regpart = ctx.global () in
let regpart, reg =
List.fold_left
(fun (regpart_acc, reg_acc) lval ->
Reg.assign_bullet lval (regpart_acc, reg_acc)
)
(old_regpart, reg)
lvals
in
if not (RegPart.leq regpart old_regpart) then
ctx.sideg () regpart;
`Lifted reg
| _ -> ctx.local
end
| _ -> ctx.local

let access ctx (a: Queries.access) =
match a with
| Point ->
Expand Down
7 changes: 7 additions & 0 deletions src/analyses/symbLocks.ml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ struct
(* TODO: why doesn't invalidate_exp involve any reachable for deep write? *)
List.fold_left (fun st e -> invalidate_exp (Analyses.ask_of_ctx ctx) e st) st write_args

let event ctx e octx =
match e with
| Events.Invalidate {lvals} ->
let ask = Analyses.ask_of_ctx ctx in
let invalidate local lval = invalidate_lval ask lval local in
List.fold_left invalidate ctx.local lvals
| _ -> ctx.local

module A =
struct
Expand Down
12 changes: 12 additions & 0 deletions src/analyses/taintPartialContexts.ml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ struct

end

let event ctx e octx =
match e with
| Events.Invalidate {lvals} ->
(* Handle the Invalidate event and update the tainted set *)
List.fold_left (fun acc lval ->
Spec.taint_lval ctx lval
) ctx.local lvals

| _ -> ctx.local



let _ =
MCP.register_analysis (module Spec : MCPSpec)

Expand Down
2 changes: 1 addition & 1 deletion src/analyses/unassumeAnalysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ struct

emit_unassume {ctx with local = st} (* doesn't query, so no need to redefine ask *)

let asm ctx =
let asm ctx outs ins =
emit_unassume ctx

let skip ctx =
Expand Down
Loading