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.
87 lines
2.1 KiB
87 lines
2.1 KiB
(*
|
|
* Copyright (c) 2017-present, Facebook, Inc.
|
|
*
|
|
* 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 F = Format
|
|
|
|
module FiniteBounds = struct
|
|
type t = int
|
|
|
|
let ( <= ) ~lhs ~rhs = lhs <= rhs
|
|
|
|
let join a b = max a b
|
|
|
|
let widen ~prev ~next ~num_iters:_ = join prev next
|
|
|
|
let pp fmt astate = F.fprintf fmt "%d" astate
|
|
end
|
|
|
|
module BoundsWithTop = struct
|
|
open AbstractDomain.Types
|
|
include AbstractDomain.TopLifted (FiniteBounds)
|
|
|
|
let widening_threshold = 5
|
|
|
|
let widen ~prev ~next ~num_iters =
|
|
match (prev, next) with
|
|
| Top, _ | _, Top ->
|
|
Top
|
|
| NonTop prev, NonTop next when num_iters < widening_threshold ->
|
|
NonTop (FiniteBounds.join prev next)
|
|
| NonTop _, NonTop _ (* num_iters >= widening_threshold *) ->
|
|
Top
|
|
end
|
|
|
|
module ReturnsResource = AbstractDomain.BooleanOr
|
|
include AbstractDomain.Pair (BoundsWithTop) (ReturnsResource)
|
|
open AbstractDomain.Types
|
|
|
|
let initial = (NonTop 0, false)
|
|
|
|
let acquire_resource = function
|
|
| (Top, _) as astate ->
|
|
astate
|
|
| NonTop held, returns_resource ->
|
|
(NonTop (held + 1), returns_resource)
|
|
|
|
|
|
let release_resource = function
|
|
| (Top, _) as astate ->
|
|
astate
|
|
| NonTop held, returns_resource ->
|
|
(NonTop (held - 1), returns_resource)
|
|
|
|
|
|
let has_leak = function
|
|
| Top, _ ->
|
|
(* UNSOUND but likely that the analyzer got confused *) false
|
|
| NonTop x, _ when x > 0 ->
|
|
true
|
|
| NonTop _, _ ->
|
|
false
|
|
|
|
|
|
let apply_summary ~summary:(summary_count, summary_returns_resource)
|
|
(current_count, current_returns_resource) =
|
|
let new_count =
|
|
match current_count with
|
|
| Top ->
|
|
Top
|
|
| NonTop current_count ->
|
|
let return_count = if summary_returns_resource then 1 else 0 in
|
|
let summary_count =
|
|
match summary_count with Top -> (* confusion => ignore *) 0 | NonTop count -> count
|
|
in
|
|
NonTop (current_count + summary_count + return_count)
|
|
in
|
|
(new_count, current_returns_resource)
|
|
|
|
|
|
let record_return_resource (count, _) = (count, true)
|
|
|
|
type summary = t
|