You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
let info =match (man.ask (Q.AllocVar{on_stack})) with
146
+
letalloced_varlocationman=
147
+
let info =match (man.ask (Q.AllocVarlocation)) with
148
148
|`Liftedvinfo -> vinfo
149
149
|_ -> failwith("Ran without a malloc analysis.") in
150
150
info
@@ -2501,9 +2501,31 @@ struct
2501
2501
|_ ->
2502
2502
set ~man st lv_a lv_typ (VD.top_value (unrollType lv_typ))
2503
2503
end
2504
-
in
2504
+
in
2505
+
(* Returns a tuple, the first is the address of the blob if one was allocated, the second is the returned address (may contain null pointer or be only null-pointer) *)
2506
+
letalloclocsize=
2507
+
(* Whether malloc(0) is assumed to return the null pointer, a valid pointer, or both cases need to be considered. *)
2508
+
let malloc_zero_null, malloc_zero_pointer =
2509
+
match get_string "sem.malloc.zero"with
2510
+
|"null" -> true, false
2511
+
|"pointer" -> false, true
2512
+
|"either" -> true, true
2513
+
|_ -> failwith "Invalid value for sem.malloc.zero."
2514
+
in
2515
+
let bytes = eval_int ~man st size in
2516
+
let cmp_bytes_with_zero =ID.equal_to Z.zero bytes in
2517
+
let bytes_may_be_zero = cmp_bytes_with_zero <>`Neqin
2518
+
let bytes_may_be_nonzero = cmp_bytes_with_zero <>`Eqin
2519
+
let include_null = (bytes_may_be_nonzero && get_bool "sem.malloc.fail") || (bytes_may_be_zero && malloc_zero_null) in
2520
+
let include_pointer = bytes_may_be_nonzero || malloc_zero_pointer in
2521
+
ifnot include_pointer then
2522
+
(None, AD.null_ptr)
2523
+
else
2524
+
let var =AD.of_var (alloced_var loc man) in
2525
+
(Some var, if include_null thenAD.join var AD.null_ptr else var)
2526
+
in
2505
2527
(* Evaluate each functions arguments. `eval_rv` is only called for its side effects, we ignore the result. *)
2506
-
List.iter (funarg -> eval_rv ~man st arg |> ignore) args;
2528
+
List.iter (funarg -> eval_rv ~man st arg |> ignore) args;
2507
2529
let st =match desc.special args, f.vname with
2508
2530
|Memset{ dest; ch; count; }, _ ->
2509
2531
(* TODO: check count *)
@@ -2720,53 +2742,39 @@ struct
2720
2742
|None, _ ->
2721
2743
st
2722
2744
end
2723
-
|Allocasize, _ -> begin
2745
+
| ((Alloca size) as op), _
2746
+
| ((Malloc size) asop), _ ->
2747
+
letopenQueries.AllocationLocationin
2748
+
begin
2749
+
(* The behavior for alloc(0) is implementation defined. Here, we rely on the options specified for the malloc also applying to alloca. *)
2724
2750
match lv with
2725
2751
|Somelv ->
2726
-
let heap_var =AD.of_var (heap_var true man) in
2752
+
let loc =match op with|Alloca_ -> Stack|Malloc_ -> Heap|_ ->assertfalsein
(eval_lv ~man st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_var heap_var)))
2760
-
]
2761
-
)
2762
-
else (
2767
+
ifID.to_int countval =SomeZ.one then
2768
+
let blob_set =Option.map_default (funheap_var -> [heap_var, TVoid [], VD.Blob (VD.bot (), sizeval, ZeroInit.calloc)]) [] heap_var in
2769
+
set_many ~man st ((eval_lv ~man st lv, (Cilfacade.typeOfLval lv), Address addr):: blob_set)
2770
+
else
2763
2771
let blobsize =ID.mul (ID.cast_to ik @@ sizeval) (ID.cast_to ik @@ countval) in
2772
+
let offset =`Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) Z.zero, `NoOffset) in
2773
+
(* the heap_var is the base address of the allocated memory, but we need to keep track of the offset for the blob *)
2774
+
let addr_offset =AD.map (funa -> Addr.add_offset a offset) addr in
2764
2775
(* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *)
letquery (man: (D.t, G.t, C.t, V.t) man) (typea) (q: a Q.t): a Q.result =
156
156
let wrapper_node, counter = man.local in
157
157
match q with
158
-
|Q.AllocVar{on_stack = on_stack} ->
158
+
|Q.AllocVarlocation ->
159
159
let node =match wrapper_node with
160
160
|`Liftedwrapper_node -> wrapper_node
161
161
|_ -> node_for_man man
162
162
in
163
163
let count =UniqueCallCounter.find (`Lifted node) counter in
164
164
let var =NodeVarinfoMap.to_varinfo (man.ask Q.CurrentThreadId, node, count) in
165
165
var.vdecl <-UpdateCil.getLoc node; (* TODO: does this do anything bad for incremental? *)
166
-
ifon_stackthen var.vattr <- addAttribute (Attr ("stack_alloca", [])) var.vattr; (* If the call was for stack allocation, add an attr to mark the heap var *)
166
+
iflocation =Stackthen var.vattr <- addAttribute (Attr ("stack_alloca", [])) var.vattr; (* If the call was for stack allocation, add an attr to mark the heap var *)
167
167
`Lifted var
168
168
|Q.IsHeapVarv ->
169
169
NodeVarinfoMap.mem_varinfo v &¬@@ hasAttribute "stack_alloca" v.vattr
Copy file name to clipboardExpand all lines: src/config/options.schema.json
+8-1Lines changed: 8 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1644,9 +1644,16 @@
1644
1644
"fail": {
1645
1645
"title": "sem.malloc.fail",
1646
1646
"description":
1647
-
"Consider the case where malloc or calloc fails.",
1647
+
"Consider the case where malloc or calloc fails when called with an argument other than zero. For the case of zero, see `sem.malloc.zero`.",
1648
1648
"type": "boolean",
1649
1649
"default": false
1650
+
},
1651
+
"zero": {
1652
+
"title": "sem.malloc.zero",
1653
+
"description": "What happens when allocating zero bytes? 'null': Return null pointer, 'pointer': Return a pointer to valid memory of size 0, 'either': Consider both cases.",
| PathQuery: int*'at -> 'at(** Query only one path under witness lifter. *)
103
107
| DYojson: FlatYojson.tt(** Get local state Yojson of one path under [PathQuery]. *)
104
-
| AllocVar: {on_stack: bool} -> VI.tt
108
+
| AllocVar: AllocationLocation.t -> VI.tt
105
109
(* Create a variable representing a dynamic allocation-site *)
106
110
(* If on_stack is [true], then the dynamic allocation is on the stack (i.e., alloca() or a similar function was called). Otherwise, allocation is on the heap *)
0 commit comments