You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.5 KiB
93 lines
3.5 KiB
(*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*)
|
|
|
|
open! IStd
|
|
module L = Logging
|
|
module SPath = Symb.SymbolPath
|
|
module FormalTyps = Caml.Map.Make (Pvar)
|
|
|
|
type t =
|
|
{ tenv: Tenv.t
|
|
; typ_of_param_path: SPath.partial -> Typ.t option
|
|
; may_last_field: SPath.partial -> bool
|
|
; entry_location: Location.t
|
|
; integer_type_widths: Typ.IntegerWidths.t
|
|
; class_name: Typ.name option }
|
|
|
|
let mk pdesc =
|
|
let formal_typs =
|
|
List.fold (Procdesc.get_pvar_formals pdesc) ~init:FormalTyps.empty ~f:(fun acc (formal, typ) ->
|
|
FormalTyps.add formal typ acc )
|
|
in
|
|
fun tenv integer_type_widths ->
|
|
let rec typ_of_param_path = function
|
|
| SPath.Pvar x ->
|
|
FormalTyps.find_opt x formal_typs
|
|
| SPath.Deref (_, x) -> (
|
|
match typ_of_param_path x with
|
|
| None ->
|
|
None
|
|
| Some typ -> (
|
|
match typ.Typ.desc with
|
|
| Tptr (typ, _) ->
|
|
Some typ
|
|
| Tarray {elt} ->
|
|
Some elt
|
|
| Tvoid ->
|
|
Some Typ.void
|
|
| Tstruct typename -> (
|
|
match BufferOverrunTypModels.dispatch tenv typename with
|
|
| Some (CArray {element_typ}) ->
|
|
Some element_typ
|
|
| Some CppStdVector ->
|
|
Some (Typ.mk (Typ.Tptr (Typ.void, Typ.Pk_pointer)))
|
|
| Some JavaCollection ->
|
|
(* Current Java frontend does give element types of Java collection. *)
|
|
None
|
|
| Some JavaInteger ->
|
|
L.internal_error "Deref of non-array modeled type `%a`" Typ.Name.pp typename ;
|
|
None
|
|
| None ->
|
|
L.(die InternalError) "Deref of unmodeled type `%a`" Typ.Name.pp typename )
|
|
| _ ->
|
|
L.(die InternalError) "Untyped expression is given." ) )
|
|
| SPath.Field {typ= Some _ as some_typ} ->
|
|
some_typ
|
|
| SPath.Field {fn; prefix= x} -> (
|
|
match BufferOverrunField.get_type fn with
|
|
| None ->
|
|
let lookup = Tenv.lookup tenv in
|
|
Option.map (typ_of_param_path x) ~f:(Struct.fld_typ ~lookup ~default:Typ.void fn)
|
|
| some_typ ->
|
|
some_typ )
|
|
| SPath.StarField {last_field} ->
|
|
BufferOverrunField.get_type last_field
|
|
| SPath.Callsite {ret_typ} ->
|
|
Some ret_typ
|
|
in
|
|
let is_last_field fn (fields : Struct.field list) =
|
|
Option.value_map (List.last fields) ~default:false ~f:(fun (last_fn, _, _) ->
|
|
Fieldname.equal fn last_fn )
|
|
in
|
|
let rec may_last_field = function
|
|
| SPath.Pvar _ | SPath.Deref _ | SPath.Callsite _ ->
|
|
true
|
|
| SPath.Field {fn; prefix= x} | SPath.StarField {last_field= fn; prefix= x} ->
|
|
may_last_field x
|
|
&& Option.value_map ~default:true (typ_of_param_path x) ~f:(fun parent_typ ->
|
|
match parent_typ.Typ.desc with
|
|
| Tstruct typename ->
|
|
let opt_struct = Tenv.lookup tenv typename in
|
|
Option.value_map opt_struct ~default:false ~f:(fun str ->
|
|
is_last_field fn str.Struct.fields )
|
|
| _ ->
|
|
true )
|
|
in
|
|
let entry_location = Procdesc.Node.get_loc (Procdesc.get_start_node pdesc) in
|
|
let class_name = Procname.get_class_type_name (Procdesc.get_proc_name pdesc) in
|
|
{tenv; typ_of_param_path; may_last_field; entry_location; integer_type_widths; class_name}
|