[inferbo] Revert external relational domains (apron, elina)

Summary:
Inferbo does not use the external relational domains, apron and elina.  At some point, the parts of
inferbo using them were broken and they do not seem to be fixed easily in the near future.  Let's
remove them and keep the code base cleaner.

Reviewed By: jvillard

Differential Revision: D19022905

fbshipit-source-id: e0eafe79f
master
Sungkeun Cho 5 years ago committed by Facebook Github Bot
parent ada1d6f3c7
commit 387ef518f9

@ -25,13 +25,12 @@ is required to compile everything from source.
- Xcode >= 6.1 (only needed for the C/Objective-C analysis) - Xcode >= 6.1 (only needed for the C/Objective-C analysis)
- autoconf >= 2.63 and automake >= 1.11.1 (if building from git) - autoconf >= 2.63 and automake >= 1.11.1 (if building from git)
- gmp - gmp
- mpfr
You can install some of these dependencies using You can install some of these dependencies using
[Homebrew](http://brew.sh/): [Homebrew](http://brew.sh/):
```sh ```sh
brew install autoconf automake cmake opam pkg-config sqlite gmp mpfr brew install autoconf automake cmake opam pkg-config sqlite gmp
brew cask install java brew cask install java
``` ```

@ -695,73 +695,6 @@ else
endif endif
endif endif
# install dynamic libraries
# use this if you want to distribute infer binaries
install-with-libs: install
test -d '$(DESTDIR)$(libdir)'/infer/infer/libso || \
$(MKDIR_P) '$(DESTDIR)$(libdir)'/infer/infer/libso
ifneq ($(OPAM),no)
set -x; \
OPAM_SHARE=$$($(OPAM) config var share); \
APRON_LIB_PATHS="$$OPAM_SHARE/apron/lib/libapron.so $$OPAM_SHARE/apron/lib/liboctMPQ.so"; \
ELINA_LIB_PATHS="$$OPAM_SHARE/elina/lib/libelinalinearize.so $$OPAM_SHARE/elina/lib/liboptpoly.so $$OPAM_SHARE/elina/lib/libpartitions.so"; \
$(INSTALL_PROGRAM) -C $$APRON_LIB_PATHS '$(DESTDIR)$(libdir)'/infer/infer/libso/; \
$(INSTALL_PROGRAM) -C $$ELINA_LIB_PATHS '$(DESTDIR)$(libdir)'/infer/infer/libso/
ifneq ($(LDD),no)
ifneq ($(PATCHELF),no)
# this sort of assumes Linux
# figure out where libgmp and libmpfr are using ldd
set -x; \
for lib in $$($(LDD) $(INFER_BIN) \
| cut -d ' ' -f 3 \
| grep -e 'lib\(gmp\|mpfr\)'); do \
$(INSTALL_PROGRAM) -C "$$lib" '$(DESTDIR)$(libdir)'/infer/infer/libso/; \
done
# update rpath of executables
for sofile in '$(DESTDIR)$(libdir)'/infer/infer/libso/*.so; do \
$(PATCHELF) --set-rpath '$$ORIGIN' --force-rpath "$$sofile"; \
done
$(PATCHELF) --set-rpath '$$ORIGIN/../libso' --force-rpath '$(DESTDIR)$(libdir)'/infer/infer/bin/infer
ifeq ($(IS_FACEBOOK_TREE),yes)
$(PATCHELF) --set-rpath '$$ORIGIN/../libso' --force-rpath '$(DESTDIR)$(libdir)'/infer/infer/bin/InferCreateTraceViewLinks
endif
else # ldd found but not patchelf
echo "ERROR: ldd (Linux?) found but not patchelf, please install patchelf" >&2; exit 1
endif
else # ldd not found
ifneq ($(OTOOL),no)
ifneq ($(INSTALL_NAME_TOOL),no)
# this sort of assumes osx
# figure out where libgmp and libmpfr are using otool
set -e; \
set -x; \
for lib in $$($(OTOOL) -L $(INFER_BIN) \
| cut -d ' ' -f 1 | tr -d '\t' \
| grep -e 'lib\(gmp\|mpfr\)'); do \
$(INSTALL_PROGRAM) -C "$$lib" '$(DESTDIR)$(libdir)'/infer/infer/libso/; \
done
set -x; \
for sofile in '$(DESTDIR)$(libdir)'/infer/infer/libso/*.{so,dylib}; do \
$(INSTALL_NAME_TOOL) -add_rpath "@executable_path" "$$sofile" 2> /dev/null || true; \
scripts/set_libso_path.sh '$(DESTDIR)$(libdir)'/infer/infer/libso "$$sofile"; \
done
$(INSTALL_NAME_TOOL) -add_rpath '@executable_path/../libso' '$(DESTDIR)$(libdir)'/infer/infer/bin/infer 2> /dev/null || true
scripts/set_libso_path.sh '$(DESTDIR)$(libdir)'/infer/infer/libso '$(DESTDIR)$(libdir)'/infer/infer/bin/infer
ifeq ($(IS_FACEBOOK_TREE),yes)
$(INSTALL_NAME_TOOL) -add_rpath '@executable_path/../libso' '$(DESTDIR)$(libdir)'/infer/infer/bin/InferCreateTraceViewLinks 2> /dev/null || true
scripts/set_libso_path.sh '$(DESTDIR)$(libdir)'/infer/infer/libso '$(DESTDIR)$(libdir)'/infer/infer/bin/InferCreateTraceViewLinks
endif
else # install_name_tool not found
echo "ERROR: otool (OSX?) found but not install_name_tool, please install install_name_tool" >&2; exit 1
endif
else # otool not found
echo "ERROR: need ldd + patchelf (Linux) or otool + install_name_tool (OSX) available" >&2; exit 1
endif
endif # ldd
else # opam
echo "ERROR: need opam" >&2; exit 1
endif
# Nuke objects built from OCaml. Useful when changing the OCaml compiler, for instance. # Nuke objects built from OCaml. Useful when changing the OCaml compiler, for instance.
.PHONY: ocaml_clean .PHONY: ocaml_clean
ocaml_clean: ocaml_clean:

@ -36,13 +36,11 @@ INFER_MINOR = @INFER_MINOR@
INFER_PATCH = @INFER_PATCH@ INFER_PATCH = @INFER_PATCH@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_NAME_TOOL = @INSTALL_NAME_TOOL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
IS_FACEBOOK_TREE = @IS_FACEBOOK_TREE@ IS_FACEBOOK_TREE = @IS_FACEBOOK_TREE@
IS_RELEASE_TREE = @IS_RELEASE_TREE@ IS_RELEASE_TREE = @IS_RELEASE_TREE@
JAVA_MAJOR_VERSION = @JAVA_MAJOR_VERSION@ JAVA_MAJOR_VERSION = @JAVA_MAJOR_VERSION@
JAVAC = @JAVAC@ JAVAC = @JAVAC@
LDD = @LDD@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
libdir = @libdir@ libdir = @libdir@
# override in your `make` command to make the install relocatable # override in your `make` command to make the install relocatable
@ -68,8 +66,6 @@ OCAMLOPT = @OCAMLOPT@
OPAM = @OPAM@ OPAM = @OPAM@
OPAMROOT = @OPAMROOT@ OPAMROOT = @OPAMROOT@
OPAMSWITCH = @OPAMSWITCH@ OPAMSWITCH = @OPAMSWITCH@
OTOOL = @OTOOL@
PATCHELF = @PATCHELF@
PATH = @PATH@ PATH = @PATH@
prefix = @prefix@ prefix = @prefix@
PYTHON_lxml = @PYTHON_lxml@ PYTHON_lxml = @PYTHON_lxml@

@ -400,15 +400,6 @@ AC_SUBST([GNU_SED])
AC_CHECK_TOOL([BREW], [brew], [no]) AC_CHECK_TOOL([BREW], [brew], [no])
AC_CHECK_TOOL([INSTALL_NAME_TOOL], [install_name_tool], [no])
AC_SUBST([INSTALL_NAME_TOOL])
AC_CHECK_TOOL([LDD], [ldd], [no])
AC_SUBST([LDD])
AC_CHECK_TOOL([OTOOL], [otool], [no])
AC_SUBST([OTOOL])
AC_CHECK_TOOL([PATCHELF], [patchelf], [no])
AC_SUBST([PATCHELF])
AC_CHECK_INFER_MAN_LAST_MODIFIED() AC_CHECK_INFER_MAN_LAST_MODIFIED()
AC_CONFIG_FILES([ AC_CONFIG_FILES([

@ -356,10 +356,6 @@ BUCK FLAVORS OPTIONS
BUFFER OVERRUN OPTIONS BUFFER OVERRUN OPTIONS
--bo-debug int --bo-debug int
Debug level for buffer-overrun checker (0-4) Debug level for buffer-overrun checker (0-4)
--bo-relational-domain { oct | poly }
Select a relational domain being used in the bufferoverrun checker
(experimental)
CLANG OPTIONS CLANG OPTIONS
--annotation-reachability-cxx json --annotation-reachability-cxx json
Specify annotation reachability analyses to be performed on Specify annotation reachability analyses to be performed on

@ -129,10 +129,6 @@ OPTIONS
--bo-debug int --bo-debug int
Debug level for buffer-overrun checker (0-4) See also infer-analyze(1). Debug level for buffer-overrun checker (0-4) See also infer-analyze(1).
--bo-relational-domain { oct | poly }
Select a relational domain being used in the bufferoverrun checker
(experimental) See also infer-analyze(1).
--bootclasspath string --bootclasspath string
Specify the Java bootclasspath See also infer-capture(1). Specify the Java bootclasspath See also infer-capture(1).
@ -1188,9 +1184,6 @@ INTERNAL OPTIONS
Activates: Mode for analyzing the biabduction models (Conversely: Activates: Mode for analyzing the biabduction models (Conversely:
--no-biabduction-models-mode) --no-biabduction-models-mode)
--bo-relational-domain-reset
Cancel the effect of --bo-relational-domain.
--bootclasspath-reset --bootclasspath-reset
Cancel the effect of --bootclasspath. Cancel the effect of --bootclasspath.

@ -129,10 +129,6 @@ OPTIONS
--bo-debug int --bo-debug int
Debug level for buffer-overrun checker (0-4) See also infer-analyze(1). Debug level for buffer-overrun checker (0-4) See also infer-analyze(1).
--bo-relational-domain { oct | poly }
Select a relational domain being used in the bufferoverrun checker
(experimental) See also infer-analyze(1).
--bootclasspath string --bootclasspath string
Specify the Java bootclasspath See also infer-capture(1). Specify the Java bootclasspath See also infer-capture(1).

@ -851,13 +851,6 @@ and biabduction_model_free_pattern =
"Regex of methods that should be modelled as free if definition is missing" "Regex of methods that should be modelled as free if definition is missing"
and bo_relational_domain =
CLOpt.mk_symbol_opt ~long:"bo-relational-domain"
~in_help:InferCommand.[(Analyze, manual_buffer_overrun)]
~symbols:[("oct", `Bo_relational_domain_oct); ("poly", `Bo_relational_domain_poly)]
"Select a relational domain being used in the bufferoverrun checker (experimental)"
and bootclasspath = and bootclasspath =
CLOpt.mk_string_opt ~long:"bootclasspath" CLOpt.mk_string_opt ~long:"bootclasspath"
~in_help:InferCommand.[(Capture, manual_java)] ~in_help:InferCommand.[(Capture, manual_java)]
@ -2756,8 +2749,6 @@ and bootclasspath = !bootclasspath
and bo_debug = !bo_debug and bo_debug = !bo_debug
and bo_relational_domain = !bo_relational_domain
and buck = !buck and buck = !buck
and buck_blacklist = !buck_blacklist and buck_blacklist = !buck_blacklist

@ -233,8 +233,6 @@ val biabduction_models_mode : bool
val bo_debug : int val bo_debug : int
val bo_relational_domain : [`Bo_relational_domain_oct | `Bo_relational_domain_poly] option
val bootclasspath : string option val bootclasspath : string option
val buck : bool val buck : bool

@ -65,8 +65,6 @@ module Allocsite = struct
let is_unknown = function Unknown -> true | Symbol _ | Known _ | LiteralString _ -> false let is_unknown = function Unknown -> true | Symbol _ | Known _ | LiteralString _ -> false
let to_string x = F.asprintf "%a" pp x
let make : let make :
Typ.Procname.t Typ.Procname.t
-> node_hash:int -> node_hash:int
@ -243,8 +241,6 @@ module Loc = struct
let pp = pp_paren ~paren:false let pp = pp_paren ~paren:false
let to_string x = F.asprintf "%a" pp x
let is_var = function Var _ -> true | _ -> false let is_var = function Var _ -> true | _ -> false
let is_c_strlen = function let is_c_strlen = function

@ -22,8 +22,6 @@ module Allocsite : sig
include PrettyPrintable.PrintableOrderedType with type t := t include PrettyPrintable.PrintableOrderedType with type t := t
val to_string : t -> string
val unknown : t val unknown : t
val make : val make :
@ -59,8 +57,6 @@ module Loc : sig
include PrettyPrintable.PrintableOrderedType with type t := t include PrettyPrintable.PrintableOrderedType with type t := t
val to_string : t -> string
val of_allocsite : Allocsite.t -> t val of_allocsite : Allocsite.t -> t
val of_c_strlen : t -> t val of_c_strlen : t -> t

@ -137,12 +137,6 @@ module TransferFunctions = struct
|> instantiate_latest_prune ~ret_id ~callee_exit_mem eval_sym_trace location |> instantiate_latest_prune ~ret_id ~callee_exit_mem eval_sym_trace location
let forget_ret_relation ret callee_pname mem =
let ret_loc = Loc.of_pvar (Pvar.get_ret_pvar callee_pname) in
let ret_var = Loc.of_var (Var.of_id (fst ret)) in
Dom.Mem.relation_forget_locs (PowLoc.add ret_loc (PowLoc.singleton ret_var)) mem
let is_external pname = let is_external pname =
match pname with match pname with
| Typ.Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
@ -160,8 +154,7 @@ module TransferFunctions = struct
let instantiate_mem : let instantiate_mem :
Tenv.t Typ.IntegerWidths.t
-> Typ.IntegerWidths.t
-> Ident.t * Typ.t -> Ident.t * Typ.t
-> (Pvar.t * Typ.t) list -> (Pvar.t * Typ.t) list
-> Typ.Procname.t -> Typ.Procname.t
@ -170,23 +163,14 @@ module TransferFunctions = struct
-> BufferOverrunAnalysisSummary.t -> BufferOverrunAnalysisSummary.t
-> Location.t -> Location.t
-> Dom.Mem.t = -> Dom.Mem.t =
fun tenv integer_type_widths ret callee_formals callee_pname params caller_mem callee_exit_mem fun integer_type_widths ret callee_formals callee_pname params caller_mem callee_exit_mem
location -> location ->
let eval_sym_trace = let eval_sym_trace =
Sem.mk_eval_sym_trace integer_type_widths callee_formals params caller_mem Sem.mk_eval_sym_trace integer_type_widths callee_formals params caller_mem
~mode:Sem.EvalNormal ~mode:Sem.EvalNormal
in in
let caller_mem' =
instantiate_mem_reachable ret callee_formals callee_pname ~callee_exit_mem eval_sym_trace instantiate_mem_reachable ret callee_formals callee_pname ~callee_exit_mem eval_sym_trace
caller_mem location caller_mem location
|> forget_ret_relation ret callee_pname
in
Option.value_map Config.bo_relational_domain ~default:caller_mem' ~f:(fun _ ->
let rel_subst_map =
Sem.get_subst_map tenv integer_type_widths callee_formals params caller_mem
callee_exit_mem
in
Dom.Mem.instantiate_relation rel_subst_map ~caller:caller_mem' ~callee:callee_exit_mem )
let rec is_array_access_exp = function let rec is_array_access_exp = function
@ -331,16 +315,6 @@ module TransferFunctions = struct
let v = let v =
Sem.eval integer_type_widths exp2 mem |> Dom.Val.add_assign_trace_elem location locs Sem.eval integer_type_widths exp2 mem |> Dom.Val.add_assign_trace_elem location locs
in in
let mem =
let sym_exps =
Dom.Relation.SymExp.of_exps
~get_int_sym_f:(Sem.get_sym_f integer_type_widths mem)
~get_offset_sym_f:(Sem.get_offset_sym_f integer_type_widths mem)
~get_size_sym_f:(Sem.get_size_sym_f integer_type_widths mem)
exp2
in
Dom.Mem.store_relation locs sym_exps mem
in
let mem = Dom.Mem.update_mem locs v mem in let mem = Dom.Mem.update_mem locs v mem in
let mem = let mem =
if Language.curr_language_is Clang && Typ.is_char typ then if Language.curr_language_is Clang && Typ.is_char typ then
@ -378,7 +352,7 @@ module TransferFunctions = struct
| None -> ( | None -> (
match get_proc_summary_and_formals callee_pname with match get_proc_summary_and_formals callee_pname with
| Some (callee_exit_mem, callee_formals) -> | Some (callee_exit_mem, callee_formals) ->
instantiate_mem tenv integer_type_widths ret callee_formals callee_pname params mem instantiate_mem integer_type_widths ret callee_formals callee_pname params mem
callee_exit_mem location callee_exit_mem location
| None -> | None ->
(* This may happen for procedures with a biabduction model too. *) (* This may happen for procedures with a biabduction model too. *)
@ -417,8 +391,6 @@ module Analyzer = AbstractInterpreter.MakeWTO (TransferFunctions)
type invariant_map = Analyzer.invariant_map type invariant_map = Analyzer.invariant_map
type local_decls = PowLoc.t
type memory_summary = BufferOverrunAnalysisSummary.t type memory_summary = BufferOverrunAnalysisSummary.t
let extract_pre = Analyzer.extract_pre let extract_pre = Analyzer.extract_pre
@ -427,17 +399,6 @@ let extract_post = Analyzer.extract_post
let extract_state = Analyzer.extract_state let extract_state = Analyzer.extract_state
let get_local_decls : Procdesc.t -> local_decls =
fun proc_desc ->
let proc_name = Procdesc.get_proc_name proc_desc in
let accum_local_decls acc {ProcAttributes.name} =
let pvar = Pvar.mk name proc_name in
let loc = Loc.of_pvar pvar in
PowLoc.add loc acc
in
Procdesc.get_locals proc_desc |> List.fold ~init:PowLoc.empty ~f:accum_local_decls
let compute_invariant_map : let compute_invariant_map :
Summary.t -> Tenv.t -> Typ.IntegerWidths.t -> get_proc_summary_and_formals -> invariant_map = Summary.t -> Tenv.t -> Typ.IntegerWidths.t -> get_proc_summary_and_formals -> invariant_map =
fun summary tenv integer_type_widths get_proc_summary_and_formals -> fun summary tenv integer_type_widths get_proc_summary_and_formals ->
@ -484,16 +445,12 @@ let cached_compute_invariant_map =
inv_map inv_map
let compute_summary : let compute_summary : (Pvar.t * Typ.t) list -> CFG.t -> invariant_map -> memory_summary =
local_decls -> (Pvar.t * Typ.t) list -> CFG.t -> invariant_map -> memory_summary = fun formals cfg inv_map ->
fun locals formals cfg inv_map ->
let exit_node_id = CFG.exit_node cfg |> CFG.Node.id in let exit_node_id = CFG.exit_node cfg |> CFG.Node.id in
match extract_post exit_node_id inv_map with match extract_post exit_node_id inv_map with
| Some exit_mem -> | Some exit_mem ->
exit_mem exit_mem |> Dom.Mem.forget_unreachable_locs ~formals |> Dom.Mem.unset_oenv
|> Dom.Mem.forget_unreachable_locs ~formals
|> Dom.Mem.relation_forget_locs locals
|> Dom.Mem.unset_oenv
| None -> | None ->
Bottom Bottom
@ -505,8 +462,7 @@ let do_analysis : Callbacks.proc_callback_args -> Summary.t =
let tenv = Exe_env.get_tenv exe_env proc_name in let tenv = Exe_env.get_tenv exe_env proc_name in
let integer_type_widths = Exe_env.get_integer_type_widths exe_env proc_name in let integer_type_widths = Exe_env.get_integer_type_widths exe_env proc_name in
let inv_map = cached_compute_invariant_map summary tenv integer_type_widths in let inv_map = cached_compute_invariant_map summary tenv integer_type_widths in
let locals = get_local_decls proc_desc in
let formals = Procdesc.get_pvar_formals proc_desc in let formals = Procdesc.get_pvar_formals proc_desc in
let cfg = CFG.from_pdesc proc_desc in let cfg = CFG.from_pdesc proc_desc in
let payload = compute_summary locals formals cfg inv_map in let payload = compute_summary formals cfg inv_map in
Payload.update_summary payload summary Payload.update_summary payload summary

@ -8,12 +8,8 @@
open! IStd open! IStd
module CFG = ProcCfg.NormalOneInstrPerNode module CFG = ProcCfg.NormalOneInstrPerNode
module Payload : SummaryPayload.S with type t = BufferOverrunAnalysisSummary.t
type invariant_map type invariant_map
type local_decls = AbsLoc.PowLoc.t
val cached_compute_invariant_map : Summary.t -> Tenv.t -> Typ.IntegerWidths.t -> invariant_map val cached_compute_invariant_map : Summary.t -> Tenv.t -> Typ.IntegerWidths.t -> invariant_map
val extract_pre : CFG.Node.id -> invariant_map -> BufferOverrunDomain.Mem.t option val extract_pre : CFG.Node.id -> invariant_map -> BufferOverrunDomain.Mem.t option
@ -23,6 +19,4 @@ val extract_post : CFG.Node.id -> invariant_map -> BufferOverrunDomain.Mem.t opt
val extract_state : val extract_state :
CFG.Node.id -> invariant_map -> BufferOverrunDomain.Mem.t AbstractInterpreter.State.t option CFG.Node.id -> invariant_map -> BufferOverrunDomain.Mem.t AbstractInterpreter.State.t option
val get_local_decls : Procdesc.t -> local_decls
val do_analysis : Callbacks.proc_callback_t val do_analysis : Callbacks.proc_callback_t

@ -16,7 +16,6 @@ module F = Format
module L = Logging module L = Logging
module Models = BufferOverrunModels module Models = BufferOverrunModels
module PO = BufferOverrunProofObligations module PO = BufferOverrunProofObligations
module Relation = BufferOverrunDomainRelation
module Sem = BufferOverrunSemantics module Sem = BufferOverrunSemantics
module Trace = BufferOverrunTrace module Trace = BufferOverrunTrace
@ -133,11 +132,8 @@ let check_binop_array_access :
fun integer_type_widths ~is_plus ~e1 ~e2 location mem cond_set -> fun integer_type_widths ~is_plus ~e1 ~e2 location mem cond_set ->
let arr = Sem.eval integer_type_widths e1 mem in let arr = Sem.eval integer_type_widths e1 mem in
let idx = Sem.eval integer_type_widths e2 mem in let idx = Sem.eval integer_type_widths e2 mem in
let idx_sym_exp = Relation.SymExp.of_exp ~get_sym_f:(Sem.get_sym_f integer_type_widths mem) e2 in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
BoUtils.Check.array_access ~arr ~idx ~idx_sym_exp ~relation ~is_plus ~last_included:false BoUtils.Check.array_access ~arr ~idx ~is_plus ~last_included:false ~latest_prune location cond_set
~latest_prune location cond_set
let check_binop : let check_binop :
@ -189,11 +185,10 @@ let check_expr_for_array_access :
match exp with match exp with
| Exp.Var _ -> | Exp.Var _ ->
let arr = Sem.eval integer_type_widths exp mem in let arr = Sem.eval integer_type_widths exp mem in
let idx, idx_sym_exp = (Dom.Val.Itv.zero, Some Relation.SymExp.zero) in let idx = Dom.Val.Itv.zero in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
BoUtils.Check.array_access ~arr ~idx ~idx_sym_exp ~relation ~is_plus:true ~last_included:false BoUtils.Check.array_access ~arr ~idx ~is_plus:true ~last_included:false ~latest_prune location
~latest_prune location cond_set cond_set
| Exp.BinOp (bop, e1, e2) -> | Exp.BinOp (bop, e1, e2) ->
check_binop integer_type_widths ~bop ~e1 ~e2 location mem cond_set check_binop integer_type_widths ~bop ~e1 ~e2 location mem cond_set
| _ -> | _ ->
@ -239,34 +234,23 @@ let rec check_expr_for_integer_overflow integer_type_widths exp location mem con
let instantiate_cond : let instantiate_cond :
Tenv.t Typ.IntegerWidths.t
-> Typ.IntegerWidths.t
-> Typ.Procname.t -> Typ.Procname.t
-> (Pvar.t * Typ.t) list -> (Pvar.t * Typ.t) list
-> (Exp.t * Typ.t) list -> (Exp.t * Typ.t) list
-> Dom.Mem.t -> Dom.Mem.t
-> BufferOverrunAnalysisSummary.t
-> BufferOverrunCheckerSummary.t -> BufferOverrunCheckerSummary.t
-> Location.t -> Location.t
-> PO.ConditionSet.checked_t = -> PO.ConditionSet.checked_t =
fun tenv integer_type_widths callee_pname callee_formals params caller_mem callee_exit_mem fun integer_type_widths callee_pname callee_formals params caller_mem callee_cond location ->
callee_cond location ->
let rel_subst_map =
Option.value_map Config.bo_relational_domain ~default:Relation.SubstMap.empty ~f:(fun _ ->
Sem.get_subst_map tenv integer_type_widths callee_formals params caller_mem callee_exit_mem
)
in
let caller_rel = Dom.Mem.get_relation caller_mem in
let eval_sym_trace = Sem.mk_eval_sym_trace integer_type_widths callee_formals params caller_mem in let eval_sym_trace = Sem.mk_eval_sym_trace integer_type_widths callee_formals params caller_mem in
let latest_prune = Dom.Mem.get_latest_prune caller_mem in let latest_prune = Dom.Mem.get_latest_prune caller_mem in
PO.ConditionSet.subst callee_cond eval_sym_trace rel_subst_map caller_rel callee_pname location PO.ConditionSet.subst callee_cond eval_sym_trace callee_pname location latest_prune
latest_prune
type checks_summary = BufferOverrunCheckerSummary.t type checks_summary = BufferOverrunCheckerSummary.t
type get_proc_summary = type get_proc_summary = Typ.Procname.t -> ((Pvar.t * Typ.t) list * checks_summary) option
Typ.Procname.t -> (BufferOverrunAnalysisSummary.t * (Pvar.t * Typ.t) list * checks_summary) option
let check_instr : let check_instr :
get_proc_summary get_proc_summary
@ -308,9 +292,9 @@ let check_instr :
check model_env mem cond_set check model_env mem cond_set
| None -> ( | None -> (
match get_proc_summary callee_pname with match get_proc_summary callee_pname with
| Some (callee_mem, callee_formals, callee_condset) -> | Some (callee_formals, callee_condset) ->
instantiate_cond tenv integer_type_widths callee_pname callee_formals params mem instantiate_cond integer_type_widths callee_pname callee_formals params mem
callee_mem callee_condset location callee_condset location
|> PO.ConditionSet.join cond_set |> PO.ConditionSet.join cond_set
| None -> | None ->
(* unknown call / no inferbo payload *) cond_set ) ) (* unknown call / no inferbo payload *) cond_set ) )
@ -416,13 +400,12 @@ let report_errors : Tenv.t -> checks -> Summary.t -> unit =
PO.ConditionSet.report_errors ~report cond_set PO.ConditionSet.report_errors ~report cond_set
let get_checks_summary : BufferOverrunAnalysis.local_decls -> checks -> checks_summary = let get_checks_summary : checks -> checks_summary =
fun locals fun Checks.
Checks.
{ cond_set { cond_set
; unused_branches= _ (* intra-procedural *) ; unused_branches= _ (* intra-procedural *)
; unreachable_statements= _ (* intra-procedural *) } -> ; unreachable_statements= _ (* intra-procedural *) } ->
PO.ConditionSet.for_summary ~relation_forget_locs:locals cond_set PO.ConditionSet.for_summary cond_set
let checker : Callbacks.proc_callback_args -> Summary.t = let checker : Callbacks.proc_callback_args -> Summary.t =
@ -442,17 +425,13 @@ let checker : Callbacks.proc_callback_args -> Summary.t =
let get_proc_summary callee_pname = let get_proc_summary callee_pname =
Ondemand.analyze_proc_name ~caller_summary:summary callee_pname Ondemand.analyze_proc_name ~caller_summary:summary callee_pname
|> Option.bind ~f:(fun summary -> |> Option.bind ~f:(fun summary ->
let analysis_payload = BufferOverrunAnalysis.Payload.of_summary summary in
let checker_payload = Payload.of_summary summary in let checker_payload = Payload.of_summary summary in
Option.map2 analysis_payload checker_payload Option.map checker_payload ~f:(fun checker_payload ->
~f:(fun analysis_payload checker_payload -> (Summary.get_proc_desc summary |> Procdesc.get_pvar_formals, checker_payload)
( analysis_payload ) )
, Summary.get_proc_desc summary |> Procdesc.get_pvar_formals
, checker_payload ) ) )
in in
compute_checks get_proc_summary proc_desc tenv integer_type_widths cfg inv_map compute_checks get_proc_summary proc_desc tenv integer_type_widths cfg inv_map
in in
report_errors tenv checks summary ; report_errors tenv checks summary ;
let locals = BufferOverrunAnalysis.get_local_decls proc_desc in let cond_set = get_checks_summary checks in
let cond_set = get_checks_summary locals checks in
Payload.update_summary cond_set summary ) Payload.update_summary cond_set summary )

@ -13,7 +13,6 @@ open! AbstractDomain.Types
module F = Format module F = Format
module L = Logging module L = Logging
module OndemandEnv = BufferOverrunOndemandEnv module OndemandEnv = BufferOverrunOndemandEnv
module Relation = BufferOverrunDomainRelation
module SPath = Symb.SymbolPath module SPath = Symb.SymbolPath
module Trace = BufferOverrunTrace module Trace = BufferOverrunTrace
module TraceSet = Trace.Set module TraceSet = Trace.Set
@ -93,11 +92,8 @@ module Val = struct
; itv_thresholds: ItvThresholds.t ; itv_thresholds: ItvThresholds.t
; itv_updated_by: ItvUpdatedBy.t ; itv_updated_by: ItvUpdatedBy.t
; modeled_range: ModeledRange.t ; modeled_range: ModeledRange.t
; sym: Relation.Sym.t
; powloc: PowLoc.t ; powloc: PowLoc.t
; arrayblk: ArrayBlk.t ; arrayblk: ArrayBlk.t
; offset_sym: Relation.Sym.t
; size_sym: Relation.Sym.t
; traces: TraceSet.t } ; traces: TraceSet.t }
let bot : t = let bot : t =
@ -105,11 +101,8 @@ module Val = struct
; itv_thresholds= ItvThresholds.empty ; itv_thresholds= ItvThresholds.empty
; itv_updated_by= ItvUpdatedBy.bottom ; itv_updated_by= ItvUpdatedBy.bottom
; modeled_range= ModeledRange.bottom ; modeled_range= ModeledRange.bottom
; sym= Relation.Sym.bot
; powloc= PowLoc.bot ; powloc= PowLoc.bot
; arrayblk= ArrayBlk.bot ; arrayblk= ArrayBlk.bot
; offset_sym= Relation.Sym.bot
; size_sym= Relation.Sym.bot
; traces= TraceSet.bottom } ; traces= TraceSet.bottom }
@ -121,9 +114,6 @@ module Val = struct
let itv_updated_by_pp fmt itv_updated_by = let itv_updated_by_pp fmt itv_updated_by =
if Config.bo_debug >= 3 then F.fprintf fmt "(updated by %a)" ItvUpdatedBy.pp itv_updated_by if Config.bo_debug >= 3 then F.fprintf fmt "(updated by %a)" ItvUpdatedBy.pp itv_updated_by
in in
let relation_sym_pp fmt sym =
if Option.is_some Config.bo_relational_domain then F.fprintf fmt ", %a" Relation.Sym.pp sym
in
let modeled_range_pp fmt range = let modeled_range_pp fmt range =
if not (ModeledRange.is_bottom range) then if not (ModeledRange.is_bottom range) then
F.fprintf fmt " (modeled_range:%a)" ModeledRange.pp range F.fprintf fmt " (modeled_range:%a)" ModeledRange.pp range
@ -131,10 +121,9 @@ module Val = struct
let trace_pp fmt traces = let trace_pp fmt traces =
if Config.bo_debug >= 1 then F.fprintf fmt ", %a" TraceSet.pp traces if Config.bo_debug >= 1 then F.fprintf fmt ", %a" TraceSet.pp traces
in in
F.fprintf fmt "(%a%a%a%a%a, %a, %a%a%a%a)" Itv.pp x.itv itv_thresholds_pp x.itv_thresholds F.fprintf fmt "(%a%a%a%a, %a, %a%a)" Itv.pp x.itv itv_thresholds_pp x.itv_thresholds
relation_sym_pp x.sym itv_updated_by_pp x.itv_updated_by modeled_range_pp x.modeled_range itv_updated_by_pp x.itv_updated_by modeled_range_pp x.modeled_range PowLoc.pp x.powloc
PowLoc.pp x.powloc ArrayBlk.pp x.arrayblk relation_sym_pp x.offset_sym relation_sym_pp ArrayBlk.pp x.arrayblk trace_pp x.traces
x.size_sym trace_pp x.traces
let unknown_from : callee_pname:_ -> location:_ -> t = let unknown_from : callee_pname:_ -> location:_ -> t =
@ -144,11 +133,8 @@ module Val = struct
; itv_thresholds= ItvThresholds.empty ; itv_thresholds= ItvThresholds.empty
; itv_updated_by= ItvUpdatedBy.Top ; itv_updated_by= ItvUpdatedBy.Top
; modeled_range= ModeledRange.bottom ; modeled_range= ModeledRange.bottom
; sym= Relation.Sym.top
; powloc= PowLoc.unknown ; powloc= PowLoc.unknown
; arrayblk= ArrayBlk.unknown ; arrayblk= ArrayBlk.unknown
; offset_sym= Relation.Sym.top
; size_sym= Relation.Sym.top
; traces } ; traces }
@ -159,11 +145,8 @@ module Val = struct
&& ItvThresholds.leq ~lhs:lhs.itv_thresholds ~rhs:rhs.itv_thresholds && ItvThresholds.leq ~lhs:lhs.itv_thresholds ~rhs:rhs.itv_thresholds
&& ItvUpdatedBy.leq ~lhs:lhs.itv_updated_by ~rhs:rhs.itv_updated_by && ItvUpdatedBy.leq ~lhs:lhs.itv_updated_by ~rhs:rhs.itv_updated_by
&& ModeledRange.leq ~lhs:lhs.modeled_range ~rhs:rhs.modeled_range && ModeledRange.leq ~lhs:lhs.modeled_range ~rhs:rhs.modeled_range
&& Relation.Sym.leq ~lhs:lhs.sym ~rhs:rhs.sym
&& PowLoc.leq ~lhs:lhs.powloc ~rhs:rhs.powloc && PowLoc.leq ~lhs:lhs.powloc ~rhs:rhs.powloc
&& ArrayBlk.leq ~lhs:lhs.arrayblk ~rhs:rhs.arrayblk && ArrayBlk.leq ~lhs:lhs.arrayblk ~rhs:rhs.arrayblk
&& Relation.Sym.leq ~lhs:lhs.offset_sym ~rhs:rhs.offset_sym
&& Relation.Sym.leq ~lhs:lhs.size_sym ~rhs:rhs.size_sym
let widen ~prev ~next ~num_iters = let widen ~prev ~next ~num_iters =
@ -179,11 +162,8 @@ module Val = struct
ItvUpdatedBy.widen ~prev:prev.itv_updated_by ~next:next.itv_updated_by ~num_iters ItvUpdatedBy.widen ~prev:prev.itv_updated_by ~next:next.itv_updated_by ~num_iters
; modeled_range= ; modeled_range=
ModeledRange.widen ~prev:prev.modeled_range ~next:next.modeled_range ~num_iters ModeledRange.widen ~prev:prev.modeled_range ~next:next.modeled_range ~num_iters
; sym= Relation.Sym.widen ~prev:prev.sym ~next:next.sym ~num_iters
; powloc= PowLoc.widen ~prev:prev.powloc ~next:next.powloc ~num_iters ; powloc= PowLoc.widen ~prev:prev.powloc ~next:next.powloc ~num_iters
; arrayblk= ArrayBlk.widen ~prev:prev.arrayblk ~next:next.arrayblk ~num_iters ; arrayblk= ArrayBlk.widen ~prev:prev.arrayblk ~next:next.arrayblk ~num_iters
; offset_sym= Relation.Sym.widen ~prev:prev.offset_sym ~next:next.offset_sym ~num_iters
; size_sym= Relation.Sym.widen ~prev:prev.size_sym ~next:next.size_sym ~num_iters
; traces= TraceSet.join prev.traces next.traces } ; traces= TraceSet.join prev.traces next.traces }
@ -195,11 +175,8 @@ module Val = struct
; itv_thresholds= ItvThresholds.join x.itv_thresholds y.itv_thresholds ; itv_thresholds= ItvThresholds.join x.itv_thresholds y.itv_thresholds
; itv_updated_by= ItvUpdatedBy.join x.itv_updated_by y.itv_updated_by ; itv_updated_by= ItvUpdatedBy.join x.itv_updated_by y.itv_updated_by
; modeled_range= ModeledRange.join x.modeled_range y.modeled_range ; modeled_range= ModeledRange.join x.modeled_range y.modeled_range
; sym= Relation.Sym.join x.sym y.sym
; powloc= PowLoc.join x.powloc y.powloc ; powloc= PowLoc.join x.powloc y.powloc
; arrayblk= ArrayBlk.join x.arrayblk y.arrayblk ; arrayblk= ArrayBlk.join x.arrayblk y.arrayblk
; offset_sym= Relation.Sym.join x.offset_sym y.offset_sym
; size_sym= Relation.Sym.join x.size_sym y.size_sym
; traces= TraceSet.join x.traces y.traces } ; traces= TraceSet.join x.traces y.traces }
@ -209,10 +186,6 @@ module Val = struct
let get_modeled_range : t -> ModeledRange.t = fun x -> x.modeled_range let get_modeled_range : t -> ModeledRange.t = fun x -> x.modeled_range
let get_sym : t -> Relation.Sym.t = fun x -> x.sym
let get_sym_var : t -> Relation.Var.t option = fun x -> Relation.Sym.get_var x.sym
let get_pow_loc : t -> PowLoc.t = fun x -> x.powloc let get_pow_loc : t -> PowLoc.t = fun x -> x.powloc
let get_array_blk : t -> ArrayBlk.t = fun x -> x.arrayblk let get_array_blk : t -> ArrayBlk.t = fun x -> x.arrayblk
@ -221,10 +194,6 @@ module Val = struct
let get_all_locs : t -> PowLoc.t = fun x -> PowLoc.join x.powloc (get_array_locs x) let get_all_locs : t -> PowLoc.t = fun x -> PowLoc.join x.powloc (get_array_locs x)
let get_offset_sym : t -> Relation.Sym.t = fun x -> x.offset_sym
let get_size_sym : t -> Relation.Sym.t = fun x -> x.size_sym
let get_traces : t -> TraceSet.t = fun x -> x.traces let get_traces : t -> TraceSet.t = fun x -> x.traces
let of_itv ?(traces = TraceSet.bottom) itv = {bot with itv; traces} let of_itv ?(traces = TraceSet.bottom) itv = {bot with itv; traces}
@ -243,19 +212,11 @@ module Val = struct
Allocsite.t -> stride:int option -> offset:Itv.t -> size:Itv.t -> traces:TraceSet.t -> t = Allocsite.t -> stride:int option -> offset:Itv.t -> size:Itv.t -> traces:TraceSet.t -> t =
fun allocsite ~stride ~offset ~size ~traces -> fun allocsite ~stride ~offset ~size ~traces ->
let stride = Option.value_map stride ~default:Itv.nat ~f:Itv.of_int in let stride = Option.value_map stride ~default:Itv.nat ~f:Itv.of_int in
{ bot with {bot with arrayblk= ArrayBlk.make_c allocsite ~offset ~size ~stride; traces}
arrayblk= ArrayBlk.make_c allocsite ~offset ~size ~stride
; offset_sym= Relation.Sym.of_allocsite_offset allocsite
; size_sym= Relation.Sym.of_allocsite_size allocsite
; traces }
let of_java_array_alloc : Allocsite.t -> length:Itv.t -> traces:TraceSet.t -> t = let of_java_array_alloc : Allocsite.t -> length:Itv.t -> traces:TraceSet.t -> t =
fun allocsite ~length ~traces -> fun allocsite ~length ~traces -> {bot with arrayblk= ArrayBlk.make_java allocsite ~length; traces}
{ bot with
arrayblk= ArrayBlk.make_java allocsite ~length
; size_sym= Relation.Sym.of_allocsite_size allocsite
; traces }
let of_literal_string : Typ.IntegerWidths.t -> string -> t = let of_literal_string : Typ.IntegerWidths.t -> string -> t =
@ -284,11 +245,11 @@ module Val = struct
let set_modeled_range range x = {x with modeled_range= range} let set_modeled_range range x = {x with modeled_range= range}
let unknown_bit : t -> t = fun x -> {x with itv= Itv.top; sym= Relation.Sym.top} let unknown_bit : t -> t = fun x -> {x with itv= Itv.top}
let neg : t -> t = fun x -> {x with itv= Itv.neg x.itv; sym= Relation.Sym.top} let neg : t -> t = fun x -> {x with itv= Itv.neg x.itv}
let lnot : t -> t = fun x -> {x with itv= Itv.lnot x.itv |> Itv.of_bool; sym= Relation.Sym.top} let lnot : t -> t = fun x -> {x with itv= Itv.lnot x.itv |> Itv.of_bool}
let lift_itv : (Itv.t -> Itv.t -> Itv.t) -> ?f_trace:_ -> t -> t -> t = let lift_itv : (Itv.t -> Itv.t -> Itv.t) -> ?f_trace:_ -> t -> t -> t =
fun f ?f_trace x y -> fun f ?f_trace x y ->
@ -1766,7 +1727,6 @@ module MemReach = struct
; mem_pure: MemPure.t ; mem_pure: MemPure.t
; alias: Alias.t ; alias: Alias.t
; latest_prune: LatestPrune.t ; latest_prune: LatestPrune.t
; relation: Relation.t
; oenv: ('has_oenv, OndemandEnv.t) GOption.t } ; oenv: ('has_oenv, OndemandEnv.t) GOption.t }
type no_oenv_t = GOption.none t0 type no_oenv_t = GOption.none t0
@ -1779,7 +1739,6 @@ module MemReach = struct
; mem_pure= MemPure.bot ; mem_pure= MemPure.bot
; alias= Alias.init ; alias= Alias.init
; latest_prune= LatestPrune.top ; latest_prune= LatestPrune.top
; relation= Relation.empty
; oenv= GOption.GSome oenv } ; oenv= GOption.GSome oenv }
@ -1790,7 +1749,6 @@ module MemReach = struct
&& MemPure.leq ~lhs:lhs.mem_pure ~rhs:rhs.mem_pure && MemPure.leq ~lhs:lhs.mem_pure ~rhs:rhs.mem_pure
&& Alias.leq ~lhs:lhs.alias ~rhs:rhs.alias && Alias.leq ~lhs:lhs.alias ~rhs:rhs.alias
&& LatestPrune.leq ~lhs:lhs.latest_prune ~rhs:rhs.latest_prune && LatestPrune.leq ~lhs:lhs.latest_prune ~rhs:rhs.latest_prune
&& Relation.leq ~lhs:lhs.relation ~rhs:rhs.relation
let widen ~prev ~next ~num_iters = let widen ~prev ~next ~num_iters =
@ -1802,7 +1760,6 @@ module MemReach = struct
; mem_pure= MemPure.widen oenv ~prev:prev.mem_pure ~next:next.mem_pure ~num_iters ; mem_pure= MemPure.widen oenv ~prev:prev.mem_pure ~next:next.mem_pure ~num_iters
; alias= Alias.widen ~prev:prev.alias ~next:next.alias ~num_iters ; alias= Alias.widen ~prev:prev.alias ~next:next.alias ~num_iters
; latest_prune= LatestPrune.widen ~prev:prev.latest_prune ~next:next.latest_prune ~num_iters ; latest_prune= LatestPrune.widen ~prev:prev.latest_prune ~next:next.latest_prune ~num_iters
; relation= Relation.widen ~prev:prev.relation ~next:next.relation ~num_iters
; oenv= prev.oenv } ) ; oenv= prev.oenv } )
@ -1814,16 +1771,13 @@ module MemReach = struct
; mem_pure= MemPure.join oenv x.mem_pure y.mem_pure ; mem_pure= MemPure.join oenv x.mem_pure y.mem_pure
; alias= Alias.join x.alias y.alias ; alias= Alias.join x.alias y.alias
; latest_prune= LatestPrune.join x.latest_prune y.latest_prune ; latest_prune= LatestPrune.join x.latest_prune y.latest_prune
; relation= Relation.join x.relation y.relation
; oenv= x.oenv } ; oenv= x.oenv }
let pp : F.formatter -> _ t0 -> unit = let pp : F.formatter -> _ t0 -> unit =
fun fmt x -> fun fmt x ->
F.fprintf fmt "StackLocs:@;%a@;MemPure:@;%a@;Alias:@;%a@;%a" StackLocs.pp x.stack_locs F.fprintf fmt "StackLocs:@;%a@;MemPure:@;%a@;Alias:@;%a@;%a" StackLocs.pp x.stack_locs
MemPure.pp x.mem_pure Alias.pp x.alias LatestPrune.pp x.latest_prune ; MemPure.pp x.mem_pure Alias.pp x.alias LatestPrune.pp x.latest_prune
if Option.is_some Config.bo_relational_domain then
F.fprintf fmt "@;Relation:@;%a" Relation.pp x.relation
let unset_oenv : t -> no_oenv_t = function x -> {x with oenv= GOption.GNone} let unset_oenv : t -> no_oenv_t = function x -> {x with oenv= GOption.GNone}
@ -1940,14 +1894,6 @@ module MemReach = struct
let add_heap : ?represents_multiple_values:bool -> Loc.t -> Val.t -> t -> t = let add_heap : ?represents_multiple_values:bool -> Loc.t -> Val.t -> t -> t =
fun ?represents_multiple_values x v m -> fun ?represents_multiple_values x v m ->
let v =
let sym = if Itv.is_bottom (Val.get_itv v) then Relation.Sym.bot else Relation.Sym.of_loc x in
let offset_sym, size_sym =
if ArrayBlk.is_bot (Val.get_array_blk v) then (Relation.Sym.bot, Relation.Sym.bot)
else (Relation.Sym.of_loc_offset x, Relation.Sym.of_loc_size x)
in
{v with Val.sym; Val.offset_sym; Val.size_sym}
in
{m with mem_pure= MemPure.add ?represents_multiple_values x v m.mem_pure} {m with mem_pure= MemPure.add ?represents_multiple_values x v m.mem_pure}
@ -2106,30 +2052,6 @@ module MemReach = struct
fun ~filter_loc ~node_id {mem_pure} -> MemPure.range ~filter_loc ~node_id mem_pure fun ~filter_loc ~node_id {mem_pure} -> MemPure.range ~filter_loc ~node_id mem_pure
let get_relation : t -> Relation.t = fun m -> m.relation
let is_relation_unsat : t -> bool = fun m -> Relation.is_unsat m.relation
let lift_relation : (Relation.t -> Relation.t) -> t -> t =
fun f m -> {m with relation= f m.relation}
let meet_constraints : Relation.Constraints.t -> t -> t =
fun constrs -> lift_relation (Relation.meet_constraints constrs)
let store_relation :
PowLoc.t
-> Relation.SymExp.t option * Relation.SymExp.t option * Relation.SymExp.t option
-> t
-> t =
fun locs symexp_opts -> lift_relation (Relation.store_relation locs symexp_opts)
let relation_forget_locs : PowLoc.t -> t -> t =
fun locs -> lift_relation (Relation.forget_locs locs)
let forget_unreachable_locs : formals:(Pvar.t * Typ.t) list -> t -> t = let forget_unreachable_locs : formals:(Pvar.t * Typ.t) list -> t -> t =
fun ~formals m -> fun ~formals m ->
let is_reachable = let is_reachable =
@ -2149,25 +2071,6 @@ module MemReach = struct
let forget_size_alias arr_locs m = {m with alias= Alias.forget_size_alias arr_locs m.alias} let forget_size_alias arr_locs m = {m with alias= Alias.forget_size_alias arr_locs m.alias}
let init_param_relation : Loc.t -> t -> t = fun loc -> lift_relation (Relation.init_param loc)
let init_array_relation :
Allocsite.t
-> offset_opt:Itv.t option
-> size:Itv.t
-> size_exp_opt:Relation.SymExp.t option
-> t
-> t =
fun allocsite ~offset_opt ~size ~size_exp_opt ->
lift_relation (Relation.init_array allocsite ~offset_opt ~size ~size_exp_opt)
let instantiate_relation : Relation.SubstMap.t -> caller:t -> callee:no_oenv_t -> t =
fun subst_map ~caller ~callee ->
{ caller with
relation= Relation.instantiate subst_map ~caller:caller.relation ~callee:callee.relation }
(* unsound *) (* unsound *)
let set_first_idx_of_null : Loc.t -> Val.t -> t -> t = let set_first_idx_of_null : Loc.t -> Val.t -> t -> t =
fun loc idx m -> update_mem (PowLoc.singleton (Loc.of_c_strlen loc)) idx m fun loc idx m -> update_mem (PowLoc.singleton (Loc.of_c_strlen loc)) idx m
@ -2412,58 +2315,12 @@ module Mem = struct
fun latest_prune m -> map ~f:(MemReach.set_latest_prune latest_prune) m fun latest_prune m -> map ~f:(MemReach.set_latest_prune latest_prune) m
let get_relation : t -> Relation.t =
fun m -> f_lift_default ~default:Relation.bot MemReach.get_relation m
let meet_constraints : Relation.Constraints.t -> t -> t =
fun constrs -> map ~f:(MemReach.meet_constraints constrs)
let is_relation_unsat m = f_lift_default ~default:true MemReach.is_relation_unsat m
let store_relation :
PowLoc.t
-> Relation.SymExp.t option * Relation.SymExp.t option * Relation.SymExp.t option
-> t
-> t =
fun locs symexp_opts -> map ~f:(MemReach.store_relation locs symexp_opts)
let relation_forget_locs : PowLoc.t -> t -> t =
fun locs -> map ~f:(MemReach.relation_forget_locs locs)
let forget_unreachable_locs : formals:(Pvar.t * Typ.t) list -> t -> t = let forget_unreachable_locs : formals:(Pvar.t * Typ.t) list -> t -> t =
fun ~formals -> map ~f:(MemReach.forget_unreachable_locs ~formals) fun ~formals -> map ~f:(MemReach.forget_unreachable_locs ~formals)
let forget_size_alias arr_locs = map ~f:(MemReach.forget_size_alias arr_locs) let forget_size_alias arr_locs = map ~f:(MemReach.forget_size_alias arr_locs)
let[@warning "-32"] init_param_relation : Loc.t -> t -> t =
fun loc -> map ~f:(MemReach.init_param_relation loc)
let init_array_relation :
Allocsite.t
-> offset_opt:Itv.t option
-> size:Itv.t
-> size_exp_opt:Relation.SymExp.t option
-> t
-> t =
fun allocsite ~offset_opt ~size ~size_exp_opt ->
map ~f:(MemReach.init_array_relation allocsite ~offset_opt ~size ~size_exp_opt)
let instantiate_relation : Relation.SubstMap.t -> caller:t -> callee:no_oenv_t -> t =
fun subst_map ~caller ~callee ->
match callee with
| Bottom | ExcRaised ->
caller
| NonBottom callee ->
map ~f:(fun caller -> MemReach.instantiate_relation subst_map ~caller ~callee) caller
let unset_oenv = function let unset_oenv = function
| (Bottom | ExcRaised) as x -> | (Bottom | ExcRaised) as x ->
x x

File diff suppressed because it is too large Load Diff

@ -13,7 +13,6 @@ module BoUtils = BufferOverrunUtils
module Dom = BufferOverrunDomain module Dom = BufferOverrunDomain
module PO = BufferOverrunProofObligations module PO = BufferOverrunProofObligations
module Sem = BufferOverrunSemantics module Sem = BufferOverrunSemantics
module Relation = BufferOverrunDomainRelation
module Trace = BufferOverrunTrace module Trace = BufferOverrunTrace
open BoUtils.ModelEnv open BoUtils.ModelEnv
open ProcnameDispatcher.Call.FuncArg open ProcnameDispatcher.Call.FuncArg
@ -128,10 +127,6 @@ let malloc ~can_be_zero size_exp =
let allocsite = let allocsite =
Allocsite.make pname ~node_hash ~inst_num:0 ~dimension:1 ~path ~represents_multiple_values Allocsite.make pname ~node_hash ~inst_num:0 ~dimension:1 ~path ~represents_multiple_values
in in
let size_exp_opt =
let size_exp = Option.value dyn_length ~default:length0 in
Relation.SymExp.of_exp ~get_sym_f:(Sem.get_sym_f integer_type_widths mem) size_exp
in
if Language.curr_language_is Java then if Language.curr_language_is Java then
let internal_arr = let internal_arr =
let allocsite = let allocsite =
@ -148,7 +143,6 @@ let malloc ~can_be_zero size_exp =
let v = Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces in let v = Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces in
mem mem
|> Dom.Mem.add_stack (Loc.of_id id) v |> Dom.Mem.add_stack (Loc.of_id id) v
|> Dom.Mem.init_array_relation allocsite ~offset_opt:(Some offset) ~size ~size_exp_opt
|> BoUtils.Exec.init_c_array_fields model_env path typ (Dom.Val.get_array_locs v) ?dyn_length |> BoUtils.Exec.init_c_array_fields model_env path typ (Dom.Val.get_array_locs v) ?dyn_length
and check = check_alloc_size ~can_be_zero size_exp in and check = check_alloc_size ~can_be_zero size_exp in
{exec; check} {exec; check}
@ -203,11 +197,10 @@ let strcpy dest_exp src_exp =
and check {integer_type_widths; location} mem cond_set = and check {integer_type_widths; location} mem cond_set =
let access_last_char = let access_last_char =
let idx = Dom.Mem.get_c_strlen (Sem.eval_locs src_exp mem) mem in let idx = Dom.Mem.get_c_strlen (Sem.eval_locs src_exp mem) mem in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
fun arr cond_set -> fun arr cond_set ->
BoUtils.Check.array_access ~arr ~idx ~idx_sym_exp:None ~relation ~is_plus:true BoUtils.Check.array_access ~arr ~idx ~is_plus:true ~last_included:false ~latest_prune
~last_included:false ~latest_prune location cond_set location cond_set
in in
cond_set cond_set
|> access_last_char (Sem.eval integer_type_widths dest_exp mem) |> access_last_char (Sem.eval integer_type_widths dest_exp mem)
@ -246,10 +239,9 @@ let strcat dest_exp src_exp =
|> Dom.Mem.add_stack (Loc.of_id id) (Sem.eval integer_type_widths dest_exp mem) |> Dom.Mem.add_stack (Loc.of_id id) (Sem.eval integer_type_widths dest_exp mem)
and check {integer_type_widths; location} mem cond_set = and check {integer_type_widths; location} mem cond_set =
let access_last_char arr idx cond_set = let access_last_char arr idx cond_set =
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
BoUtils.Check.array_access ~arr ~idx ~idx_sym_exp:None ~relation ~is_plus:true BoUtils.Check.array_access ~arr ~idx ~is_plus:true ~last_included:false ~latest_prune location
~last_included:false ~latest_prune location cond_set cond_set
in in
let src_strlen = let src_strlen =
let str_loc = Sem.eval_locs src_exp mem in let str_loc = Sem.eval_locs src_exp mem in
@ -575,10 +567,9 @@ module ArrObjCommon = struct
and check ({location; integer_type_widths} as model_env) mem cond_set = and check ({location; integer_type_widths} as model_env) mem cond_set =
let idx = Sem.eval integer_type_widths index_exp mem in let idx = Sem.eval integer_type_widths index_exp mem in
let arr = Dom.Mem.find_set (deref_of model_env arr_exp ~fn mem) mem in let arr = Dom.Mem.find_set (deref_of model_env arr_exp ~fn mem) mem in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
BoUtils.Check.array_access ~arr ~idx ~idx_sym_exp:None ~relation ~is_plus:true BoUtils.Check.array_access ~arr ~idx ~is_plus:true ~last_included:false ~latest_prune location
~last_included:false ~latest_prune location cond_set cond_set
in in
{exec; check} {exec; check}
@ -978,13 +969,9 @@ module Collection = struct
Dom.Mem.find_set arr_locs mem Dom.Mem.find_set arr_locs mem
in in
let idx = Sem.eval integer_type_widths index_exp mem in let idx = Sem.eval integer_type_widths index_exp mem in
let idx_sym_exp =
Relation.SymExp.of_exp ~get_sym_f:(Sem.get_sym_f integer_type_widths mem) index_exp
in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
BoUtils.Check.array_access ~arr ~idx ~idx_sym_exp ~relation ~is_plus:true ~last_included BoUtils.Check.array_access ~arr ~idx ~is_plus:true ~last_included ~latest_prune location
~latest_prune location cond_set cond_set
let add_at_index (coll_id : Ident.t) index_exp = let add_at_index (coll_id : Ident.t) index_exp =

@ -13,7 +13,6 @@ module Bound = Bounds.Bound
module Dom = BufferOverrunDomain module Dom = BufferOverrunDomain
module ItvPure = Itv.ItvPure module ItvPure = Itv.ItvPure
module MF = MarkupFormatter module MF = MarkupFormatter
module Relation = BufferOverrunDomainRelation
module Sem = BufferOverrunSemantics module Sem = BufferOverrunSemantics
module ValTrace = BufferOverrunTrace module ValTrace = BufferOverrunTrace
@ -195,15 +194,7 @@ module AllocSizeCondition = struct
end end
module ArrayAccessCondition = struct module ArrayAccessCondition = struct
type t = type t = {offset: ItvPure.t; idx: ItvPure.t; size: ItvPure.t; last_included: bool; void_ptr: bool}
{ offset: ItvPure.t
; idx: ItvPure.t
; size: ItvPure.t
; last_included: bool
; idx_sym_exp: Relation.SymExp.t option
; size_sym_exp: Relation.SymExp.t option
; relation: Relation.t
; void_ptr: bool }
[@@deriving compare] [@@deriving compare]
let get_symbols c = let get_symbols c =
@ -218,10 +209,7 @@ module ArrayAccessCondition = struct
in in
let cmp = if c.last_included then "<=" else "<" in let cmp = if c.last_included then "<=" else "<" in
F.fprintf fmt "%t%a %s %a" pp_offset ItvPure.pp c.idx cmp ItvPure.pp F.fprintf fmt "%t%a %s %a" pp_offset ItvPure.pp c.idx cmp ItvPure.pp
(ItvPure.make_positive c.size) ; (ItvPure.make_positive c.size)
if Option.is_some Config.bo_relational_domain then
F.fprintf fmt "@,%a %s %a when %a" Relation.SymExp.pp_opt c.idx_sym_exp cmp
Relation.SymExp.pp_opt c.size_sym_exp Relation.pp c.relation
let pp_description : markup:bool -> F.formatter -> t -> unit = let pp_description : markup:bool -> F.formatter -> t -> unit =
@ -239,20 +227,12 @@ module ArrayAccessCondition = struct
pp_offset (ItvPure.pp_mark ~markup) (ItvPure.make_positive c.size) pp_offset (ItvPure.pp_mark ~markup) (ItvPure.make_positive c.size)
let make : let make : offset:ItvPure.t -> idx:ItvPure.t -> size:ItvPure.t -> last_included:bool -> t option =
offset:ItvPure.t fun ~offset ~idx ~size ~last_included ->
-> idx:ItvPure.t
-> size:ItvPure.t
-> last_included:bool
-> idx_sym_exp:Relation.SymExp.t option
-> size_sym_exp:Relation.SymExp.t option
-> relation:Relation.t
-> t option =
fun ~offset ~idx ~size ~last_included ~idx_sym_exp ~size_sym_exp ~relation ->
if ItvPure.is_invalid offset || ItvPure.is_invalid idx || ItvPure.is_invalid size then None if ItvPure.is_invalid offset || ItvPure.is_invalid idx || ItvPure.is_invalid size then None
else else
let void_ptr = ItvPure.has_void_ptr_symb offset || ItvPure.has_void_ptr_symb size in let void_ptr = ItvPure.has_void_ptr_symb offset || ItvPure.has_void_ptr_symb size in
Some {offset; idx; size; last_included; idx_sym_exp; size_sym_exp; relation; void_ptr} Some {offset; idx; size; last_included; void_ptr}
let have_similar_bounds {offset= loff; idx= lidx; size= lsiz; last_included= lcol} let have_similar_bounds {offset= loff; idx= lidx; size= lsiz; last_included= lcol}
@ -365,14 +345,8 @@ module ArrayAccessCondition = struct
if c.last_included then ItvPure.succ size_pos else size_pos if c.last_included then ItvPure.succ size_pos else size_pos
in in
(* if sl < 0, use sl' = 0 *) (* if sl < 0, use sl' = 0 *)
let not_overrun = let not_overrun = ItvPure.lt_sem real_idx size in
if Relation.lt_sat_opt c.idx_sym_exp c.size_sym_exp c.relation then Boolean.True let not_underrun = ItvPure.le_sem ItvPure.zero real_idx in
else ItvPure.lt_sem real_idx size
in
let not_underrun =
if Relation.le_sat_opt (Some Relation.SymExp.zero) c.idx_sym_exp c.relation then Boolean.True
else ItvPure.le_sem ItvPure.zero real_idx
in
(* il >= 0 and iu < sl, definitely not an error *) (* il >= 0 and iu < sl, definitely not an error *)
if Boolean.is_true not_overrun && Boolean.is_true not_underrun then if Boolean.is_true not_overrun && Boolean.is_true not_underrun then
{report_issue_type= NotIssue; propagate= false} (* iu < 0 or il >= su, definitely an error *) {report_issue_type= NotIssue; propagate= false} (* iu < 0 or il >= su, definitely an error *)
@ -400,30 +374,19 @@ module ArrayAccessCondition = struct
{report_issue_type; propagate= is_symbolic} {report_issue_type; propagate= is_symbolic}
let subst : Bound.eval_sym -> Relation.SubstMap.t -> Relation.t -> t -> t option = let subst : Bound.eval_sym -> t -> t option =
fun eval_sym rel_map caller_relation c -> fun eval_sym c ->
match match
(ItvPure.subst c.offset eval_sym, ItvPure.subst c.idx eval_sym, ItvPure.subst c.size eval_sym) (ItvPure.subst c.offset eval_sym, ItvPure.subst c.idx eval_sym, ItvPure.subst c.size eval_sym)
with with
| NonBottom offset, NonBottom idx, NonBottom size -> | NonBottom offset, NonBottom idx, NonBottom size ->
let idx_sym_exp, size_sym_exp, relation =
if Option.is_none Config.bo_relational_domain then (None, None, Relation.bot)
else
( Relation.SubstMap.symexp_subst_opt rel_map c.idx_sym_exp
, Relation.SubstMap.symexp_subst_opt rel_map c.size_sym_exp
, Relation.instantiate rel_map ~caller:caller_relation ~callee:c.relation )
in
let void_ptr = let void_ptr =
c.void_ptr || ItvPure.has_void_ptr_symb offset || ItvPure.has_void_ptr_symb idx c.void_ptr || ItvPure.has_void_ptr_symb offset || ItvPure.has_void_ptr_symb idx
|| ItvPure.has_void_ptr_symb size || ItvPure.has_void_ptr_symb size
in in
Some {c with offset; idx; size; idx_sym_exp; size_sym_exp; relation; void_ptr} Some {c with offset; idx; size; void_ptr}
| _ -> | _ ->
None None
let relation_forget_locs : AbsLoc.PowLoc.t -> t -> t =
fun locs c -> {c with relation= Relation.forget_locs locs c.relation}
end end
module BinaryOperationCondition = struct module BinaryOperationCondition = struct
@ -631,11 +594,11 @@ module Condition = struct
BinaryOperationCondition.get_symbols c BinaryOperationCondition.get_symbols c
let subst eval_sym rel_map caller_relation = function let subst eval_sym = function
| AllocSize c -> | AllocSize c ->
AllocSizeCondition.subst eval_sym c |> make_alloc_size AllocSizeCondition.subst eval_sym c |> make_alloc_size
| ArrayAccess c -> | ArrayAccess c ->
ArrayAccessCondition.subst eval_sym rel_map caller_relation c |> make_array_access ArrayAccessCondition.subst eval_sym c |> make_array_access
| BinaryOperation c -> | BinaryOperation c ->
BinaryOperationCondition.subst eval_sym c |> make_binary_operation BinaryOperationCondition.subst eval_sym c |> make_binary_operation
@ -701,14 +664,6 @@ module Condition = struct
BinaryOperationCondition.check c trace BinaryOperationCondition.check c trace
let relation_forget_locs locs x =
match x with
| ArrayAccess c ->
ArrayAccess (ArrayAccessCondition.relation_forget_locs locs c)
| AllocSize _ | BinaryOperation _ ->
x
let is_array_access_of_void_ptr = function ArrayAccess {void_ptr} -> void_ptr | _ -> false let is_array_access_of_void_ptr = function ArrayAccess {void_ptr} -> void_ptr | _ -> false
end end
@ -756,7 +711,7 @@ module ConditionWithTrace = struct
else `NotComparable else `NotComparable
let subst eval_sym_trace rel_map caller_relation callee_pname call_site cwt = let subst eval_sym_trace callee_pname call_site cwt =
let symbols = Condition.get_symbols cwt.cond in let symbols = Condition.get_symbols cwt.cond in
if Symb.SymbolSet.is_empty symbols then if Symb.SymbolSet.is_empty symbols then
L.(die InternalError) L.(die InternalError)
@ -770,7 +725,7 @@ module ConditionWithTrace = struct
with with
| `Reachable reachability -> ( | `Reachable reachability -> (
let {Dom.eval_sym; trace_of_sym} = eval_sym_trace ~mode:Sem.EvalPOCond in let {Dom.eval_sym; trace_of_sym} = eval_sym_trace ~mode:Sem.EvalPOCond in
match Condition.subst eval_sym rel_map caller_relation cwt.cond with match Condition.subst eval_sym cwt.cond with
| None -> | None ->
None None
| Some cond -> | Some cond ->
@ -834,7 +789,7 @@ module ConditionWithTrace = struct
report cwt.cond cwt.trace issue_type report cwt.cond cwt.trace issue_type
let for_summary ~relation_forget_locs = function let for_summary = function
| _, {propagate= false} | _, {report_issue_type= NotIssue} -> | _, {propagate= false} | _, {report_issue_type= NotIssue} ->
None None
| {cond; trace; reported; reachability}, {report_issue_type} -> | {cond; trace; reported; reachability}, {report_issue_type} ->
@ -847,7 +802,6 @@ module ConditionWithTrace = struct
| Issue issue_type -> | Issue issue_type ->
Some (Reported.make issue_type) Some (Reported.make issue_type)
in in
let cond = Condition.relation_forget_locs relation_forget_locs cond in
let trace = ConditionTrace.for_summary trace in let trace = ConditionTrace.for_summary trace in
Some {cond; trace; reported; reachability} Some {cond; trace; reported; reachability}
end end
@ -926,9 +880,9 @@ module ConditionSet = struct
join_one condset (check_one cwt) join_one condset (check_one cwt)
let add_array_access location ~offset ~idx ~size ~last_included ~idx_sym_exp ~size_sym_exp let add_array_access location ~offset ~idx ~size ~last_included ~idx_traces ~arr_traces
~relation ~idx_traces ~arr_traces ~latest_prune condset = ~latest_prune condset =
ArrayAccessCondition.make ~offset ~idx ~size ~last_included ~idx_sym_exp ~size_sym_exp ~relation ArrayAccessCondition.make ~offset ~idx ~size ~last_included
|> Condition.make_array_access |> Condition.make_array_access
|> add_opt location |> add_opt location
(ValTrace.Issue.(binary location ArrayAccess) idx_traces arr_traces) (ValTrace.Issue.(binary location ArrayAccess) idx_traces arr_traces)
@ -950,13 +904,9 @@ module ConditionSet = struct
latest_prune condset latest_prune condset
let subst condset eval_sym_trace rel_subst_map caller_relation callee_pname call_site latest_prune let subst condset eval_sym_trace callee_pname call_site latest_prune =
=
let subst_add_cwt condset cwt = let subst_add_cwt condset cwt =
match match ConditionWithTrace.subst eval_sym_trace callee_pname call_site cwt with
ConditionWithTrace.subst eval_sym_trace rel_subst_map caller_relation callee_pname call_site
cwt
with
| None -> | None ->
condset condset
| Some cwt -> | Some cwt ->
@ -970,9 +920,7 @@ module ConditionSet = struct
List.iter condset ~f:(ConditionWithTrace.report_errors ~report) List.iter condset ~f:(ConditionWithTrace.report_errors ~report)
let for_summary ~relation_forget_locs condset = let for_summary condset = List.filter_map condset ~f:ConditionWithTrace.for_summary
List.filter_map condset ~f:(ConditionWithTrace.for_summary ~relation_forget_locs)
let pp_summary : F.formatter -> _ t0 -> unit = let pp_summary : F.formatter -> _ t0 -> unit =
fun fmt condset -> fun fmt condset ->

@ -8,7 +8,6 @@
open! IStd open! IStd
open! AbstractDomain.Types open! AbstractDomain.Types
module ItvPure = Itv.ItvPure module ItvPure = Itv.ItvPure
module Relation = BufferOverrunDomainRelation
module Condition : sig module Condition : sig
type t type t
@ -39,9 +38,6 @@ module ConditionSet : sig
-> idx:ItvPure.t -> idx:ItvPure.t
-> size:ItvPure.t -> size:ItvPure.t
-> last_included:bool -> last_included:bool
-> idx_sym_exp:Relation.SymExp.t option
-> size_sym_exp:Relation.SymExp.t option
-> relation:Relation.t
-> idx_traces:BufferOverrunTrace.Set.t -> idx_traces:BufferOverrunTrace.Set.t
-> arr_traces:BufferOverrunTrace.Set.t -> arr_traces:BufferOverrunTrace.Set.t
-> latest_prune:BufferOverrunDomain.LatestPrune.t -> latest_prune:BufferOverrunDomain.LatestPrune.t
@ -74,8 +70,6 @@ module ConditionSet : sig
val subst : val subst :
summary_t summary_t
-> (mode:BufferOverrunSemantics.eval_mode -> BufferOverrunDomain.eval_sym_trace) -> (mode:BufferOverrunSemantics.eval_mode -> BufferOverrunDomain.eval_sym_trace)
-> Relation.SubstMap.t
-> Relation.t
-> Typ.Procname.t -> Typ.Procname.t
-> Location.t -> Location.t
-> BufferOverrunDomain.LatestPrune.t -> BufferOverrunDomain.LatestPrune.t
@ -84,7 +78,7 @@ module ConditionSet : sig
val report_errors : val report_errors :
report:(Condition.t -> ConditionTrace.t -> IssueType.t -> unit) -> checked_t -> unit report:(Condition.t -> ConditionTrace.t -> IssueType.t -> unit) -> checked_t -> unit
val for_summary : relation_forget_locs:AbsLoc.PowLoc.t -> checked_t -> summary_t val for_summary : checked_t -> summary_t
end end
val description : markup:bool -> Condition.t -> ConditionTrace.t -> string val description : markup:bool -> Condition.t -> ConditionTrace.t -> string

@ -475,12 +475,6 @@ let mk_eval_sym_mode ~mode integer_type_widths callee_formals actual_exps caller
let mk_eval_sym_cost = mk_eval_sym_mode ~mode:EvalCost let mk_eval_sym_cost = mk_eval_sym_mode ~mode:EvalCost
let get_sym_f integer_type_widths mem e = Val.get_sym (eval integer_type_widths e mem)
let get_offset_sym_f integer_type_widths mem e = Val.get_offset_sym (eval integer_type_widths e mem)
let get_size_sym_f integer_type_widths mem e = Val.get_size_sym (eval integer_type_widths e mem)
(* This function evaluates the array length conservatively, which is useful when there are multiple (* This function evaluates the array length conservatively, which is useful when there are multiple
array locations and their lengths are joined to top. For example, if the [arr_locs] points to array locations and their lengths are joined to top. For example, if the [arr_locs] points to
two arrays [a] and [b] and if their lengths are [a.length] and [b.length], this function two arrays [a] and [b] and if their lengths are [a.length] and [b.length], this function
@ -732,9 +726,7 @@ module Prune = struct
let prune_unreachable : Typ.IntegerWidths.t -> Exp.t -> t -> t = let prune_unreachable : Typ.IntegerWidths.t -> Exp.t -> t -> t =
fun integer_type_widths e ({mem} as astate) -> fun integer_type_widths e ({mem} as astate) ->
if is_unreachable_constant integer_type_widths e mem || Mem.is_relation_unsat mem then if is_unreachable_constant integer_type_widths e mem then {astate with mem= Mem.bot} else astate
{astate with mem= Mem.bot}
else astate
let rec prune_helper integer_type_widths e astate = let rec prune_helper integer_type_widths e astate =
@ -779,129 +771,6 @@ module Prune = struct
let prune : Typ.IntegerWidths.t -> Exp.t -> Mem.t -> Mem.t = let prune : Typ.IntegerWidths.t -> Exp.t -> Mem.t -> Mem.t =
fun integer_type_widths e mem -> fun integer_type_widths e mem ->
let mem, prune_pairs = Mem.apply_latest_prune e mem in let mem, prune_pairs = Mem.apply_latest_prune e mem in
let mem =
let constrs = Relation.Constraints.of_exp e ~get_sym_f:(get_sym_f integer_type_widths mem) in
Mem.meet_constraints constrs mem
in
let {mem; prune_pairs} = prune_helper integer_type_widths e {mem; prune_pairs} in let {mem; prune_pairs} = prune_helper integer_type_widths e {mem; prune_pairs} in
if PrunePairs.is_reachable prune_pairs then Mem.set_prune_pairs prune_pairs mem else Mem.bot if PrunePairs.is_reachable prune_pairs then Mem.set_prune_pairs prune_pairs mem else Mem.bot
end end
let get_matching_pairs :
Tenv.t
-> Typ.IntegerWidths.t
-> Val.t
-> Val.t
-> Exp.t option
-> Typ.t
-> Mem.t
-> _ Mem.t0
-> (Relation.Var.t * Relation.SymExp.t option) list =
fun tenv integer_type_widths callee_v actual actual_exp_opt typ caller_mem callee_exit_mem ->
let get_offset_sym v = Val.get_offset_sym v in
let get_size_sym v = Val.get_size_sym v in
let get_field_name (fn, _, _) = fn in
let append_field v fn = PowLoc.append_field (Val.get_all_locs v) ~fn in
let deref_field v fn mem = Mem.find_set (append_field v fn) mem in
let deref_ptr v mem =
let array_locs = Val.get_array_locs v in
let locs = if PowLoc.is_empty array_locs then Val.get_pow_loc v else array_locs in
Mem.find_set locs mem
in
let add_pair_sym_main_value v1 v2 ~e2_opt l =
Option.value_map (Val.get_sym_var v1) ~default:l ~f:(fun var ->
let sym_exp_opt =
Option.first_some
(Relation.SymExp.of_exp_opt
~get_sym_f:(get_sym_f integer_type_widths caller_mem)
e2_opt)
(Relation.SymExp.of_sym (Val.get_sym v2))
in
(var, sym_exp_opt) :: l )
in
let add_pair_sym s1 s2 l =
Option.value_map (Relation.Sym.get_var s1) ~default:l ~f:(fun var ->
(var, Relation.SymExp.of_sym s2) :: l )
in
let add_pair_val v1 v2 ~e2_opt rel_pairs =
rel_pairs
|> add_pair_sym_main_value v1 v2 ~e2_opt
|> add_pair_sym (get_offset_sym v1) (get_offset_sym v2)
|> add_pair_sym (get_size_sym v1) (get_size_sym v2)
in
let add_pair_field v1 v2 pairs fn =
let v1' = deref_field v1 fn callee_exit_mem in
let v2' = deref_field v2 fn caller_mem in
add_pair_val v1' v2' ~e2_opt:None pairs
in
let add_pair_ptr typ v1 v2 pairs =
match typ.Typ.desc with
| Typ.Tptr ({desc= Tstruct typename}, _) -> (
match Tenv.lookup tenv typename with
| Some str ->
let fns = List.map ~f:get_field_name str.Typ.Struct.fields in
List.fold ~f:(add_pair_field v1 v2) ~init:pairs fns
| _ ->
pairs )
| Typ.Tptr (_, _) ->
let v1' = deref_ptr v1 callee_exit_mem in
let v2' = deref_ptr v2 caller_mem in
add_pair_val v1' v2' ~e2_opt:None pairs
| _ ->
pairs
in
[] |> add_pair_val callee_v actual ~e2_opt:actual_exp_opt |> add_pair_ptr typ callee_v actual
let subst_map_of_rel_pairs : (Relation.Var.t * Relation.SymExp.t option) list -> Relation.SubstMap.t
=
fun pairs ->
let add_pair rel_map (x, e) = Relation.SubstMap.add x e rel_map in
List.fold pairs ~init:Relation.SubstMap.empty ~f:add_pair
let rec list_fold2_def :
default:Val.t * Exp.t option
-> f:('a -> Val.t * Exp.t option -> 'b -> 'b)
-> 'a list
-> (Val.t * Exp.t option) list
-> init:'b
-> 'b =
fun ~default ~f xs ys ~init:acc ->
match (xs, ys) with
| [], _ ->
acc
| x :: xs', [] ->
list_fold2_def ~default ~f xs' ys ~init:(f x default acc)
| [x], _ :: _ ->
let v = List.fold ys ~init:Val.bot ~f:(fun acc (y, _) -> Val.join y acc) in
let exp_opt = match ys with [(_, exp_opt)] -> exp_opt | _ -> None in
f x (v, exp_opt) acc
| x :: xs', y :: ys' ->
list_fold2_def ~default ~f xs' ys' ~init:(f x y acc)
let get_subst_map :
Tenv.t
-> Typ.IntegerWidths.t
-> (Pvar.t * Typ.t) list
-> (Exp.t * 'a) list
-> Mem.t
-> _ Mem.t0
-> Relation.SubstMap.t =
fun tenv integer_type_widths callee_formals params caller_mem callee_exit_mem ->
let add_pair (formal, typ) (actual, actual_exp) rel_l =
let callee_v = Mem.find (Loc.of_pvar formal) callee_exit_mem in
let new_rel_matching =
get_matching_pairs tenv integer_type_widths callee_v actual actual_exp typ caller_mem
callee_exit_mem
in
List.rev_append new_rel_matching rel_l
in
let actuals =
List.map ~f:(fun (a, _) -> (eval integer_type_widths a caller_mem, Some a)) params
in
let rel_pairs =
list_fold2_def ~default:(Val.Itv.top, None) ~f:add_pair callee_formals actuals ~init:[]
in
subst_map_of_rel_pairs rel_pairs

@ -10,7 +10,6 @@ open AbsLoc
open! AbstractDomain.Types open! AbstractDomain.Types
module L = Logging module L = Logging
module Dom = BufferOverrunDomain module Dom = BufferOverrunDomain
module Relation = BufferOverrunDomainRelation
module PO = BufferOverrunProofObligations module PO = BufferOverrunProofObligations
module Sem = BufferOverrunSemantics module Sem = BufferOverrunSemantics
module Trace = BufferOverrunTrace module Trace = BufferOverrunTrace
@ -77,16 +76,15 @@ module Exec = struct
Allocsite.make pname ~node_hash ~inst_num ~dimension ~path ~represents_multiple_values Allocsite.make pname ~node_hash ~inst_num ~dimension ~path ~represents_multiple_values
in in
let mem = let mem =
let arr, offset_opt = let arr =
let traces = Trace.(Set.singleton location ArrayDeclaration) in let traces = Trace.(Set.singleton location ArrayDeclaration) in
match Typ.Procname.get_language pname with match Typ.Procname.get_language pname with
| Language.Clang -> | Language.Clang ->
let offset = Itv.zero in let offset = Itv.zero in
(Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces, Some offset) Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces
| Language.Java -> | Language.Java ->
(Dom.Val.of_java_array_alloc allocsite ~length:size ~traces, None) Dom.Val.of_java_array_alloc allocsite ~length:size ~traces
in in
let mem = Dom.Mem.init_array_relation allocsite ~offset_opt ~size ~size_exp_opt:None mem in
if Int.equal dimension 1 then Dom.Mem.add_stack ~represents_multiple_values loc arr mem if Int.equal dimension 1 then Dom.Mem.add_stack ~represents_multiple_values loc arr mem
else Dom.Mem.add_heap ~represents_multiple_values loc arr mem else Dom.Mem.add_heap ~represents_multiple_values loc arr mem
in in
@ -128,8 +126,6 @@ module Exec = struct
Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces Dom.Val.of_c_array_alloc allocsite ~stride ~offset ~size ~traces
in in
mem |> Dom.Mem.strong_update field_loc v mem |> Dom.Mem.strong_update field_loc v
|> Dom.Mem.init_array_relation allocsite ~offset_opt:(Some offset) ~size
~size_exp_opt:None
| _ -> | _ ->
init_fields field_path field_typ field_loc dimension ?dyn_length mem init_fields field_path field_typ field_loc dimension ?dyn_length mem
in in
@ -239,12 +235,12 @@ module Exec = struct
end end
module Check = struct module Check = struct
let check_access ~size ~idx ~offset ~size_sym_exp ~idx_sym_exp ~relation ~arr_traces ~idx_traces let check_access ~size ~idx ~offset ~arr_traces ~idx_traces ~last_included ~latest_prune location
~last_included ~latest_prune location cond_set = cond_set =
match (size, idx) with match (size, idx) with
| NonBottom length, NonBottom idx -> | NonBottom length, NonBottom idx ->
PO.ConditionSet.add_array_access location ~size:length ~offset ~idx ~size_sym_exp PO.ConditionSet.add_array_access location ~size:length ~offset ~idx ~last_included
~idx_sym_exp ~relation ~last_included ~idx_traces ~arr_traces ~latest_prune cond_set ~idx_traces ~arr_traces ~latest_prune cond_set
| _ -> | _ ->
cond_set cond_set
@ -264,27 +260,19 @@ module Check = struct
offset offset
let array_access ~arr ~idx ~idx_sym_exp ~relation ~is_plus ~last_included ~latest_prune location let array_access ~arr ~idx ~is_plus ~last_included ~latest_prune location cond_set =
cond_set =
let idx_traces = Dom.Val.get_traces idx in let idx_traces = Dom.Val.get_traces idx in
let idx = let idx =
let idx_itv = Dom.Val.get_itv idx in let idx_itv = Dom.Val.get_itv idx in
if is_plus then idx_itv else Itv.neg idx_itv if is_plus then idx_itv else Itv.neg idx_itv
in in
let arr_traces = Dom.Val.get_traces arr in let arr_traces = Dom.Val.get_traces arr in
let size_sym_exp = Relation.SymExp.of_sym (Dom.Val.get_size_sym arr) in
let idx_sym_exp =
let offset_sym_exp = Relation.SymExp.of_sym (Dom.Val.get_offset_sym arr) in
Option.map2 offset_sym_exp idx_sym_exp ~f:(fun offset_sym_exp idx_sym_exp ->
let op = if is_plus then Relation.SymExp.plus else Relation.SymExp.minus in
op idx_sym_exp offset_sym_exp )
in
let array_access1 allocsite arr_info acc = let array_access1 allocsite arr_info acc =
let size = ArrayBlk.ArrInfo.get_size arr_info in let size = ArrayBlk.ArrInfo.get_size arr_info in
let offset = offsetof arr_info in let offset = offsetof arr_info in
log_array_access allocsite size offset idx ; log_array_access allocsite size offset idx ;
check_access ~size ~idx ~offset ~size_sym_exp ~idx_sym_exp ~relation ~arr_traces ~idx_traces check_access ~size ~idx ~offset ~arr_traces ~idx_traces ~last_included ~latest_prune location
~last_included ~latest_prune location acc acc
in in
ArrayBlk.fold array_access1 (Dom.Val.get_array_blk arr) cond_set ArrayBlk.fold array_access1 (Dom.Val.get_array_blk arr) cond_set
@ -297,17 +285,11 @@ module Check = struct
if PowLoc.is_empty arr_locs then Dom.Val.Itv.top else Dom.Mem.find_set arr_locs mem if PowLoc.is_empty arr_locs then Dom.Val.Itv.top else Dom.Mem.find_set arr_locs mem
else Sem.eval_arr integer_type_widths array_exp mem else Sem.eval_arr integer_type_widths array_exp mem
in in
let idx_sym_exp =
Relation.SymExp.of_exp ~get_sym_f:(Sem.get_sym_f integer_type_widths mem) index_exp
in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
array_access ~arr ~idx ~idx_sym_exp ~relation ~is_plus:true ~last_included ~latest_prune array_access ~arr ~idx ~is_plus:true ~last_included ~latest_prune location cond_set
location cond_set
let array_access_byte ~arr ~idx ~relation ~is_plus ~last_included ~latest_prune location cond_set let array_access_byte ~arr ~idx ~is_plus ~last_included ~latest_prune location cond_set =
=
let idx_traces = Dom.Val.get_traces idx in let idx_traces = Dom.Val.get_traces idx in
let idx = let idx =
let idx_itv = Dom.Val.get_itv idx in let idx_itv = Dom.Val.get_itv idx in
@ -318,8 +300,8 @@ module Check = struct
let size = ArrayBlk.ArrInfo.byte_size arr_info in let size = ArrayBlk.ArrInfo.byte_size arr_info in
let offset = offsetof arr_info in let offset = offsetof arr_info in
log_array_access allocsite size offset idx ; log_array_access allocsite size offset idx ;
check_access ~size ~idx ~offset ~size_sym_exp:None ~idx_sym_exp:None ~relation ~arr_traces check_access ~size ~idx ~offset ~arr_traces ~idx_traces ~last_included ~latest_prune location
~idx_traces ~last_included ~latest_prune location acc acc
in in
ArrayBlk.fold array_access_byte1 (Dom.Val.get_array_blk arr) cond_set ArrayBlk.fold array_access_byte1 (Dom.Val.get_array_blk arr) cond_set
@ -328,10 +310,8 @@ module Check = struct
cond_set = cond_set =
let idx = Sem.eval integer_type_widths byte_index_exp mem in let idx = Sem.eval integer_type_widths byte_index_exp mem in
let arr = Sem.eval_arr integer_type_widths array_exp mem in let arr = Sem.eval_arr integer_type_widths array_exp mem in
let relation = Dom.Mem.get_relation mem in
let latest_prune = Dom.Mem.get_latest_prune mem in let latest_prune = Dom.Mem.get_latest_prune mem in
array_access_byte ~arr ~idx ~relation ~is_plus:true ~last_included ~latest_prune location array_access_byte ~arr ~idx ~is_plus:true ~last_included ~latest_prune location cond_set
cond_set
let binary_operation integer_type_widths bop ~lhs ~rhs ~latest_prune location cond_set = let binary_operation integer_type_widths bop ~lhs ~rhs ~latest_prune location cond_set =

@ -8,7 +8,6 @@
open! IStd open! IStd
open AbsLoc open AbsLoc
module Dom = BufferOverrunDomain module Dom = BufferOverrunDomain
module Relation = BufferOverrunDomainRelation
module PO = BufferOverrunProofObligations module PO = BufferOverrunProofObligations
module ModelEnv : sig module ModelEnv : sig
@ -56,8 +55,6 @@ module Check : sig
val array_access : val array_access :
arr:Dom.Val.t arr:Dom.Val.t
-> idx:Dom.Val.t -> idx:Dom.Val.t
-> idx_sym_exp:Relation.SymExp.t option
-> relation:Relation.t
-> is_plus:bool -> is_plus:bool
-> last_included:bool -> last_included:bool
-> latest_prune:Dom.LatestPrune.t -> latest_prune:Dom.LatestPrune.t

@ -66,15 +66,12 @@ let common_optflags = match build_mode with Opt -> ["-O3"] | Default | Test -> [
let common_libraries = let common_libraries =
(if java then ["javalib"; "sawja"] else []) (if java then ["javalib"; "sawja"] else [])
@ [ "ANSITerminal" @ [ "ANSITerminal"
; "apron"
; "apron.octMPQ"
; "async" ; "async"
; "atdgen" ; "atdgen"
; "base" ; "base"
; "base64" ; "base64"
; "cmdliner" ; "cmdliner"
; "core" ; "core"
; "elina"
; "mtime.clock.os" ; "mtime.clock.os"
; "ocamlgraph" ; "ocamlgraph"
; "oUnit" ; "oUnit"

@ -21,20 +21,16 @@ install: [
] ]
depends: [ depends: [
"ANSITerminal" {>="0.7"} "ANSITerminal" {>="0.7"}
"apron" {<"v0.9.12"}
"async" {>="v0.12.0" & < "v0.13"} "async" {>="v0.12.0" & < "v0.13"}
"atdgen" {>="2.0.0"} "atdgen" {>="2.0.0"}
"base64" {>="3.0.0"} "base64" {>="3.0.0"}
"cmdliner" {>="1.0.0"} "cmdliner" {>="1.0.0"}
"core" {>="v0.12.0" & < "v0.13"} "core" {>="v0.12.0" & < "v0.13"}
"conf-autoconf" {build} "conf-autoconf" {build}
"conf-gmp" {build}
"conf-mpfr" {build}
"conf-sqlite3" {build} "conf-sqlite3" {build}
"conf-zlib" {build} "conf-zlib" {build}
"ctypes" {>="0.9.2"} "ctypes" {>="0.9.2"}
"dune" {build & >="1.0"} "dune" {build & >="1.0"}
"elina" {>="1.1"}
"javalib" {>="3.1.1"} "javalib" {>="3.1.1"}
"mlgmpidl" {>="1.2.12"} "mlgmpidl" {>="1.2.12"}
"mtime" "mtime"

@ -21,7 +21,6 @@ install: [
] ]
depends: [ depends: [
"ANSITerminal" {= "0.8.1"} "ANSITerminal" {= "0.8.1"}
"apron" {= "20160125"}
"async" {= "v0.12.0"} "async" {= "v0.12.0"}
"async_extra" {= "v0.12.0"} "async_extra" {= "v0.12.0"}
"async_kernel" {= "v0.12.0"} "async_kernel" {= "v0.12.0"}
@ -40,13 +39,11 @@ depends: [
"base_quickcheck" {= "v0.12.1"} "base_quickcheck" {= "v0.12.1"}
"bin_prot" {= "v0.12.0"} "bin_prot" {= "v0.12.0"}
"biniou" {= "1.2.1"} "biniou" {= "1.2.1"}
"camlidl" {= "1.07"}
"camlzip" {= "1.09"} "camlzip" {= "1.09"}
"cmdliner" {= "1.0.4"} "cmdliner" {= "1.0.4"}
"conf-autoconf" {= "0.1"} "conf-autoconf" {= "0.1"}
"conf-gmp" {= "1"} "conf-gmp" {= "1"}
"conf-m4" {= "1"} "conf-m4" {= "1"}
"conf-mpfr" {= "1"}
"conf-perl" {= "1"} "conf-perl" {= "1"}
"conf-pkg-config" {= "1.1"} "conf-pkg-config" {= "1.1"}
"conf-sqlite3" {= "1"} "conf-sqlite3" {= "1"}
@ -59,7 +56,6 @@ depends: [
"dune" {= "1.11.4"} "dune" {= "1.11.4"}
"dune-configurator" {= "1.0.0"} "dune-configurator" {= "1.0.0"}
"easy-format" {= "1.3.2"} "easy-format" {= "1.3.2"}
"elina" {= "1.1"}
"extlib" {= "1.7.6"} "extlib" {= "1.7.6"}
"fieldslib" {= "v0.12.0"} "fieldslib" {= "v0.12.0"}
"integers" {= "0.3.0"} "integers" {= "0.3.0"}
@ -68,7 +64,6 @@ depends: [
"jbuilder" {= "transition"} "jbuilder" {= "transition"}
"jst-config" {= "v0.12.0"} "jst-config" {= "v0.12.0"}
"menhir" {= "20190924"} "menhir" {= "20190924"}
"mlgmpidl" {= "1.2.12"}
"mtime" {= "1.2.0"} "mtime" {= "1.2.0"}
"num" {= "1.3"} "num" {= "1.3"}
"ocaml" {= "4.08.1"} "ocaml" {= "4.08.1"}

@ -46,7 +46,7 @@ touch .release
--prefix="/$RELEASE_NAME" --prefix="/$RELEASE_NAME"
make -j "$JOBS" \ make -j "$JOBS" \
install-with-libs \ install \
BUILD_MODE=opt \ BUILD_MODE=opt \
DESTDIR="$ROOT_DIR" \ DESTDIR="$ROOT_DIR" \
libdir_relative_to_bindir=../lib libdir_relative_to_bindir=../lib

@ -1,30 +0,0 @@
#!/bin/bash
# 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.
# Usage: set_libso_path.sh [LIBSO_DIR] [TARGET]
#
# This changes MacOSX's executable [TARGET] to use shared libraries in
# [LIBSO_DIR] when rpath has been set to [LIBSO_DIR].
set -e
set -o pipefail
set -u
LIBSO_DIR=$1
TARGET=$2
TMP=$( mktemp )
trap "rm $TMP" EXIT
otool -L "$TARGET" | tail -n +2 > "$TMP"
while IFS='' read -r line || [[ -n "$line" ]]; do
LIB_PATH=$( echo $line | awk '{print $1}' )
LIB_FILE=$( basename "${LIB_PATH}" )
if [ -f "${LIBSO_DIR}/${LIB_FILE}" ]; then
install_name_tool -change "${LIB_PATH}" "@rpath/${LIB_FILE}" "$TARGET"
fi
done < "$TMP"
Loading…
Cancel
Save