Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
186 commits
Select commit Hold shift + click to select a range
4aeb47e
Add tests from #764
michael-schwarz Jan 20, 2023
19e5cda
Add looping test
michael-schwarz Jan 20, 2023
1e405d0
Add library definition
michael-schwarz Jan 20, 2023
f29df38
Add rudimentary jumpbufferset domain
michael-schwarz Jan 22, 2023
ea79053
Rudimentary tracking of jmp targets
michael-schwarz Jan 22, 2023
3885a17
Analysis getting jump targets
michael-schwarz Jan 22, 2023
029b5af
Store hash in jmpbuf
michael-schwarz Jan 22, 2023
c277745
Lift to deal with setjmp
michael-schwarz Jan 22, 2023
ed0e795
Detect if longjmp comes from same context
michael-schwarz Jan 22, 2023
66cd6af
Add special node for longjmp targets
michael-schwarz Jan 26, 2023
80d54fb
Towards a working implementation
michael-schwarz Jan 26, 2023
c121838
Raise deadcode
michael-schwarz Jan 27, 2023
8899033
Add new node type for returns through longjmp
michael-schwarz Jan 27, 2023
3633c2e
Side-effecting to new unknown for non-local jumps
michael-schwarz Jan 30, 2023
4de1cee
First steps for longjump across functions
michael-schwarz Feb 3, 2023
ecd0746
Insert TODO
michael-schwarz Feb 6, 2023
e5bb2b9
Track second component in activeLongjmp
michael-schwarz Feb 6, 2023
34ecc9f
Pass along return value
michael-schwarz Feb 6, 2023
934cffe
Skip failing tests
michael-schwarz Feb 6, 2023
04626e3
Make global example global
michael-schwarz Feb 6, 2023
78ec16d
Add missing cases for JumpBuffers
michael-schwarz Feb 6, 2023
74a43fc
Replace `assert` with `__goblint_check`
michael-schwarz Feb 6, 2023
cbb6832
Uncomment working test
michael-schwarz Feb 6, 2023
25ce5ca
Add TODO
michael-schwarz Feb 6, 2023
3c20157
Fixes & Unskip two tests
michael-schwarz Feb 8, 2023
9b392d3
Solve issue with duplicate locals
michael-schwarz Feb 9, 2023
c14881b
Unskip further working test
michael-schwarz Feb 9, 2023
6746713
Add working tests
michael-schwarz Feb 9, 2023
5595704
Unskip all working tests
michael-schwarz Feb 9, 2023
bf8e761
Test 64/18 add explanation
michael-schwarz Feb 9, 2023
ea017ae
Add some tests for jumping through multiple functions
michael-schwarz Feb 9, 2023
d9b1c15
Add comments & failing test
michael-schwarz Feb 9, 2023
1c9c75e
Use combine, highlight issue
michael-schwarz Feb 9, 2023
105cac4
Add `longjmpthrough` option to combine
michael-schwarz Feb 9, 2023
1c622ac
Handling for logjump from deeper down callstack
michael-schwarz Feb 10, 2023
ab7e3b9
Cleanup debug messages
michael-schwarz Feb 10, 2023
887d919
Produce warnings for inappropriate longjmp arg
michael-schwarz Feb 10, 2023
6a42c3e
Use typeOf from Cilfacade instead of from CIL
michael-schwarz Feb 10, 2023
cf0b766
Cleanup tracing
michael-schwarz Feb 10, 2023
2b4a1b4
Warn for longjmps up the stack
michael-schwarz Feb 13, 2023
f9cd2b5
Better error messages for invalid jumps
michael-schwarz Feb 13, 2023
b1fc86b
Add example where warnings still break :(
michael-schwarz Feb 13, 2023
2e4b46f
Add path-sensitive analysis of active setjumps
michael-schwarz Feb 13, 2023
c784dd3
Be path-sensitive in set of active longjumps
michael-schwarz Feb 14, 2023
a30455a
Fix typos in test name
michael-schwarz Feb 14, 2023
cc37046
Use set of valid longjmps to warn if invalid one is performed
michael-schwarz Feb 14, 2023
98b5ab5
Add example for the non-termination of the analysis
michael-schwarz Feb 14, 2023
bd80fbc
Add further example
michael-schwarz Feb 14, 2023
f4ebfd4
Simplify code
michael-schwarz Feb 14, 2023
cd0d9ff
Cleanup
michael-schwarz Feb 14, 2023
3eafede
Add example of multi-threaded case
michael-schwarz Feb 14, 2023
57c21a6
Example for non-unique jmpbufs
michael-schwarz Feb 14, 2023
4462258
Fix so warn is annotation and not race
michael-schwarz Feb 14, 2023
026c000
Merge branch 'master' into longjmp
michael-schwarz Feb 16, 2023
9e6e48f
Update gobview
michael-schwarz Feb 16, 2023
ec95f29
Formatting
michael-schwarz Feb 16, 2023
5ec9b26
Add analysis tracking set of locally wirtten values since setjmp
michael-schwarz Feb 16, 2023
8554e39
Tracking of modified locals
michael-schwarz Feb 16, 2023
850b0d6
Add poison variables analysis
michael-schwarz Feb 17, 2023
aaf3516
Proof of Concept Poison
michael-schwarz Feb 17, 2023
2777e08
Add libpng example
michael-schwarz Feb 27, 2023
e244c0b
Example where wrappers are needed
michael-schwarz Feb 27, 2023
a6b8537
Upon invalidate keep jmp_buffers
michael-schwarz Feb 28, 2023
a05872a
Actually start with `JmpBufs.bot()` in `bot_value`
michael-schwarz Mar 1, 2023
e3550fe
Also poison for non-local longjmps
michael-schwarz Mar 1, 2023
a7a0122
Add possibility to trace setjmp
michael-schwarz Mar 1, 2023
53988b8
Remove LHS of assignments again in `poisonVariables`
michael-schwarz Mar 1, 2023
1ba7e5b
Add future test for malloc uniqueness
michael-schwarz Mar 1, 2023
ec1ce3e
Use domain for jump buffers that keeps def. elems on T
michael-schwarz Mar 1, 2023
be75b8e
Add test for strange things they actually do
michael-schwarz Mar 1, 2023
4bb1492
Slimmed down version of the evil men do
michael-schwarz Mar 1, 2023
af4ce3b
Strong updates of structs (#1006)
michael-schwarz Mar 1, 2023
dfd8eae
Provide proper ask for taints
michael-schwarz Mar 2, 2023
3c0bcbb
Fix outdated comment
michael-schwarz Mar 2, 2023
7ae2cd2
Comment on `IterSysVars` missing in `hash_arg`
michael-schwarz Mar 2, 2023
a8eba70
Include `goblint.h` where that was missing
michael-schwarz Mar 2, 2023
d5cbef1
Rm TODO from test that now succeeds
michael-schwarz Mar 2, 2023
3053b7a
Modify test 66/05 so it does something different
michael-schwarz Mar 2, 2023
7823e24
Temporary stopgap
michael-schwarz Mar 2, 2023
98d7401
Use appropriate ask from `ctx_fd'` in combine
michael-schwarz Mar 3, 2023
cc193c8
Use iter on JmpBufDomain directly
michael-schwarz Mar 3, 2023
6b90d22
Add readme to setjmp/longjmp examples
michael-schwarz Mar 3, 2023
1fe9175
Cleanup
michael-schwarz Mar 3, 2023
8df94e7
Use correct one-path value also if setjmp has no LHS
michael-schwarz Mar 3, 2023
db7d39c
Remove variables from poison again when function returns
michael-schwarz Mar 3, 2023
886981d
Use `path_ctx` in `rec_ctx`
michael-schwarz Mar 3, 2023
7a81623
Better comment
michael-schwarz Mar 3, 2023
132004d
Removed unused argument `origins`
michael-schwarz Mar 3, 2023
0b8426d
Update comments
michael-schwarz Mar 3, 2023
1954860
Cleanup
michael-schwarz Mar 3, 2023
f503719
66/39 disable intervals to get rid of overflow warning
michael-schwarz Mar 5, 2023
97e53d4
Take pointers into account for poison
michael-schwarz Mar 5, 2023
896f897
Do not call `filter` on top
michael-schwarz Mar 5, 2023
4dc4672
Add case for lval of call poisonous
michael-schwarz Mar 5, 2023
e53162e
Deal with poisoning issues arising from recursive calls
michael-schwarz Mar 5, 2023
7e4bfdc
Do not flag poison for `AddrOf` and `StartOf`
michael-schwarz Mar 6, 2023
aa58c5e
Add possibility to split according to return value of `setjmp`
michael-schwarz Mar 6, 2023
489656d
Use `exsplit` for sensitivity in lval of setjmp
michael-schwarz Mar 6, 2023
97512ba
Analysis to warn when calls to setjmp happen potentially in the scope…
michael-schwarz Mar 7, 2023
0276700
`66/45` disable deadcode warnings so `NOWARN` tests correct thing
michael-schwarz Mar 7, 2023
26af4d1
Warn when jmpbufs are copied simply by content
michael-schwarz Mar 7, 2023
2776a1d
Derive eq, ord, hash for FlagHelper to allow comparisons between diff…
jerhard Mar 7, 2023
3ff73b2
Add example highlighting the issue with this keyword binding
michael-schwarz Mar 8, 2023
abb9f1a
Warn on `longjmp` to bottom buffer
michael-schwarz Mar 8, 2023
99c73fc
Do not set for explicit bot value
michael-schwarz Mar 8, 2023
3478609
unskip working test
michael-schwarz Mar 10, 2023
7c41ae5
Skip incrementally broken OS X tests
michael-schwarz Mar 13, 2023
7a605fb
Skip incremental 13/01
michael-schwarz Mar 13, 2023
4c80826
Prefix warning about modified locals with Information to make sure th…
michael-schwarz Mar 13, 2023
8c0af07
Remove unnecessary TODO
michael-schwarz Mar 14, 2023
9681d36
Add C argument to GVarF
sim642 Mar 15, 2023
e3dc81b
Add longjmpto and longjmpret to GVarF
sim642 Mar 15, 2023
7c6a154
Add D argument to GVarG
sim642 Mar 15, 2023
d02a85a
Add local domain to GVarG
sim642 Mar 15, 2023
dd47104
Replace LongjmpTo node with longjmpto global
sim642 Mar 15, 2023
3125e06
Replace LongjmpFromFunction node with longjmpret global
sim642 Mar 15, 2023
f4ec418
Remove now unnecessary LongjmpTo and LongjmpFromFunction nodes
sim642 Mar 15, 2023
6d0e55d
Extract ControlSpecC to file module to allow dependency cycle breaking
sim642 Mar 7, 2023
1f7424f
Don't use hash for longjmp
sim642 Mar 15, 2023
5511e85
Make longjmpthrough argument non-optional
sim642 Mar 15, 2023
3a1a173
Do return before longjmpret
sim642 Mar 15, 2023
0ead7ae
Add failing test for local longjmp with value 0
sim642 Mar 15, 2023
4b249c1
Add separate longjmp_return variable
sim642 Mar 16, 2023
76edb0e
Remove now unnecessary longjmpthrough
sim642 Mar 16, 2023
d1c7796
Merge branch 'longjmp' into longjmp-refactor
sim642 Mar 16, 2023
3964ccb
Move longjmp modified locals warning to setjmp
sim642 Mar 16, 2023
de36d50
Fix longjmp modified vars warning locations in test
sim642 Mar 16, 2023
a1f3db3
Move longjmp poisoning to setjmp
sim642 Mar 16, 2023
3f76a99
Remove longjmp target node statement matching
sim642 Mar 16, 2023
47f4287
Clean up longjmp handling in tf_normal_call
sim642 Mar 16, 2023
16f5619
Clean up longjmp handling in tf_special_call
sim642 Mar 16, 2023
b5d0548
Clean up setjmp handling in tf_special_call
sim642 Mar 16, 2023
c0ec4e4
Fixes in tf_normal_call longjmp handling
sim642 Mar 16, 2023
7e70553
Unify normal and longjmp combine
sim642 Mar 16, 2023
e7ca236
Unskip incremental tests
sim642 Mar 17, 2023
7aa0202
Merge branch 'master' into longjmp-refactor
sim642 Mar 17, 2023
fa87bb9
Shorten longjmp helper analyses' code
sim642 Mar 17, 2023
910560c
Upload suite_result as artifact in locked workflow
sim642 Mar 17, 2023
d0934fd
Extract LongjmpLifter from FromSpec
sim642 Mar 20, 2023
ef07840
Revert "Add local domain to GVarG"
sim642 Mar 20, 2023
b7a04e5
Revert "Add D argument to GVarG"
sim642 Mar 20, 2023
72e7e95
Revert "Add longjmpto and longjmpret to GVarF"
sim642 Mar 20, 2023
11189cf
Revert "Add C argument to GVarF"
sim642 Mar 20, 2023
e92700f
Check tracing before longjmp trace
sim642 Mar 20, 2023
d39cd31
Fix LongjmpLifter domain naming
sim642 Mar 20, 2023
9bb73ee
Extract conv_ctx in LongjmpLifter
sim642 Mar 20, 2023
ca26a83
Fix expsplit setjmp warnings
sim642 Mar 20, 2023
6c6e45a
Remove unused savesigs and sigrestore fields
sim642 Mar 20, 2023
1f6f195
Fix LongjmpLifter lazy indentation
sim642 Mar 20, 2023
2120845
Move longjmp-ed variable warning to poisonVariables analysis
sim642 Mar 20, 2023
ccbd06b
Remove now-unused Poison event
sim642 Mar 20, 2023
2be1c73
Use Longjmped event for base assign
sim642 Mar 20, 2023
aaaba6e
Use IdentitySpec for vla analysis
sim642 Mar 20, 2023
e9b884a
Move setjmp VLA warning to vla analysis
sim642 Mar 20, 2023
cfdcd1a
Remove now-unused MayBeInVLAScope query
sim642 Mar 20, 2023
4b90f4a
Move Goblintutil.longjmp_return to base analysis
sim642 Mar 20, 2023
dfe6f5c
Remove LONGJMP_RETURN from base state
sim642 Mar 20, 2023
ba3437a
Use Access events for modifiedSinceLongjmp
sim642 Mar 20, 2023
d7708d3
Use Access events for poisonVariables checks
sim642 Mar 20, 2023
6eafd22
Remove now-unnecessary check_exp in poisonVariables analysis
sim642 Mar 20, 2023
f2eb6e0
Use Access events for poisonVariables writes
sim642 Mar 20, 2023
5c121a4
Remove unused relevants_from_lval_opt in modifiedSinceLongjmp analysis
sim642 Mar 20, 2023
e10a091
Refactor poisonVariables return
sim642 Mar 20, 2023
3713ef9
Clean up EvalJumpBuf
sim642 Mar 20, 2023
0e43d1e
Clean up base Setjmp & Longjmp
sim642 Mar 20, 2023
61e7e3c
Add failing test for longjmp with indeterminate non-top value
sim642 Mar 20, 2023
4937abf
Merge branch 'longjmp' into longjmp-refactor
sim642 Mar 20, 2023
0c5d390
Fix base longjmp indefinite value change
sim642 Mar 20, 2023
a1e13ba
Categorize longjmp warnings
sim642 Mar 20, 2023
0bc2f1e
Add Cilfacade.isVLAType for vla analysis
sim642 Mar 20, 2023
e81f3b3
Add is_top checks back to poisonVariables analysis
sim642 Mar 20, 2023
0f8f7b0
Enable OCaml backtraces in locked workflow
sim642 Mar 20, 2023
04c56e5
Use pretty instead of show in longjmp messages and tracing
sim642 Mar 20, 2023
37c3ce1
Refactor taintPartialContexts return
sim642 Mar 20, 2023
0e9af2c
Remove hardcoded analysis names in access analysis
sim642 Mar 21, 2023
e4d855e
Check global_initialization for threadreturn main thread workaround
sim642 Mar 21, 2023
be360d1
Merge branch 'master' into longjmp
sim642 Mar 21, 2023
7940e98
Merge branch 'longjmp' into longjmp-refactor
sim642 Mar 21, 2023
b25b900
Add must/may back to longjmp value messages
sim642 Mar 21, 2023
655a7ae
Fix activeLongjmp analysis threadenter TODO
sim642 Mar 21, 2023
63fdd47
Add problematic example
michael-schwarz Mar 21, 2023
2937c0a
Fix longjmp combine to not assign to lval
sim642 Mar 22, 2023
167a13b
Remove passing TODO from longjmp/multifun test
sim642 Mar 22, 2023
1f38378
Merge pull request #1015 from goblint/longjmp-refactor
sim642 Mar 22, 2023
578264c
Move sigsetjmp & siglongjmp to POSIX group
sim642 Mar 22, 2023
99ed984
Fix base longjmp comment indentation
sim642 Mar 22, 2023
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
60 changes: 60 additions & 0 deletions src/analyses/activeLongjmp.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
(** Analysis tracking which longjmp is currently active *)

open Prelude.Ana
open Analyses

(* module Spec : Analyses.MCPSpec with module D = Lattice.Unit and module C = Lattice.Unit and type marshal = unit = *)
(* No signature so others can override module G *)
module Spec =
struct
include Analyses.DefaultSpec

let name () = "activeLongjmp"
module D = JmpBufDomain.JmpBufSet
module C = Lattice.Unit

(* transfer functions *)
let assign ctx (lval:lval) (rval:exp) : D.t =
ctx.local

let branch ctx (exp:exp) (tv:bool) : D.t =
ctx.local

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

let return ctx (exp:exp option) (f:fundec) : D.t =
ctx.local

let enter ctx (lval: lval option) (f:fundec) (args:exp list) : (D.t * D.t) list =
[ctx.local, ctx.local]

let combine ctx (lval:lval option) fexp (f:fundec) (args:exp list) fc (au:D.t) : D.t =
au

let special ctx (lval: lval option) (f:varinfo) (arglist:exp list) : D.t =
let desc = LibraryFunctions.find f in
match desc.special arglist, f.vname with
| Longjmp {env; value; sigrestore}, _ ->
(* Put current buffer into set *)
let bufs = ctx.ask (EvalJumpBuf env) in
bufs
| _ -> ctx.local

let startstate v = D.bot ()
let threadenter ctx lval f args = [D.top ()]
let threadspawn ctx lval f args fctx = ctx.local
let exitstate v = D.top ()

let context _ _ = ()

let query ctx (type a) (q: a Queries.t): a Queries.result =
match q with
| ActiveJumpBuf ->
(* Does not compile without annotation: "This instance (...) is ambiguous: it would escape the scope of its equation" *)
(ctx.local:JmpBufDomain.JmpBufSet.t)
| _ -> Queries.Result.top q
end

let _ =
MCP.register_analysis (module Spec : MCPSpec)
30 changes: 29 additions & 1 deletion src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ struct
| `Int _ -> empty
| `Float _ -> empty
| `Thread _ -> empty (* thread IDs are abstract and nothing known can be reached from them *)
| `JmpBuf _ -> empty (* Jump buffers are abstract and nothing known can be reached from them *)
| `Mutex -> empty (* mutexes are abstract and nothing known can be reached from them *)

(* Get the list of addresses accessable immediately from a given address, thus
Expand Down Expand Up @@ -668,6 +669,7 @@ struct
| `Int _ -> (empty, TS.bot (), false)
| `Float _ -> (empty, TS.bot (), false)
| `Thread _ -> (empty, TS.bot (), false) (* TODO: is this right? *)
| `JmpBuf _ -> (empty, TS.bot (), false) (* TODO: is this right? *)
| `Mutex -> (empty, TS.bot (), false) (* TODO: is this right? *)
in
reachable_from_value (get (Analyses.ask_of_ctx ctx) ctx.global ctx.local adr None)
Expand Down Expand Up @@ -1246,6 +1248,14 @@ struct
let fs = eval_funvar ctx e in
List.fold_left (fun xs v -> Q.LS.add (v,`NoOffset) xs) (Q.LS.empty ()) fs
end
| Q.EvalJumpBuf e ->
(match eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local e with
| `Address jmp_buf ->
begin match get (Analyses.ask_of_ctx ctx) ctx.global ctx.local jmp_buf None with
| `JmpBuf x -> x
| y -> failwith (Printf.sprintf "problem?! is %s" (VD.show y))
end
| _ -> failwith "problem?!");
| Q.EvalInt e ->
query_evalint (Analyses.ask_of_ctx ctx) ctx.global ctx.local e
| Q.EvalLength e -> begin
Expand Down Expand Up @@ -1684,7 +1694,7 @@ struct
| _ -> ()
);
match lval with (* this section ensure global variables contain bottom values of the proper type before setting them *)
| (Var v, offs) when AD.is_definite lval_val && v.vglob ->
| (Var v, offs) when v.vglob ->
(* Optimization: In case of simple integral types, we not need to evaluate the old value.
v is not an allocated block, as v directly appears as a variable in the program;
so no explicit check is required here (unlike in set) *)
Expand Down Expand Up @@ -2217,6 +2227,24 @@ struct
st
end
| Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine
| Setjmp { env; savesigs}, _ ->
(let st' = (match (eval_rv (Analyses.ask_of_ctx ctx) gs st env) with
| `Address jmp_buf ->
let controlctx = ControlSpecC.hash (ctx.control_context ()) in
let value = `JmpBuf (ValueDomain.JmpBufs.singleton (ctx.node, IntDomain.Flattened.of_int (Int64.of_int controlctx))) in
set ~ctx (Analyses.ask_of_ctx ctx) gs st jmp_buf (Cilfacade.typeOf env) value
| _ -> failwith "problem?!")
in
match lv with
| Some lv ->
set ~ctx (Analyses.ask_of_ctx ctx) gs st' (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st lv) (Cilfacade.typeOfLval lv) (`Int (ID.of_int IInt BI.zero))
| None -> st')
| Longjmp {env; value; sigrestore}, _ ->
let rv = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local value in
let t = Cil.typeOf value in
let res = set ~ctx ~t_override:t (Analyses.ask_of_ctx ctx) ctx.global ctx.local (return_var ()) t rv in
res
(* Not rasing Deadode here, deadcode is raised at a higher level! *)
| _, _ -> begin
let st =
special_unknown_invalidate ctx (Analyses.ask_of_ctx ctx) gs st f args
Expand Down
2 changes: 2 additions & 0 deletions src/analyses/libraryDesc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ type special =
| Strcpy of { dest: Cil.exp; src: Cil.exp } (* TODO: add count for strncpy when actually used *)
| Abort
| Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *)
| Setjmp of {env: Cil.exp; savesigs: Cil.exp; }
| Longjmp of {env: Cil.exp; value: Cil.exp; sigrestore: bool}
| Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *)


Expand Down
6 changes: 6 additions & 0 deletions src/analyses/libraryFunctions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ let c_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[
("setbuf", unknown [drop "stream" [w]; drop "buf" [w]]);
("swprintf", unknown (drop "wcs" [w] :: drop "maxlen" [] :: drop "fmt" [r] :: VarArgs (drop' [])));
("assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); (* only used if assert is used without include, e.g. in transformed files *)
("_setjmp", special [__ "env" [w]] @@ fun env -> Setjmp { env; savesigs = Cil.zero }); (* only has one underscore *)
("setjmp", special [__ "env" [w]] @@ fun env -> Setjmp { env; savesigs = Cil.zero });
("__sigsetjmp", special [__ "env" [w]; __ "savesigs" []] @@ fun env savesigs -> Setjmp { env; savesigs }); (* has two underscores *)
("sigsetjmp", special [__ "env" [w]; __ "savesigs" []] @@ fun env savesigs -> Setjmp { env; savesigs });
("longjmp", special [__ "env" [r]; __ "value" []] @@ fun env value -> Longjmp { env; value; sigrestore = false });
("siglongjmp", special [__ "env" [r]; __ "value" []] @@ fun env value -> Longjmp { env; value; sigrestore = true });
]

(** C POSIX library functions.
Expand Down
7 changes: 7 additions & 0 deletions src/cdomains/jmpBufDomain.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module BufferEntry = Printable.ProdSimple(Node)(IntDomain.Flattened)

module JmpBufSet =
struct
include SetDomain.ToppedSet (BufferEntry) (struct let topname = "All jumpbufs" end)
let name () = "Jumpbuffers"
end
43 changes: 39 additions & 4 deletions src/cdomains/valueDomain.ml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct
end

module Threads = ConcDomain.ThreadSet
module JmpBufs = JmpBufDomain.JmpBufSet

module rec Compound: S with type t = [
| `Top
Expand All @@ -77,6 +78,7 @@ module rec Compound: S with type t = [
| `Array of CArrays.t
| `Blob of Blobs.t
| `Thread of Threads.t
| `JmpBuf of JmpBufs.t
| `Mutex
| `Bot
] and type offs = (fieldinfo,IndexDomain.t) Lval.offs =
Expand All @@ -91,6 +93,7 @@ struct
| `Array of CArrays.t
| `Blob of Blobs.t
| `Thread of Threads.t
| `JmpBuf of JmpBufs.t
| `Mutex
| `Bot
] [@@deriving eq, ord, hash]
Expand All @@ -106,13 +109,18 @@ struct
| TNamed ({tname = "pthread_t"; _}, _) -> true
| _ -> false

let is_jmp_buf_type = function
| TNamed ({tname = "jmp_buf"; _}, _) -> true
| _ -> false

let array_length_idx default length =
let l = BatOption.bind length (fun e -> Cil.getInteger (Cil.constFold true e)) in
BatOption.map_default (fun x-> IndexDomain.of_int (Cilfacade.ptrdiff_ikind ()) @@ Cilint.big_int_of_cilint x) default l

let rec bot_value ?(varAttr=[]) (t: typ): t =
match t with
| _ when is_mutex_type t -> `Mutex
| t when is_jmp_buf_type t -> `JmpBuf (JmpBufs.top ())
| TInt _ -> `Bot (*`Int (ID.bot ()) -- should be lower than any int or address*)
| TFloat _ -> `Bot
| TPtr _ -> `Address (AD.bot ())
Expand All @@ -123,6 +131,7 @@ struct
let len = array_length_idx (IndexDomain.bot ()) length in
`Array (CArrays.make ~varAttr ~typAttr len (bot_value ai))
| t when is_thread_type t -> `Thread (ConcDomain.ThreadSet.empty ())
| t when is_jmp_buf_type t -> `JmpBuf (JmpBufs.empty ())
| TNamed ({ttype=t; _}, _) -> bot_value ~varAttr (unrollType t)
| _ -> `Bot

Expand All @@ -136,13 +145,15 @@ struct
| `Array x -> CArrays.is_bot x
| `Blob x -> Blobs.is_bot x
| `Thread x -> Threads.is_bot x
| `JmpBuf x -> JmpBufs.is_bot x
| `Mutex -> true
| `Bot -> true
| `Top -> false

let rec init_value ?(varAttr=[]) (t: typ): t = (* top_value is not used here because structs, blob etc will not contain the right members *)
match t with
| t when is_mutex_type t -> `Mutex
| t when is_jmp_buf_type t -> `JmpBuf (JmpBufs.top ())
| TInt (ik,_) -> `Int (ID.top_of ik)
| TFloat ((FFloat | FDouble | FLongDouble as fkind), _) -> `Float (FD.top_of fkind)
| TPtr _ -> `Address AD.top_ptr
Expand All @@ -160,6 +171,7 @@ struct
let rec top_value ?(varAttr=[]) (t: typ): t =
match t with
| _ when is_mutex_type t -> `Mutex
| t when is_jmp_buf_type t -> `JmpBuf (JmpBufs.top ())
| TInt (ik,_) -> `Int (ID.(cast_to ik (top_of ik)))
| TFloat ((FFloat | FDouble | FLongDouble as fkind), _) -> `Float (FD.top_of fkind)
| TPtr _ -> `Address AD.top_ptr
Expand All @@ -183,13 +195,15 @@ struct
| `Array x -> CArrays.is_top x
| `Blob x -> Blobs.is_top x
| `Thread x -> Threads.is_top x
| `JmpBuf x -> JmpBufs.is_top x
| `Mutex -> true
| `Top -> true
| `Bot -> false

let rec zero_init_value ?(varAttr=[]) (t:typ): t =
match t with
| _ when is_mutex_type t -> `Mutex
| t when is_jmp_buf_type t -> `JmpBuf (JmpBufs.top ())
| TInt (ikind, _) -> `Int (ID.of_int ikind BI.zero)
| TFloat ((FFloat | FDouble | FLongDouble as fkind), _) -> `Float (FD.of_const fkind 0.0)
| TPtr _ -> `Address AD.null_ptr
Expand All @@ -213,7 +227,7 @@ struct
| _ -> `Top

let tag_name : t -> string = function
| `Top -> "Top" | `Int _ -> "Int" | `Float _ -> "Float" | `Address _ -> "Address" | `Struct _ -> "Struct" | `Union _ -> "Union" | `Array _ -> "Array" | `Blob _ -> "Blob" | `Thread _ -> "Thread" | `Mutex -> "Mutex" | `Bot -> "Bot"
| `Top -> "Top" | `Int _ -> "Int" | `Float _ -> "Float" | `Address _ -> "Address" | `Struct _ -> "Struct" | `Union _ -> "Union" | `Array _ -> "Array" | `Blob _ -> "Blob" | `Thread _ -> "Thread" | `Mutex -> "Mutex" | `JmpBuf _ -> "JmpBuf" | `Bot -> "Bot"

include Printable.Std
let name () = "compound"
Expand All @@ -238,6 +252,7 @@ struct
| `Array n -> CArrays.pretty () n
| `Blob n -> Blobs.pretty () n
| `Thread n -> Threads.pretty () n
| `JmpBuf n -> JmpBufs.pretty () n
| `Mutex -> text "mutex"
| `Bot -> text bot_name
| `Top -> text top_name
Expand All @@ -252,6 +267,7 @@ struct
| `Array n -> CArrays.show n
| `Blob n -> Blobs.show n
| `Thread n -> Threads.show n
| `JmpBuf n -> JmpBufs.show n
| `Mutex -> "mutex"
| `Bot -> bot_name
| `Top -> top_name
Expand All @@ -266,6 +282,7 @@ struct
| (`Array x, `Array y) -> CArrays.pretty_diff () (x,y)
| (`Blob x, `Blob y) -> Blobs.pretty_diff () (x,y)
| (`Thread x, `Thread y) -> Threads.pretty_diff () (x, y)
| (`JmpBuf x, `JmpBuf y) -> JmpBufs.pretty_diff () (x, y)
| _ -> dprintf "%s: %a not same type as %a" (name ()) pretty x pretty y

(************************************************************
Expand Down Expand Up @@ -371,7 +388,8 @@ struct
match v with
| `Bot
| `Thread _
| `Mutex ->
| `Mutex
| `JmpBuf _ ->
v
| _ ->
let log_top (_,l,_,_) = Messages.tracel "cast" "log_top at %d: %a to %a is top!\n" l pretty v d_type t in
Expand Down Expand Up @@ -457,7 +475,7 @@ struct

let warn_type op x y =
if GobConfig.get_bool "dbg.verbose" then
ignore @@ printf "warn_type %s: incomparable abstr. values %s and %s at %a: %a and %a\n" op (tag_name x) (tag_name y) CilType.Location.pretty !Tracing.current_loc pretty x pretty y
ignore @@ printf "warn_type %s: incomparable abstr. values %s and %s at %a: %a and %a\n" op (tag_name (x:t)) (tag_name (y:t)) CilType.Location.pretty !Tracing.current_loc pretty x pretty y

let rec leq x y =
match (x,y) with
Expand All @@ -480,6 +498,7 @@ struct
| (`Thread x, `Thread y) -> Threads.leq x y
| (`Int x, `Thread y) -> true
| (`Address x, `Thread y) -> true
| (`JmpBuf x, `JmpBuf y) -> JmpBufs.leq x y
| (`Mutex, `Mutex) -> true
| _ -> warn_type "leq" x y; false

Expand Down Expand Up @@ -512,6 +531,7 @@ struct
| (`Address x, `Thread y)
| (`Thread y, `Address x) ->
`Thread y (* TODO: ignores address! *)
| (`JmpBuf x, `JmpBuf y) -> `JmpBuf (JmpBufs.join x y)
| (`Mutex, `Mutex) -> `Mutex
| _ ->
warn_type "join" x y;
Expand Down Expand Up @@ -549,6 +569,7 @@ struct
| (`Thread y, `Address x) ->
`Thread y (* TODO: ignores address! *)
| (`Mutex, `Mutex) -> `Mutex
| (`JmpBuf x, `JmpBuf y) -> `JmpBuf (JmpBufs.join x y)
| _ ->
warn_type "join" x y;
`Top
Expand Down Expand Up @@ -640,7 +661,7 @@ struct
warn_type "meet" x y;
`Bot

let rec widen x y =
let rec widen (x:t) (y:t):t =
match (x,y) with
| (`Top, _) -> `Top
| (_, `Top) -> `Top
Expand All @@ -662,6 +683,7 @@ struct
| (`Array x, `Array y) -> `Array (CArrays.widen x y)
| (`Blob x, `Blob y) -> `Blob (Blobs.widen x y)
| (`Thread x, `Thread y) -> `Thread (Threads.widen x y)
| (`JmpBuf x, `JmpBuf y) -> `JmpBuf (JmpBufs.widen x y)
| (`Int x, `Thread y)
| (`Thread y, `Int x) ->
`Thread y (* TODO: ignores int! *)
Expand All @@ -685,6 +707,7 @@ struct
| (`Array x, `Array y) -> `Array (CArrays.narrow x y)
| (`Blob x, `Blob y) -> `Blob (Blobs.narrow x y)
| (`Thread x, `Thread y) -> `Thread (Threads.narrow x y)
| (`JmpBuf x, `JmpBuf y) -> `JmpBuf (JmpBufs.narrow x y)
| (`Int x, `Thread y)
| (`Thread y, `Int x) ->
`Int x (* TODO: ignores thread! *)
Expand Down Expand Up @@ -958,6 +981,16 @@ struct
else
`Top
end
| `JmpBuf _, _ ->
(* hack for pthread_t variables *)
begin match value with
| `JmpBuf t -> value (* if actually assigning thread, use value *)
| _ ->
if !GU.global_initialization then
`JmpBuf (JmpBufs.empty ()) (* if assigning global init (int on linux, ptr to struct on mac), use empty set instead *)
else
`Top
end
| _ ->
let result =
match offs with
Expand Down Expand Up @@ -1128,6 +1161,7 @@ struct
| `Array n -> CArrays.printXml f n
| `Blob n -> Blobs.printXml f n
| `Thread n -> Threads.printXml f n
| `JmpBuf n -> JmpBufs.printXml f n
| `Mutex -> BatPrintf.fprintf f "<value>\n<data>\nmutex\n</data>\n</value>\n"
| `Bot -> BatPrintf.fprintf f "<value>\n<data>\nbottom\n</data>\n</value>\n"
| `Top -> BatPrintf.fprintf f "<value>\n<data>\ntop\n</data>\n</value>\n"
Expand All @@ -1141,6 +1175,7 @@ struct
| `Array n -> CArrays.to_yojson n
| `Blob n -> Blobs.to_yojson n
| `Thread n -> Threads.to_yojson n
| `JmpBuf n -> JmpBufs.to_yojson n
| `Mutex -> `String "mutex"
| `Bot -> `String "⊥"
| `Top -> `String "⊤"
Expand Down
Loading