@ -95,12 +95,16 @@ module ConditionTrace = struct
let for_summary : _ t0 -> summary_t = fun ct -> { ct with cond_trace = () }
let for_summary : _ t0 -> summary_t = fun ct -> { ct with cond_trace = () }
end
end
type report_issue_type = NotIssue | Issue of IssueType . t | SymbolicIssue
type report_issue_type =
| NotIssue
| Issue of IssueType . t
| SymbolicIssue
| TaintedIssue of IssueType . t
type checked_condition = { report_issue_type : report_issue_type ; propagate : bool }
type checked_condition = { report_issue_type : report_issue_type ; propagate : bool }
module AllocSizeCondition = struct
module AllocSizeCondition = struct
type t = { length : ItvPure . t ; can_be_zero : bool } [ @@ deriving compare ]
type t = { length : ItvPure . t ; can_be_zero : bool ; taint : Dom . Taint . t } [ @@ deriving compare ]
let get_symbols { length } = ItvPure . get_symbols length
let get_symbols { length } = ItvPure . get_symbols length
@ -110,8 +114,8 @@ module AllocSizeCondition = struct
F . fprintf fmt " Length: %a " ( ItvPure . pp_mark ~ markup ) length
F . fprintf fmt " Length: %a " ( ItvPure . pp_mark ~ markup ) length
let make ~ can_be_zero ~ length =
let make ~ can_be_zero ~ length ~taint =
if ItvPure . is_invalid length then None else Some { length ; can_be_zero }
if ItvPure . is_invalid length then None else Some { length ; can_be_zero ; taint }
let have_similar_bounds x y =
let have_similar_bounds x y =
@ -151,50 +155,59 @@ module AllocSizeCondition = struct
let itv_big = ItvPure . of_int 1_000_000
let itv_big = ItvPure . of_int 1_000_000
let check { length ; can_be_zero } =
let check { length ; can_be_zero ; taint } =
match ItvPure . xcompare ~ lhs : length ~ rhs : ItvPure . zero with
if Config . bo_service_handler_request && Dom . Taint . is_tainted taint then
| ` Equal | ` RightSubsumesLeft ->
{ report_issue_type = TaintedIssue IssueType . inferbo_alloc_may_be_tainted ; propagate = false }
if can_be_zero then { report_issue_type = NotIssue ; propagate = false }
else
else { report_issue_type = Issue IssueType . inferbo_alloc_is_zero ; propagate = false }
match ItvPure . xcompare ~ lhs : length ~ rhs : ItvPure . zero with
| ` LeftSmallerThanRight ->
| ` Equal | ` RightSubsumesLeft ->
{ report_issue_type = Issue IssueType . inferbo_alloc_is_negative ; propagate = false }
if can_be_zero then { report_issue_type = NotIssue ; propagate = false }
| _ -> (
else { report_issue_type = Issue IssueType . inferbo_alloc_is_zero ; propagate = false }
let is_symbolic = ItvPure . is_symbolic length in
| ` LeftSmallerThanRight ->
match ItvPure . xcompare ~ lhs : length ~ rhs : ItvPure . mone with
{ report_issue_type = Issue IssueType . inferbo_alloc_is_negative ; propagate = false }
| ` Equal | ` LeftSmallerThanRight | ` RightSubsumesLeft ->
| _ -> (
{ report_issue_type = Issue IssueType . inferbo_alloc_is_negative ; propagate = false }
let is_symbolic = ItvPure . is_symbolic length in
| ` LeftSubsumesRight when Bound . is_not_infty ( ItvPure . lb length ) ->
match ItvPure . xcompare ~ lhs : length ~ rhs : ItvPure . mone with
{ report_issue_type = Issue IssueType . inferbo_alloc_may_be_negative
| ` Equal | ` LeftSmallerThanRight | ` RightSubsumesLeft ->
; propagate = is_symbolic }
{ report_issue_type = Issue IssueType . inferbo_alloc_is_negative ; propagate = false }
| cmp_mone -> (
| ` LeftSubsumesRight when Bound . is_not_infty ( ItvPure . lb length ) ->
match ItvPure . xcompare ~ lhs : length ~ rhs : itv_big with
{ report_issue_type = Issue IssueType . inferbo_alloc_may_be_negative
| ` Equal | ` RightSmallerThanLeft | ` RightSubsumesLeft ->
; propagate = is_symbolic }
{ report_issue_type = Issue IssueType . inferbo_alloc_is_big ; propagate = false }
| cmp_mone -> (
| ` LeftSubsumesRight when Bound . is_not_infty ( ItvPure . ub length ) ->
match ItvPure . xcompare ~ lhs : length ~ rhs : itv_big with
{ report_issue_type = Issue IssueType . inferbo_alloc_may_be_big ; propagate = is_symbolic }
| ` Equal | ` RightSmallerThanLeft | ` RightSubsumesLeft ->
| cmp_big ->
{ report_issue_type = Issue IssueType . inferbo_alloc_is_big ; propagate = false }
let propagate =
| ` LeftSubsumesRight when Bound . is_not_infty ( ItvPure . ub length ) ->
match ( cmp_mone , cmp_big ) with
{ report_issue_type = Issue IssueType . inferbo_alloc_may_be_big ; propagate = is_symbolic }
| ( ` NotComparable | ` LeftSubsumesRight ) , _ | _ , ( ` NotComparable | ` LeftSubsumesRight )
| cmp_big ->
->
let propagate =
is_symbolic
match ( cmp_mone , cmp_big ) with
| _ ->
| ( ` NotComparable | ` LeftSubsumesRight ) , _
false
| _ , ( ` NotComparable | ` LeftSubsumesRight ) ->
in
is_symbolic
if propagate then { report_issue_type = SymbolicIssue ; propagate }
| _ ->
else { report_issue_type = NotIssue ; propagate } ) )
false
in
if propagate then { report_issue_type = SymbolicIssue ; propagate }
let subst eval_sym { length ; can_be_zero } =
else { report_issue_type = NotIssue ; propagate } ) )
let subst eval_sym { length ; can_be_zero ; taint } =
match ItvPure . subst length eval_sym with
match ItvPure . subst length eval_sym with
| NonBottom length ->
| NonBottom length ->
Some { length ; can_be_zero }
Some { length ; can_be_zero ; taint }
| Bottom ->
| Bottom ->
None
None
end
end
module ArrayAccessCondition = struct
module ArrayAccessCondition = struct
type t = { offset : ItvPure . t ; idx : ItvPure . t ; size : ItvPure . t ; last_included : bool ; void_ptr : bool }
type t =
{ offset : ItvPure . t
; idx : ItvPure . t
; size : ItvPure . t
; last_included : bool
; void_ptr : bool
; taint : Dom . Taint . t }
[ @@ deriving compare ]
[ @@ deriving compare ]
let get_symbols c =
let get_symbols c =
@ -227,12 +240,18 @@ 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 : offset : ItvPure . t -> idx : ItvPure . t -> size : ItvPure . t -> last_included : bool -> t option =
let make :
fun ~ offset ~ idx ~ size ~ last_included ->
offset : ItvPure . t
-> idx : ItvPure . t
-> size : ItvPure . t
-> last_included : bool
-> taint : Dom . Taint . t
-> t option =
fun ~ offset ~ idx ~ size ~ last_included ~ taint ->
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 ; void_ptr }
Some { offset ; idx ; size ; last_included ; void_ptr ; taint }
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 }
@ -350,6 +369,9 @@ module ArrayAccessCondition = struct
(* 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 *)
else if Config . bo_service_handler_request && Dom . Taint . is_tainted c . taint then
{ report_issue_type = Issue IssueType . buffer_overrun_t1 ; propagate = false }
(* tainted values are used in array accesses *)
else if Boolean . is_false not_overrun | | Boolean . is_false not_underrun then
else if Boolean . is_false not_overrun | | Boolean . is_false not_underrun then
{ report_issue_type = Issue IssueType . buffer_overrun_l1 ; propagate = false }
{ report_issue_type = Issue IssueType . buffer_overrun_l1 ; propagate = false }
(* su <= iu < +oo, most probably an error *)
(* su <= iu < +oo, most probably an error *)
@ -764,7 +786,7 @@ module ConditionWithTrace = struct
let check cwt =
let check cwt =
let ( { report_issue_type ; propagate } as checked ) = Condition . check cwt . cond cwt . trace in
let ( { report_issue_type ; propagate } as checked ) = Condition . check cwt . cond cwt . trace in
match report_issue_type with
match report_issue_type with
| NotIssue | SymbolicIssue ->
| NotIssue | SymbolicIssue | TaintedIssue _ ->
checked
checked
| Issue issue_type ->
| Issue issue_type ->
let issue_type = set_u5 cwt issue_type in
let issue_type = set_u5 cwt issue_type in
@ -785,7 +807,7 @@ module ConditionWithTrace = struct
match checked . report_issue_type with
match checked . report_issue_type with
| NotIssue | SymbolicIssue ->
| NotIssue | SymbolicIssue ->
()
()
| Issue issue_type ->
| TaintedIssue issue_type | Issue issue_type ->
report cwt . cond cwt . trace issue_type
report cwt . cond cwt . trace issue_type
@ -797,7 +819,7 @@ module ConditionWithTrace = struct
match report_issue_type with
match report_issue_type with
| NotIssue ->
| NotIssue ->
assert false
assert false
| SymbolicIssue ->
| SymbolicIssue | TaintedIssue _ ->
reported
reported
| Issue issue_type ->
| Issue issue_type ->
Some ( Reported . make issue_type )
Some ( Reported . make issue_type )
@ -880,17 +902,17 @@ 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_traces ~ arr_traces
let add_array_access location ~ offset ~ idx ~ size ~ last_included ~ taint ~ idx_traces ~ arr_traces
~ latest_prune condset =
~ latest_prune condset =
ArrayAccessCondition . make ~ offset ~ idx ~ size ~ last_included
ArrayAccessCondition . make ~ offset ~ idx ~ size ~ last_included ~ taint
| > 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 )
latest_prune condset
latest_prune condset
let add_alloc_size location ~ can_be_zero ~ length val_traces latest_prune condset =
let add_alloc_size location ~ can_be_zero ~ length ~ taint val_traces latest_prune condset =
AllocSizeCondition . make ~ can_be_zero ~ length
AllocSizeCondition . make ~ can_be_zero ~ length ~ taint
| > Condition . make_alloc_size
| > Condition . make_alloc_size
| > add_opt location ( ValTrace . Issue . alloc location val_traces ) latest_prune condset
| > add_opt location ( ValTrace . Issue . alloc location val_traces ) latest_prune condset