@ -59,62 +59,56 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
( Typ . mk ( Typ . Tint Typ . IChar ) , Some 1 , x )
let model_malloc
: Typ . Procname . t -> ( Ident . t * Typ . t ) option -> ( Exp . t * Typ . t ) list -> CFG . node
-> Location . t -> Dom . Mem . astate -> Dom . Mem . astate =
fun pname ret params node location mem ->
match ret with
| Some ( id , _ ) ->
let typ , stride , length0 = get_malloc_info ( List . hd_exn params | > fst ) in
let length = Sem . eval length0 mem ( CFG . loc node ) in
let traces = TraceSet . add_elem ( Trace . ArrDecl location ) ( Dom . Val . get_traces length ) in
let v =
Sem . eval_array_alloc pname node typ ? stride Itv . zero ( Dom . Val . get_itv length ) 0 1
| > Dom . Val . set_traces traces
in
mem | > Dom . Mem . add_stack ( Loc . of_id id ) v
| > set_uninitialized node typ ( Dom . Val . get_array_locs v )
| _ ->
L . ( debug BufferOverrun Verbose )
" /! \\ Do not know where to model malloc at %a@ \n " Location . pp ( CFG . loc node ) ;
mem
type model_fun =
Typ . Procname . t -> ( Ident . t * Typ . t ) option -> ( Exp . t * Typ . t ) list -> CFG . node -> Location . t
-> Dom . Mem . astate -> Dom . Mem . astate
let model_malloc pname ret params node location mem =
match ret with
| Some ( id , _ ) ->
let typ , stride , length0 = get_malloc_info ( List . hd_exn params | > fst ) in
let length = Sem . eval length0 mem ( CFG . loc node ) in
let traces = TraceSet . add_elem ( Trace . ArrDecl location ) ( Dom . Val . get_traces length ) in
let v =
Sem . eval_array_alloc pname node typ ? stride Itv . zero ( Dom . Val . get_itv length ) 0 1
| > Dom . Val . set_traces traces
in
mem | > Dom . Mem . add_stack ( Loc . of_id id ) v
| > set_uninitialized node typ ( Dom . Val . get_array_locs v )
| _ ->
L . ( debug BufferOverrun Verbose )
" /! \\ Do not know where to model malloc at %a@ \n " Location . pp ( CFG . loc node ) ;
mem
let model_realloc
: Typ . Procname . t -> ( Ident . t * Typ . t ) option -> ( Exp . t * Typ . t ) list -> CFG . node
-> Location . t -> Dom . Mem . astate -> Dom . Mem . astate =
fun pname ret params node location mem ->
model_malloc pname ret ( List . tl_exn params ) node location mem
let model_realloc pname ret params node location mem =
model_malloc pname ret ( List . tl_exn params ) node location mem
let model_min
: ( Ident . t * Typ . t ) option -> ( Exp . t * Typ . t ) list -> Location . t -> Dom . Mem . astate
-> Dom . Mem . astate =
fun ret params location mem ->
match ( ret , params ) with
| Some ( id , _ ) , [ ( e1 , _ ) ; ( e2 , _ ) ] ->
let i1 = Sem . eval e1 mem location | > Dom . Val . get_itv in
let i2 = Sem . eval e2 mem location | > Dom . Val . get_itv in
let v = Itv . min_sem i1 i2 | > Dom . Val . of_itv in
mem | > Dom . Mem . add_stack ( Loc . of_id id ) v
| _ ->
mem
let model_min _ pname ret params _ node location mem =
match ( ret , params ) with
| Some ( id , _ ) , [ ( e1 , _ ) ; ( e2 , _ ) ] ->
let i1 = Sem . eval e1 mem location | > Dom . Val . get_itv in
let i2 = Sem . eval e2 mem location | > Dom . Val . get_itv in
let v = Itv . min_sem i1 i2 | > Dom . Val . of_itv in
mem | > Dom . Mem . add_stack ( Loc . of_id id ) v
| _ ->
mem
let model_set_size : ( Exp . t * Typ . t ) list -> Location . t -> Dom . Mem . astate -> Dom . Mem . astate =
fun params location mem ->
match params with
| [ ( e1 , _ ) ; ( e2 , _ ) ] ->
let locs = Sem . eval_locs e1 mem location | > Dom . Val . get_pow_loc in
let size = Sem . eval e2 mem location | > Dom . Val . get_itv in
let arr = Dom . Mem . find_heap_set locs mem in
let arr = Dom . Val . set_array_size size arr in
Dom . Mem . strong_update_heap locs arr mem
| _ ->
mem
let model_set_size _ pname _ ret params _ node location mem =
match params with
| [ ( e1 , _ ) ; ( e2 , _ ) ] ->
let locs = Sem . eval_locs e1 mem location | > Dom . Val . get_pow_loc in
let size = Sem . eval e2 mem location | > Dom . Val . get_itv in
let arr = Dom . Mem . find_heap_set locs mem in
let arr = Dom . Val . set_array_size size arr in
Dom . Mem . strong_update_heap locs arr mem
| _ ->
mem
let model_by_value value ret mem =
let model_by_value value _ pname ret _ params _ node _ location mem =
match ret with
| Some ( id , _ ) ->
Dom . Mem . add_stack ( Loc . of_id id ) value mem
@ -124,22 +118,23 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
mem
let model_infer_print : ( Exp . t * Typ . t ) list -> Dom . Mem . astate -> Location . t -> Dom . Mem . astate =
fun params mem loc ->
match params with
| ( e , _ ) :: _ ->
L . ( debug BufferOverrun Medium )
" @[<v>=== Infer Print === at %a@,%a@]%! " Location . pp loc Dom . Val . pp
( Sem . eval e mem loc ) ;
mem
| _ ->
mem
let model_bottom _ pname _ ret _ params _ node _ location _ mem = Bottom
let model_infer_print _ pname _ ret params _ node location mem =
match params with
| ( e , _ ) :: _ ->
L . ( debug BufferOverrun Medium )
" @[<v>=== Infer Print === at %a@,%a@]%! " Location . pp location Dom . Val . pp
( Sem . eval e mem location ) ;
mem
| _ ->
mem
let model_infer_set_array_length pname node params mem loc =
let model_infer_set_array_length pname _ ret params node location mem =
match params with
| [ ( Exp . Lvar array_pvar , { Typ . desc = Typ . Tarray ( typ , _ , stride0 ) } ) ; ( length_exp , _ ) ] ->
let length = Sem . eval length_exp mem loc | > Dom . Val . get_itv in
let length = Sem . eval length_exp mem loc ation | > Dom . Val . get_itv in
let stride = Option . map ~ f : IntLit . to_int stride0 in
let v = Sem . eval_array_alloc pname node typ ? stride Itv . zero length 0 1 in
mem | > Dom . Mem . add_stack ( Loc . of_pvar array_pvar ) v
@ -150,33 +145,17 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
L . ( die InternalError ) " Unexpected number of arguments for __set_array_length() "
let handle_unknown_call
: Typ . Procname . t -> ( Ident . t * Typ . t ) option -> Typ . Procname . t -> ( Exp . t * Typ . t ) list
-> CFG . node -> Dom . Mem . astate -> Location . t -> Dom . Mem . astate =
fun pname ret callee_pname params node mem loc ->
match Typ . Procname . get_method callee_pname with
| " __inferbo_min " ->
model_min ret params loc mem
| " __inferbo_set_size " ->
model_set_size params loc mem
| " __exit " | " exit " ->
Bottom
| " fgetc " ->
model_by_value Dom . Val . Itv . m1_255 ret mem
| " infer_print " ->
model_infer_print params mem loc
| " malloc " | " __new_array " ->
model_malloc pname ret params node loc mem
| " realloc " ->
model_realloc pname ret params node loc mem
| " __set_array_length " ->
model_infer_set_array_length pname node params mem loc
| " strlen " ->
model_by_value Dom . Val . Itv . nat ret mem
| proc_name ->
L . ( debug BufferOverrun Verbose )
" /! \\ Unknown call to %s at %a@ \n " proc_name Location . pp loc ;
model_by_value Dom . Val . unknown ret mem | > Dom . Mem . add_heap Loc . unknown Dom . Val . unknown
let model_dispatcher : model_fun QualifiedCppName . Dispatch . quals_dispatcher =
QualifiedCppName . Dispatch . of_fuzzy_qual_names
[ ( [ " __inferbo_min " ] , model_min )
; ( [ " __inferbo_set_size " ] , model_set_size )
; ( [ " __exit " ; " exit " ] , model_bottom )
; ( [ " fgetc " ] , model_by_value Dom . Val . Itv . m1_255 )
; ( [ " infer_print " ] , model_infer_print )
; ( [ " malloc " ; " __new_array " ] , model_malloc )
; ( [ " realloc " ] , model_realloc )
; ( [ " __set_array_length " ] , model_infer_set_array_length )
; ( [ " strlen " ] , model_by_value Dom . Val . Itv . nat ) ]
let rec declare_array
@ -405,13 +384,22 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
else mem
| Prune ( exp , loc , _ , _ ) ->
Sem . prune exp loc mem
| Call ( ret , Const Cfun callee_pname , params , loc , _ ) -> (
match Summary . read_summary pdesc callee_pname with
| Some summary ->
let callee = extras callee_pname in
instantiate_mem tenv ret callee callee_pname params mem summary loc
| None ->
handle_unknown_call pname ret callee_pname params node mem loc )
| Call ( ret , Const Cfun callee_pname , params , loc , _ )
-> (
let quals = Typ . Procname . get_qualifiers callee_pname in
match QualifiedCppName . Dispatch . dispatch_qualifiers model_dispatcher quals with
| Some model ->
model callee_pname ret params node loc mem
| None ->
match Summary . read_summary pdesc callee_pname with
| Some summary ->
let callee = extras callee_pname in
instantiate_mem tenv ret callee callee_pname params mem summary loc
| None ->
L . ( debug BufferOverrun Verbose )
" /! \\ Unknown call to %a at %a@ \n " Typ . Procname . pp callee_pname Location . pp loc ;
model_by_value Dom . Val . unknown callee_pname ret params node loc mem
| > Dom . Mem . add_heap Loc . unknown Dom . Val . unknown )
| Declare_locals ( locals , location ) ->
(* array allocation in stack e.g., int arr[10] *)
let try_decl_arr location ( mem , inst_num ) ( pvar , typ ) =