Skip to content
Snippets Groups Projects
Commit e92da27f authored by David Bühler's avatar David Bühler Committed by Andre Maroneze
Browse files

[Eva] Rewrites memcpy and memmove builtins.

Avoids using exceptions, splits the implementation into several functions,
adds some comments.
parent 18b5f13c
No related branches found
No related tags found
No related merge requests found
...@@ -74,25 +74,8 @@ let frama_c_offset _state = function ...@@ -74,25 +74,8 @@ let frama_c_offset _state = function
let () = register_builtin "Frama_C_offset" frama_c_offset let () = register_builtin "Frama_C_offset" frama_c_offset
exception Memcpy_result of (Cvalue.Model.t * Assigns.t * Zone.t)
exception Indeterminate of V_Or_Uninitialized.t let plevel = Parameters.ArrayPrecisionLevel.get
(* Called by the [memcpy] builtin. Warns when the offsetmap contains
an indeterminate value, when the imprecision category is enabled *)
let memcpy_check_indeterminate_offsetmap offsm =
if Self.is_debug_key_enabled dkey then
try
let aux_offset _ (v, _, _) =
match v with
| V_Or_Uninitialized.C_init_noesc _ -> ()
| _ -> raise (Indeterminate v)
in
V_Offsetmap.iter aux_offset offsm
with Indeterminate v ->
Self.debug ~current:true ~dkey ~once:true
"@[In memcpy@ builtin:@ precise@ copy of@ indeterminate@ values %a@]%t"
V_Or_Uninitialized.pretty v Eva_utils.pp_callstack
(* Create a dependency [\from arg_n] where n is the nth argument of the (* Create a dependency [\from arg_n] where n is the nth argument of the
currently called function. *) currently called function. *)
...@@ -103,206 +86,209 @@ let deps_nth_arg n = ...@@ -103,206 +86,209 @@ let deps_nth_arg n =
Deps.add_data Deps.bottom (Locations.zone_of_varinfo vi) Deps.add_data Deps.bottom (Locations.zone_of_varinfo vi)
with Failure _ -> Kernel.fatal "%d arguments expected" n with Failure _ -> Kernel.fatal "%d arguments expected" n
(* -------------------------------------------------------------------------- *)
(* Memcpy & Memmove *)
(* -------------------------------------------------------------------------- *)
(* Warns when the value is indeterminate. *)
let warn_indeterminate_value ?(precise = false) = function
| V_Or_Uninitialized.C_init_noesc _ -> ()
| _ ->
Self.result ~dkey ~current:true ~once:true
"@[In memcpy builtin:@ %sprecise copy@ of indeterminate values.@]%t"
(if precise then "" else "im") Eva_utils.pp_callstack
(* Warns when the offsetmap contains an indeterminate value. *)
let check_indeterminate_offsetmap offsm =
if Self.is_debug_key_enabled dkey then
let warn _ (v, _, _) = warn_indeterminate_value ~precise:true v in
V_Offsetmap.iter warn offsm
(* Adds \from dependency from [src_loc] to [dst_loc]. *)
let add_deps_loc ~exact ~src_loc ~dst_loc deps_table =
let src_zone = Locations.(enumerate_valid_bits Read src_loc) in
let dst_zone = Locations.(enumerate_valid_bits Write dst_loc) in
let deps = Deps.(add_data bottom src_zone) in
Assigns.Memory.add_binding ~exact deps_table dst_zone deps
(* Adds a sure \from dependency of size [size] from [src] to [dst].
Also returns the written zone if it is a singleton. *)
let add_sure_deps ~size ~src ~dst (deps_table, sure_output) =
let size = Int_Base.inject size in
let src_loc = Locations.make_loc src size in
let dst_loc = Locations.make_loc dst size in
let exact = Location_Bits.cardinal_zero_or_one dst in
let deps_table = add_deps_loc ~exact ~src_loc ~dst_loc deps_table in
let dst_zone = Locations.(enumerate_valid_bits Write dst_loc) in
let sure_zone = if exact then dst_zone else Zone.bottom in
deps_table, Zone.join sure_zone sure_output
(* Copy the offsetmap of size [size] from [src] to [dst] in [state]. *)
let copy_offsetmap ~exact ~size ~src ~dst ~dst_lval state =
match Cvalue.Model.copy_offsetmap src size state with
| `Bottom -> Cvalue.Model.bottom
| `Value offsetmap ->
check_indeterminate_offsetmap offsetmap;
let prefix = "Builtin memcpy" in
Cvalue_transfer.warn_imprecise_offsm_write ~prefix dst_lval offsetmap;
Cvalue.Model.paste_offsetmap ~from:offsetmap ~dst_loc:dst ~size ~exact state
(* Returns the min and max size of a copy from an Ival.t. *)
let min_max_size size =
let min, max = Ival.min_and_max size in
let min = Option.fold min ~none:Int.zero ~some:Int.(max zero) in
let max_max = Bit_utils.max_bit_size () in
let max = Option.fold max ~none:max_max ~some:Int.(max zero) in
min, max
(* Computes the remaining [src], [dst] and [size] to be copied after [factor]
bits have already been copied. *)
let shift ~factor:i src dst size =
let new_size = Int.sub size i in
let ival = Ival.inject_singleton i in
let new_src = Location_Bits.shift ival src in
let new_dst = Location_Bits.shift ival dst in
new_src, new_dst, new_size
(* Performs the remaining copy from [src] to [dst] for all other possible [size],
after the copy for the minimum size has already been done.
Iterates on all possible values of [size] (after the first), and does the
copy for [previous_size..size]. *)
let copy_remaining_size_by_size ~src ~dst ~dst_lval ~size state =
let exception Result of Cvalue.Model.t in
let do_size size (state, previous_size) =
(* First iteration: this copy has already been performed, skip. *)
if Int.(equal previous_size minus_one)
then state, size
else
(* Copy data between [previous_size] and [size]. *)
let src, dst, size = shift ~factor:previous_size src dst size in
(* [exact] is false as all these copies may not happen according to the
concrete value of [size]. *)
let exact = false in
let new_state = copy_offsetmap ~exact ~size ~src ~dst ~dst_lval state in
(* If this copy failed, the current size is completely invalid, and so
will be the following ones. Stop now with the previous state. *)
if not (Cvalue.Model.is_reachable new_state) then raise (Result state);
new_state, size
in
try fst (Ival.fold_int do_size size (state, Int.minus_one))
with Result state -> state
(* Copy the value at location [src_loc] to location [dst_loc] in [state]. *)
let imprecise_copy ~src_loc ~dst_loc ~dst_lval state =
Self.debug ~dkey ~once:true
~current:true "In memcpy builtin: too many sizes to enumerate, \
possible loss of precision";
(* conflate_bottom:false as we want to copy padding bits *)
let v = Model.find_indeterminate ~conflate_bottom:false state src_loc in
warn_indeterminate_value v;
let value = Cvalue.V_Or_Uninitialized.get_v v in
let prefix = "Builtin memcpy" in
Cvalue_transfer.warn_imprecise_write ~prefix dst_lval dst_loc value;
let new_state =
Cvalue.Model.add_indeterminate_binding ~exact:false state dst_loc v
in
(* Beware that all sizes may be invalid, in which case [add_binding] will
return [bottom]. In this case, return the previously computed state *)
if Model.is_reachable new_state then new_state else state
(* Creates the location {loc + [0..size]} of size char. *)
let char_location loc max_size =
let size_char = Bit_utils.sizeofchar () in
let max = Int.sub max_size size_char in
(* Use ranges modulo char_bits to read and write byte-by-byte, which can
preserve some precision.*)
let shift =
Ival.inject_interval ~min:(Some Int.zero) ~max:(Some max)
~rem:Int.zero ~modu:size_char
in
let loc = Location_Bits.shift shift loc in
make_loc loc (Int_Base.inject size_char)
let compute_memcpy ~dst_lval ~dst ~src ~size state =
let size_min, size_max = min_max_size size in
(* Empty \from dependencies and sure output *)
let empty_deps = Assigns.Memory.empty, Zone.bottom in
(* First step: copy the bits we are sure to copy, i.e. for the minimum size
[size_min] if it is not zero. *)
let state, (deps_table, written_zone) =
if Int.gt size_min Int.zero
then
let state =
copy_offsetmap ~exact:true ~size:size_min ~src ~dst ~dst_lval state
in
(* If the copy succeeded, update \from dependencies and sure output. *)
if Cvalue.Model.is_reachable state
then state, add_sure_deps ~size:size_min ~src ~dst empty_deps
else state, empty_deps
else state, empty_deps
in
(* Stop here if the first copy failed or if there is nothing more to copy. *)
if not (Cvalue.Model.is_reachable state) || Int.equal size_min size_max
then state, deps_table, written_zone
else
(* Second step: size is imprecise, we will now copy some bits that we are
not sure to copy, for all possible sizes greater than [size_min]. *)
(* [size_min] bits have already been copied. *)
let src_shift, dst_shift, size_diff = shift ~factor:size_min src dst size_max in
(* Remaining locations to be read/written, as locations of char size. *)
let src_loc = char_location src_shift size_diff
and dst_loc = char_location dst_shift size_diff in
let deps_table = add_deps_loc ~exact:false ~src_loc ~dst_loc deps_table in
(* If there is sufficiently few possible sizes, iter on each possible size
via [copy_remaining_size_by_size]. Otherwise, use [imprecise_copy] in one
step to read the entire range src+(size_min..size_max-1) as one byte, and
write the result as one byte in dst+(size_min..size_max-1). *)
let state =
if Ival.cardinal_is_less_than size (plevel () / 10)
then copy_remaining_size_by_size ~src ~dst ~dst_lval ~size state
else imprecise_copy ~src_loc ~dst_loc ~dst_lval state
in
state, deps_table, written_zone
let frama_c_memcpy name state actuals = let frama_c_memcpy _name state actuals =
let prefix = "Builtin " ^ name in match actuals with
let compute (exp_dst,dst_bytes) (_exp_src,src_bytes) (_exp_size,size) = | [(dst_exp, dst_cvalue); (_src_exp, src_cvalue); (_size_exp, size_cvalue)] ->
let dst_lval = lval_of_address exp_dst in let dst_lval = lval_of_address dst_exp in
let plevel = Parameters.ArrayPrecisionLevel.get() in
let size = let size =
try Cvalue.V.project_ival size try Cvalue.V.project_ival size_cvalue
with Cvalue.V.Not_based_on_null -> Ival.top (* TODO: use size_t *) with Cvalue.V.Not_based_on_null -> Ival.top (* TODO: use size_t *)
in in
let min,max = Ival.min_and_max size in (* Convert locations and size into bits. *)
let min = match min with None -> Int.zero | Some m -> Int.max m Int.zero in let size = Ival.scale (Bit_utils.sizeofchar ()) size in
let char_bits = Bit_utils.sizeofchar() in let src = loc_bytes_to_loc_bits src_cvalue in
let size_min = Int.mul char_bits min in let dst = loc_bytes_to_loc_bits dst_cvalue in
let src = loc_bytes_to_loc_bits src_bytes in (* Remove read-only destinations. *)
let dst = loc_bytes_to_loc_bits dst_bytes in let dst =
(* Remove read-only destinations *)
let dst_bits =
Location_Bits.filter_base (fun b -> not (Base.is_read_only b)) dst Location_Bits.filter_base (fun b -> not (Base.is_read_only b)) dst
in in
let deps_return = deps_nth_arg 0 in (* Do the copy. *)
let empty_cfrom = let state, memory, sure_output =
Assigns.{ memory = Memory.empty; return = deps_return } compute_memcpy ~dst_lval ~dst ~src ~size state
in in
let precise_copy state = (* Build the builtin results. *)
(* First step: copy the bytes we are sure to copy *) let return = deps_nth_arg 0 in
if Int.gt size_min Int.zero then begin let froms = Assigns.{ memory; return } in
match Cvalue.Model.copy_offsetmap src size_min state with let c_assigns = Some (froms, sure_output) in
| `Bottom -> (* Read failed. Source was invalid, but must be read, we let return, c_clobbered =
stop the analysis *) if Model.is_reachable state then
raise (Memcpy_result (Cvalue.Model.bottom,empty_cfrom,Zone.bottom)) (* Copy at least partially succeeded *)
| `Value offsetmap -> Some dst_cvalue, Builtins.clobbered_set_from_ret state dst_cvalue
let loc_dst = make_loc dst_bits (Int_Base.inject size_min) in
memcpy_check_indeterminate_offsetmap offsetmap;
(* Read succeeded. We write the result *)
let loc_src = make_loc src (Int_Base.inject size_min) in
Cvalue_transfer.warn_imprecise_offsm_write ~prefix dst_lval offsetmap;
let new_state =
Cvalue.Model.paste_offsetmap
~from:offsetmap ~dst_loc:dst_bits ~size:size_min ~exact:true state
in
let (deps_table, sure_zone) =
let zone_dst = enumerate_valid_bits Locations.Write loc_dst in
let zone_src = enumerate_valid_bits Locations.Read loc_src in
let deps = Deps.data zone_src in
(* Note: actually a part may be written for sure (if the
difference between the offsets in loc_dst is smaller
than size), but keeping it imprecise reflects more the
imprecision of the value analysis here. *)
let exact = Location_Bits.cardinal_zero_or_one dst_bits in
let deps_table =
Assigns.Memory.add_binding ~exact
Assigns.Memory.empty zone_dst deps
in
let sure_zone = if exact then zone_dst else Zone.bottom in
(deps_table, sure_zone)
in
new_state, deps_table, sure_zone
end
else (* Nothing certain can be copied *)
(state, Assigns.Memory.empty, Zone.bottom)
in
let imprecise_copy new_state precise_assigns sure_zone =
(* Second step. Size is imprecise, we will now copy some bits
that we are not sure to copy *)
let size_min_ival = Ival.inject_singleton size_min in
let dst = Location_Bits.shift size_min_ival dst_bits in
let src = Location_Bits.shift size_min_ival src in
(* Size remaining to copy imprecisely *)
let diff = match max with
| Some max -> Some (Int.mul char_bits (Int.pred (Int.sub max min)))
| None -> None
in
(* Imprecise locations remaining to be read/written. By using ranges
modulo char_bits, we read and write byte-by-byte, which can preserve
some precision in the fallback. If sufficiently few sizes need
to be copied, we use a more precise method (see do_size below).
However, in all cases, those locations are used to compute the
read and written bits. *)
let range =
Ival.inject_interval ~min:(Some Int.zero) ~max:diff
~rem:Int.zero ~modu:char_bits
in
let size_char = Int_Base.inject char_bits in
let loc_src = make_loc (Location_Bits.shift range src) size_char in
let loc_dst = make_loc (Location_Bits.shift range dst) size_char in
let c_from =
let zone_src = enumerate_valid_bits Locations.Read loc_src in
let zone_dst = enumerate_valid_bits Locations.Write loc_dst in
let deps = Deps.data zone_src in
let memory =
Assigns.Memory.add_binding ~exact:false precise_assigns zone_dst deps
in
Assigns.{ memory; return = deps_return }
in
try
(* We try to iter on all the slices inside the value of slice.
If there are more too many of them, we use a backup solution *)
ignore (Ival.cardinal_less_than size (plevel / 10));
let do_size s (dst, src, prev_size, state) =
let s = Int.mul char_bits s in
let diff = Int.sub s prev_size in
if Int.equal s size_min then
(* occurs the very first time. This copy has already been
performed at the beginning, skip *)
(dst, src, s, state)
else begin
(* Copy data between prev_size and s *)
match Cvalue.Model.copy_offsetmap src diff state with
| `Bottom ->
(* This size is completely invalid. The following ones
will also be invalid, stop now with current result *)
raise (Memcpy_result (state,c_from,sure_zone))
| `Value offsetmap ->
memcpy_check_indeterminate_offsetmap offsetmap;
Cvalue_transfer.warn_imprecise_offsm_write ~prefix dst_lval offsetmap;
let new_state =
Cvalue.Model.paste_offsetmap
~from:offsetmap ~dst_loc:dst ~size:diff ~exact:false state
in
if Cvalue.Model.is_reachable new_state then
let diffi = Ival.inject_singleton diff in
let dst = Location_Bits.shift diffi dst in
let src = Location_Bits.shift diffi src in
(dst, src, s, new_state)
else (* As above, invalid size, this time for the destination.
We stop there *)
raise (Memcpy_result (state,c_from,sure_zone))
end
in
let _, _, _, state =
Ival.fold_int do_size size (dst, src, Int.zero, new_state)
in
raise (Memcpy_result (state,c_from,sure_zone))
with
| Abstract_interp.Not_less_than ->
Self.debug ~dkey ~once:true
~current:true "In memcpy builtin: too many sizes to enumerate, \
possible loss of precision";
(* Too many slices in the size. We read the entire range
src+(size_min..size_max-1) in one step, as one byte, and write the
result as one byte in dst+(size_min..size_max-1) *)
let v = (* conflate_bottom=false: we want to copy padding bits *)
Model.find_indeterminate ~conflate_bottom:false state loc_src
in
begin match v with
| V_Or_Uninitialized.C_init_noesc _ -> ()
| _ -> Self.result ~dkey ~current:true ~once:true
"@[In memcpy@ builtin:@ imprecise@ copy of@ indeterminate@ values@]%t"
Eva_utils.pp_callstack
end;
let value = Cvalue.V_Or_Uninitialized.get_v v in
Cvalue_transfer.warn_imprecise_write ~prefix dst_lval loc_dst value;
let updated_state =
Cvalue.Model.add_indeterminate_binding
~exact:false new_state loc_dst v
in
(* Beware that all the imprecise sizes may be invalid, in which case
[add_binding] will return [Bottom]. In this case, return the
previously computed state *)
if Model.is_reachable updated_state then
raise (Memcpy_result (updated_state,c_from,sure_zone))
else
raise (Memcpy_result (new_state,c_from,sure_zone))
in
try
if Ival.is_zero size then
raise (Memcpy_result (state, empty_cfrom, Zone.bottom));
let (precise_state,precise_assigns,sure_zone) = precise_copy state in
if Option.fold ~none:false ~some:(Int.equal min) max then
begin
let c_assigns =
Assigns.{ memory = precise_assigns; return = deps_return }
in
raise (Memcpy_result (precise_state, c_assigns, sure_zone))
end;
imprecise_copy precise_state precise_assigns sure_zone
with
| Memcpy_result (new_state,c_assigns,sure_zone) ->
if Model.is_reachable new_state then
(* Copy at least partially succeeded (with perhaps an
alarm for some of the sizes *)
Builtins.Full
{ Builtins.c_values = [Some dst_bytes, new_state];
c_clobbered = Builtins.clobbered_set_from_ret new_state dst_bytes;
c_assigns = Some (c_assigns, sure_zone); }
else else
Builtins.Full None, Base.SetLattice.bottom
{ Builtins.c_values = [ None, Cvalue.Model.bottom]; in
c_clobbered = Base.SetLattice.bottom; Builtins.Full { c_values = [ return, state ]; c_clobbered; c_assigns }
c_assigns = Some (c_assigns, sure_zone); }
in
match actuals with
| [dst; src; size] -> compute dst src size
| _ -> raise (Builtins.Invalid_nb_of_args 3) | _ -> raise (Builtins.Invalid_nb_of_args 3)
let () = let () =
register_builtin ~replace:"memcpy" "Frama_C_memcpy" (frama_c_memcpy "memcpy"); register_builtin ~replace:"memcpy" "Frama_C_memcpy" (frama_c_memcpy "memcpy");
register_builtin ~replace:"memmove" "Frama_C_memmove" (frama_c_memcpy "memmove") register_builtin ~replace:"memmove" "Frama_C_memmove" (frama_c_memcpy "memmove")
(* -------------------------------------------------------------------------- *)
(* Memset *)
(* -------------------------------------------------------------------------- *)
(* Implementation of [memset] that accepts imprecise arguments. *) (* Implementation of [memset] that accepts imprecise arguments. *)
let frama_c_memset_imprecise state dst_lval dst v size = let frama_c_memset_imprecise state dst_lval dst v size =
let prefix = "Builtin memset" in let prefix = "Builtin memset" in
......
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
[eva] memcpy.c:172: function memcpy: precondition 'valid_src' got status valid. [eva] memcpy.c:172: function memcpy: precondition 'valid_src' got status valid.
[eva] memcpy.c:172: function memcpy: precondition 'separation' got status valid. [eva] memcpy.c:172: function memcpy: precondition 'separation' got status valid.
[eva:imprecision] memcpy.c:172: [eva:imprecision] memcpy.c:172:
In memcpy builtin: precise copy of indeterminate values UNINITIALIZED In memcpy builtin: precise copy of indeterminate values.
[eva] memcpy.c:173: assertion got status valid. [eva] memcpy.c:173: assertion got status valid.
[eva] computing for function itv <- main_uninit <- main_all. [eva] computing for function itv <- main_uninit <- main_all.
Called from memcpy.c:174. Called from memcpy.c:174.
...@@ -233,7 +233,7 @@ ...@@ -233,7 +233,7 @@
[eva:imprecision] memcpy.c:174: [eva:imprecision] memcpy.c:174:
In memcpy builtin: too many sizes to enumerate, possible loss of precision In memcpy builtin: too many sizes to enumerate, possible loss of precision
[eva:imprecision] memcpy.c:174: [eva:imprecision] memcpy.c:174:
In memcpy builtin: imprecise copy of indeterminate values In memcpy builtin: imprecise copy of indeterminate values.
[eva] memcpy.c:175: assertion got status valid. [eva] memcpy.c:175: assertion got status valid.
[eva] computing for function make_unknown <- main_uninit <- main_all. [eva] computing for function make_unknown <- main_uninit <- main_all.
Called from memcpy.c:178. Called from memcpy.c:178.
...@@ -255,7 +255,7 @@ ...@@ -255,7 +255,7 @@
[eva:imprecision] memcpy.c:181: [eva:imprecision] memcpy.c:181:
In memcpy builtin: too many sizes to enumerate, possible loss of precision In memcpy builtin: too many sizes to enumerate, possible loss of precision
[eva:imprecision] memcpy.c:181: [eva:imprecision] memcpy.c:181:
In memcpy builtin: imprecise copy of indeterminate values In memcpy builtin: imprecise copy of indeterminate values.
[eva:alarm] memcpy.c:182: Warning: [eva:alarm] memcpy.c:182: Warning:
accessing uninitialized left-value. assert \initialized(&b[11]); accessing uninitialized left-value. assert \initialized(&b[11]);
[eva] computing for function make_unknown <- main_uninit <- main_all. [eva] computing for function make_unknown <- main_uninit <- main_all.
...@@ -267,7 +267,7 @@ ...@@ -267,7 +267,7 @@
[eva] memcpy.c:187: function memcpy: precondition 'valid_src' got status valid. [eva] memcpy.c:187: function memcpy: precondition 'valid_src' got status valid.
[eva] memcpy.c:187: function memcpy: precondition 'separation' got status valid. [eva] memcpy.c:187: function memcpy: precondition 'separation' got status valid.
[eva:imprecision] memcpy.c:187: [eva:imprecision] memcpy.c:187:
In memcpy builtin: precise copy of indeterminate values UNINITIALIZED In memcpy builtin: precise copy of indeterminate values.
[eva] memcpy.c:188: assertion got status valid. [eva] memcpy.c:188: assertion got status valid.
[eva] computing for function itv <- main_uninit <- main_all. [eva] computing for function itv <- main_uninit <- main_all.
Called from memcpy.c:190. Called from memcpy.c:190.
...@@ -279,7 +279,7 @@ ...@@ -279,7 +279,7 @@
[eva:imprecision] memcpy.c:190: [eva:imprecision] memcpy.c:190:
In memcpy builtin: too many sizes to enumerate, possible loss of precision In memcpy builtin: too many sizes to enumerate, possible loss of precision
[eva:imprecision] memcpy.c:190: [eva:imprecision] memcpy.c:190:
In memcpy builtin: imprecise copy of indeterminate values In memcpy builtin: imprecise copy of indeterminate values.
[eva] memcpy.c:191: assertion got status valid. [eva] memcpy.c:191: assertion got status valid.
[eva:alarm] memcpy.c:192: Warning: [eva:alarm] memcpy.c:192: Warning:
accessing uninitialized left-value. assert \initialized(&b[8]); accessing uninitialized left-value. assert \initialized(&b[8]);
...@@ -306,7 +306,7 @@ ...@@ -306,7 +306,7 @@
[eva:imprecision] memcpy.c:200: [eva:imprecision] memcpy.c:200:
In memcpy builtin: too many sizes to enumerate, possible loss of precision In memcpy builtin: too many sizes to enumerate, possible loss of precision
[eva:imprecision] memcpy.c:200: [eva:imprecision] memcpy.c:200:
In memcpy builtin: imprecise copy of indeterminate values In memcpy builtin: imprecise copy of indeterminate values.
[eva:alarm] memcpy.c:201: Warning: [eva:alarm] memcpy.c:201: Warning:
accessing uninitialized left-value. assert \initialized(&b[11]); accessing uninitialized left-value. assert \initialized(&b[11]);
[eva] Recording results for main_uninit [eva] Recording results for main_uninit
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment