1 /* Classes for modeling the state of memory.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
22 #define INCLUDE_MEMORY
23 #define INCLUDE_ALGORITHM
25 #include "coretypes.h"
26 #include "make-unique.h"
29 #include "basic-block.h"
31 #include "gimple-iterator.h"
32 #include "diagnostic-core.h"
37 #include "stringpool.h"
40 #include "fold-const.h"
41 #include "tree-pretty-print.h"
42 #include "diagnostic-color.h"
43 #include "diagnostic-metadata.h"
46 #include "analyzer/analyzer.h"
47 #include "analyzer/analyzer-logging.h"
48 #include "ordered-hash-map.h"
52 #include "analyzer/supergraph.h"
54 #include "analyzer/call-string.h"
55 #include "analyzer/program-point.h"
56 #include "analyzer/store.h"
57 #include "analyzer/region-model.h"
58 #include "analyzer/constraint-manager.h"
59 #include "diagnostic-event-id.h"
60 #include "analyzer/sm.h"
61 #include "diagnostic-event-id.h"
62 #include "analyzer/sm.h"
63 #include "analyzer/pending-diagnostic.h"
64 #include "analyzer/region-model-reachability.h"
65 #include "analyzer/analyzer-selftests.h"
66 #include "analyzer/program-state.h"
67 #include "analyzer/call-summary.h"
68 #include "stor-layout.h"
70 #include "tree-object-size.h"
71 #include "gimple-ssa.h"
72 #include "tree-phinodes.h"
73 #include "tree-ssa-operands.h"
74 #include "ssa-iterators.h"
77 #include "gcc-rich-location.h"
78 #include "analyzer/checker-event.h"
79 #include "analyzer/checker-path.h"
80 #include "analyzer/feasible-graph.h"
81 #include "analyzer/record-layout.h"
87 auto_vec
<pop_frame_callback
> region_model::pop_frame_callbacks
;
89 /* Dump T to PP in language-independent form, for debugging/logging/dumping
93 dump_tree (pretty_printer
*pp
, tree t
)
95 dump_generic_node (pp
, t
, 0, TDF_SLIM
, 0);
98 /* Dump T to PP in language-independent form in quotes, for
99 debugging/logging/dumping purposes. */
102 dump_quoted_tree (pretty_printer
*pp
, tree t
)
104 pp_begin_quote (pp
, pp_show_color (pp
));
106 pp_end_quote (pp
, pp_show_color (pp
));
109 /* Equivalent to pp_printf (pp, "%qT", t), to avoid nesting pp_printf
110 calls within other pp_printf calls.
112 default_tree_printer handles 'T' and some other codes by calling
113 dump_generic_node (pp, t, 0, TDF_SLIM, 0);
114 dump_generic_node calls pp_printf in various places, leading to
117 Ideally pp_printf could be made to be reentrant, but in the meantime
118 this function provides a workaround. */
121 print_quoted_type (pretty_printer
*pp
, tree t
)
123 pp_begin_quote (pp
, pp_show_color (pp
));
124 dump_generic_node (pp
, t
, 0, TDF_SLIM
, 0);
125 pp_end_quote (pp
, pp_show_color (pp
));
128 /* class region_to_value_map. */
130 /* Assignment operator for region_to_value_map. */
132 region_to_value_map
&
133 region_to_value_map::operator= (const region_to_value_map
&other
)
136 for (auto iter
: other
.m_hash_map
)
138 const region
*reg
= iter
.first
;
139 const svalue
*sval
= iter
.second
;
140 m_hash_map
.put (reg
, sval
);
145 /* Equality operator for region_to_value_map. */
148 region_to_value_map::operator== (const region_to_value_map
&other
) const
150 if (m_hash_map
.elements () != other
.m_hash_map
.elements ())
153 for (auto iter
: *this)
155 const region
*reg
= iter
.first
;
156 const svalue
*sval
= iter
.second
;
157 const svalue
* const *other_slot
= other
.get (reg
);
158 if (other_slot
== NULL
)
160 if (sval
!= *other_slot
)
167 /* Dump this object to PP. */
170 region_to_value_map::dump_to_pp (pretty_printer
*pp
, bool simple
,
171 bool multiline
) const
173 auto_vec
<const region
*> regs
;
174 for (iterator iter
= begin (); iter
!= end (); ++iter
)
175 regs
.safe_push ((*iter
).first
);
176 regs
.qsort (region::cmp_ptr_ptr
);
180 pp_string (pp
, " {");
183 FOR_EACH_VEC_ELT (regs
, i
, reg
)
188 pp_string (pp
, ", ");
189 reg
->dump_to_pp (pp
, simple
);
190 pp_string (pp
, ": ");
191 const svalue
*sval
= *get (reg
);
192 sval
->dump_to_pp (pp
, true);
200 /* Dump this object to stderr. */
203 region_to_value_map::dump (bool simple
) const
206 pp_format_decoder (&pp
) = default_tree_printer
;
207 pp_show_color (&pp
) = pp_show_color (global_dc
->printer
);
208 pp
.buffer
->stream
= stderr
;
209 dump_to_pp (&pp
, simple
, true);
215 /* Attempt to merge THIS with OTHER, writing the result
218 For now, write (region, value) mappings that are in common between THIS
219 and OTHER to OUT, effectively taking the intersection.
221 Reject merger of different values. */
224 region_to_value_map::can_merge_with_p (const region_to_value_map
&other
,
225 region_to_value_map
*out
) const
227 for (auto iter
: *this)
229 const region
*iter_reg
= iter
.first
;
230 const svalue
*iter_sval
= iter
.second
;
231 const svalue
* const * other_slot
= other
.get (iter_reg
);
234 if (iter_sval
== *other_slot
)
235 out
->put (iter_reg
, iter_sval
);
243 /* Purge any state involving SVAL. */
246 region_to_value_map::purge_state_involving (const svalue
*sval
)
248 auto_vec
<const region
*> to_purge
;
249 for (auto iter
: *this)
251 const region
*iter_reg
= iter
.first
;
252 const svalue
*iter_sval
= iter
.second
;
253 if (iter_reg
->involves_p (sval
) || iter_sval
->involves_p (sval
))
254 to_purge
.safe_push (iter_reg
);
256 for (auto iter
: to_purge
)
257 m_hash_map
.remove (iter
);
260 /* class region_model. */
262 /* Ctor for region_model: construct an "empty" model. */
264 region_model::region_model (region_model_manager
*mgr
)
265 : m_mgr (mgr
), m_store (), m_current_frame (NULL
),
268 m_constraints
= new constraint_manager (mgr
);
271 /* region_model's copy ctor. */
273 region_model::region_model (const region_model
&other
)
274 : m_mgr (other
.m_mgr
), m_store (other
.m_store
),
275 m_constraints (new constraint_manager (*other
.m_constraints
)),
276 m_current_frame (other
.m_current_frame
),
277 m_dynamic_extents (other
.m_dynamic_extents
)
281 /* region_model's dtor. */
283 region_model::~region_model ()
285 delete m_constraints
;
288 /* region_model's assignment operator. */
291 region_model::operator= (const region_model
&other
)
293 /* m_mgr is const. */
294 gcc_assert (m_mgr
== other
.m_mgr
);
296 m_store
= other
.m_store
;
298 delete m_constraints
;
299 m_constraints
= new constraint_manager (*other
.m_constraints
);
301 m_current_frame
= other
.m_current_frame
;
303 m_dynamic_extents
= other
.m_dynamic_extents
;
308 /* Equality operator for region_model.
310 Amongst other things this directly compares the stores and the constraint
311 managers, so for this to be meaningful both this and OTHER should
312 have been canonicalized. */
315 region_model::operator== (const region_model
&other
) const
317 /* We can only compare instances that use the same manager. */
318 gcc_assert (m_mgr
== other
.m_mgr
);
320 if (m_store
!= other
.m_store
)
323 if (*m_constraints
!= *other
.m_constraints
)
326 if (m_current_frame
!= other
.m_current_frame
)
329 if (m_dynamic_extents
!= other
.m_dynamic_extents
)
332 gcc_checking_assert (hash () == other
.hash ());
337 /* Generate a hash value for this region_model. */
340 region_model::hash () const
342 hashval_t result
= m_store
.hash ();
343 result
^= m_constraints
->hash ();
347 /* Dump a representation of this model to PP, showing the
348 stack, the store, and any constraints.
349 Use SIMPLE to control how svalues and regions are printed. */
352 region_model::dump_to_pp (pretty_printer
*pp
, bool simple
,
353 bool multiline
) const
356 pp_printf (pp
, "stack depth: %i", get_stack_depth ());
360 pp_string (pp
, " {");
361 for (const frame_region
*iter_frame
= m_current_frame
; iter_frame
;
362 iter_frame
= iter_frame
->get_calling_frame ())
366 else if (iter_frame
!= m_current_frame
)
367 pp_string (pp
, ", ");
368 pp_printf (pp
, "frame (index %i): ", iter_frame
->get_index ());
369 iter_frame
->dump_to_pp (pp
, simple
);
378 pp_string (pp
, ", {");
379 m_store
.dump_to_pp (pp
, simple
, multiline
,
380 m_mgr
->get_store_manager ());
384 /* Dump constraints. */
385 pp_string (pp
, "constraint_manager:");
389 pp_string (pp
, " {");
390 m_constraints
->dump_to_pp (pp
, multiline
);
394 /* Dump sizes of dynamic regions, if any are known. */
395 if (!m_dynamic_extents
.is_empty ())
397 pp_string (pp
, "dynamic_extents:");
398 m_dynamic_extents
.dump_to_pp (pp
, simple
, multiline
);
402 /* Dump a representation of this model to FILE. */
405 region_model::dump (FILE *fp
, bool simple
, bool multiline
) const
408 pp_format_decoder (&pp
) = default_tree_printer
;
409 pp_show_color (&pp
) = pp_show_color (global_dc
->printer
);
410 pp
.buffer
->stream
= fp
;
411 dump_to_pp (&pp
, simple
, multiline
);
416 /* Dump a multiline representation of this model to stderr. */
419 region_model::dump (bool simple
) const
421 dump (stderr
, simple
, true);
424 /* Dump a multiline representation of this model to stderr. */
427 region_model::debug () const
432 /* Assert that this object is valid. */
435 region_model::validate () const
440 /* Canonicalize the store and constraints, to maximize the chance of
441 equality between region_model instances. */
444 region_model::canonicalize ()
446 m_store
.canonicalize (m_mgr
->get_store_manager ());
447 m_constraints
->canonicalize ();
450 /* Return true if this region_model is in canonical form. */
453 region_model::canonicalized_p () const
455 region_model
copy (*this);
456 copy
.canonicalize ();
457 return *this == copy
;
460 /* See the comment for store::loop_replay_fixup. */
463 region_model::loop_replay_fixup (const region_model
*dst_state
)
465 m_store
.loop_replay_fixup (dst_state
->get_store (), m_mgr
);
468 /* A subclass of pending_diagnostic for complaining about uses of
471 class poisoned_value_diagnostic
472 : public pending_diagnostic_subclass
<poisoned_value_diagnostic
>
475 poisoned_value_diagnostic (tree expr
, enum poison_kind pkind
,
476 const region
*src_region
,
478 : m_expr (expr
), m_pkind (pkind
),
479 m_src_region (src_region
),
480 m_check_expr (check_expr
)
483 const char *get_kind () const final override
{ return "poisoned_value_diagnostic"; }
485 bool use_of_uninit_p () const final override
487 return m_pkind
== POISON_KIND_UNINIT
;
490 bool operator== (const poisoned_value_diagnostic
&other
) const
492 return (m_expr
== other
.m_expr
493 && m_pkind
== other
.m_pkind
494 && m_src_region
== other
.m_src_region
);
497 int get_controlling_option () const final override
503 case POISON_KIND_UNINIT
:
504 return OPT_Wanalyzer_use_of_uninitialized_value
;
505 case POISON_KIND_FREED
:
506 case POISON_KIND_DELETED
:
507 return OPT_Wanalyzer_use_after_free
;
508 case POISON_KIND_POPPED_STACK
:
509 return OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame
;
513 bool terminate_path_p () const final override
{ return true; }
515 bool emit (rich_location
*rich_loc
, logger
*) final override
521 case POISON_KIND_UNINIT
:
523 diagnostic_metadata m
;
524 m
.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
525 return warning_meta (rich_loc
, m
, get_controlling_option (),
526 "use of uninitialized value %qE",
530 case POISON_KIND_FREED
:
532 diagnostic_metadata m
;
533 m
.add_cwe (416); /* "CWE-416: Use After Free". */
534 return warning_meta (rich_loc
, m
, get_controlling_option (),
535 "use after %<free%> of %qE",
539 case POISON_KIND_DELETED
:
541 diagnostic_metadata m
;
542 m
.add_cwe (416); /* "CWE-416: Use After Free". */
543 return warning_meta (rich_loc
, m
, get_controlling_option (),
544 "use after %<delete%> of %qE",
548 case POISON_KIND_POPPED_STACK
:
550 /* TODO: which CWE? */
552 (rich_loc
, get_controlling_option (),
553 "dereferencing pointer %qE to within stale stack frame",
560 label_text
describe_final_event (const evdesc::final_event
&ev
) final override
566 case POISON_KIND_UNINIT
:
567 return ev
.formatted_print ("use of uninitialized value %qE here",
569 case POISON_KIND_FREED
:
570 return ev
.formatted_print ("use after %<free%> of %qE here",
572 case POISON_KIND_DELETED
:
573 return ev
.formatted_print ("use after %<delete%> of %qE here",
575 case POISON_KIND_POPPED_STACK
:
576 return ev
.formatted_print
577 ("dereferencing pointer %qE to within stale stack frame",
582 void mark_interesting_stuff (interesting_t
*interest
) final override
585 interest
->add_region_creation (m_src_region
);
588 /* Attempt to suppress false positives.
589 Reject paths where the value of the underlying region isn't poisoned.
590 This can happen due to state merging when exploring the exploded graph,
591 where the more precise analysis during feasibility analysis finds that
592 the region is in fact valid.
593 To do this we need to get the value from the fgraph. Unfortunately
594 we can't simply query the state of m_src_region (from the enode),
595 since it might be a different region in the fnode state (e.g. with
596 heap-allocated regions, the numbering could be different).
597 Hence we access m_check_expr, if available. */
599 bool check_valid_fpath_p (const feasible_node
&fnode
,
600 const gimple
*emission_stmt
)
606 /* We've reached the enode, but not necessarily the right function_point.
607 Try to get the state at the correct stmt. */
608 region_model
emission_model (fnode
.get_model ().get_manager());
609 if (!fnode
.get_state_at_stmt (emission_stmt
, &emission_model
))
610 /* Couldn't get state; accept this diagnostic. */
613 const svalue
*fsval
= emission_model
.get_rvalue (m_check_expr
, NULL
);
614 /* Check to see if the expr is also poisoned in FNODE (and in the
616 const poisoned_svalue
* fspval
= fsval
->dyn_cast_poisoned_svalue ();
619 if (fspval
->get_poison_kind () != m_pkind
)
626 enum poison_kind m_pkind
;
627 const region
*m_src_region
;
631 /* A subclass of pending_diagnostic for complaining about shifts
632 by negative counts. */
634 class shift_count_negative_diagnostic
635 : public pending_diagnostic_subclass
<shift_count_negative_diagnostic
>
638 shift_count_negative_diagnostic (const gassign
*assign
, tree count_cst
)
639 : m_assign (assign
), m_count_cst (count_cst
)
642 const char *get_kind () const final override
644 return "shift_count_negative_diagnostic";
647 bool operator== (const shift_count_negative_diagnostic
&other
) const
649 return (m_assign
== other
.m_assign
650 && same_tree_p (m_count_cst
, other
.m_count_cst
));
653 int get_controlling_option () const final override
655 return OPT_Wanalyzer_shift_count_negative
;
658 bool emit (rich_location
*rich_loc
, logger
*) final override
660 return warning_at (rich_loc
, get_controlling_option (),
661 "shift by negative count (%qE)", m_count_cst
);
664 label_text
describe_final_event (const evdesc::final_event
&ev
) final override
666 return ev
.formatted_print ("shift by negative amount here (%qE)", m_count_cst
);
670 const gassign
*m_assign
;
674 /* A subclass of pending_diagnostic for complaining about shifts
675 by counts >= the width of the operand type. */
677 class shift_count_overflow_diagnostic
678 : public pending_diagnostic_subclass
<shift_count_overflow_diagnostic
>
681 shift_count_overflow_diagnostic (const gassign
*assign
,
682 int operand_precision
,
684 : m_assign (assign
), m_operand_precision (operand_precision
),
685 m_count_cst (count_cst
)
688 const char *get_kind () const final override
690 return "shift_count_overflow_diagnostic";
693 bool operator== (const shift_count_overflow_diagnostic
&other
) const
695 return (m_assign
== other
.m_assign
696 && m_operand_precision
== other
.m_operand_precision
697 && same_tree_p (m_count_cst
, other
.m_count_cst
));
700 int get_controlling_option () const final override
702 return OPT_Wanalyzer_shift_count_overflow
;
705 bool emit (rich_location
*rich_loc
, logger
*) final override
707 return warning_at (rich_loc
, get_controlling_option (),
708 "shift by count (%qE) >= precision of type (%qi)",
709 m_count_cst
, m_operand_precision
);
712 label_text
describe_final_event (const evdesc::final_event
&ev
) final override
714 return ev
.formatted_print ("shift by count %qE here", m_count_cst
);
718 const gassign
*m_assign
;
719 int m_operand_precision
;
723 /* If ASSIGN is a stmt that can be modelled via
724 set_value (lhs_reg, SVALUE, CTXT)
725 for some SVALUE, get the SVALUE.
726 Otherwise return NULL. */
729 region_model::get_gassign_result (const gassign
*assign
,
730 region_model_context
*ctxt
)
732 tree lhs
= gimple_assign_lhs (assign
);
734 if (gimple_has_volatile_ops (assign
)
735 && !gimple_clobber_p (assign
))
737 conjured_purge
p (this, ctxt
);
738 return m_mgr
->get_or_create_conjured_svalue (TREE_TYPE (lhs
),
740 get_lvalue (lhs
, ctxt
),
744 tree rhs1
= gimple_assign_rhs1 (assign
);
745 enum tree_code op
= gimple_assign_rhs_code (assign
);
751 case POINTER_PLUS_EXPR
:
753 /* e.g. "_1 = a_10(D) + 12;" */
755 tree offset
= gimple_assign_rhs2 (assign
);
757 const svalue
*ptr_sval
= get_rvalue (ptr
, ctxt
);
758 const svalue
*offset_sval
= get_rvalue (offset
, ctxt
);
759 /* Quoting tree.def, "the second operand [of a POINTER_PLUS_EXPR]
760 is an integer of type sizetype". */
761 offset_sval
= m_mgr
->get_or_create_cast (size_type_node
, offset_sval
);
763 const svalue
*sval_binop
764 = m_mgr
->get_or_create_binop (TREE_TYPE (lhs
), op
,
765 ptr_sval
, offset_sval
);
770 case POINTER_DIFF_EXPR
:
772 /* e.g. "_1 = p_2(D) - q_3(D);". */
773 tree rhs2
= gimple_assign_rhs2 (assign
);
774 const svalue
*rhs1_sval
= get_rvalue (rhs1
, ctxt
);
775 const svalue
*rhs2_sval
= get_rvalue (rhs2
, ctxt
);
777 // TODO: perhaps fold to zero if they're known to be equal?
779 const svalue
*sval_binop
780 = m_mgr
->get_or_create_binop (TREE_TYPE (lhs
), op
,
781 rhs1_sval
, rhs2_sval
);
786 /* Assignments of the form
787 set_value (lvalue (LHS), rvalue (EXPR))
789 We already have the lvalue for the LHS above, as "lhs_reg". */
790 case ADDR_EXPR
: /* LHS = &RHS; */
792 case COMPONENT_REF
: /* LHS = op0.op1; */
799 case SSA_NAME
: /* LHS = VAR; */
800 case VAR_DECL
: /* LHS = VAR; */
801 case PARM_DECL
:/* LHS = VAR; */
804 return get_rvalue (rhs1
, ctxt
);
814 case VIEW_CONVERT_EXPR
:
817 const svalue
*rhs_sval
= get_rvalue (rhs1
, ctxt
);
818 const svalue
*sval_unaryop
819 = m_mgr
->get_or_create_unaryop (TREE_TYPE (lhs
), op
, rhs_sval
);
832 tree rhs2
= gimple_assign_rhs2 (assign
);
834 const svalue
*rhs1_sval
= get_rvalue (rhs1
, ctxt
);
835 const svalue
*rhs2_sval
= get_rvalue (rhs2
, ctxt
);
837 if (TREE_TYPE (lhs
) == boolean_type_node
)
839 /* Consider constraints between svalues. */
840 tristate t
= eval_condition (rhs1_sval
, op
, rhs2_sval
);
842 return m_mgr
->get_or_create_constant_svalue
843 (t
.is_true () ? boolean_true_node
: boolean_false_node
);
846 /* Otherwise, generate a symbolic binary op. */
847 const svalue
*sval_binop
848 = m_mgr
->get_or_create_binop (TREE_TYPE (lhs
), op
,
849 rhs1_sval
, rhs2_sval
);
857 case MULT_HIGHPART_EXPR
:
880 tree rhs2
= gimple_assign_rhs2 (assign
);
882 const svalue
*rhs1_sval
= get_rvalue (rhs1
, ctxt
);
883 const svalue
*rhs2_sval
= get_rvalue (rhs2
, ctxt
);
885 if (ctxt
&& (op
== LSHIFT_EXPR
|| op
== RSHIFT_EXPR
))
887 /* "INT34-C. Do not shift an expression by a negative number of bits
888 or by greater than or equal to the number of bits that exist in
890 if (const tree rhs2_cst
= rhs2_sval
->maybe_get_constant ())
891 if (TREE_CODE (rhs2_cst
) == INTEGER_CST
892 && INTEGRAL_TYPE_P (TREE_TYPE (rhs1
)))
894 if (tree_int_cst_sgn (rhs2_cst
) < 0)
896 (make_unique
<shift_count_negative_diagnostic
>
898 else if (compare_tree_int (rhs2_cst
,
899 TYPE_PRECISION (TREE_TYPE (rhs1
)))
902 (make_unique
<shift_count_overflow_diagnostic
>
904 int (TYPE_PRECISION (TREE_TYPE (rhs1
))),
909 const svalue
*sval_binop
910 = m_mgr
->get_or_create_binop (TREE_TYPE (lhs
), op
,
911 rhs1_sval
, rhs2_sval
);
915 /* Vector expressions. In theory we could implement these elementwise,
916 but for now, simply return unknown values. */
917 case VEC_DUPLICATE_EXPR
:
918 case VEC_SERIES_EXPR
:
921 case VEC_WIDEN_MULT_HI_EXPR
:
922 case VEC_WIDEN_MULT_LO_EXPR
:
923 case VEC_WIDEN_MULT_EVEN_EXPR
:
924 case VEC_WIDEN_MULT_ODD_EXPR
:
925 case VEC_UNPACK_HI_EXPR
:
926 case VEC_UNPACK_LO_EXPR
:
927 case VEC_UNPACK_FLOAT_HI_EXPR
:
928 case VEC_UNPACK_FLOAT_LO_EXPR
:
929 case VEC_UNPACK_FIX_TRUNC_HI_EXPR
:
930 case VEC_UNPACK_FIX_TRUNC_LO_EXPR
:
931 case VEC_PACK_TRUNC_EXPR
:
932 case VEC_PACK_SAT_EXPR
:
933 case VEC_PACK_FIX_TRUNC_EXPR
:
934 case VEC_PACK_FLOAT_EXPR
:
935 case VEC_WIDEN_LSHIFT_HI_EXPR
:
936 case VEC_WIDEN_LSHIFT_LO_EXPR
:
937 return m_mgr
->get_or_create_unknown_svalue (TREE_TYPE (lhs
));
941 /* Workaround for discarding certain false positives from
942 -Wanalyzer-use-of-uninitialized-value
944 ((A OR-IF B) OR-IF C)
946 ((A AND-IF B) AND-IF C)
947 where evaluating B is redundant, but could involve simple accesses of
948 uninitialized locals.
950 When optimization is turned on the FE can immediately fold compound
951 conditionals. Specifically, c_parser_condition parses this condition:
952 ((A OR-IF B) OR-IF C)
953 and calls c_fully_fold on the condition.
954 Within c_fully_fold, fold_truth_andor is called, which bails when
955 optimization is off, but if any optimization is turned on can convert the
956 ((A OR-IF B) OR-IF C)
959 for sufficiently simple B
960 i.e. the inner OR-IF becomes an OR.
961 At gimplification time the inner OR becomes BIT_IOR_EXPR (in gimplify_expr),
962 giving this for the inner condition:
965 thus effectively synthesizing a redundant access of B when optimization
966 is turned on, when compared to:
967 if (A) goto L1; else goto L4;
968 L1: if (B) goto L2; else goto L4;
969 L2: if (C) goto L3; else goto L4;
970 for the unoptimized case.
972 Return true if CTXT appears to be handling such a short-circuitable stmt,
973 such as the def-stmt for B for the:
975 case above, for the case where A is true and thus B would have been
976 short-circuited without optimization, using MODEL for the value of A. */
979 within_short_circuited_stmt_p (const region_model
*model
,
980 const gassign
*assign_stmt
)
982 /* We must have an assignment to a temporary of _Bool type. */
983 tree lhs
= gimple_assign_lhs (assign_stmt
);
984 if (TREE_TYPE (lhs
) != boolean_type_node
)
986 if (TREE_CODE (lhs
) != SSA_NAME
)
988 if (SSA_NAME_VAR (lhs
) != NULL_TREE
)
991 /* The temporary bool must be used exactly once: as the second arg of
992 a BIT_IOR_EXPR or BIT_AND_EXPR. */
993 use_operand_p use_op
;
995 if (!single_imm_use (lhs
, &use_op
, &use_stmt
))
997 const gassign
*use_assign
= dyn_cast
<const gassign
*> (use_stmt
);
1000 enum tree_code op
= gimple_assign_rhs_code (use_assign
);
1001 if (!(op
== BIT_IOR_EXPR
||op
== BIT_AND_EXPR
))
1003 if (!(gimple_assign_rhs1 (use_assign
) != lhs
1004 && gimple_assign_rhs2 (use_assign
) == lhs
))
1007 /* The first arg of the bitwise stmt must have a known value in MODEL
1008 that implies that the value of the second arg doesn't matter, i.e.
1009 1 for bitwise or, 0 for bitwise and. */
1010 tree other_arg
= gimple_assign_rhs1 (use_assign
);
1011 /* Use a NULL ctxt here to avoid generating warnings. */
1012 const svalue
*other_arg_sval
= model
->get_rvalue (other_arg
, NULL
);
1013 tree other_arg_cst
= other_arg_sval
->maybe_get_constant ();
1021 if (zerop (other_arg_cst
))
1025 if (!zerop (other_arg_cst
))
1030 /* All tests passed. We appear to be in a stmt that generates a boolean
1031 temporary with a value that won't matter. */
1035 /* Workaround for discarding certain false positives from
1036 -Wanalyzer-use-of-uninitialized-value
1037 seen with -ftrivial-auto-var-init=.
1039 -ftrivial-auto-var-init= will generate calls to IFN_DEFERRED_INIT.
1041 If the address of the var is taken, gimplification will give us
1044 _1 = .DEFERRED_INIT (4, 2, &"len"[0]);
1047 The result of DEFERRED_INIT will be an uninit value; we don't
1048 want to emit a false positive for "len = _1;"
1050 Return true if ASSIGN_STMT is such a stmt. */
1053 due_to_ifn_deferred_init_p (const gassign
*assign_stmt
)
1056 /* We must have an assignment to a decl from an SSA name that's the
1057 result of a IFN_DEFERRED_INIT call. */
1058 if (gimple_assign_rhs_code (assign_stmt
) != SSA_NAME
)
1060 tree lhs
= gimple_assign_lhs (assign_stmt
);
1061 if (TREE_CODE (lhs
) != VAR_DECL
)
1063 tree rhs
= gimple_assign_rhs1 (assign_stmt
);
1064 if (TREE_CODE (rhs
) != SSA_NAME
)
1066 const gimple
*def_stmt
= SSA_NAME_DEF_STMT (rhs
);
1067 const gcall
*call
= dyn_cast
<const gcall
*> (def_stmt
);
1070 if (gimple_call_internal_p (call
)
1071 && gimple_call_internal_fn (call
) == IFN_DEFERRED_INIT
)
1076 /* Check for SVAL being poisoned, adding a warning to CTXT.
1077 Return SVAL, or, if a warning is added, another value, to avoid
1078 repeatedly complaining about the same poisoned value in followup code.
1079 SRC_REGION is a hint about where SVAL came from, and can be NULL. */
1082 region_model::check_for_poison (const svalue
*sval
,
1084 const region
*src_region
,
1085 region_model_context
*ctxt
) const
1090 if (const poisoned_svalue
*poisoned_sval
= sval
->dyn_cast_poisoned_svalue ())
1092 enum poison_kind pkind
= poisoned_sval
->get_poison_kind ();
1094 /* Ignore uninitialized uses of empty types; there's nothing
1096 if (pkind
== POISON_KIND_UNINIT
1097 && sval
->get_type ()
1098 && is_empty_type (sval
->get_type ()))
1101 if (pkind
== POISON_KIND_UNINIT
)
1102 if (const gimple
*curr_stmt
= ctxt
->get_stmt ())
1103 if (const gassign
*assign_stmt
1104 = dyn_cast
<const gassign
*> (curr_stmt
))
1106 /* Special case to avoid certain false positives. */
1107 if (within_short_circuited_stmt_p (this, assign_stmt
))
1110 /* Special case to avoid false positive on
1111 -ftrivial-auto-var-init=. */
1112 if (due_to_ifn_deferred_init_p (assign_stmt
))
1116 /* If we have an SSA name for a temporary, we don't want to print
1118 Poisoned values are shared by type, and so we can't reconstruct
1119 the tree other than via the def stmts, using
1120 fixup_tree_for_diagnostic. */
1121 tree diag_arg
= fixup_tree_for_diagnostic (expr
);
1122 if (src_region
== NULL
&& pkind
== POISON_KIND_UNINIT
)
1123 src_region
= get_region_for_poisoned_expr (expr
);
1125 /* Can we reliably get the poisoned value from "expr"?
1126 This is for use by poisoned_value_diagnostic::check_valid_fpath_p.
1127 Unfortunately, we might not have a reliable value for EXPR.
1128 Hence we only query its value now, and only use it if we get the
1129 poisoned value back again. */
1130 tree check_expr
= expr
;
1131 const svalue
*foo_sval
= get_rvalue (expr
, NULL
);
1132 if (foo_sval
== sval
)
1136 if (ctxt
->warn (make_unique
<poisoned_value_diagnostic
> (diag_arg
,
1141 /* We only want to report use of a poisoned value at the first
1142 place it gets used; return an unknown value to avoid generating
1143 a chain of followup warnings. */
1144 sval
= m_mgr
->get_or_create_unknown_svalue (sval
->get_type ());
1153 /* Attempt to get a region for describing EXPR, the source of region of
1154 a poisoned_svalue for use in a poisoned_value_diagnostic.
1155 Return NULL if there is no good region to use. */
1158 region_model::get_region_for_poisoned_expr (tree expr
) const
1160 if (TREE_CODE (expr
) == SSA_NAME
)
1162 tree decl
= SSA_NAME_VAR (expr
);
1163 if (decl
&& DECL_P (decl
))
1168 return get_lvalue (expr
, NULL
);
1171 /* Update this model for the ASSIGN stmt, using CTXT to report any
1175 region_model::on_assignment (const gassign
*assign
, region_model_context
*ctxt
)
1177 tree lhs
= gimple_assign_lhs (assign
);
1178 tree rhs1
= gimple_assign_rhs1 (assign
);
1180 const region
*lhs_reg
= get_lvalue (lhs
, ctxt
);
1182 /* Most assignments are handled by:
1183 set_value (lhs_reg, SVALUE, CTXT)
1185 if (const svalue
*sval
= get_gassign_result (assign
, ctxt
))
1187 tree expr
= get_diagnostic_tree_for_gassign (assign
);
1188 check_for_poison (sval
, expr
, NULL
, ctxt
);
1189 set_value (lhs_reg
, sval
, ctxt
);
1193 enum tree_code op
= gimple_assign_rhs_code (assign
);
1199 sorry_at (assign
->location
, "unhandled assignment op: %qs",
1200 get_tree_code_name (op
));
1201 const svalue
*unknown_sval
1202 = m_mgr
->get_or_create_unknown_svalue (TREE_TYPE (lhs
));
1203 set_value (lhs_reg
, unknown_sval
, ctxt
);
1209 if (TREE_CLOBBER_P (rhs1
))
1211 /* e.g. "x ={v} {CLOBBER};" */
1212 clobber_region (lhs_reg
);
1216 /* Any CONSTRUCTOR that survives to this point is either
1217 just a zero-init of everything, or a vector. */
1218 if (!CONSTRUCTOR_NO_CLEARING (rhs1
))
1219 zero_fill_region (lhs_reg
, ctxt
);
1223 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs1
), ix
, index
, val
)
1225 gcc_assert (TREE_CODE (TREE_TYPE (rhs1
)) == VECTOR_TYPE
);
1227 index
= build_int_cst (integer_type_node
, ix
);
1228 gcc_assert (TREE_CODE (index
) == INTEGER_CST
);
1229 const svalue
*index_sval
1230 = m_mgr
->get_or_create_constant_svalue (index
);
1231 gcc_assert (index_sval
);
1232 const region
*sub_reg
1233 = m_mgr
->get_element_region (lhs_reg
,
1236 const svalue
*val_sval
= get_rvalue (val
, ctxt
);
1237 set_value (sub_reg
, val_sval
, ctxt
);
1245 /* e.g. "struct s2 x = {{'A', 'B', 'C', 'D'}};". */
1246 const svalue
*rhs_sval
= get_rvalue (rhs1
, ctxt
);
1247 m_store
.set_value (m_mgr
->get_store_manager(), lhs_reg
, rhs_sval
,
1248 ctxt
? ctxt
->get_uncertainty () : NULL
);
1254 /* Handle the pre-sm-state part of STMT, modifying this object in-place.
1255 Write true to *OUT_UNKNOWN_SIDE_EFFECTS if the stmt has unknown
1259 region_model::on_stmt_pre (const gimple
*stmt
,
1260 bool *out_unknown_side_effects
,
1261 region_model_context
*ctxt
)
1263 switch (gimple_code (stmt
))
1266 /* No-op for now. */
1271 const gassign
*assign
= as_a
<const gassign
*> (stmt
);
1272 on_assignment (assign
, ctxt
);
1278 const gasm
*asm_stmt
= as_a
<const gasm
*> (stmt
);
1279 on_asm_stmt (asm_stmt
, ctxt
);
1285 /* Track whether we have a gcall to a function that's not recognized by
1286 anything, for which we don't have a function body, or for which we
1287 don't know the fndecl. */
1288 const gcall
*call
= as_a
<const gcall
*> (stmt
);
1289 *out_unknown_side_effects
= on_call_pre (call
, ctxt
);
1295 const greturn
*return_
= as_a
<const greturn
*> (stmt
);
1296 on_return (return_
, ctxt
);
1302 /* Given a call CD with function attribute FORMAT_ATTR, check that the
1303 format arg to the call is a valid null-terminated string. */
1306 region_model::check_call_format_attr (const call_details
&cd
,
1307 tree format_attr
) const
1309 /* We assume that FORMAT_ATTR has already been validated. */
1311 /* arg0 of the attribute should be kind of format strings
1312 that this function expects (e.g. "printf"). */
1313 const tree arg0_tree_list
= TREE_VALUE (format_attr
);
1314 if (!arg0_tree_list
)
1317 /* arg1 of the attribute should be the 1-based parameter index
1318 to treat as the format string. */
1319 const tree arg1_tree_list
= TREE_CHAIN (arg0_tree_list
);
1320 if (!arg1_tree_list
)
1322 const tree arg1_value
= TREE_VALUE (arg1_tree_list
);
1326 unsigned format_arg_idx
= TREE_INT_CST_LOW (arg1_value
) - 1;
1327 if (cd
.num_args () <= format_arg_idx
)
1330 /* Subclass of annotating_context that
1331 adds a note about the format attr to any saved diagnostics. */
1332 class annotating_ctxt
: public annotating_context
1335 annotating_ctxt (const call_details
&cd
,
1336 unsigned fmt_param_idx
)
1337 : annotating_context (cd
.get_ctxt ()),
1339 m_fmt_param_idx (fmt_param_idx
)
1342 void add_annotations () final override
1344 class reason_format_attr
1345 : public pending_note_subclass
<reason_format_attr
>
1348 reason_format_attr (const call_arg_details
&arg_details
)
1349 : m_arg_details (arg_details
)
1353 const char *get_kind () const final override
1355 return "reason_format_attr";
1358 void emit () const final override
1360 inform (DECL_SOURCE_LOCATION (m_arg_details
.m_called_fndecl
),
1361 "parameter %i of %qD marked as a format string"
1362 " via %qs attribute",
1363 m_arg_details
.m_arg_idx
+ 1, m_arg_details
.m_called_fndecl
,
1367 bool operator== (const reason_format_attr
&other
) const
1369 return m_arg_details
== other
.m_arg_details
;
1373 call_arg_details m_arg_details
;
1376 call_arg_details
arg_details (m_cd
, m_fmt_param_idx
);
1377 add_note (make_unique
<reason_format_attr
> (arg_details
));
1380 const call_details
&m_cd
;
1381 unsigned m_fmt_param_idx
;
1384 annotating_ctxt
my_ctxt (cd
, format_arg_idx
);
1385 call_details
my_cd (cd
, &my_ctxt
);
1386 my_cd
.check_for_null_terminated_string_arg (format_arg_idx
);
1389 /* Ensure that all arguments at the call described by CD are checked
1390 for poisoned values, by calling get_rvalue on each argument.
1392 Check that calls to functions with "format" attribute have valid
1393 null-terminated strings for their format argument. */
1396 region_model::check_call_args (const call_details
&cd
) const
1398 for (unsigned arg_idx
= 0; arg_idx
< cd
.num_args (); arg_idx
++)
1399 cd
.get_arg_svalue (arg_idx
);
1401 /* Handle attribute "format". */
1402 if (tree format_attr
= cd
.lookup_function_attribute ("format"))
1403 check_call_format_attr (cd
, format_attr
);
1406 /* Update this model for an outcome of a call that returns a specific
1408 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1409 the state-merger code from merging success and failure outcomes. */
1412 region_model::update_for_int_cst_return (const call_details
&cd
,
1416 if (!cd
.get_lhs_type ())
1418 if (TREE_CODE (cd
.get_lhs_type ()) != INTEGER_TYPE
)
1420 const svalue
*result
1421 = m_mgr
->get_or_create_int_cst (cd
.get_lhs_type (), retval
);
1423 result
= m_mgr
->get_or_create_unmergeable (result
);
1424 set_value (cd
.get_lhs_region (), result
, cd
.get_ctxt ());
1427 /* Update this model for an outcome of a call that returns zero.
1428 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1429 the state-merger code from merging success and failure outcomes. */
1432 region_model::update_for_zero_return (const call_details
&cd
,
1435 update_for_int_cst_return (cd
, 0, unmergeable
);
1438 /* Update this model for an outcome of a call that returns non-zero.
1439 Specifically, assign an svalue to the LHS, and add a constraint that
1440 that svalue is non-zero. */
1443 region_model::update_for_nonzero_return (const call_details
&cd
)
1445 if (!cd
.get_lhs_type ())
1447 if (TREE_CODE (cd
.get_lhs_type ()) != INTEGER_TYPE
)
1449 cd
.set_any_lhs_with_defaults ();
1451 = m_mgr
->get_or_create_int_cst (cd
.get_lhs_type (), 0);
1452 const svalue
*result
1453 = get_store_value (cd
.get_lhs_region (), cd
.get_ctxt ());
1454 add_constraint (result
, NE_EXPR
, zero
, cd
.get_ctxt ());
1457 /* Subroutine of region_model::maybe_get_copy_bounds.
1458 The Linux kernel commonly uses
1459 min_t([unsigned] long, VAR, sizeof(T));
1460 to set an upper bound on the size of a copy_to_user.
1461 Attempt to simplify such sizes by trying to get the upper bound as a
1463 Return the simplified svalue if possible, or NULL otherwise. */
1465 static const svalue
*
1466 maybe_simplify_upper_bound (const svalue
*num_bytes_sval
,
1467 region_model_manager
*mgr
)
1469 tree type
= num_bytes_sval
->get_type ();
1470 while (const svalue
*raw
= num_bytes_sval
->maybe_undo_cast ())
1471 num_bytes_sval
= raw
;
1472 if (const binop_svalue
*binop_sval
= num_bytes_sval
->dyn_cast_binop_svalue ())
1473 if (binop_sval
->get_op () == MIN_EXPR
)
1474 if (binop_sval
->get_arg1 ()->get_kind () == SK_CONSTANT
)
1476 return mgr
->get_or_create_cast (type
, binop_sval
->get_arg1 ());
1477 /* TODO: we might want to also capture the constraint
1478 when recording the diagnostic, or note that we're using
1484 /* Attempt to get an upper bound for the size of a copy when simulating a
1487 NUM_BYTES_SVAL is the symbolic value for the size of the copy.
1488 Use it if it's constant, otherwise try to simplify it. Failing
1489 that, use the size of SRC_REG if constant.
1491 Return a symbolic value for an upper limit on the number of bytes
1492 copied, or NULL if no such value could be determined. */
1495 region_model::maybe_get_copy_bounds (const region
*src_reg
,
1496 const svalue
*num_bytes_sval
)
1498 if (num_bytes_sval
->maybe_get_constant ())
1499 return num_bytes_sval
;
1501 if (const svalue
*simplified
1502 = maybe_simplify_upper_bound (num_bytes_sval
, m_mgr
))
1503 num_bytes_sval
= simplified
;
1505 if (num_bytes_sval
->maybe_get_constant ())
1506 return num_bytes_sval
;
1508 /* For now, try just guessing the size as the capacity of the
1509 base region of the src.
1510 This is a hack; we might get too large a value. */
1511 const region
*src_base_reg
= src_reg
->get_base_region ();
1512 num_bytes_sval
= get_capacity (src_base_reg
);
1514 if (num_bytes_sval
->maybe_get_constant ())
1515 return num_bytes_sval
;
1517 /* Non-constant: give up. */
1521 /* Get any known_function for FNDECL for call CD.
1523 The call must match all assumptions made by the known_function (such as
1524 e.g. "argument 1's type must be a pointer type").
1526 Return NULL if no known_function is found, or it does not match the
1529 const known_function
*
1530 region_model::get_known_function (tree fndecl
, const call_details
&cd
) const
1532 known_function_manager
*known_fn_mgr
= m_mgr
->get_known_function_manager ();
1533 return known_fn_mgr
->get_match (fndecl
, cd
);
1536 /* Get any known_function for IFN, or NULL. */
1538 const known_function
*
1539 region_model::get_known_function (enum internal_fn ifn
) const
1541 known_function_manager
*known_fn_mgr
= m_mgr
->get_known_function_manager ();
1542 return known_fn_mgr
->get_internal_fn (ifn
);
1545 /* Get any builtin_known_function for CALL and emit any warning to CTXT
1548 The call must match all assumptions made by the known_function (such as
1549 e.g. "argument 1's type must be a pointer type").
1551 Return NULL if no builtin_known_function is found, or it does
1552 not match the assumption(s).
1554 Internally calls get_known_function to find a known_function and cast it
1555 to a builtin_known_function.
1557 For instance, calloc is a C builtin, defined in gcc/builtins.def
1558 by the DEF_LIB_BUILTIN macro. Such builtins are recognized by the
1559 analyzer by their name, so that even in C++ or if the user redeclares
1560 them but mismatch their signature, they are still recognized as builtins.
1562 Cases when a supposed builtin is not flagged as one by the FE:
1564 The C++ FE does not recognize calloc as a builtin if it has not been
1565 included from a standard header, but the C FE does. Hence in C++ if
1566 CALL comes from a calloc and stdlib is not included,
1567 gcc/tree.h:fndecl_built_in_p (CALL) would be false.
1569 In C code, a __SIZE_TYPE__ calloc (__SIZE_TYPE__, __SIZE_TYPE__) user
1570 declaration has obviously a mismatching signature from the standard, and
1571 its function_decl tree won't be unified by
1572 gcc/c-decl.cc:match_builtin_function_types.
1574 Yet in both cases the analyzer should treat the calls as a builtin calloc
1575 so that extra attributes unspecified by the standard but added by GCC
1576 (e.g. sprintf attributes in gcc/builtins.def), useful for the detection of
1577 dangerous behavior, are indeed processed.
1579 Therefore for those cases when a "builtin flag" is not added by the FE,
1580 builtins' kf are derived from builtin_known_function, whose method
1581 builtin_known_function::builtin_decl returns the builtin's
1582 function_decl tree as defined in gcc/builtins.def, with all the extra
1585 const builtin_known_function
*
1586 region_model::get_builtin_kf (const gcall
*call
,
1587 region_model_context
*ctxt
/* = NULL */) const
1589 region_model
*mut_this
= const_cast <region_model
*> (this);
1590 tree callee_fndecl
= mut_this
->get_fndecl_for_call (call
, ctxt
);
1591 if (! callee_fndecl
)
1594 call_details
cd (call
, mut_this
, ctxt
);
1595 if (const known_function
*kf
= get_known_function (callee_fndecl
, cd
))
1596 return kf
->dyn_cast_builtin_kf ();
1601 /* Update this model for the CALL stmt, using CTXT to report any
1602 diagnostics - the first half.
1604 Updates to the region_model that should be made *before* sm-states
1605 are updated are done here; other updates to the region_model are done
1606 in region_model::on_call_post.
1608 Return true if the function call has unknown side effects (it wasn't
1609 recognized and we don't have a body for it, or are unable to tell which
1613 region_model::on_call_pre (const gcall
*call
, region_model_context
*ctxt
)
1615 call_details
cd (call
, this, ctxt
);
1617 /* Special-case for IFN_DEFERRED_INIT.
1618 We want to report uninitialized variables with -fanalyzer (treating
1619 -ftrivial-auto-var-init= as purely a mitigation feature).
1620 Handle IFN_DEFERRED_INIT by treating it as no-op: don't touch the
1621 lhs of the call, so that it is still uninitialized from the point of
1622 view of the analyzer. */
1623 if (gimple_call_internal_p (call
)
1624 && gimple_call_internal_fn (call
) == IFN_DEFERRED_INIT
)
1625 return false; /* No side effects. */
1627 /* Get svalues for all of the arguments at the callsite, to ensure that we
1628 complain about any uninitialized arguments. This might lead to
1629 duplicates if any of the handling below also looks up the svalues,
1630 but the deduplication code should deal with that. */
1632 check_call_args (cd
);
1634 tree callee_fndecl
= get_fndecl_for_call (call
, ctxt
);
1636 if (gimple_call_internal_p (call
))
1637 if (const known_function
*kf
1638 = get_known_function (gimple_call_internal_fn (call
)))
1640 kf
->impl_call_pre (cd
);
1641 return false; /* No further side effects. */
1646 cd
.set_any_lhs_with_defaults ();
1647 return true; /* Unknown side effects. */
1650 if (const known_function
*kf
= get_known_function (callee_fndecl
, cd
))
1652 kf
->impl_call_pre (cd
);
1653 return false; /* No further side effects. */
1656 cd
.set_any_lhs_with_defaults ();
1658 const int callee_fndecl_flags
= flags_from_decl_or_type (callee_fndecl
);
1659 if (callee_fndecl_flags
& (ECF_CONST
| ECF_PURE
))
1660 return false; /* No side effects. */
1662 if (fndecl_built_in_p (callee_fndecl
))
1663 return true; /* Unknown side effects. */
1665 if (!fndecl_has_gimple_body_p (callee_fndecl
))
1666 return true; /* Unknown side effects. */
1668 return false; /* No side effects. */
1671 /* Update this model for the CALL stmt, using CTXT to report any
1672 diagnostics - the second half.
1674 Updates to the region_model that should be made *after* sm-states
1675 are updated are done here; other updates to the region_model are done
1676 in region_model::on_call_pre.
1678 If UNKNOWN_SIDE_EFFECTS is true, also call handle_unrecognized_call
1682 region_model::on_call_post (const gcall
*call
,
1683 bool unknown_side_effects
,
1684 region_model_context
*ctxt
)
1686 if (tree callee_fndecl
= get_fndecl_for_call (call
, ctxt
))
1688 call_details
cd (call
, this, ctxt
);
1689 if (const known_function
*kf
= get_known_function (callee_fndecl
, cd
))
1691 kf
->impl_call_post (cd
);
1694 /* Was this fndecl referenced by
1695 __attribute__((malloc(FOO)))? */
1696 if (lookup_attribute ("*dealloc", DECL_ATTRIBUTES (callee_fndecl
)))
1698 impl_deallocation_call (cd
);
1703 if (unknown_side_effects
)
1704 handle_unrecognized_call (call
, ctxt
);
1707 /* Purge state involving SVAL from this region_model, using CTXT
1708 (if non-NULL) to purge other state in a program_state.
1710 For example, if we're at the def-stmt of an SSA name, then we need to
1711 purge any state for svalues that involve that SSA name. This avoids
1712 false positives in loops, since a symbolic value referring to the
1713 SSA name will be referring to the previous value of that SSA name.
1716 while ((e = hashmap_iter_next(&iter))) {
1717 struct oid2strbuf *e_strbuf = (struct oid2strbuf *)e;
1718 free (e_strbuf->value);
1720 at the def-stmt of e_8:
1721 e_8 = hashmap_iter_next (&iter);
1722 we should purge the "freed" state of:
1723 INIT_VAL(CAST_REG(‘struct oid2strbuf’, (*INIT_VAL(e_8))).value)
1724 which is the "e_strbuf->value" value from the previous iteration,
1725 or we will erroneously report a double-free - the "e_8" within it
1726 refers to the previous value. */
1729 region_model::purge_state_involving (const svalue
*sval
,
1730 region_model_context
*ctxt
)
1732 if (!sval
->can_have_associated_state_p ())
1734 m_store
.purge_state_involving (sval
, m_mgr
);
1735 m_constraints
->purge_state_involving (sval
);
1736 m_dynamic_extents
.purge_state_involving (sval
);
1738 ctxt
->purge_state_involving (sval
);
1741 /* A pending_note subclass for adding a note about an
1742 __attribute__((access, ...)) to a diagnostic. */
1744 class reason_attr_access
: public pending_note_subclass
<reason_attr_access
>
1747 reason_attr_access (tree callee_fndecl
, const attr_access
&access
)
1748 : m_callee_fndecl (callee_fndecl
),
1749 m_ptr_argno (access
.ptrarg
),
1750 m_access_str (TREE_STRING_POINTER (access
.to_external_string ()))
1754 const char *get_kind () const final override
{ return "reason_attr_access"; }
1756 void emit () const final override
1758 inform (DECL_SOURCE_LOCATION (m_callee_fndecl
),
1759 "parameter %i of %qD marked with attribute %qs",
1760 m_ptr_argno
+ 1, m_callee_fndecl
, m_access_str
);
1763 bool operator== (const reason_attr_access
&other
) const
1765 return (m_callee_fndecl
== other
.m_callee_fndecl
1766 && m_ptr_argno
== other
.m_ptr_argno
1767 && !strcmp (m_access_str
, other
.m_access_str
));
1771 tree m_callee_fndecl
;
1772 unsigned m_ptr_argno
;
1773 const char *m_access_str
;
1776 /* Check CALL a call to external function CALLEE_FNDECL based on
1777 any __attribute__ ((access, ....) on the latter, complaining to
1778 CTXT about any issues.
1780 Currently we merely call check_region_for_write on any regions
1781 pointed to by arguments marked with a "write_only" or "read_write"
1785 region_model::check_function_attr_access (const gcall
*call
,
1787 region_model_context
*ctxt
,
1788 rdwr_map
&rdwr_idx
) const
1791 gcc_assert (callee_fndecl
);
1794 tree fntype
= TREE_TYPE (callee_fndecl
);
1795 gcc_assert (fntype
);
1799 for (tree iter
= TYPE_ARG_TYPES (fntype
); iter
;
1800 iter
= TREE_CHAIN (iter
), ++argno
)
1802 const attr_access
* access
= rdwr_idx
.get (argno
);
1806 /* Ignore any duplicate entry in the map for the size argument. */
1807 if (access
->ptrarg
!= argno
)
1810 if (access
->mode
== access_write_only
1811 || access
->mode
== access_read_write
)
1813 /* Subclass of annotating_context that
1814 adds a note about the attr access to any saved diagnostics. */
1815 class annotating_ctxt
: public annotating_context
1818 annotating_ctxt (tree callee_fndecl
,
1819 const attr_access
&access
,
1820 region_model_context
*ctxt
)
1821 : annotating_context (ctxt
),
1822 m_callee_fndecl (callee_fndecl
),
1826 void add_annotations () final override
1828 add_note (make_unique
<reason_attr_access
>
1829 (m_callee_fndecl
, m_access
));
1832 tree m_callee_fndecl
;
1833 const attr_access
&m_access
;
1836 /* Use this ctxt below so that any diagnostics get the
1837 note added to them. */
1838 annotating_ctxt
my_ctxt (callee_fndecl
, *access
, ctxt
);
1840 tree ptr_tree
= gimple_call_arg (call
, access
->ptrarg
);
1841 const svalue
*ptr_sval
= get_rvalue (ptr_tree
, &my_ctxt
);
1842 const region
*reg
= deref_rvalue (ptr_sval
, ptr_tree
, &my_ctxt
);
1843 check_region_for_write (reg
, nullptr, &my_ctxt
);
1844 /* We don't use the size arg for now. */
1849 /* Subroutine of region_model::check_function_attr_null_terminated_string_arg,
1850 checking one instance of __attribute__((null_terminated_string_arg)). */
1854 check_one_function_attr_null_terminated_string_arg (const gcall
*call
,
1856 region_model_context
*ctxt
,
1861 gcc_assert (callee_fndecl
);
1865 tree arg
= TREE_VALUE (attr
);
1869 /* Convert from 1-based to 0-based index. */
1870 unsigned int arg_idx
= TREE_INT_CST_LOW (TREE_VALUE (arg
)) - 1;
1872 /* If there's also an "access" attribute on the ptr param
1873 for reading with a size param specified, then that size
1874 limits the size of the possible read from the pointer. */
1875 if (const attr_access
* access
= rdwr_idx
.get (arg_idx
))
1876 if ((access
->mode
== access_read_only
1877 || access
->mode
== access_read_write
)
1878 && access
->sizarg
!= UINT_MAX
)
1880 call_details
cd_checked (call
, this, ctxt
);
1881 const svalue
*limit_sval
1882 = cd_checked
.get_arg_svalue (access
->sizarg
);
1883 const svalue
*ptr_sval
1884 = cd_checked
.get_arg_svalue (arg_idx
);
1885 /* Try reading all of the bytes expressed by the size param,
1886 but without emitting warnings (via a null context). */
1887 const svalue
*limited_sval
1888 = read_bytes (deref_rvalue (ptr_sval
, NULL_TREE
, nullptr),
1892 if (limited_sval
->get_kind () == SK_POISONED
)
1894 /* Reading up to the truncation limit caused issues.
1895 Assume that the string is meant to be terminated
1896 before then, so perform a *checked* check for the
1898 check_for_null_terminated_string_arg (cd_checked
,
1903 /* Reading up to the truncation limit seems OK; repeat
1904 the read, but with checking enabled. */
1905 read_bytes (deref_rvalue (ptr_sval
, NULL_TREE
, ctxt
),
1913 /* Otherwise, we don't have an access-attribute limiting the read.
1914 Simulate a read up to the null terminator (if any). */
1916 call_details
cd (call
, this, ctxt
);
1917 check_for_null_terminated_string_arg (cd
, arg_idx
);
1920 /* Check CALL a call to external function CALLEE_FNDECL for any uses
1921 of __attribute__ ((null_terminated_string_arg)), compaining
1922 to CTXT about any issues.
1924 Use RDWR_IDX for tracking uses of __attribute__ ((access, ....). */
1928 check_function_attr_null_terminated_string_arg (const gcall
*call
,
1930 region_model_context
*ctxt
,
1934 gcc_assert (callee_fndecl
);
1937 tree fntype
= TREE_TYPE (callee_fndecl
);
1938 gcc_assert (fntype
);
1940 /* A function declaration can specify multiple attribute
1941 null_terminated_string_arg, each with one argument. */
1942 for (tree attr
= TYPE_ATTRIBUTES (fntype
); attr
; attr
= TREE_CHAIN (attr
))
1944 attr
= lookup_attribute ("null_terminated_string_arg", attr
);
1948 check_one_function_attr_null_terminated_string_arg (call
, callee_fndecl
,
1954 /* Check CALL a call to external function CALLEE_FNDECL for any
1955 function attributes, complaining to CTXT about any issues. */
1958 region_model::check_function_attrs (const gcall
*call
,
1960 region_model_context
*ctxt
)
1963 gcc_assert (callee_fndecl
);
1966 tree fntype
= TREE_TYPE (callee_fndecl
);
1970 if (!TYPE_ATTRIBUTES (fntype
))
1973 /* Initialize a map of attribute access specifications for arguments
1974 to the function call. */
1976 init_attr_rdwr_indices (&rdwr_idx
, TYPE_ATTRIBUTES (fntype
));
1978 check_function_attr_access (call
, callee_fndecl
, ctxt
, rdwr_idx
);
1979 check_function_attr_null_terminated_string_arg (call
, callee_fndecl
,
1983 /* Handle a call CALL to a function with unknown behavior.
1985 Traverse the regions in this model, determining what regions are
1986 reachable from pointer arguments to CALL and from global variables,
1989 Set all reachable regions to new unknown values and purge sm-state
1990 from their values, and from values that point to them. */
1993 region_model::handle_unrecognized_call (const gcall
*call
,
1994 region_model_context
*ctxt
)
1996 tree fndecl
= get_fndecl_for_call (call
, ctxt
);
1999 check_function_attrs (call
, fndecl
, ctxt
);
2001 reachable_regions
reachable_regs (this);
2003 /* Determine the reachable regions and their mutability. */
2005 /* Add globals and regions that already escaped in previous
2007 m_store
.for_each_cluster (reachable_regions::init_cluster_cb
,
2010 /* Params that are pointers. */
2011 tree iter_param_types
= NULL_TREE
;
2013 iter_param_types
= TYPE_ARG_TYPES (TREE_TYPE (fndecl
));
2014 for (unsigned arg_idx
= 0; arg_idx
< gimple_call_num_args (call
); arg_idx
++)
2016 /* Track expected param type, where available. */
2017 tree param_type
= NULL_TREE
;
2018 if (iter_param_types
)
2020 param_type
= TREE_VALUE (iter_param_types
);
2021 gcc_assert (param_type
);
2022 iter_param_types
= TREE_CHAIN (iter_param_types
);
2025 tree parm
= gimple_call_arg (call
, arg_idx
);
2026 const svalue
*parm_sval
= get_rvalue (parm
, ctxt
);
2027 reachable_regs
.handle_parm (parm_sval
, param_type
);
2031 uncertainty_t
*uncertainty
= ctxt
? ctxt
->get_uncertainty () : NULL
;
2033 /* Purge sm-state for the svalues that were reachable,
2034 both in non-mutable and mutable form. */
2035 for (svalue_set::iterator iter
2036 = reachable_regs
.begin_reachable_svals ();
2037 iter
!= reachable_regs
.end_reachable_svals (); ++iter
)
2039 const svalue
*sval
= (*iter
);
2041 ctxt
->on_unknown_change (sval
, false);
2043 for (svalue_set::iterator iter
2044 = reachable_regs
.begin_mutable_svals ();
2045 iter
!= reachable_regs
.end_mutable_svals (); ++iter
)
2047 const svalue
*sval
= (*iter
);
2049 ctxt
->on_unknown_change (sval
, true);
2051 uncertainty
->on_mutable_sval_at_unknown_call (sval
);
2054 /* Mark any clusters that have escaped. */
2055 reachable_regs
.mark_escaped_clusters (ctxt
);
2057 /* Update bindings for all clusters that have escaped, whether above,
2059 m_store
.on_unknown_fncall (call
, m_mgr
->get_store_manager (),
2060 conjured_purge (this, ctxt
));
2062 /* Purge dynamic extents from any regions that have escaped mutably:
2063 realloc could have been called on them. */
2064 for (hash_set
<const region
*>::iterator
2065 iter
= reachable_regs
.begin_mutable_base_regs ();
2066 iter
!= reachable_regs
.end_mutable_base_regs ();
2069 const region
*base_reg
= (*iter
);
2070 unset_dynamic_extents (base_reg
);
2074 /* Traverse the regions in this model, determining what regions are
2075 reachable from the store and populating *OUT.
2077 If EXTRA_SVAL is non-NULL, treat it as an additional "root"
2078 for reachability (for handling return values from functions when
2079 analyzing return of the only function on the stack).
2081 If UNCERTAINTY is non-NULL, treat any svalues that were recorded
2082 within it as being maybe-bound as additional "roots" for reachability.
2084 Find svalues that haven't leaked. */
2087 region_model::get_reachable_svalues (svalue_set
*out
,
2088 const svalue
*extra_sval
,
2089 const uncertainty_t
*uncertainty
)
2091 reachable_regions
reachable_regs (this);
2093 /* Add globals and regions that already escaped in previous
2095 m_store
.for_each_cluster (reachable_regions::init_cluster_cb
,
2099 reachable_regs
.handle_sval (extra_sval
);
2102 for (uncertainty_t::iterator iter
2103 = uncertainty
->begin_maybe_bound_svals ();
2104 iter
!= uncertainty
->end_maybe_bound_svals (); ++iter
)
2105 reachable_regs
.handle_sval (*iter
);
2107 /* Get regions for locals that have explicitly bound values. */
2108 for (store::cluster_map_t::iterator iter
= m_store
.begin ();
2109 iter
!= m_store
.end (); ++iter
)
2111 const region
*base_reg
= (*iter
).first
;
2112 if (const region
*parent
= base_reg
->get_parent_region ())
2113 if (parent
->get_kind () == RK_FRAME
)
2114 reachable_regs
.add (base_reg
, false);
2117 /* Populate *OUT based on the values that were reachable. */
2118 for (svalue_set::iterator iter
2119 = reachable_regs
.begin_reachable_svals ();
2120 iter
!= reachable_regs
.end_reachable_svals (); ++iter
)
2124 /* Update this model for the RETURN_STMT, using CTXT to report any
2128 region_model::on_return (const greturn
*return_stmt
, region_model_context
*ctxt
)
2130 tree callee
= get_current_function ()->decl
;
2131 tree lhs
= DECL_RESULT (callee
);
2132 tree rhs
= gimple_return_retval (return_stmt
);
2136 const svalue
*sval
= get_rvalue (rhs
, ctxt
);
2137 const region
*ret_reg
= get_lvalue (lhs
, ctxt
);
2138 set_value (ret_reg
, sval
, ctxt
);
2142 /* Update this model for a call and return of setjmp/sigsetjmp at CALL within
2143 ENODE, using CTXT to report any diagnostics.
2145 This is for the initial direct invocation of setjmp/sigsetjmp (which returns
2146 0), as opposed to any second return due to longjmp/sigsetjmp. */
2149 region_model::on_setjmp (const gcall
*call
, const exploded_node
*enode
,
2150 region_model_context
*ctxt
)
2152 const svalue
*buf_ptr
= get_rvalue (gimple_call_arg (call
, 0), ctxt
);
2153 const region
*buf_reg
= deref_rvalue (buf_ptr
, gimple_call_arg (call
, 0),
2156 /* Create a setjmp_svalue for this call and store it in BUF_REG's
2160 setjmp_record
r (enode
, call
);
2162 = m_mgr
->get_or_create_setjmp_svalue (r
, buf_reg
->get_type ());
2163 set_value (buf_reg
, sval
, ctxt
);
2166 /* Direct calls to setjmp return 0. */
2167 if (tree lhs
= gimple_call_lhs (call
))
2169 const svalue
*new_sval
2170 = m_mgr
->get_or_create_int_cst (TREE_TYPE (lhs
), 0);
2171 const region
*lhs_reg
= get_lvalue (lhs
, ctxt
);
2172 set_value (lhs_reg
, new_sval
, ctxt
);
2176 /* Update this region_model for rewinding from a "longjmp" at LONGJMP_CALL
2177 to a "setjmp" at SETJMP_CALL where the final stack depth should be
2178 SETJMP_STACK_DEPTH. Pop any stack frames. Leak detection is *not*
2179 done, and should be done by the caller. */
2182 region_model::on_longjmp (const gcall
*longjmp_call
, const gcall
*setjmp_call
,
2183 int setjmp_stack_depth
, region_model_context
*ctxt
)
2185 /* Evaluate the val, using the frame of the "longjmp". */
2186 tree fake_retval
= gimple_call_arg (longjmp_call
, 1);
2187 const svalue
*fake_retval_sval
= get_rvalue (fake_retval
, ctxt
);
2189 /* Pop any frames until we reach the stack depth of the function where
2190 setjmp was called. */
2191 gcc_assert (get_stack_depth () >= setjmp_stack_depth
);
2192 while (get_stack_depth () > setjmp_stack_depth
)
2193 pop_frame (NULL
, NULL
, ctxt
, false);
2195 gcc_assert (get_stack_depth () == setjmp_stack_depth
);
2197 /* Assign to LHS of "setjmp" in new_state. */
2198 if (tree lhs
= gimple_call_lhs (setjmp_call
))
2200 /* Passing 0 as the val to longjmp leads to setjmp returning 1. */
2201 const svalue
*zero_sval
2202 = m_mgr
->get_or_create_int_cst (TREE_TYPE (fake_retval
), 0);
2203 tristate eq_zero
= eval_condition (fake_retval_sval
, EQ_EXPR
, zero_sval
);
2204 /* If we have 0, use 1. */
2205 if (eq_zero
.is_true ())
2207 const svalue
*one_sval
2208 = m_mgr
->get_or_create_int_cst (TREE_TYPE (fake_retval
), 1);
2209 fake_retval_sval
= one_sval
;
2213 /* Otherwise note that the value is nonzero. */
2214 m_constraints
->add_constraint (fake_retval_sval
, NE_EXPR
, zero_sval
);
2217 /* Decorate the return value from setjmp as being unmergeable,
2218 so that we don't attempt to merge states with it as zero
2219 with states in which it's nonzero, leading to a clean distinction
2220 in the exploded_graph betweeen the first return and the second
2222 fake_retval_sval
= m_mgr
->get_or_create_unmergeable (fake_retval_sval
);
2224 const region
*lhs_reg
= get_lvalue (lhs
, ctxt
);
2225 set_value (lhs_reg
, fake_retval_sval
, ctxt
);
2229 /* Update this region_model for a phi stmt of the form
2230 LHS = PHI <...RHS...>.
2231 where RHS is for the appropriate edge.
2232 Get state from OLD_STATE so that all of the phi stmts for a basic block
2233 are effectively handled simultaneously. */
2236 region_model::handle_phi (const gphi
*phi
,
2238 const region_model
&old_state
,
2239 region_model_context
*ctxt
)
2241 /* For now, don't bother tracking the .MEM SSA names. */
2242 if (tree var
= SSA_NAME_VAR (lhs
))
2243 if (TREE_CODE (var
) == VAR_DECL
)
2244 if (VAR_DECL_IS_VIRTUAL_OPERAND (var
))
2247 const svalue
*src_sval
= old_state
.get_rvalue (rhs
, ctxt
);
2248 const region
*dst_reg
= old_state
.get_lvalue (lhs
, ctxt
);
2250 set_value (dst_reg
, src_sval
, ctxt
);
2253 ctxt
->on_phi (phi
, rhs
);
2256 /* Implementation of region_model::get_lvalue; the latter adds type-checking.
2258 Get the id of the region for PV within this region_model,
2259 emitting any diagnostics to CTXT. */
2262 region_model::get_lvalue_1 (path_var pv
, region_model_context
*ctxt
) const
2264 tree expr
= pv
.m_tree
;
2268 switch (TREE_CODE (expr
))
2271 return m_mgr
->get_region_for_unexpected_tree_code (ctxt
, expr
,
2272 dump_location_t ());
2276 tree array
= TREE_OPERAND (expr
, 0);
2277 tree index
= TREE_OPERAND (expr
, 1);
2279 const region
*array_reg
= get_lvalue (array
, ctxt
);
2280 const svalue
*index_sval
= get_rvalue (index
, ctxt
);
2281 return m_mgr
->get_element_region (array_reg
,
2282 TREE_TYPE (TREE_TYPE (array
)),
2289 tree inner_expr
= TREE_OPERAND (expr
, 0);
2290 const region
*inner_reg
= get_lvalue (inner_expr
, ctxt
);
2291 tree num_bits
= TREE_OPERAND (expr
, 1);
2292 tree first_bit_offset
= TREE_OPERAND (expr
, 2);
2293 gcc_assert (TREE_CODE (num_bits
) == INTEGER_CST
);
2294 gcc_assert (TREE_CODE (first_bit_offset
) == INTEGER_CST
);
2295 bit_range
bits (TREE_INT_CST_LOW (first_bit_offset
),
2296 TREE_INT_CST_LOW (num_bits
));
2297 return m_mgr
->get_bit_range (inner_reg
, TREE_TYPE (expr
), bits
);
2303 tree ptr
= TREE_OPERAND (expr
, 0);
2304 tree offset
= TREE_OPERAND (expr
, 1);
2305 const svalue
*ptr_sval
= get_rvalue (ptr
, ctxt
);
2306 const svalue
*offset_sval
= get_rvalue (offset
, ctxt
);
2307 const region
*star_ptr
= deref_rvalue (ptr_sval
, ptr
, ctxt
);
2308 return m_mgr
->get_offset_region (star_ptr
,
2315 return m_mgr
->get_region_for_fndecl (expr
);
2318 return m_mgr
->get_region_for_label (expr
);
2321 /* Handle globals. */
2322 if (is_global_var (expr
))
2323 return m_mgr
->get_region_for_global (expr
);
2331 gcc_assert (TREE_CODE (expr
) == SSA_NAME
2332 || TREE_CODE (expr
) == PARM_DECL
2334 || TREE_CODE (expr
) == RESULT_DECL
);
2336 int stack_index
= pv
.m_stack_depth
;
2337 const frame_region
*frame
= get_frame_at_index (stack_index
);
2339 return frame
->get_region_for_local (m_mgr
, expr
, ctxt
);
2345 tree obj
= TREE_OPERAND (expr
, 0);
2346 tree field
= TREE_OPERAND (expr
, 1);
2347 const region
*obj_reg
= get_lvalue (obj
, ctxt
);
2348 return m_mgr
->get_field_region (obj_reg
, field
);
2353 return m_mgr
->get_region_for_string (expr
);
2357 /* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op. */
2360 assert_compat_types (tree src_type
, tree dst_type
)
2362 if (src_type
&& dst_type
&& !VOID_TYPE_P (dst_type
))
2365 if (!(useless_type_conversion_p (src_type
, dst_type
)))
2366 internal_error ("incompatible types: %qT and %qT", src_type
, dst_type
);
2371 /* Return true if SRC_TYPE can be converted to DST_TYPE as a no-op. */
2374 compat_types_p (tree src_type
, tree dst_type
)
2376 if (src_type
&& dst_type
&& !VOID_TYPE_P (dst_type
))
2377 if (!(useless_type_conversion_p (src_type
, dst_type
)))
2382 /* Get the region for PV within this region_model,
2383 emitting any diagnostics to CTXT. */
2386 region_model::get_lvalue (path_var pv
, region_model_context
*ctxt
) const
2388 if (pv
.m_tree
== NULL_TREE
)
2391 const region
*result_reg
= get_lvalue_1 (pv
, ctxt
);
2392 assert_compat_types (result_reg
->get_type (), TREE_TYPE (pv
.m_tree
));
2396 /* Get the region for EXPR within this region_model (assuming the most
2397 recent stack frame if it's a local). */
2400 region_model::get_lvalue (tree expr
, region_model_context
*ctxt
) const
2402 return get_lvalue (path_var (expr
, get_stack_depth () - 1), ctxt
);
2405 /* Implementation of region_model::get_rvalue; the latter adds type-checking.
2407 Get the value of PV within this region_model,
2408 emitting any diagnostics to CTXT. */
2411 region_model::get_rvalue_1 (path_var pv
, region_model_context
*ctxt
) const
2413 gcc_assert (pv
.m_tree
);
2415 switch (TREE_CODE (pv
.m_tree
))
2418 return m_mgr
->get_or_create_unknown_svalue (TREE_TYPE (pv
.m_tree
));
2423 tree expr
= pv
.m_tree
;
2424 tree op0
= TREE_OPERAND (expr
, 0);
2425 const region
*expr_reg
= get_lvalue (op0
, ctxt
);
2426 return m_mgr
->get_ptr_svalue (TREE_TYPE (expr
), expr_reg
);
2432 tree expr
= pv
.m_tree
;
2433 tree op0
= TREE_OPERAND (expr
, 0);
2434 const region
*reg
= get_lvalue (op0
, ctxt
);
2435 tree num_bits
= TREE_OPERAND (expr
, 1);
2436 tree first_bit_offset
= TREE_OPERAND (expr
, 2);
2437 gcc_assert (TREE_CODE (num_bits
) == INTEGER_CST
);
2438 gcc_assert (TREE_CODE (first_bit_offset
) == INTEGER_CST
);
2439 bit_range
bits (TREE_INT_CST_LOW (first_bit_offset
),
2440 TREE_INT_CST_LOW (num_bits
));
2441 return get_rvalue_for_bits (TREE_TYPE (expr
), reg
, bits
, ctxt
);
2445 if (DECL_HARD_REGISTER (pv
.m_tree
))
2447 /* If it has a hard register, it doesn't have a memory region
2448 and can't be referred to as an lvalue. */
2449 return m_mgr
->get_or_create_unknown_svalue (TREE_TYPE (pv
.m_tree
));
2457 const region
*reg
= get_lvalue (pv
, ctxt
);
2458 return get_store_value (reg
, ctxt
);
2463 case VIEW_CONVERT_EXPR
:
2465 tree expr
= pv
.m_tree
;
2466 tree arg
= TREE_OPERAND (expr
, 0);
2467 const svalue
*arg_sval
= get_rvalue (arg
, ctxt
);
2468 const svalue
*sval_unaryop
2469 = m_mgr
->get_or_create_unaryop (TREE_TYPE (expr
), TREE_CODE (expr
),
2471 return sval_unaryop
;
2479 return m_mgr
->get_or_create_constant_svalue (pv
.m_tree
);
2481 case POINTER_PLUS_EXPR
:
2483 tree expr
= pv
.m_tree
;
2484 tree ptr
= TREE_OPERAND (expr
, 0);
2485 tree offset
= TREE_OPERAND (expr
, 1);
2486 const svalue
*ptr_sval
= get_rvalue (ptr
, ctxt
);
2487 const svalue
*offset_sval
= get_rvalue (offset
, ctxt
);
2488 const svalue
*sval_binop
2489 = m_mgr
->get_or_create_binop (TREE_TYPE (expr
), POINTER_PLUS_EXPR
,
2490 ptr_sval
, offset_sval
);
2501 tree expr
= pv
.m_tree
;
2502 tree arg0
= TREE_OPERAND (expr
, 0);
2503 tree arg1
= TREE_OPERAND (expr
, 1);
2504 const svalue
*arg0_sval
= get_rvalue (arg0
, ctxt
);
2505 const svalue
*arg1_sval
= get_rvalue (arg1
, ctxt
);
2506 const svalue
*sval_binop
2507 = m_mgr
->get_or_create_binop (TREE_TYPE (expr
), TREE_CODE (expr
),
2508 arg0_sval
, arg1_sval
);
2515 const region
*ref_reg
= get_lvalue (pv
, ctxt
);
2516 return get_store_value (ref_reg
, ctxt
);
2520 tree expr
= OBJ_TYPE_REF_EXPR (pv
.m_tree
);
2521 return get_rvalue (expr
, ctxt
);
2526 /* Get the value of PV within this region_model,
2527 emitting any diagnostics to CTXT. */
2530 region_model::get_rvalue (path_var pv
, region_model_context
*ctxt
) const
2532 if (pv
.m_tree
== NULL_TREE
)
2535 const svalue
*result_sval
= get_rvalue_1 (pv
, ctxt
);
2537 assert_compat_types (result_sval
->get_type (), TREE_TYPE (pv
.m_tree
));
2539 result_sval
= check_for_poison (result_sval
, pv
.m_tree
, NULL
, ctxt
);
2544 /* Get the value of EXPR within this region_model (assuming the most
2545 recent stack frame if it's a local). */
2548 region_model::get_rvalue (tree expr
, region_model_context
*ctxt
) const
2550 return get_rvalue (path_var (expr
, get_stack_depth () - 1), ctxt
);
2553 /* Return true if this model is on a path with "main" as the entrypoint
2554 (as opposed to one in which we're merely analyzing a subset of the
2555 path through the code). */
2558 region_model::called_from_main_p () const
2560 if (!m_current_frame
)
2562 /* Determine if the oldest stack frame in this model is for "main". */
2563 const frame_region
*frame0
= get_frame_at_index (0);
2564 gcc_assert (frame0
);
2565 return id_equal (DECL_NAME (frame0
->get_function ()->decl
), "main");
2568 /* Subroutine of region_model::get_store_value for when REG is (or is within)
2569 a global variable that hasn't been touched since the start of this path
2570 (or was implicitly touched due to a call to an unknown function). */
2573 region_model::get_initial_value_for_global (const region
*reg
) const
2575 /* Get the decl that REG is for (or is within). */
2576 const decl_region
*base_reg
2577 = reg
->get_base_region ()->dyn_cast_decl_region ();
2578 gcc_assert (base_reg
);
2579 tree decl
= base_reg
->get_decl ();
2581 /* Special-case: to avoid having to explicitly update all previously
2582 untracked globals when calling an unknown fn, they implicitly have
2583 an unknown value if an unknown call has occurred, unless this is
2584 static to-this-TU and hasn't escaped. Globals that have escaped
2585 are explicitly tracked, so we shouldn't hit this case for them. */
2586 if (m_store
.called_unknown_fn_p ()
2587 && TREE_PUBLIC (decl
)
2588 && !TREE_READONLY (decl
))
2589 return m_mgr
->get_or_create_unknown_svalue (reg
->get_type ());
2591 /* If we are on a path from the entrypoint from "main" and we have a
2592 global decl defined in this TU that hasn't been touched yet, then
2593 the initial value of REG can be taken from the initialization value
2595 if (called_from_main_p () || TREE_READONLY (decl
))
2596 return reg
->get_initial_value_at_main (m_mgr
);
2598 /* Otherwise, return INIT_VAL(REG). */
2599 return m_mgr
->get_or_create_initial_value (reg
);
2602 /* Get a value for REG, looking it up in the store, or otherwise falling
2603 back to "initial" or "unknown" values.
2604 Use CTXT to report any warnings associated with reading from REG. */
2607 region_model::get_store_value (const region
*reg
,
2608 region_model_context
*ctxt
) const
2610 /* Getting the value of an empty region gives an unknown_svalue. */
2611 if (reg
->empty_p ())
2612 return m_mgr
->get_or_create_unknown_svalue (reg
->get_type ());
2614 bool check_poisoned
= true;
2615 if (check_region_for_read (reg
, ctxt
))
2616 check_poisoned
= false;
2618 /* Special-case: handle var_decls in the constant pool. */
2619 if (const decl_region
*decl_reg
= reg
->dyn_cast_decl_region ())
2620 if (const svalue
*sval
= decl_reg
->maybe_get_constant_value (m_mgr
))
2624 = m_store
.get_any_binding (m_mgr
->get_store_manager (), reg
);
2627 if (reg
->get_type ())
2628 sval
= m_mgr
->get_or_create_cast (reg
->get_type (), sval
);
2632 /* Special-case: read at a constant index within a STRING_CST. */
2633 if (const offset_region
*offset_reg
= reg
->dyn_cast_offset_region ())
2634 if (tree byte_offset_cst
2635 = offset_reg
->get_byte_offset ()->maybe_get_constant ())
2636 if (const string_region
*str_reg
2637 = reg
->get_parent_region ()->dyn_cast_string_region ())
2639 tree string_cst
= str_reg
->get_string_cst ();
2640 if (const svalue
*char_sval
2641 = m_mgr
->maybe_get_char_from_string_cst (string_cst
,
2643 return m_mgr
->get_or_create_cast (reg
->get_type (), char_sval
);
2646 /* Special-case: read the initial char of a STRING_CST. */
2647 if (const cast_region
*cast_reg
= reg
->dyn_cast_cast_region ())
2648 if (const string_region
*str_reg
2649 = cast_reg
->get_original_region ()->dyn_cast_string_region ())
2651 tree string_cst
= str_reg
->get_string_cst ();
2652 tree byte_offset_cst
= build_int_cst (integer_type_node
, 0);
2653 if (const svalue
*char_sval
2654 = m_mgr
->maybe_get_char_from_string_cst (string_cst
,
2656 return m_mgr
->get_or_create_cast (reg
->get_type (), char_sval
);
2659 /* Otherwise we implicitly have the initial value of the region
2660 (if the cluster had been touched, binding_cluster::get_any_binding,
2661 would have returned UNKNOWN, and we would already have returned
2664 /* Handle globals. */
2665 if (reg
->get_base_region ()->get_parent_region ()->get_kind ()
2667 return get_initial_value_for_global (reg
);
2669 return m_mgr
->get_or_create_initial_value (reg
, check_poisoned
);
2672 /* Return false if REG does not exist, true if it may do.
2673 This is for detecting regions within the stack that don't exist anymore
2674 after frames are popped. */
2677 region_model::region_exists_p (const region
*reg
) const
2679 /* If within a stack frame, check that the stack frame is live. */
2680 if (const frame_region
*enclosing_frame
= reg
->maybe_get_frame_region ())
2682 /* Check that the current frame is the enclosing frame, or is called
2684 for (const frame_region
*iter_frame
= get_current_frame (); iter_frame
;
2685 iter_frame
= iter_frame
->get_calling_frame ())
2686 if (iter_frame
== enclosing_frame
)
2694 /* Get a region for referencing PTR_SVAL, creating a region if need be, and
2695 potentially generating warnings via CTXT.
2696 PTR_SVAL must be of pointer type.
2697 PTR_TREE if non-NULL can be used when emitting diagnostics. */
2700 region_model::deref_rvalue (const svalue
*ptr_sval
, tree ptr_tree
,
2701 region_model_context
*ctxt
,
2702 bool add_nonnull_constraint
) const
2704 gcc_assert (ptr_sval
);
2705 gcc_assert (POINTER_TYPE_P (ptr_sval
->get_type ()));
2707 /* If we're dereferencing PTR_SVAL, assume that it is non-NULL; add this
2708 as a constraint. This suppresses false positives from
2709 -Wanalyzer-null-dereference for the case where we later have an
2710 if (PTR_SVAL) that would occur if we considered the false branch
2711 and transitioned the malloc state machine from start->null. */
2712 if (add_nonnull_constraint
)
2714 tree null_ptr_cst
= build_int_cst (ptr_sval
->get_type (), 0);
2715 const svalue
*null_ptr
2716 = m_mgr
->get_or_create_constant_svalue (null_ptr_cst
);
2717 m_constraints
->add_constraint (ptr_sval
, NE_EXPR
, null_ptr
);
2720 switch (ptr_sval
->get_kind ())
2727 const region_svalue
*region_sval
2728 = as_a
<const region_svalue
*> (ptr_sval
);
2729 return region_sval
->get_pointee ();
2734 const binop_svalue
*binop_sval
2735 = as_a
<const binop_svalue
*> (ptr_sval
);
2736 switch (binop_sval
->get_op ())
2738 case POINTER_PLUS_EXPR
:
2740 /* If we have a symbolic value expressing pointer arithmentic,
2741 try to convert it to a suitable region. */
2742 const region
*parent_region
2743 = deref_rvalue (binop_sval
->get_arg0 (), NULL_TREE
, ctxt
);
2744 const svalue
*offset
= binop_sval
->get_arg1 ();
2745 tree type
= TREE_TYPE (ptr_sval
->get_type ());
2746 return m_mgr
->get_offset_region (parent_region
, type
, offset
);
2758 tree ptr
= get_representative_tree (ptr_sval
);
2759 /* If we can't get a representative tree for PTR_SVAL
2760 (e.g. if it hasn't been bound into the store), then
2761 fall back on PTR_TREE, if non-NULL. */
2766 const poisoned_svalue
*poisoned_sval
2767 = as_a
<const poisoned_svalue
*> (ptr_sval
);
2768 enum poison_kind pkind
= poisoned_sval
->get_poison_kind ();
2769 ctxt
->warn (::make_unique
<poisoned_value_diagnostic
>
2770 (ptr
, pkind
, nullptr, nullptr));
2777 return m_mgr
->get_symbolic_region (ptr_sval
);
2780 /* Attempt to get BITS within any value of REG, as TYPE.
2781 In particular, extract values from compound_svalues for the case
2782 where there's a concrete binding at BITS.
2783 Return an unknown svalue if we can't handle the given case.
2784 Use CTXT to report any warnings associated with reading from REG. */
2787 region_model::get_rvalue_for_bits (tree type
,
2789 const bit_range
&bits
,
2790 region_model_context
*ctxt
) const
2792 const svalue
*sval
= get_store_value (reg
, ctxt
);
2793 return m_mgr
->get_or_create_bits_within (type
, bits
, sval
);
2796 /* A subclass of pending_diagnostic for complaining about writes to
2797 constant regions of memory. */
2799 class write_to_const_diagnostic
2800 : public pending_diagnostic_subclass
<write_to_const_diagnostic
>
2803 write_to_const_diagnostic (const region
*reg
, tree decl
)
2804 : m_reg (reg
), m_decl (decl
)
2807 const char *get_kind () const final override
2809 return "write_to_const_diagnostic";
2812 bool operator== (const write_to_const_diagnostic
&other
) const
2814 return (m_reg
== other
.m_reg
2815 && m_decl
== other
.m_decl
);
2818 int get_controlling_option () const final override
2820 return OPT_Wanalyzer_write_to_const
;
2823 bool emit (rich_location
*rich_loc
, logger
*) final override
2825 auto_diagnostic_group d
;
2827 switch (m_reg
->get_kind ())
2830 warned
= warning_at (rich_loc
, get_controlling_option (),
2831 "write to %<const%> object %qE", m_decl
);
2834 warned
= warning_at (rich_loc
, get_controlling_option (),
2835 "write to function %qE", m_decl
);
2838 warned
= warning_at (rich_loc
, get_controlling_option (),
2839 "write to label %qE", m_decl
);
2843 inform (DECL_SOURCE_LOCATION (m_decl
), "declared here");
2847 label_text
describe_final_event (const evdesc::final_event
&ev
) final override
2849 switch (m_reg
->get_kind ())
2852 return ev
.formatted_print ("write to %<const%> object %qE here", m_decl
);
2854 return ev
.formatted_print ("write to function %qE here", m_decl
);
2856 return ev
.formatted_print ("write to label %qE here", m_decl
);
2861 const region
*m_reg
;
2865 /* A subclass of pending_diagnostic for complaining about writes to
2868 class write_to_string_literal_diagnostic
2869 : public pending_diagnostic_subclass
<write_to_string_literal_diagnostic
>
2872 write_to_string_literal_diagnostic (const region
*reg
)
2876 const char *get_kind () const final override
2878 return "write_to_string_literal_diagnostic";
2881 bool operator== (const write_to_string_literal_diagnostic
&other
) const
2883 return m_reg
== other
.m_reg
;
2886 int get_controlling_option () const final override
2888 return OPT_Wanalyzer_write_to_string_literal
;
2891 bool emit (rich_location
*rich_loc
, logger
*) final override
2893 return warning_at (rich_loc
, get_controlling_option (),
2894 "write to string literal");
2895 /* Ideally we would show the location of the STRING_CST as well,
2896 but it is not available at this point. */
2899 label_text
describe_final_event (const evdesc::final_event
&ev
) final override
2901 return ev
.formatted_print ("write to string literal here");
2905 const region
*m_reg
;
2908 /* Use CTXT to warn If DEST_REG is a region that shouldn't be written to. */
2911 region_model::check_for_writable_region (const region
* dest_reg
,
2912 region_model_context
*ctxt
) const
2914 /* Fail gracefully if CTXT is NULL. */
2918 const region
*base_reg
= dest_reg
->get_base_region ();
2919 switch (base_reg
->get_kind ())
2925 const function_region
*func_reg
= as_a
<const function_region
*> (base_reg
);
2926 tree fndecl
= func_reg
->get_fndecl ();
2927 ctxt
->warn (make_unique
<write_to_const_diagnostic
>
2928 (func_reg
, fndecl
));
2933 const label_region
*label_reg
= as_a
<const label_region
*> (base_reg
);
2934 tree label
= label_reg
->get_label ();
2935 ctxt
->warn (make_unique
<write_to_const_diagnostic
>
2936 (label_reg
, label
));
2941 const decl_region
*decl_reg
= as_a
<const decl_region
*> (base_reg
);
2942 tree decl
= decl_reg
->get_decl ();
2943 /* Warn about writes to const globals.
2944 Don't warn for writes to const locals, and params in particular,
2945 since we would warn in push_frame when setting them up (e.g the
2946 "this" param is "T* const"). */
2947 if (TREE_READONLY (decl
)
2948 && is_global_var (decl
))
2949 ctxt
->warn (make_unique
<write_to_const_diagnostic
> (dest_reg
, decl
));
2953 ctxt
->warn (make_unique
<write_to_string_literal_diagnostic
> (dest_reg
));
2958 /* Get the capacity of REG in bytes. */
2961 region_model::get_capacity (const region
*reg
) const
2963 switch (reg
->get_kind ())
2969 const decl_region
*decl_reg
= as_a
<const decl_region
*> (reg
);
2970 tree decl
= decl_reg
->get_decl ();
2971 if (TREE_CODE (decl
) == SSA_NAME
)
2973 tree type
= TREE_TYPE (decl
);
2974 tree size
= TYPE_SIZE (type
);
2975 return get_rvalue (size
, NULL
);
2979 tree size
= decl_init_size (decl
, false);
2981 return get_rvalue (size
, NULL
);
2986 /* Look through sized regions to get at the capacity
2987 of the underlying regions. */
2988 return get_capacity (reg
->get_parent_region ());
2991 /* "Capacity" here means "size". */
2992 const string_region
*string_reg
= as_a
<const string_region
*> (reg
);
2993 tree string_cst
= string_reg
->get_string_cst ();
2994 return m_mgr
->get_or_create_int_cst (size_type_node
,
2995 TREE_STRING_LENGTH (string_cst
));
3000 if (const svalue
*recorded
= get_dynamic_extents (reg
))
3003 return m_mgr
->get_or_create_unknown_svalue (sizetype
);
3006 /* If CTXT is non-NULL, use it to warn about any problems accessing REG,
3007 using DIR to determine if this access is a read or write.
3008 Return TRUE if an OOB access was detected.
3009 If SVAL_HINT is non-NULL, use it as a hint in diagnostics
3010 about the value that would be written to REG. */
3013 region_model::check_region_access (const region
*reg
,
3014 enum access_direction dir
,
3015 const svalue
*sval_hint
,
3016 region_model_context
*ctxt
) const
3018 /* Fail gracefully if CTXT is NULL. */
3022 bool oob_access_detected
= false;
3023 check_region_for_taint (reg
, dir
, ctxt
);
3024 if (!check_region_bounds (reg
, dir
, sval_hint
, ctxt
))
3025 oob_access_detected
= true;
3032 /* Currently a no-op. */
3035 check_for_writable_region (reg
, ctxt
);
3038 return oob_access_detected
;
3041 /* If CTXT is non-NULL, use it to warn about any problems writing to REG. */
3044 region_model::check_region_for_write (const region
*dest_reg
,
3045 const svalue
*sval_hint
,
3046 region_model_context
*ctxt
) const
3048 check_region_access (dest_reg
, DIR_WRITE
, sval_hint
, ctxt
);
3051 /* If CTXT is non-NULL, use it to warn about any problems reading from REG.
3052 Returns TRUE if an OOB read was detected. */
3055 region_model::check_region_for_read (const region
*src_reg
,
3056 region_model_context
*ctxt
) const
3058 return check_region_access (src_reg
, DIR_READ
, NULL
, ctxt
);
3061 /* Concrete subclass for casts of pointers that lead to trailing bytes. */
3063 class dubious_allocation_size
3064 : public pending_diagnostic_subclass
<dubious_allocation_size
>
3067 dubious_allocation_size (const region
*lhs
, const region
*rhs
,
3069 : m_lhs (lhs
), m_rhs (rhs
), m_expr (NULL_TREE
), m_stmt (stmt
),
3070 m_has_allocation_event (false)
3073 dubious_allocation_size (const region
*lhs
, const region
*rhs
,
3074 tree expr
, const gimple
*stmt
)
3075 : m_lhs (lhs
), m_rhs (rhs
), m_expr (expr
), m_stmt (stmt
),
3076 m_has_allocation_event (false)
3079 const char *get_kind () const final override
3081 return "dubious_allocation_size";
3084 bool operator== (const dubious_allocation_size
&other
) const
3086 return (m_stmt
== other
.m_stmt
3087 && pending_diagnostic::same_tree_p (m_expr
, other
.m_expr
));
3090 int get_controlling_option () const final override
3092 return OPT_Wanalyzer_allocation_size
;
3095 bool emit (rich_location
*rich_loc
, logger
*) final override
3097 diagnostic_metadata m
;
3100 return warning_meta (rich_loc
, m
, get_controlling_option (),
3101 "allocated buffer size is not a multiple"
3102 " of the pointee's size");
3105 label_text
describe_final_event (const evdesc::final_event
&ev
) final
3108 tree pointee_type
= TREE_TYPE (m_lhs
->get_type ());
3109 if (m_has_allocation_event
)
3110 return ev
.formatted_print ("assigned to %qT here;"
3111 " %<sizeof (%T)%> is %qE",
3112 m_lhs
->get_type (), pointee_type
,
3113 size_in_bytes (pointee_type
));
3114 /* Fallback: Typically, we should always see an allocation_event
3118 if (TREE_CODE (m_expr
) == INTEGER_CST
)
3119 return ev
.formatted_print ("allocated %E bytes and assigned to"
3120 " %qT here; %<sizeof (%T)%> is %qE",
3121 m_expr
, m_lhs
->get_type (), pointee_type
,
3122 size_in_bytes (pointee_type
));
3124 return ev
.formatted_print ("allocated %qE bytes and assigned to"
3125 " %qT here; %<sizeof (%T)%> is %qE",
3126 m_expr
, m_lhs
->get_type (), pointee_type
,
3127 size_in_bytes (pointee_type
));
3130 return ev
.formatted_print ("allocated and assigned to %qT here;"
3131 " %<sizeof (%T)%> is %qE",
3132 m_lhs
->get_type (), pointee_type
,
3133 size_in_bytes (pointee_type
));
3137 add_region_creation_events (const region
*,
3139 const event_loc_info
&loc_info
,
3140 checker_path
&emission_path
) final override
3142 emission_path
.add_event
3143 (make_unique
<region_creation_event_allocation_size
> (capacity
, loc_info
));
3145 m_has_allocation_event
= true;
3148 void mark_interesting_stuff (interesting_t
*interest
) final override
3150 interest
->add_region_creation (m_rhs
);
3154 const region
*m_lhs
;
3155 const region
*m_rhs
;
3157 const gimple
*m_stmt
;
3158 bool m_has_allocation_event
;
3161 /* Return true on dubious allocation sizes for constant sizes. */
3164 capacity_compatible_with_type (tree cst
, tree pointee_size_tree
,
3167 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
3168 gcc_assert (TREE_CODE (pointee_size_tree
) == INTEGER_CST
);
3170 unsigned HOST_WIDE_INT pointee_size
= TREE_INT_CST_LOW (pointee_size_tree
);
3171 unsigned HOST_WIDE_INT alloc_size
= TREE_INT_CST_LOW (cst
);
3174 return alloc_size
== 0 || alloc_size
>= pointee_size
;
3175 return alloc_size
% pointee_size
== 0;
3179 capacity_compatible_with_type (tree cst
, tree pointee_size_tree
)
3181 return capacity_compatible_with_type (cst
, pointee_size_tree
, false);
3184 /* Checks whether SVAL could be a multiple of SIZE_CST.
3186 It works by visiting all svalues inside SVAL until it reaches
3187 atomic nodes. From those, it goes back up again and adds each
3188 node that is not a multiple of SIZE_CST to the RESULT_SET. */
3190 class size_visitor
: public visitor
3193 size_visitor (tree size_cst
, const svalue
*root_sval
, constraint_manager
*cm
)
3194 : m_size_cst (size_cst
), m_root_sval (root_sval
), m_cm (cm
)
3196 m_root_sval
->accept (this);
3199 bool is_dubious_capacity ()
3201 return result_set
.contains (m_root_sval
);
3204 void visit_constant_svalue (const constant_svalue
*sval
) final override
3206 check_constant (sval
->get_constant (), sval
);
3209 void visit_unaryop_svalue (const unaryop_svalue
*sval
) final override
3211 if (CONVERT_EXPR_CODE_P (sval
->get_op ())
3212 && result_set
.contains (sval
->get_arg ()))
3213 result_set
.add (sval
);
3216 void visit_binop_svalue (const binop_svalue
*sval
) final override
3218 const svalue
*arg0
= sval
->get_arg0 ();
3219 const svalue
*arg1
= sval
->get_arg1 ();
3221 switch (sval
->get_op ())
3224 if (result_set
.contains (arg0
) && result_set
.contains (arg1
))
3225 result_set
.add (sval
);
3229 if (result_set
.contains (arg0
) || result_set
.contains (arg1
))
3230 result_set
.add (sval
);
3237 void visit_unmergeable_svalue (const unmergeable_svalue
*sval
) final override
3239 if (result_set
.contains (sval
->get_arg ()))
3240 result_set
.add (sval
);
3243 void visit_widening_svalue (const widening_svalue
*sval
) final override
3245 const svalue
*base
= sval
->get_base_svalue ();
3246 const svalue
*iter
= sval
->get_iter_svalue ();
3248 if (result_set
.contains (base
) || result_set
.contains (iter
))
3249 result_set
.add (sval
);
3252 void visit_initial_svalue (const initial_svalue
*sval
) final override
3254 equiv_class_id id
= equiv_class_id::null ();
3255 if (m_cm
->get_equiv_class_by_svalue (sval
, &id
))
3257 if (tree cst
= id
.get_obj (*m_cm
).get_any_constant ())
3258 check_constant (cst
, sval
);
3260 else if (!m_cm
->sval_constrained_p (sval
))
3262 result_set
.add (sval
);
3266 void visit_conjured_svalue (const conjured_svalue
*sval
) final override
3268 equiv_class_id id
= equiv_class_id::null ();
3269 if (m_cm
->get_equiv_class_by_svalue (sval
, &id
))
3270 if (tree cst
= id
.get_obj (*m_cm
).get_any_constant ())
3271 check_constant (cst
, sval
);
3275 void check_constant (tree cst
, const svalue
*sval
)
3277 switch (TREE_CODE (cst
))
3280 /* Assume all unhandled operands are compatible. */
3283 if (!capacity_compatible_with_type (cst
, m_size_cst
))
3284 result_set
.add (sval
);
3290 const svalue
*m_root_sval
;
3291 constraint_manager
*m_cm
;
3292 svalue_set result_set
; /* Used as a mapping of svalue*->bool. */
3295 /* Return true if a struct or union either uses the inheritance pattern,
3296 where the first field is a base struct, or the flexible array member
3297 pattern, where the last field is an array without a specified size. */
3300 struct_or_union_with_inheritance_p (tree struc
)
3302 tree iter
= TYPE_FIELDS (struc
);
3303 if (iter
== NULL_TREE
)
3305 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (iter
)))
3309 while (iter
!= NULL_TREE
)
3312 iter
= DECL_CHAIN (iter
);
3315 if (last_field
!= NULL_TREE
3316 && TREE_CODE (TREE_TYPE (last_field
)) == ARRAY_TYPE
)
3322 /* Return true if the lhs and rhs of an assignment have different types. */
3325 is_any_cast_p (const gimple
*stmt
)
3327 if (const gassign
*assign
= dyn_cast
<const gassign
*> (stmt
))
3328 return gimple_assign_cast_p (assign
)
3329 || !pending_diagnostic::same_tree_p (
3330 TREE_TYPE (gimple_assign_lhs (assign
)),
3331 TREE_TYPE (gimple_assign_rhs1 (assign
)));
3332 else if (const gcall
*call
= dyn_cast
<const gcall
*> (stmt
))
3334 tree lhs
= gimple_call_lhs (call
);
3335 return lhs
!= NULL_TREE
&& !pending_diagnostic::same_tree_p (
3336 TREE_TYPE (gimple_call_lhs (call
)),
3337 gimple_call_return_type (call
));
3343 /* On pointer assignments, check whether the buffer size of
3344 RHS_SVAL is compatible with the type of the LHS_REG.
3345 Use a non-null CTXT to report allocation size warnings. */
3348 region_model::check_region_size (const region
*lhs_reg
, const svalue
*rhs_sval
,
3349 region_model_context
*ctxt
) const
3351 if (!ctxt
|| ctxt
->get_stmt () == NULL
)
3353 /* Only report warnings on assignments that actually change the type. */
3354 if (!is_any_cast_p (ctxt
->get_stmt ()))
3357 tree pointer_type
= lhs_reg
->get_type ();
3358 if (pointer_type
== NULL_TREE
|| !POINTER_TYPE_P (pointer_type
))
3361 tree pointee_type
= TREE_TYPE (pointer_type
);
3362 /* Make sure that the type on the left-hand size actually has a size. */
3363 if (pointee_type
== NULL_TREE
|| VOID_TYPE_P (pointee_type
)
3364 || TYPE_SIZE_UNIT (pointee_type
) == NULL_TREE
)
3367 /* Bail out early on pointers to structs where we can
3368 not deduce whether the buffer size is compatible. */
3369 bool is_struct
= RECORD_OR_UNION_TYPE_P (pointee_type
);
3370 if (is_struct
&& struct_or_union_with_inheritance_p (pointee_type
))
3373 tree pointee_size_tree
= size_in_bytes (pointee_type
);
3374 /* We give up if the type size is not known at compile-time or the
3375 type size is always compatible regardless of the buffer size. */
3376 if (TREE_CODE (pointee_size_tree
) != INTEGER_CST
3377 || integer_zerop (pointee_size_tree
)
3378 || integer_onep (pointee_size_tree
))
3381 const region
*rhs_reg
= deref_rvalue (rhs_sval
, NULL_TREE
, ctxt
, false);
3382 const svalue
*capacity
= get_capacity (rhs_reg
);
3383 switch (capacity
->get_kind ())
3385 case svalue_kind::SK_CONSTANT
:
3387 const constant_svalue
*cst_cap_sval
3388 = as_a
<const constant_svalue
*> (capacity
);
3389 tree cst_cap
= cst_cap_sval
->get_constant ();
3390 if (TREE_CODE (cst_cap
) == INTEGER_CST
3391 && !capacity_compatible_with_type (cst_cap
, pointee_size_tree
,
3393 ctxt
->warn (make_unique
<dubious_allocation_size
> (lhs_reg
, rhs_reg
,
3395 ctxt
->get_stmt ()));
3402 size_visitor
v (pointee_size_tree
, capacity
, m_constraints
);
3403 if (v
.is_dubious_capacity ())
3405 tree expr
= get_representative_tree (capacity
);
3406 ctxt
->warn (make_unique
<dubious_allocation_size
> (lhs_reg
,
3409 ctxt
->get_stmt ()));
3417 /* Set the value of the region given by LHS_REG to the value given
3419 Use CTXT to report any warnings associated with writing to LHS_REG. */
3422 region_model::set_value (const region
*lhs_reg
, const svalue
*rhs_sval
,
3423 region_model_context
*ctxt
)
3425 gcc_assert (lhs_reg
);
3426 gcc_assert (rhs_sval
);
3428 /* Setting the value of an empty region is a no-op. */
3429 if (lhs_reg
->empty_p ())
3432 check_region_size (lhs_reg
, rhs_sval
, ctxt
);
3434 check_region_for_write (lhs_reg
, rhs_sval
, ctxt
);
3436 m_store
.set_value (m_mgr
->get_store_manager(), lhs_reg
, rhs_sval
,
3437 ctxt
? ctxt
->get_uncertainty () : NULL
);
3440 /* Set the value of the region given by LHS to the value given by RHS. */
3443 region_model::set_value (tree lhs
, tree rhs
, region_model_context
*ctxt
)
3445 const region
*lhs_reg
= get_lvalue (lhs
, ctxt
);
3446 const svalue
*rhs_sval
= get_rvalue (rhs
, ctxt
);
3447 gcc_assert (lhs_reg
);
3448 gcc_assert (rhs_sval
);
3449 set_value (lhs_reg
, rhs_sval
, ctxt
);
3452 /* Issue a note specifying that a particular function parameter is expected
3453 to be a valid null-terminated string. */
3456 inform_about_expected_null_terminated_string_arg (const call_arg_details
&ad
)
3458 // TODO: ideally we'd underline the param here
3459 inform (DECL_SOURCE_LOCATION (ad
.m_called_fndecl
),
3460 "argument %d of %qD must be a pointer to a null-terminated string",
3461 ad
.m_arg_idx
+ 1, ad
.m_called_fndecl
);
3464 /* A binding of a specific svalue at a concrete byte range. */
3469 : m_byte_range (0, 0), m_sval (nullptr)
3473 fragment (const byte_range
&bytes
, const svalue
*sval
)
3474 : m_byte_range (bytes
), m_sval (sval
)
3478 static int cmp_ptrs (const void *p1
, const void *p2
)
3480 const fragment
*f1
= (const fragment
*)p1
;
3481 const fragment
*f2
= (const fragment
*)p2
;
3482 return byte_range::cmp (f1
->m_byte_range
, f2
->m_byte_range
);
3485 /* Determine if there is a zero terminator somewhere in the
3486 bytes of this fragment, starting at START_READ_OFFSET (which
3487 is absolute to the start of the cluster as a whole), and stopping
3488 at the end of this fragment.
3491 - true if there definitely is a zero byte, writing to *OUT_BYTES_READ
3492 the number of bytes from that would be read, including the zero byte.
3493 - false if there definitely isn't a zero byte
3494 - unknown if we don't know. */
3495 tristate
has_null_terminator (byte_offset_t start_read_offset
,
3496 byte_offset_t
*out_bytes_read
) const
3498 byte_offset_t rel_start_read_offset
3499 = start_read_offset
- m_byte_range
.get_start_byte_offset ();
3500 gcc_assert (rel_start_read_offset
>= 0);
3501 byte_offset_t available_bytes
3502 = (m_byte_range
.get_next_byte_offset () - start_read_offset
);
3503 gcc_assert (available_bytes
>= 0);
3505 if (rel_start_read_offset
> INT_MAX
)
3506 return tristate::TS_UNKNOWN
;
3507 HOST_WIDE_INT rel_start_read_offset_hwi
= rel_start_read_offset
.slow ();
3509 if (available_bytes
> INT_MAX
)
3510 return tristate::TS_UNKNOWN
;
3511 HOST_WIDE_INT available_bytes_hwi
= available_bytes
.slow ();
3513 switch (m_sval
->get_kind ())
3518 = as_a
<const constant_svalue
*> (m_sval
)->get_constant ();
3519 switch (TREE_CODE (cst
))
3522 return string_cst_has_null_terminator (cst
,
3523 rel_start_read_offset_hwi
,
3524 available_bytes_hwi
,
3527 if (rel_start_read_offset_hwi
== 0
3528 && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (cst
))))
3530 /* Model accesses to the initial byte of a 1-byte
3534 *out_bytes_read
= 1;
3535 return tristate (true);
3539 *out_bytes_read
= available_bytes
;
3540 return tristate (false);
3543 /* Treat any other access to an INTEGER_CST as unknown. */
3544 return tristate::TS_UNKNOWN
;
3555 const initial_svalue
*initial_sval
= (const initial_svalue
*)m_sval
;
3556 const region
*reg
= initial_sval
->get_region ();
3557 if (const string_region
*string_reg
= reg
->dyn_cast_string_region ())
3559 tree string_cst
= string_reg
->get_string_cst ();
3560 return string_cst_has_null_terminator (string_cst
,
3561 rel_start_read_offset_hwi
,
3562 available_bytes_hwi
,
3565 return tristate::TS_UNKNOWN
;
3569 case SK_BITS_WITHIN
:
3571 const bits_within_svalue
*bits_within_sval
3572 = (const bits_within_svalue
*)m_sval
;
3573 byte_range
bytes (0, 0);
3574 if (bits_within_sval
->get_bits ().as_byte_range (&bytes
))
3576 const svalue
*inner_sval
= bits_within_sval
->get_inner_svalue ();
3577 fragment
f (byte_range
3578 (start_read_offset
- bytes
.get_start_bit_offset (),
3579 std::max
<byte_size_t
> (bytes
.m_size_in_bytes
,
3582 return f
.has_null_terminator (start_read_offset
, out_bytes_read
);
3588 // TODO: it may be possible to handle other cases here.
3591 return tristate::TS_UNKNOWN
;
3595 string_cst_has_null_terminator (tree string_cst
,
3596 HOST_WIDE_INT rel_start_read_offset_hwi
,
3597 HOST_WIDE_INT available_bytes_hwi
,
3598 byte_offset_t
*out_bytes_read
)
3600 /* Look for the first 0 byte within STRING_CST
3601 from START_READ_OFFSET onwards. */
3602 const HOST_WIDE_INT num_bytes_to_search
3603 = std::min
<HOST_WIDE_INT
> ((TREE_STRING_LENGTH (string_cst
)
3604 - rel_start_read_offset_hwi
),
3605 available_bytes_hwi
);
3606 const char *start
= (TREE_STRING_POINTER (string_cst
)
3607 + rel_start_read_offset_hwi
);
3608 if (num_bytes_to_search
>= 0)
3609 if (const void *p
= memchr (start
, 0,
3610 num_bytes_to_search
))
3612 *out_bytes_read
= (const char *)p
- start
+ 1;
3613 return tristate (true);
3616 *out_bytes_read
= available_bytes_hwi
;
3617 return tristate (false);
3620 byte_range m_byte_range
;
3621 const svalue
*m_sval
;
3624 /* A frozen copy of a single base region's binding_cluster within a store,
3625 optimized for traversal of the concrete parts in byte order.
3626 This only captures concrete bindings, and is an implementation detail
3627 of region_model::scan_for_null_terminator. */
3629 class iterable_cluster
3632 iterable_cluster (const binding_cluster
*cluster
)
3636 for (auto iter
: *cluster
)
3638 const binding_key
*key
= iter
.first
;
3639 const svalue
*sval
= iter
.second
;
3641 if (const concrete_binding
*concrete_key
3642 = key
->dyn_cast_concrete_binding ())
3644 byte_range
fragment_bytes (0, 0);
3645 if (concrete_key
->get_byte_range (&fragment_bytes
))
3646 m_fragments
.safe_push (fragment (fragment_bytes
, sval
));
3649 m_symbolic_bindings
.safe_push (key
);
3651 m_fragments
.qsort (fragment::cmp_ptrs
);
3655 get_fragment_for_byte (byte_offset_t byte
, fragment
*out_frag
) const
3657 /* TODO: binary search rather than linear. */
3659 for (iter_idx
= 0; iter_idx
< m_fragments
.length (); iter_idx
++)
3661 if (m_fragments
[iter_idx
].m_byte_range
.contains_p (byte
))
3663 *out_frag
= m_fragments
[iter_idx
];
3670 bool has_symbolic_bindings_p () const
3672 return !m_symbolic_bindings
.is_empty ();
3676 auto_vec
<fragment
> m_fragments
;
3677 auto_vec
<const binding_key
*> m_symbolic_bindings
;
3680 /* Simulate reading the bytes at BYTES from BASE_REG.
3681 Complain to CTXT about any issues with the read e.g. out-of-bounds. */
3684 region_model::get_store_bytes (const region
*base_reg
,
3685 const byte_range
&bytes
,
3686 region_model_context
*ctxt
) const
3688 /* Shortcut reading all of a string_region. */
3689 if (bytes
.get_start_byte_offset () == 0)
3690 if (const string_region
*string_reg
= base_reg
->dyn_cast_string_region ())
3691 if (bytes
.m_size_in_bytes
3692 == TREE_STRING_LENGTH (string_reg
->get_string_cst ()))
3693 return m_mgr
->get_or_create_initial_value (base_reg
);
3695 const svalue
*index_sval
3696 = m_mgr
->get_or_create_int_cst (size_type_node
,
3697 bytes
.get_start_byte_offset ());
3698 const region
*offset_reg
= m_mgr
->get_offset_region (base_reg
,
3701 const svalue
*byte_size_sval
3702 = m_mgr
->get_or_create_int_cst (size_type_node
, bytes
.m_size_in_bytes
);
3703 const region
*read_reg
= m_mgr
->get_sized_region (offset_reg
,
3707 /* Simulate reading those bytes from the store. */
3708 const svalue
*sval
= get_store_value (read_reg
, ctxt
);
3713 get_tree_for_byte_offset (tree ptr_expr
, byte_offset_t byte_offset
)
3715 gcc_assert (ptr_expr
);
3716 return fold_build2 (MEM_REF
,
3718 ptr_expr
, wide_int_to_tree (size_type_node
, byte_offset
));
3721 /* Simulate a series of reads of REG until we find a 0 byte
3722 (equivalent to calling strlen).
3724 Complain to CTXT and return NULL if:
3725 - the buffer pointed to isn't null-terminated
3726 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3727 - any of the reads aren't within the bounds of the underlying base region
3729 Otherwise, return a svalue for the number of bytes read (strlen + 1),
3730 and, if OUT_SVAL is non-NULL, write to *OUT_SVAL with an svalue
3731 representing the content of REG up to and including the terminator.
3736 Get offset for first byte to read.
3737 Find the binding (if any) that contains it.
3738 Find the size in bits of that binding.
3739 Round to the nearest byte (which way???)
3740 Or maybe give up if we have a partial binding there.
3741 Get the svalue from the binding.
3742 Determine the strlen (if any) of that svalue.
3743 Does it have a 0-terminator within it?
3744 If so, we have a partial read up to and including that terminator
3745 Read those bytes from the store; add to the result in the correct place.
3747 If not, we have a full read of that svalue
3748 Read those bytes from the store; add to the result in the correct place.
3749 Update read/write offsets
3757 region_model::scan_for_null_terminator (const region
*reg
,
3759 const svalue
**out_sval
,
3760 region_model_context
*ctxt
) const
3762 store_manager
*store_mgr
= m_mgr
->get_store_manager ();
3764 region_offset offset
= reg
->get_offset (m_mgr
);
3765 if (offset
.symbolic_p ())
3768 *out_sval
= get_store_value (reg
, nullptr);
3769 return m_mgr
->get_or_create_unknown_svalue (size_type_node
);
3771 byte_offset_t src_byte_offset
;
3772 if (!offset
.get_concrete_byte_offset (&src_byte_offset
))
3775 *out_sval
= get_store_value (reg
, nullptr);
3776 return m_mgr
->get_or_create_unknown_svalue (size_type_node
);
3778 const byte_offset_t initial_src_byte_offset
= src_byte_offset
;
3779 byte_offset_t dst_byte_offset
= 0;
3781 const region
*base_reg
= reg
->get_base_region ();
3783 if (const string_region
*str_reg
= base_reg
->dyn_cast_string_region ())
3785 tree string_cst
= str_reg
->get_string_cst ();
3786 if (const void *p
= memchr (TREE_STRING_POINTER (string_cst
),
3788 TREE_STRING_LENGTH (string_cst
)))
3790 size_t num_bytes_read
3791 = (const char *)p
- TREE_STRING_POINTER (string_cst
) + 1;
3792 /* Simulate the read. */
3793 byte_range
bytes_to_read (0, num_bytes_read
);
3794 const svalue
*sval
= get_store_bytes (reg
, bytes_to_read
, ctxt
);
3797 return m_mgr
->get_or_create_int_cst (size_type_node
,
3802 const binding_cluster
*cluster
= m_store
.get_cluster (base_reg
);
3803 iterable_cluster
c (cluster
);
3809 if (c
.get_fragment_for_byte (src_byte_offset
, &f
))
3811 byte_offset_t fragment_bytes_read
;
3812 tristate is_terminated
3813 = f
.has_null_terminator (src_byte_offset
, &fragment_bytes_read
);
3814 if (is_terminated
.is_unknown ())
3817 *out_sval
= get_store_value (reg
, nullptr);
3818 return m_mgr
->get_or_create_unknown_svalue (size_type_node
);
3821 /* Simulate reading those bytes from the store. */
3822 byte_range
bytes_to_read (src_byte_offset
, fragment_bytes_read
);
3823 const svalue
*sval
= get_store_bytes (base_reg
, bytes_to_read
, ctxt
);
3824 check_for_poison (sval
, expr
, nullptr, ctxt
);
3828 byte_range
bytes_to_write (dst_byte_offset
, fragment_bytes_read
);
3829 const binding_key
*key
3830 = store_mgr
->get_concrete_binding (bytes_to_write
);
3831 result
.put (key
, sval
);
3834 src_byte_offset
+= fragment_bytes_read
;
3835 dst_byte_offset
+= fragment_bytes_read
;
3837 if (is_terminated
.is_true ())
3840 *out_sval
= m_mgr
->get_or_create_compound_svalue (NULL_TREE
,
3842 return m_mgr
->get_or_create_int_cst (size_type_node
,
3850 /* No binding for this base_region, or no binding at src_byte_offset
3851 (or a symbolic binding). */
3853 if (c
.has_symbolic_bindings_p ())
3856 *out_sval
= get_store_value (reg
, nullptr);
3857 return m_mgr
->get_or_create_unknown_svalue (size_type_node
);
3860 /* TODO: the various special-cases seen in
3861 region_model::get_store_value. */
3863 /* Simulate reading from this byte, then give up. */
3864 byte_range
bytes_to_read (src_byte_offset
, 1);
3865 const svalue
*sval
= get_store_bytes (base_reg
, bytes_to_read
, ctxt
);
3867 = get_tree_for_byte_offset (expr
,
3868 src_byte_offset
- initial_src_byte_offset
);
3869 check_for_poison (sval
, byte_expr
, nullptr, ctxt
);
3870 if (base_reg
->can_have_initial_svalue_p ())
3873 *out_sval
= get_store_value (reg
, nullptr);
3874 return m_mgr
->get_or_create_unknown_svalue (size_type_node
);
3880 /* Check that argument ARG_IDX (0-based) to the call described by CD
3881 is a pointer to a valid null-terminated string.
3883 Simulate scanning through the buffer, reading until we find a 0 byte
3884 (equivalent to calling strlen).
3886 Complain and return NULL if:
3887 - the buffer pointed to isn't null-terminated
3888 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3889 - any of the reads aren't within the bounds of the underlying base region
3891 Otherwise, return a svalue for strlen of the buffer (*not* including
3892 the null terminator).
3894 TODO: we should also complain if:
3895 - the pointer is NULL (or could be). */
3898 region_model::check_for_null_terminated_string_arg (const call_details
&cd
,
3899 unsigned arg_idx
) const
3901 return check_for_null_terminated_string_arg (cd
,
3903 false, /* include_terminator */
3904 nullptr); // out_sval
3908 /* Check that argument ARG_IDX (0-based) to the call described by CD
3909 is a pointer to a valid null-terminated string.
3911 Simulate scanning through the buffer, reading until we find a 0 byte
3912 (equivalent to calling strlen).
3914 Complain and return NULL if:
3915 - the buffer pointed to isn't null-terminated
3916 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3917 - any of the reads aren't within the bounds of the underlying base region
3919 Otherwise, return a svalue. This will be the number of bytes read
3920 (including the null terminator) if INCLUDE_TERMINATOR is true, or strlen
3921 of the buffer (not including the null terminator) if it is false.
3923 Also, when returning an svalue, if OUT_SVAL is non-NULL, write to
3924 *OUT_SVAL with an svalue representing the content of the buffer up to
3925 and including the terminator.
3927 TODO: we should also complain if:
3928 - the pointer is NULL (or could be). */
3931 region_model::check_for_null_terminated_string_arg (const call_details
&cd
,
3933 bool include_terminator
,
3934 const svalue
**out_sval
) const
3936 class null_terminator_check_event
: public custom_event
3939 null_terminator_check_event (const event_loc_info
&loc_info
,
3940 const call_arg_details
&arg_details
)
3941 : custom_event (loc_info
),
3942 m_arg_details (arg_details
)
3946 label_text
get_desc (bool can_colorize
) const final override
3948 if (m_arg_details
.m_arg_expr
)
3949 return make_label_text (can_colorize
,
3950 "while looking for null terminator"
3951 " for argument %i (%qE) of %qD...",
3952 m_arg_details
.m_arg_idx
+ 1,
3953 m_arg_details
.m_arg_expr
,
3954 m_arg_details
.m_called_fndecl
);
3956 return make_label_text (can_colorize
,
3957 "while looking for null terminator"
3958 " for argument %i of %qD...",
3959 m_arg_details
.m_arg_idx
+ 1,
3960 m_arg_details
.m_called_fndecl
);
3964 const call_arg_details m_arg_details
;
3967 class null_terminator_check_decl_note
3968 : public pending_note_subclass
<null_terminator_check_decl_note
>
3971 null_terminator_check_decl_note (const call_arg_details
&arg_details
)
3972 : m_arg_details (arg_details
)
3976 const char *get_kind () const final override
3978 return "null_terminator_check_decl_note";
3981 void emit () const final override
3983 inform_about_expected_null_terminated_string_arg (m_arg_details
);
3986 bool operator== (const null_terminator_check_decl_note
&other
) const
3988 return m_arg_details
== other
.m_arg_details
;
3992 const call_arg_details m_arg_details
;
3995 /* Subclass of decorated_region_model_context that
3996 adds the above event and note to any saved diagnostics. */
3997 class annotating_ctxt
: public annotating_context
4000 annotating_ctxt (const call_details
&cd
,
4002 : annotating_context (cd
.get_ctxt ()),
4007 void add_annotations () final override
4009 call_arg_details
arg_details (m_cd
, m_arg_idx
);
4010 event_loc_info
loc_info (m_cd
.get_location (),
4011 m_cd
.get_model ()->get_current_function ()->decl
,
4012 m_cd
.get_model ()->get_stack_depth ());
4014 add_event (make_unique
<null_terminator_check_event
> (loc_info
,
4016 add_note (make_unique
<null_terminator_check_decl_note
> (arg_details
));
4019 const call_details
&m_cd
;
4023 /* Use this ctxt below so that any diagnostics that get added
4025 annotating_ctxt
my_ctxt (cd
, arg_idx
);
4027 const svalue
*arg_sval
= cd
.get_arg_svalue (arg_idx
);
4028 const region
*buf_reg
4029 = deref_rvalue (arg_sval
, cd
.get_arg_tree (arg_idx
), &my_ctxt
);
4031 if (const svalue
*num_bytes_read_sval
4032 = scan_for_null_terminator (buf_reg
,
4033 cd
.get_arg_tree (arg_idx
),
4037 if (include_terminator
)
4038 return num_bytes_read_sval
;
4041 /* strlen is (bytes_read - 1). */
4042 const svalue
*one
= m_mgr
->get_or_create_int_cst (size_type_node
, 1);
4043 return m_mgr
->get_or_create_binop (size_type_node
,
4045 num_bytes_read_sval
,
4053 /* Remove all bindings overlapping REG within the store. */
4056 region_model::clobber_region (const region
*reg
)
4058 m_store
.clobber_region (m_mgr
->get_store_manager(), reg
);
4061 /* Remove any bindings for REG within the store. */
4064 region_model::purge_region (const region
*reg
)
4066 m_store
.purge_region (m_mgr
->get_store_manager(), reg
);
4069 /* Fill REG with SVAL.
4070 Use CTXT to report any warnings associated with the write
4071 (e.g. out-of-bounds). */
4074 region_model::fill_region (const region
*reg
,
4076 region_model_context
*ctxt
)
4078 check_region_for_write (reg
, nullptr, ctxt
);
4079 m_store
.fill_region (m_mgr
->get_store_manager(), reg
, sval
);
4083 Use CTXT to report any warnings associated with the write
4084 (e.g. out-of-bounds). */
4087 region_model::zero_fill_region (const region
*reg
,
4088 region_model_context
*ctxt
)
4090 check_region_for_write (reg
, nullptr, ctxt
);
4091 m_store
.zero_fill_region (m_mgr
->get_store_manager(), reg
);
4094 /* Copy NUM_BYTES_SVAL of SVAL to DEST_REG.
4095 Use CTXT to report any warnings associated with the copy
4096 (e.g. out-of-bounds writes). */
4099 region_model::write_bytes (const region
*dest_reg
,
4100 const svalue
*num_bytes_sval
,
4102 region_model_context
*ctxt
)
4104 const region
*sized_dest_reg
4105 = m_mgr
->get_sized_region (dest_reg
, NULL_TREE
, num_bytes_sval
);
4106 set_value (sized_dest_reg
, sval
, ctxt
);
4109 /* Read NUM_BYTES_SVAL from SRC_REG.
4110 Use CTXT to report any warnings associated with the copy
4111 (e.g. out-of-bounds reads, copying of uninitialized values, etc). */
4114 region_model::read_bytes (const region
*src_reg
,
4116 const svalue
*num_bytes_sval
,
4117 region_model_context
*ctxt
) const
4119 if (num_bytes_sval
->get_kind () == SK_UNKNOWN
)
4120 return m_mgr
->get_or_create_unknown_svalue (NULL_TREE
);
4121 const region
*sized_src_reg
4122 = m_mgr
->get_sized_region (src_reg
, NULL_TREE
, num_bytes_sval
);
4123 const svalue
*src_contents_sval
= get_store_value (sized_src_reg
, ctxt
);
4124 check_for_poison (src_contents_sval
, src_ptr_expr
,
4125 sized_src_reg
, ctxt
);
4126 return src_contents_sval
;
4129 /* Copy NUM_BYTES_SVAL bytes from SRC_REG to DEST_REG.
4130 Use CTXT to report any warnings associated with the copy
4131 (e.g. out-of-bounds reads/writes, copying of uninitialized values,
4135 region_model::copy_bytes (const region
*dest_reg
,
4136 const region
*src_reg
,
4138 const svalue
*num_bytes_sval
,
4139 region_model_context
*ctxt
)
4141 const svalue
*data_sval
4142 = read_bytes (src_reg
, src_ptr_expr
, num_bytes_sval
, ctxt
);
4143 write_bytes (dest_reg
, num_bytes_sval
, data_sval
, ctxt
);
4146 /* Mark REG as having unknown content. */
4149 region_model::mark_region_as_unknown (const region
*reg
,
4150 uncertainty_t
*uncertainty
)
4152 svalue_set maybe_live_values
;
4153 m_store
.mark_region_as_unknown (m_mgr
->get_store_manager(), reg
,
4154 uncertainty
, &maybe_live_values
);
4155 m_store
.on_maybe_live_values (maybe_live_values
);
4158 /* Determine what is known about the condition "LHS_SVAL OP RHS_SVAL" within
4162 region_model::eval_condition (const svalue
*lhs
,
4164 const svalue
*rhs
) const
4169 /* For now, make no attempt to capture constraints on floating-point
4171 if ((lhs
->get_type () && FLOAT_TYPE_P (lhs
->get_type ()))
4172 || (rhs
->get_type () && FLOAT_TYPE_P (rhs
->get_type ())))
4173 return tristate::unknown ();
4175 /* See what we know based on the values. */
4177 /* Unwrap any unmergeable values. */
4178 lhs
= lhs
->unwrap_any_unmergeable ();
4179 rhs
= rhs
->unwrap_any_unmergeable ();
4183 /* If we have the same svalue, then we have equality
4184 (apart from NaN-handling).
4185 TODO: should this definitely be the case for poisoned values? */
4186 /* Poisoned and unknown values are "unknowable". */
4187 if (lhs
->get_kind () == SK_POISONED
4188 || lhs
->get_kind () == SK_UNKNOWN
)
4189 return tristate::TS_UNKNOWN
;
4196 return tristate::TS_TRUE
;
4201 return tristate::TS_FALSE
;
4204 /* For other ops, use the logic below. */
4209 /* If we have a pair of region_svalues, compare them. */
4210 if (const region_svalue
*lhs_ptr
= lhs
->dyn_cast_region_svalue ())
4211 if (const region_svalue
*rhs_ptr
= rhs
->dyn_cast_region_svalue ())
4213 tristate res
= region_svalue::eval_condition (lhs_ptr
, op
, rhs_ptr
);
4214 if (res
.is_known ())
4216 /* Otherwise, only known through constraints. */
4219 if (const constant_svalue
*cst_lhs
= lhs
->dyn_cast_constant_svalue ())
4221 /* If we have a pair of constants, compare them. */
4222 if (const constant_svalue
*cst_rhs
= rhs
->dyn_cast_constant_svalue ())
4223 return constant_svalue::eval_condition (cst_lhs
, op
, cst_rhs
);
4226 /* When we have one constant, put it on the RHS. */
4227 std::swap (lhs
, rhs
);
4228 op
= swap_tree_comparison (op
);
4231 gcc_assert (lhs
->get_kind () != SK_CONSTANT
);
4233 /* Handle comparison against zero. */
4234 if (const constant_svalue
*cst_rhs
= rhs
->dyn_cast_constant_svalue ())
4235 if (zerop (cst_rhs
->get_constant ()))
4237 if (const region_svalue
*ptr
= lhs
->dyn_cast_region_svalue ())
4239 /* A region_svalue is a non-NULL pointer, except in certain
4240 special cases (see the comment for region::non_null_p). */
4241 const region
*pointee
= ptr
->get_pointee ();
4242 if (pointee
->non_null_p ())
4252 return tristate::TS_FALSE
;
4257 return tristate::TS_TRUE
;
4261 else if (const binop_svalue
*binop
= lhs
->dyn_cast_binop_svalue ())
4263 /* Treat offsets from a non-NULL pointer as being non-NULL. This
4264 isn't strictly true, in that eventually ptr++ will wrap
4265 around and be NULL, but it won't occur in practise and thus
4266 can be used to suppress effectively false positives that we
4267 shouldn't warn for. */
4268 if (binop
->get_op () == POINTER_PLUS_EXPR
)
4270 tristate lhs_ts
= eval_condition (binop
->get_arg0 (), op
, rhs
);
4271 if (lhs_ts
.is_known ())
4275 else if (const unaryop_svalue
*unaryop
4276 = lhs
->dyn_cast_unaryop_svalue ())
4278 if (unaryop
->get_op () == NEGATE_EXPR
)
4280 /* e.g. "-X <= 0" is equivalent to X >= 0". */
4281 tristate lhs_ts
= eval_condition (unaryop
->get_arg (),
4282 swap_tree_comparison (op
),
4284 if (lhs_ts
.is_known ())
4290 /* Handle rejection of equality for comparisons of the initial values of
4291 "external" values (such as params) with the address of locals. */
4292 if (const initial_svalue
*init_lhs
= lhs
->dyn_cast_initial_svalue ())
4293 if (const region_svalue
*rhs_ptr
= rhs
->dyn_cast_region_svalue ())
4295 tristate res
= compare_initial_and_pointer (init_lhs
, rhs_ptr
);
4296 if (res
.is_known ())
4299 if (const initial_svalue
*init_rhs
= rhs
->dyn_cast_initial_svalue ())
4300 if (const region_svalue
*lhs_ptr
= lhs
->dyn_cast_region_svalue ())
4302 tristate res
= compare_initial_and_pointer (init_rhs
, lhs_ptr
);
4303 if (res
.is_known ())
4307 if (const widening_svalue
*widen_lhs
= lhs
->dyn_cast_widening_svalue ())
4308 if (tree rhs_cst
= rhs
->maybe_get_constant ())
4310 tristate res
= widen_lhs
->eval_condition_without_cm (op
, rhs_cst
);
4311 if (res
.is_known ())
4315 /* Handle comparisons between two svalues with more than one operand. */
4316 if (const binop_svalue
*binop
= lhs
->dyn_cast_binop_svalue ())
4324 /* TODO: binops can be equal even if they are not structurally
4325 equal in case of commutative operators. */
4326 tristate res
= structural_equality (lhs
, rhs
);
4333 tristate res
= structural_equality (lhs
, rhs
);
4340 tristate res
= structural_equality (lhs
, rhs
);
4343 res
= symbolic_greater_than (binop
, rhs
);
4350 tristate res
= symbolic_greater_than (binop
, rhs
);
4358 /* Attempt to unwrap cast if there is one, and the types match. */
4359 tree lhs_type
= lhs
->get_type ();
4360 tree rhs_type
= rhs
->get_type ();
4361 if (lhs_type
&& rhs_type
)
4363 const unaryop_svalue
*lhs_un_op
= dyn_cast
<const unaryop_svalue
*> (lhs
);
4364 const unaryop_svalue
*rhs_un_op
= dyn_cast
<const unaryop_svalue
*> (rhs
);
4365 if (lhs_un_op
&& CONVERT_EXPR_CODE_P (lhs_un_op
->get_op ())
4366 && rhs_un_op
&& CONVERT_EXPR_CODE_P (rhs_un_op
->get_op ())
4367 && lhs_type
== rhs_type
)
4368 return eval_condition (lhs_un_op
->get_arg (),
4370 rhs_un_op
->get_arg ());
4372 else if (lhs_un_op
&& CONVERT_EXPR_CODE_P (lhs_un_op
->get_op ())
4373 && lhs_type
== rhs_type
)
4374 return eval_condition (lhs_un_op
->get_arg (), op
, rhs
);
4376 else if (rhs_un_op
&& CONVERT_EXPR_CODE_P (rhs_un_op
->get_op ())
4377 && lhs_type
== rhs_type
)
4378 return eval_condition (lhs
, op
, rhs_un_op
->get_arg ());
4381 /* Otherwise, try constraints.
4382 Cast to const to ensure we don't change the constraint_manager as we
4383 do this (e.g. by creating equivalence classes). */
4384 const constraint_manager
*constraints
= m_constraints
;
4385 return constraints
->eval_condition (lhs
, op
, rhs
);
4388 /* Subroutine of region_model::eval_condition, for rejecting
4389 equality of INIT_VAL(PARM) with &LOCAL. */
4392 region_model::compare_initial_and_pointer (const initial_svalue
*init
,
4393 const region_svalue
*ptr
) const
4395 const region
*pointee
= ptr
->get_pointee ();
4397 /* If we have a pointer to something within a stack frame, it can't be the
4398 initial value of a param. */
4399 if (pointee
->maybe_get_frame_region ())
4400 if (init
->initial_value_of_param_p ())
4401 return tristate::TS_FALSE
;
4403 return tristate::TS_UNKNOWN
;
4406 /* Return true if SVAL is definitely positive. */
4409 is_positive_svalue (const svalue
*sval
)
4411 if (tree cst
= sval
->maybe_get_constant ())
4412 return !zerop (cst
) && get_range_pos_neg (cst
) == 1;
4413 tree type
= sval
->get_type ();
4416 /* Consider a binary operation size_t + int. The analyzer wraps the int in
4417 an unaryop_svalue, converting it to a size_t, but in the dynamic execution
4418 the result is smaller than the first operand. Thus, we have to look if
4419 the argument of the unaryop_svalue is also positive. */
4420 if (const unaryop_svalue
*un_op
= dyn_cast
<const unaryop_svalue
*> (sval
))
4421 return CONVERT_EXPR_CODE_P (un_op
->get_op ()) && TYPE_UNSIGNED (type
)
4422 && is_positive_svalue (un_op
->get_arg ());
4423 return TYPE_UNSIGNED (type
);
4426 /* Return true if A is definitely larger than B.
4428 Limitation: does not account for integer overflows and does not try to
4429 return false, so it can not be used negated. */
4432 region_model::symbolic_greater_than (const binop_svalue
*bin_a
,
4433 const svalue
*b
) const
4435 if (bin_a
->get_op () == PLUS_EXPR
|| bin_a
->get_op () == MULT_EXPR
)
4437 /* Eliminate the right-hand side of both svalues. */
4438 if (const binop_svalue
*bin_b
= dyn_cast
<const binop_svalue
*> (b
))
4439 if (bin_a
->get_op () == bin_b
->get_op ()
4440 && eval_condition (bin_a
->get_arg1 (),
4442 bin_b
->get_arg1 ()).is_true ()
4443 && eval_condition (bin_a
->get_arg0 (),
4445 bin_b
->get_arg0 ()).is_true ())
4446 return tristate (tristate::TS_TRUE
);
4448 /* Otherwise, try to remove a positive offset or factor from BIN_A. */
4449 if (is_positive_svalue (bin_a
->get_arg1 ())
4450 && eval_condition (bin_a
->get_arg0 (),
4451 GE_EXPR
, b
).is_true ())
4452 return tristate (tristate::TS_TRUE
);
4454 return tristate::unknown ();
4457 /* Return true if A and B are equal structurally.
4459 Structural equality means that A and B are equal if the svalues A and B have
4460 the same nodes at the same positions in the tree and the leafs are equal.
4461 Equality for conjured_svalues and initial_svalues is determined by comparing
4462 the pointers while constants are compared by value. That behavior is useful
4463 to check for binaryop_svlaues that evaluate to the same concrete value but
4464 might use one operand with a different type but the same constant value.
4467 binop_svalue (mult_expr,
4468 initial_svalue (‘size_t’, decl_region (..., 'some_var')),
4469 constant_svalue (‘size_t’, 4))
4471 binop_svalue (mult_expr,
4472 initial_svalue (‘size_t’, decl_region (..., 'some_var'),
4473 constant_svalue (‘sizetype’, 4))
4474 are structurally equal. A concrete C code example, where this occurs, can
4475 be found in test7 of out-of-bounds-5.c. */
4478 region_model::structural_equality (const svalue
*a
, const svalue
*b
) const
4480 /* If A and B are referentially equal, they are also structurally equal. */
4482 return tristate (tristate::TS_TRUE
);
4484 switch (a
->get_kind ())
4487 return tristate::unknown ();
4488 /* SK_CONJURED and SK_INITIAL are already handled
4489 by the referential equality above. */
4492 tree a_cst
= a
->maybe_get_constant ();
4493 tree b_cst
= b
->maybe_get_constant ();
4495 return tristate (tree_int_cst_equal (a_cst
, b_cst
));
4497 return tristate (tristate::TS_FALSE
);
4500 const unaryop_svalue
*un_a
= as_a
<const unaryop_svalue
*> (a
);
4501 if (const unaryop_svalue
*un_b
= dyn_cast
<const unaryop_svalue
*> (b
))
4502 return tristate (pending_diagnostic::same_tree_p (un_a
->get_type (),
4504 && un_a
->get_op () == un_b
->get_op ()
4505 && structural_equality (un_a
->get_arg (),
4508 return tristate (tristate::TS_FALSE
);
4511 const binop_svalue
*bin_a
= as_a
<const binop_svalue
*> (a
);
4512 if (const binop_svalue
*bin_b
= dyn_cast
<const binop_svalue
*> (b
))
4513 return tristate (bin_a
->get_op () == bin_b
->get_op ()
4514 && structural_equality (bin_a
->get_arg0 (),
4516 && structural_equality (bin_a
->get_arg1 (),
4517 bin_b
->get_arg1 ()));
4519 return tristate (tristate::TS_FALSE
);
4523 /* Handle various constraints of the form:
4524 LHS: ((bool)INNER_LHS INNER_OP INNER_RHS))
4528 LHS: CAST([long]int, ((bool)INNER_LHS INNER_OP INNER_RHS))
4531 by adding constraints for INNER_LHS INNEROP INNER_RHS.
4533 Return true if this function can fully handle the constraint; if
4534 so, add the implied constraint(s) and write true to *OUT if they
4535 are consistent with existing constraints, or write false to *OUT
4536 if they contradicts existing constraints.
4538 Return false for cases that this function doeesn't know how to handle.
4540 For example, if we're checking a stored conditional, we'll have
4542 LHS: CAST(long int, (&HEAP_ALLOCATED_REGION(8)!=(int *)0B))
4545 which this function can turn into an add_constraint of:
4546 (&HEAP_ALLOCATED_REGION(8) != (int *)0B)
4548 Similarly, optimized && and || conditionals lead to e.g.
4550 becoming gimple like this:
4554 On the "_3 is false" branch we can have constraints of the form:
4555 ((&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
4556 | (&HEAP_ALLOCATED_REGION(10)!=(int *)0B))
4558 which implies that both _1 and _2 are false,
4559 which this function can turn into a pair of add_constraints of
4560 (&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
4562 (&HEAP_ALLOCATED_REGION(10)!=(int *)0B). */
4565 region_model::add_constraints_from_binop (const svalue
*outer_lhs
,
4566 enum tree_code outer_op
,
4567 const svalue
*outer_rhs
,
4569 region_model_context
*ctxt
)
4571 while (const svalue
*cast
= outer_lhs
->maybe_undo_cast ())
4573 const binop_svalue
*binop_sval
= outer_lhs
->dyn_cast_binop_svalue ();
4576 if (!outer_rhs
->all_zeroes_p ())
4579 const svalue
*inner_lhs
= binop_sval
->get_arg0 ();
4580 enum tree_code inner_op
= binop_sval
->get_op ();
4581 const svalue
*inner_rhs
= binop_sval
->get_arg1 ();
4583 if (outer_op
!= NE_EXPR
&& outer_op
!= EQ_EXPR
)
4587 - "OUTER_LHS != false" (i.e. OUTER is true), or
4588 - "OUTER_LHS == false" (i.e. OUTER is false). */
4589 bool is_true
= outer_op
== NE_EXPR
;
4603 /* ...and "(inner_lhs OP inner_rhs) == 0"
4604 then (inner_lhs OP inner_rhs) must have the same
4605 logical value as LHS. */
4607 inner_op
= invert_tree_comparison (inner_op
, false /* honor_nans */);
4608 *out
= add_constraint (inner_lhs
, inner_op
, inner_rhs
, ctxt
);
4616 /* ...and "(inner_lhs & inner_rhs) != 0"
4617 then both inner_lhs and inner_rhs must be true. */
4618 const svalue
*false_sval
4619 = m_mgr
->get_or_create_constant_svalue (boolean_false_node
);
4620 bool sat1
= add_constraint (inner_lhs
, NE_EXPR
, false_sval
, ctxt
);
4621 bool sat2
= add_constraint (inner_rhs
, NE_EXPR
, false_sval
, ctxt
);
4622 *out
= sat1
&& sat2
;
4630 /* ...and "(inner_lhs | inner_rhs) == 0"
4631 i.e. "(inner_lhs | inner_rhs)" is false
4632 then both inner_lhs and inner_rhs must be false. */
4633 const svalue
*false_sval
4634 = m_mgr
->get_or_create_constant_svalue (boolean_false_node
);
4635 bool sat1
= add_constraint (inner_lhs
, EQ_EXPR
, false_sval
, ctxt
);
4636 bool sat2
= add_constraint (inner_rhs
, EQ_EXPR
, false_sval
, ctxt
);
4637 *out
= sat1
&& sat2
;
4644 /* Attempt to add the constraint "LHS OP RHS" to this region_model.
4645 If it is consistent with existing constraints, add it, and return true.
4646 Return false if it contradicts existing constraints.
4647 Use CTXT for reporting any diagnostics associated with the accesses. */
4650 region_model::add_constraint (tree lhs
, enum tree_code op
, tree rhs
,
4651 region_model_context
*ctxt
)
4653 /* For now, make no attempt to capture constraints on floating-point
4655 if (FLOAT_TYPE_P (TREE_TYPE (lhs
)) || FLOAT_TYPE_P (TREE_TYPE (rhs
)))
4658 const svalue
*lhs_sval
= get_rvalue (lhs
, ctxt
);
4659 const svalue
*rhs_sval
= get_rvalue (rhs
, ctxt
);
4661 return add_constraint (lhs_sval
, op
, rhs_sval
, ctxt
);
4664 /* Attempt to add the constraint "LHS OP RHS" to this region_model.
4665 If it is consistent with existing constraints, add it, and return true.
4666 Return false if it contradicts existing constraints.
4667 Use CTXT for reporting any diagnostics associated with the accesses. */
4670 region_model::add_constraint (const svalue
*lhs
,
4673 region_model_context
*ctxt
)
4675 tristate t_cond
= eval_condition (lhs
, op
, rhs
);
4677 /* If we already have the condition, do nothing. */
4678 if (t_cond
.is_true ())
4681 /* Reject a constraint that would contradict existing knowledge, as
4683 if (t_cond
.is_false ())
4687 if (add_constraints_from_binop (lhs
, op
, rhs
, &out
, ctxt
))
4690 /* Attempt to store the constraint. */
4691 if (!m_constraints
->add_constraint (lhs
, op
, rhs
))
4694 /* Notify the context, if any. This exists so that the state machines
4695 in a program_state can be notified about the condition, and so can
4696 set sm-state for e.g. unchecked->checked, both for cfg-edges, and
4697 when synthesizing constraints as above. */
4699 ctxt
->on_condition (lhs
, op
, rhs
);
4701 /* If we have ®ION == NULL, then drop dynamic extents for REGION (for
4702 the case where REGION is heap-allocated and thus could be NULL). */
4703 if (tree rhs_cst
= rhs
->maybe_get_constant ())
4704 if (op
== EQ_EXPR
&& zerop (rhs_cst
))
4705 if (const region_svalue
*region_sval
= lhs
->dyn_cast_region_svalue ())
4706 unset_dynamic_extents (region_sval
->get_pointee ());
4711 /* As above, but when returning false, if OUT is non-NULL, write a
4712 new rejected_constraint to *OUT. */
4715 region_model::add_constraint (tree lhs
, enum tree_code op
, tree rhs
,
4716 region_model_context
*ctxt
,
4717 std::unique_ptr
<rejected_constraint
> *out
)
4719 bool sat
= add_constraint (lhs
, op
, rhs
, ctxt
);
4721 *out
= make_unique
<rejected_op_constraint
> (*this, lhs
, op
, rhs
);
4725 /* Determine what is known about the condition "LHS OP RHS" within
4727 Use CTXT for reporting any diagnostics associated with the accesses. */
4730 region_model::eval_condition (tree lhs
,
4733 region_model_context
*ctxt
) const
4735 /* For now, make no attempt to model constraints on floating-point
4737 if (FLOAT_TYPE_P (TREE_TYPE (lhs
)) || FLOAT_TYPE_P (TREE_TYPE (rhs
)))
4738 return tristate::unknown ();
4740 return eval_condition (get_rvalue (lhs
, ctxt
), op
, get_rvalue (rhs
, ctxt
));
4743 /* Implementation of region_model::get_representative_path_var.
4744 Attempt to return a path_var that represents SVAL, or return NULL_TREE.
4745 Use VISITED to prevent infinite mutual recursion with the overload for
4749 region_model::get_representative_path_var_1 (const svalue
*sval
,
4750 svalue_set
*visited
) const
4754 /* Prevent infinite recursion. */
4755 if (visited
->contains (sval
))
4757 if (sval
->get_kind () == SK_CONSTANT
)
4758 return path_var (sval
->maybe_get_constant (), 0);
4760 return path_var (NULL_TREE
, 0);
4762 visited
->add (sval
);
4764 /* Handle casts by recursion into get_representative_path_var. */
4765 if (const svalue
*cast_sval
= sval
->maybe_undo_cast ())
4767 path_var result
= get_representative_path_var (cast_sval
, visited
);
4768 tree orig_type
= sval
->get_type ();
4769 /* If necessary, wrap the result in a cast. */
4770 if (result
.m_tree
&& orig_type
)
4771 result
.m_tree
= build1 (NOP_EXPR
, orig_type
, result
.m_tree
);
4775 auto_vec
<path_var
> pvs
;
4776 m_store
.get_representative_path_vars (this, visited
, sval
, &pvs
);
4778 if (tree cst
= sval
->maybe_get_constant ())
4779 pvs
.safe_push (path_var (cst
, 0));
4781 /* Handle string literals and various other pointers. */
4782 if (const region_svalue
*ptr_sval
= sval
->dyn_cast_region_svalue ())
4784 const region
*reg
= ptr_sval
->get_pointee ();
4785 if (path_var pv
= get_representative_path_var (reg
, visited
))
4786 return path_var (build1 (ADDR_EXPR
,
4792 /* If we have a sub_svalue, look for ways to represent the parent. */
4793 if (const sub_svalue
*sub_sval
= sval
->dyn_cast_sub_svalue ())
4795 const svalue
*parent_sval
= sub_sval
->get_parent ();
4796 const region
*subreg
= sub_sval
->get_subregion ();
4797 if (path_var parent_pv
4798 = get_representative_path_var (parent_sval
, visited
))
4799 if (const field_region
*field_reg
= subreg
->dyn_cast_field_region ())
4800 return path_var (build3 (COMPONENT_REF
,
4803 field_reg
->get_field (),
4805 parent_pv
.m_stack_depth
);
4808 /* Handle binops. */
4809 if (const binop_svalue
*binop_sval
= sval
->dyn_cast_binop_svalue ())
4811 = get_representative_path_var (binop_sval
->get_arg0 (), visited
))
4813 = get_representative_path_var (binop_sval
->get_arg1 (), visited
))
4814 return path_var (build2 (binop_sval
->get_op (),
4816 lhs_pv
.m_tree
, rhs_pv
.m_tree
),
4817 lhs_pv
.m_stack_depth
);
4819 if (pvs
.length () < 1)
4820 return path_var (NULL_TREE
, 0);
4822 pvs
.qsort (readability_comparator
);
4826 /* Attempt to return a path_var that represents SVAL, or return NULL_TREE.
4827 Use VISITED to prevent infinite mutual recursion with the overload for
4830 This function defers to get_representative_path_var_1 to do the work;
4831 it adds verification that get_representative_path_var_1 returned a tree
4832 of the correct type. */
4835 region_model::get_representative_path_var (const svalue
*sval
,
4836 svalue_set
*visited
) const
4839 return path_var (NULL_TREE
, 0);
4841 tree orig_type
= sval
->get_type ();
4843 path_var result
= get_representative_path_var_1 (sval
, visited
);
4845 /* Verify that the result has the same type as SVAL, if any. */
4846 if (result
.m_tree
&& orig_type
)
4847 gcc_assert (TREE_TYPE (result
.m_tree
) == orig_type
);
4852 /* Attempt to return a tree that represents SVAL, or return NULL_TREE.
4854 Strip off any top-level cast, to avoid messages like
4855 double-free of '(void *)ptr'
4856 from analyzer diagnostics. */
4859 region_model::get_representative_tree (const svalue
*sval
) const
4862 tree expr
= get_representative_path_var (sval
, &visited
).m_tree
;
4864 /* Strip off any top-level cast. */
4865 if (expr
&& TREE_CODE (expr
) == NOP_EXPR
)
4866 expr
= TREE_OPERAND (expr
, 0);
4868 return fixup_tree_for_diagnostic (expr
);
4872 region_model::get_representative_tree (const region
*reg
) const
4875 tree expr
= get_representative_path_var (reg
, &visited
).m_tree
;
4877 /* Strip off any top-level cast. */
4878 if (expr
&& TREE_CODE (expr
) == NOP_EXPR
)
4879 expr
= TREE_OPERAND (expr
, 0);
4881 return fixup_tree_for_diagnostic (expr
);
4884 /* Implementation of region_model::get_representative_path_var.
4886 Attempt to return a path_var that represents REG, or return
4888 For example, a region for a field of a local would be a path_var
4889 wrapping a COMPONENT_REF.
4890 Use VISITED to prevent infinite mutual recursion with the overload for
4894 region_model::get_representative_path_var_1 (const region
*reg
,
4895 svalue_set
*visited
) const
4897 switch (reg
->get_kind ())
4907 case RK_THREAD_LOCAL
:
4909 /* Regions that represent memory spaces are not expressible as trees. */
4910 return path_var (NULL_TREE
, 0);
4914 const function_region
*function_reg
4915 = as_a
<const function_region
*> (reg
);
4916 return path_var (function_reg
->get_fndecl (), 0);
4920 const label_region
*label_reg
= as_a
<const label_region
*> (reg
);
4921 return path_var (label_reg
->get_label (), 0);
4926 const symbolic_region
*symbolic_reg
4927 = as_a
<const symbolic_region
*> (reg
);
4928 const svalue
*pointer
= symbolic_reg
->get_pointer ();
4929 path_var pointer_pv
= get_representative_path_var (pointer
, visited
);
4931 return path_var (NULL_TREE
, 0);
4932 tree offset
= build_int_cst (pointer
->get_type (), 0);
4933 return path_var (build2 (MEM_REF
,
4937 pointer_pv
.m_stack_depth
);
4941 const decl_region
*decl_reg
= as_a
<const decl_region
*> (reg
);
4942 return path_var (decl_reg
->get_decl (), decl_reg
->get_stack_depth ());
4946 const field_region
*field_reg
= as_a
<const field_region
*> (reg
);
4948 = get_representative_path_var (reg
->get_parent_region (), visited
);
4950 return path_var (NULL_TREE
, 0);
4951 return path_var (build3 (COMPONENT_REF
,
4954 field_reg
->get_field (),
4956 parent_pv
.m_stack_depth
);
4961 const element_region
*element_reg
4962 = as_a
<const element_region
*> (reg
);
4964 = get_representative_path_var (reg
->get_parent_region (), visited
);
4966 return path_var (NULL_TREE
, 0);
4968 = get_representative_path_var (element_reg
->get_index (), visited
);
4970 return path_var (NULL_TREE
, 0);
4971 return path_var (build4 (ARRAY_REF
,
4973 parent_pv
.m_tree
, index_pv
.m_tree
,
4974 NULL_TREE
, NULL_TREE
),
4975 parent_pv
.m_stack_depth
);
4980 const offset_region
*offset_reg
4981 = as_a
<const offset_region
*> (reg
);
4983 = get_representative_path_var (reg
->get_parent_region (), visited
);
4985 return path_var (NULL_TREE
, 0);
4987 = get_representative_path_var (offset_reg
->get_byte_offset (),
4989 if (!offset_pv
|| TREE_CODE (offset_pv
.m_tree
) != INTEGER_CST
)
4990 return path_var (NULL_TREE
, 0);
4991 tree addr_parent
= build1 (ADDR_EXPR
,
4992 build_pointer_type (reg
->get_type ()),
4994 return path_var (build2 (MEM_REF
,
4996 addr_parent
, offset_pv
.m_tree
),
4997 parent_pv
.m_stack_depth
);
5001 return path_var (NULL_TREE
, 0);
5006 = get_representative_path_var (reg
->get_parent_region (), visited
);
5008 return path_var (NULL_TREE
, 0);
5009 return path_var (build1 (NOP_EXPR
,
5012 parent_pv
.m_stack_depth
);
5015 case RK_HEAP_ALLOCATED
:
5017 /* No good way to express heap-allocated/alloca regions as trees. */
5018 return path_var (NULL_TREE
, 0);
5022 const string_region
*string_reg
= as_a
<const string_region
*> (reg
);
5023 return path_var (string_reg
->get_string_cst (), 0);
5029 return path_var (NULL_TREE
, 0);
5033 /* Attempt to return a path_var that represents REG, or return
5035 For example, a region for a field of a local would be a path_var
5036 wrapping a COMPONENT_REF.
5037 Use VISITED to prevent infinite mutual recursion with the overload for
5040 This function defers to get_representative_path_var_1 to do the work;
5041 it adds verification that get_representative_path_var_1 returned a tree
5042 of the correct type. */
5045 region_model::get_representative_path_var (const region
*reg
,
5046 svalue_set
*visited
) const
5048 path_var result
= get_representative_path_var_1 (reg
, visited
);
5050 /* Verify that the result has the same type as REG, if any. */
5051 if (result
.m_tree
&& reg
->get_type ())
5052 gcc_assert (TREE_TYPE (result
.m_tree
) == reg
->get_type ());
5057 /* Update this model for any phis in SNODE, assuming we came from
5058 LAST_CFG_SUPEREDGE. */
5061 region_model::update_for_phis (const supernode
*snode
,
5062 const cfg_superedge
*last_cfg_superedge
,
5063 region_model_context
*ctxt
)
5065 gcc_assert (last_cfg_superedge
);
5067 /* Copy this state and pass it to handle_phi so that all of the phi stmts
5068 are effectively handled simultaneously. */
5069 const region_model
old_state (*this);
5071 for (gphi_iterator gpi
= const_cast<supernode
*>(snode
)->start_phis ();
5072 !gsi_end_p (gpi
); gsi_next (&gpi
))
5074 gphi
*phi
= gpi
.phi ();
5076 tree src
= last_cfg_superedge
->get_phi_arg (phi
);
5077 tree lhs
= gimple_phi_result (phi
);
5079 /* Update next_state based on phi and old_state. */
5080 handle_phi (phi
, lhs
, src
, old_state
, ctxt
);
5084 /* Attempt to update this model for taking EDGE (where the last statement
5085 was LAST_STMT), returning true if the edge can be taken, false
5087 When returning false, if OUT is non-NULL, write a new rejected_constraint
5090 For CFG superedges where LAST_STMT is a conditional or a switch
5091 statement, attempt to add the relevant conditions for EDGE to this
5092 model, returning true if they are feasible, or false if they are
5095 For call superedges, push frame information and store arguments
5098 For return superedges, pop frame information and store return
5099 values into any lhs.
5101 Rejection of call/return superedges happens elsewhere, in
5102 program_point::on_edge (i.e. based on program point, rather
5103 than program state). */
5106 region_model::maybe_update_for_edge (const superedge
&edge
,
5107 const gimple
*last_stmt
,
5108 region_model_context
*ctxt
,
5109 std::unique_ptr
<rejected_constraint
> *out
)
5111 /* Handle frame updates for interprocedural edges. */
5112 switch (edge
.m_kind
)
5117 case SUPEREDGE_CALL
:
5119 const call_superedge
*call_edge
= as_a
<const call_superedge
*> (&edge
);
5120 update_for_call_superedge (*call_edge
, ctxt
);
5124 case SUPEREDGE_RETURN
:
5126 const return_superedge
*return_edge
5127 = as_a
<const return_superedge
*> (&edge
);
5128 update_for_return_superedge (*return_edge
, ctxt
);
5132 case SUPEREDGE_INTRAPROCEDURAL_CALL
:
5133 /* This is a no-op for call summaries; we should already
5134 have handled the effect of the call summary at the call stmt. */
5138 if (last_stmt
== NULL
)
5141 /* Apply any constraints for conditionals/switch/computed-goto statements. */
5143 if (const gcond
*cond_stmt
= dyn_cast
<const gcond
*> (last_stmt
))
5145 const cfg_superedge
*cfg_sedge
= as_a
<const cfg_superedge
*> (&edge
);
5146 return apply_constraints_for_gcond (*cfg_sedge
, cond_stmt
, ctxt
, out
);
5149 if (const gswitch
*switch_stmt
= dyn_cast
<const gswitch
*> (last_stmt
))
5151 const switch_cfg_superedge
*switch_sedge
5152 = as_a
<const switch_cfg_superedge
*> (&edge
);
5153 return apply_constraints_for_gswitch (*switch_sedge
, switch_stmt
,
5157 if (const ggoto
*goto_stmt
= dyn_cast
<const ggoto
*> (last_stmt
))
5159 const cfg_superedge
*cfg_sedge
= as_a
<const cfg_superedge
*> (&edge
);
5160 return apply_constraints_for_ggoto (*cfg_sedge
, goto_stmt
, ctxt
);
5163 /* Apply any constraints due to an exception being thrown. */
5164 if (const cfg_superedge
*cfg_sedge
= dyn_cast
<const cfg_superedge
*> (&edge
))
5165 if (cfg_sedge
->get_flags () & EDGE_EH
)
5166 return apply_constraints_for_exception (last_stmt
, ctxt
, out
);
5171 /* Push a new frame_region on to the stack region.
5172 Populate the frame_region with child regions for the function call's
5173 parameters, using values from the arguments at the callsite in the
5177 region_model::update_for_gcall (const gcall
*call_stmt
,
5178 region_model_context
*ctxt
,
5181 /* Build a vec of argument svalues, using the current top
5182 frame for resolving tree expressions. */
5183 auto_vec
<const svalue
*> arg_svals (gimple_call_num_args (call_stmt
));
5185 for (unsigned i
= 0; i
< gimple_call_num_args (call_stmt
); i
++)
5187 tree arg
= gimple_call_arg (call_stmt
, i
);
5188 arg_svals
.quick_push (get_rvalue (arg
, ctxt
));
5193 /* Get the function * from the gcall. */
5194 tree fn_decl
= get_fndecl_for_call (call_stmt
,ctxt
);
5195 callee
= DECL_STRUCT_FUNCTION (fn_decl
);
5198 push_frame (callee
, &arg_svals
, ctxt
);
5201 /* Pop the top-most frame_region from the stack, and copy the return
5202 region's values (if any) into the region for the lvalue of the LHS of
5203 the call (if any). */
5206 region_model::update_for_return_gcall (const gcall
*call_stmt
,
5207 region_model_context
*ctxt
)
5209 /* Get the lvalue for the result of the call, passing it to pop_frame,
5210 so that pop_frame can determine the region with respect to the
5212 tree lhs
= gimple_call_lhs (call_stmt
);
5213 pop_frame (lhs
, NULL
, ctxt
);
5216 /* Extract calling information from the superedge and update the model for the
5220 region_model::update_for_call_superedge (const call_superedge
&call_edge
,
5221 region_model_context
*ctxt
)
5223 const gcall
*call_stmt
= call_edge
.get_call_stmt ();
5224 update_for_gcall (call_stmt
, ctxt
, call_edge
.get_callee_function ());
5227 /* Extract calling information from the return superedge and update the model
5228 for the returning call */
5231 region_model::update_for_return_superedge (const return_superedge
&return_edge
,
5232 region_model_context
*ctxt
)
5234 const gcall
*call_stmt
= return_edge
.get_call_stmt ();
5235 update_for_return_gcall (call_stmt
, ctxt
);
5238 /* Attempt to to use R to replay SUMMARY into this object.
5239 Return true if it is possible. */
5242 region_model::replay_call_summary (call_summary_replay
&r
,
5243 const region_model
&summary
)
5245 gcc_assert (summary
.get_stack_depth () == 1);
5247 m_store
.replay_call_summary (r
, summary
.m_store
);
5249 if (!m_constraints
->replay_call_summary (r
, *summary
.m_constraints
))
5252 for (auto kv
: summary
.m_dynamic_extents
)
5254 const region
*summary_reg
= kv
.first
;
5255 const region
*caller_reg
= r
.convert_region_from_summary (summary_reg
);
5258 const svalue
*summary_sval
= kv
.second
;
5259 const svalue
*caller_sval
= r
.convert_svalue_from_summary (summary_sval
);
5262 m_dynamic_extents
.put (caller_reg
, caller_sval
);
5268 /* Given a true or false edge guarded by conditional statement COND_STMT,
5269 determine appropriate constraints for the edge to be taken.
5271 If they are feasible, add the constraints and return true.
5273 Return false if the constraints contradict existing knowledge
5274 (and so the edge should not be taken).
5275 When returning false, if OUT is non-NULL, write a new rejected_constraint
5280 apply_constraints_for_gcond (const cfg_superedge
&sedge
,
5281 const gcond
*cond_stmt
,
5282 region_model_context
*ctxt
,
5283 std::unique_ptr
<rejected_constraint
> *out
)
5285 ::edge cfg_edge
= sedge
.get_cfg_edge ();
5286 gcc_assert (cfg_edge
!= NULL
);
5287 gcc_assert (cfg_edge
->flags
& (EDGE_TRUE_VALUE
| EDGE_FALSE_VALUE
));
5289 enum tree_code op
= gimple_cond_code (cond_stmt
);
5290 tree lhs
= gimple_cond_lhs (cond_stmt
);
5291 tree rhs
= gimple_cond_rhs (cond_stmt
);
5292 if (cfg_edge
->flags
& EDGE_FALSE_VALUE
)
5293 op
= invert_tree_comparison (op
, false /* honor_nans */);
5294 return add_constraint (lhs
, op
, rhs
, ctxt
, out
);
5297 /* Return true iff SWITCH_STMT has a non-default label that contains
5301 has_nondefault_case_for_value_p (const gswitch
*switch_stmt
, tree int_cst
)
5303 /* We expect the initial label to be the default; skip it. */
5304 gcc_assert (CASE_LOW (gimple_switch_label (switch_stmt
, 0)) == NULL
);
5305 unsigned min_idx
= 1;
5306 unsigned max_idx
= gimple_switch_num_labels (switch_stmt
) - 1;
5308 /* Binary search: try to find the label containing INT_CST.
5309 This requires the cases to be sorted by CASE_LOW (done by the
5311 while (max_idx
>= min_idx
)
5313 unsigned case_idx
= (min_idx
+ max_idx
) / 2;
5314 tree label
= gimple_switch_label (switch_stmt
, case_idx
);
5315 tree low
= CASE_LOW (label
);
5317 tree high
= CASE_HIGH (label
);
5320 if (tree_int_cst_compare (int_cst
, low
) < 0)
5322 /* INT_CST is below the range of this label. */
5323 gcc_assert (case_idx
> 0);
5324 max_idx
= case_idx
- 1;
5326 else if (tree_int_cst_compare (int_cst
, high
) > 0)
5328 /* INT_CST is above the range of this case. */
5329 min_idx
= case_idx
+ 1;
5332 /* This case contains INT_CST. */
5339 /* Return true iff SWITCH_STMT (which must be on an enum value)
5340 has nondefault cases handling all values in the enum. */
5343 has_nondefault_cases_for_all_enum_values_p (const gswitch
*switch_stmt
)
5345 gcc_assert (switch_stmt
);
5346 tree type
= TREE_TYPE (gimple_switch_index (switch_stmt
));
5347 gcc_assert (TREE_CODE (type
) == ENUMERAL_TYPE
);
5349 for (tree enum_val_iter
= TYPE_VALUES (type
);
5351 enum_val_iter
= TREE_CHAIN (enum_val_iter
))
5353 tree enum_val
= TREE_VALUE (enum_val_iter
);
5354 gcc_assert (TREE_CODE (enum_val
) == CONST_DECL
);
5355 gcc_assert (TREE_CODE (DECL_INITIAL (enum_val
)) == INTEGER_CST
);
5356 if (!has_nondefault_case_for_value_p (switch_stmt
,
5357 DECL_INITIAL (enum_val
)))
5363 /* Given an EDGE guarded by SWITCH_STMT, determine appropriate constraints
5364 for the edge to be taken.
5366 If they are feasible, add the constraints and return true.
5368 Return false if the constraints contradict existing knowledge
5369 (and so the edge should not be taken).
5370 When returning false, if OUT is non-NULL, write a new rejected_constraint
5375 apply_constraints_for_gswitch (const switch_cfg_superedge
&edge
,
5376 const gswitch
*switch_stmt
,
5377 region_model_context
*ctxt
,
5378 std::unique_ptr
<rejected_constraint
> *out
)
5380 tree index
= gimple_switch_index (switch_stmt
);
5381 const svalue
*index_sval
= get_rvalue (index
, ctxt
);
5383 /* If we're switching based on an enum type, assume that the user is only
5384 working with values from the enum. Hence if this is an
5385 implicitly-created "default", assume it doesn't get followed.
5386 This fixes numerous "uninitialized" false positives where we otherwise
5387 consider jumping past the initialization cases. */
5389 if (/* Don't check during feasibility-checking (when ctxt is NULL). */
5391 /* Must be an enum value. */
5392 && index_sval
->get_type ()
5393 && TREE_CODE (TREE_TYPE (index
)) == ENUMERAL_TYPE
5394 && TREE_CODE (index_sval
->get_type ()) == ENUMERAL_TYPE
5395 /* If we have a constant, then we can check it directly. */
5396 && index_sval
->get_kind () != SK_CONSTANT
5397 && edge
.implicitly_created_default_p ()
5398 && has_nondefault_cases_for_all_enum_values_p (switch_stmt
)
5399 /* Don't do this if there's a chance that the index is
5400 attacker-controlled. */
5401 && !ctxt
->possibly_tainted_p (index_sval
))
5404 *out
= make_unique
<rejected_default_case
> (*this);
5408 bounded_ranges_manager
*ranges_mgr
= get_range_manager ();
5409 const bounded_ranges
*all_cases_ranges
5410 = ranges_mgr
->get_or_create_ranges_for_switch (&edge
, switch_stmt
);
5411 bool sat
= m_constraints
->add_bounded_ranges (index_sval
, all_cases_ranges
);
5413 *out
= make_unique
<rejected_ranges_constraint
> (*this, index
, all_cases_ranges
);
5414 if (sat
&& ctxt
&& !all_cases_ranges
->empty_p ())
5415 ctxt
->on_bounded_ranges (*index_sval
, *all_cases_ranges
);
5419 /* Given an edge reached by GOTO_STMT, determine appropriate constraints
5420 for the edge to be taken.
5422 If they are feasible, add the constraints and return true.
5424 Return false if the constraints contradict existing knowledge
5425 (and so the edge should not be taken). */
5428 region_model::apply_constraints_for_ggoto (const cfg_superedge
&edge
,
5429 const ggoto
*goto_stmt
,
5430 region_model_context
*ctxt
)
5432 tree dest
= gimple_goto_dest (goto_stmt
);
5433 const svalue
*dest_sval
= get_rvalue (dest
, ctxt
);
5435 /* If we know we were jumping to a specific label. */
5436 if (tree dst_label
= edge
.m_dest
->get_label ())
5438 const label_region
*dst_label_reg
5439 = m_mgr
->get_region_for_label (dst_label
);
5440 const svalue
*dst_label_ptr
5441 = m_mgr
->get_ptr_svalue (ptr_type_node
, dst_label_reg
);
5443 if (!add_constraint (dest_sval
, EQ_EXPR
, dst_label_ptr
, ctxt
))
5450 /* Apply any constraints due to an exception being thrown at LAST_STMT.
5452 If they are feasible, add the constraints and return true.
5454 Return false if the constraints contradict existing knowledge
5455 (and so the edge should not be taken).
5456 When returning false, if OUT is non-NULL, write a new rejected_constraint
5461 apply_constraints_for_exception (const gimple
*last_stmt
,
5462 region_model_context
*ctxt
,
5463 std::unique_ptr
<rejected_constraint
> *out
)
5465 gcc_assert (last_stmt
);
5466 if (const gcall
*call
= dyn_cast
<const gcall
*> (last_stmt
))
5467 if (tree callee_fndecl
= get_fndecl_for_call (call
, ctxt
))
5468 if (is_named_call_p (callee_fndecl
, "operator new", call
, 1)
5469 || is_named_call_p (callee_fndecl
, "operator new []", call
, 1))
5471 /* We have an exception thrown from operator new.
5472 Add a constraint that the result was NULL, to avoid a false
5473 leak report due to the result being lost when following
5475 if (tree lhs
= gimple_call_lhs (call
))
5476 return add_constraint (lhs
, EQ_EXPR
, null_pointer_node
, ctxt
, out
);
5482 /* For use with push_frame when handling a top-level call within the analysis.
5483 PARAM has a defined but unknown initial value.
5484 Anything it points to has escaped, since the calling context "knows"
5485 the pointer, and thus calls to unknown functions could read/write into
5487 If NONNULL is true, then assume that PARAM must be non-NULL. */
5490 region_model::on_top_level_param (tree param
,
5492 region_model_context
*ctxt
)
5494 if (POINTER_TYPE_P (TREE_TYPE (param
)))
5496 const region
*param_reg
= get_lvalue (param
, ctxt
);
5497 const svalue
*init_ptr_sval
5498 = m_mgr
->get_or_create_initial_value (param_reg
);
5499 const region
*pointee_reg
= m_mgr
->get_symbolic_region (init_ptr_sval
);
5500 m_store
.mark_as_escaped (pointee_reg
);
5503 const svalue
*null_ptr_sval
5504 = m_mgr
->get_or_create_null_ptr (TREE_TYPE (param
));
5505 add_constraint (init_ptr_sval
, NE_EXPR
, null_ptr_sval
, ctxt
);
5510 /* Update this region_model to reflect pushing a frame onto the stack
5513 If ARG_SVALS is non-NULL, use it to populate the parameters
5515 Otherwise, the params have their initial_svalues.
5517 Return the frame_region for the new frame. */
5520 region_model::push_frame (function
*fun
, const vec
<const svalue
*> *arg_svals
,
5521 region_model_context
*ctxt
)
5523 m_current_frame
= m_mgr
->get_frame_region (m_current_frame
, fun
);
5526 /* Arguments supplied from a caller frame. */
5527 tree fndecl
= fun
->decl
;
5529 for (tree iter_parm
= DECL_ARGUMENTS (fndecl
); iter_parm
;
5530 iter_parm
= DECL_CHAIN (iter_parm
), ++idx
)
5532 /* If there's a mismatching declaration, the call stmt might
5533 not have enough args. Handle this case by leaving the
5534 rest of the params as uninitialized. */
5535 if (idx
>= arg_svals
->length ())
5537 tree parm_lval
= iter_parm
;
5538 if (tree parm_default_ssa
= ssa_default_def (fun
, iter_parm
))
5539 parm_lval
= parm_default_ssa
;
5540 const region
*parm_reg
= get_lvalue (parm_lval
, ctxt
);
5541 const svalue
*arg_sval
= (*arg_svals
)[idx
];
5542 set_value (parm_reg
, arg_sval
, ctxt
);
5545 /* Handle any variadic args. */
5546 unsigned va_arg_idx
= 0;
5547 for (; idx
< arg_svals
->length (); idx
++, va_arg_idx
++)
5549 const svalue
*arg_sval
= (*arg_svals
)[idx
];
5550 const region
*var_arg_reg
5551 = m_mgr
->get_var_arg_region (m_current_frame
,
5553 set_value (var_arg_reg
, arg_sval
, ctxt
);
5558 /* Otherwise we have a top-level call within the analysis. The params
5559 have defined but unknown initial values.
5560 Anything they point to has escaped. */
5561 tree fndecl
= fun
->decl
;
5563 /* Handle "__attribute__((nonnull))". */
5564 tree fntype
= TREE_TYPE (fndecl
);
5565 bitmap nonnull_args
= get_nonnull_args (fntype
);
5567 unsigned parm_idx
= 0;
5568 for (tree iter_parm
= DECL_ARGUMENTS (fndecl
); iter_parm
;
5569 iter_parm
= DECL_CHAIN (iter_parm
))
5571 bool non_null
= (nonnull_args
5572 ? (bitmap_empty_p (nonnull_args
)
5573 || bitmap_bit_p (nonnull_args
, parm_idx
))
5575 if (tree parm_default_ssa
= ssa_default_def (fun
, iter_parm
))
5576 on_top_level_param (parm_default_ssa
, non_null
, ctxt
);
5578 on_top_level_param (iter_parm
, non_null
, ctxt
);
5582 BITMAP_FREE (nonnull_args
);
5585 return m_current_frame
;
5588 /* Get the function of the top-most frame in this region_model's stack.
5589 There must be such a frame. */
5592 region_model::get_current_function () const
5594 const frame_region
*frame
= get_current_frame ();
5596 return frame
->get_function ();
5599 /* Pop the topmost frame_region from this region_model's stack;
5601 If RESULT_LVALUE is non-null, copy any return value from the frame
5602 into the corresponding region (evaluated with respect to the *caller*
5603 frame, rather than the called frame).
5604 If OUT_RESULT is non-null, copy any return value from the frame
5607 If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
5608 This is for use when unwinding frames e.g. due to longjmp, to suppress
5609 erroneously reporting uninitialized return values.
5611 Purge the frame region and all its descendent regions.
5612 Convert any pointers that point into such regions into
5613 POISON_KIND_POPPED_STACK svalues. */
5616 region_model::pop_frame (tree result_lvalue
,
5617 const svalue
**out_result
,
5618 region_model_context
*ctxt
,
5619 bool eval_return_svalue
)
5621 gcc_assert (m_current_frame
);
5623 const region_model pre_popped_model
= *this;
5624 const frame_region
*frame_reg
= m_current_frame
;
5626 /* Notify state machines. */
5628 ctxt
->on_pop_frame (frame_reg
);
5630 /* Evaluate the result, within the callee frame. */
5631 tree fndecl
= m_current_frame
->get_function ()->decl
;
5632 tree result
= DECL_RESULT (fndecl
);
5633 const svalue
*retval
= NULL
;
5635 && TREE_TYPE (result
) != void_type_node
5636 && eval_return_svalue
)
5638 retval
= get_rvalue (result
, ctxt
);
5640 *out_result
= retval
;
5643 /* Pop the frame. */
5644 m_current_frame
= m_current_frame
->get_calling_frame ();
5646 if (result_lvalue
&& retval
)
5648 gcc_assert (eval_return_svalue
);
5650 /* Compute result_dst_reg using RESULT_LVALUE *after* popping
5651 the frame, but before poisoning pointers into the old frame. */
5652 const region
*result_dst_reg
= get_lvalue (result_lvalue
, ctxt
);
5653 set_value (result_dst_reg
, retval
, ctxt
);
5656 unbind_region_and_descendents (frame_reg
,POISON_KIND_POPPED_STACK
);
5657 notify_on_pop_frame (this, &pre_popped_model
, retval
, ctxt
);
5660 /* Get the number of frames in this region_model's stack. */
5663 region_model::get_stack_depth () const
5665 const frame_region
*frame
= get_current_frame ();
5667 return frame
->get_stack_depth ();
5672 /* Get the frame_region with the given index within the stack.
5673 The frame_region must exist. */
5675 const frame_region
*
5676 region_model::get_frame_at_index (int index
) const
5678 const frame_region
*frame
= get_current_frame ();
5680 gcc_assert (index
>= 0);
5681 gcc_assert (index
<= frame
->get_index ());
5682 while (index
!= frame
->get_index ())
5684 frame
= frame
->get_calling_frame ();
5690 /* Unbind svalues for any regions in REG and below.
5691 Find any pointers to such regions; convert them to
5692 poisoned values of kind PKIND.
5693 Also purge any dynamic extents. */
5696 region_model::unbind_region_and_descendents (const region
*reg
,
5697 enum poison_kind pkind
)
5699 /* Gather a set of base regions to be unbound. */
5700 hash_set
<const region
*> base_regs
;
5701 for (store::cluster_map_t::iterator iter
= m_store
.begin ();
5702 iter
!= m_store
.end (); ++iter
)
5704 const region
*iter_base_reg
= (*iter
).first
;
5705 if (iter_base_reg
->descendent_of_p (reg
))
5706 base_regs
.add (iter_base_reg
);
5708 for (hash_set
<const region
*>::iterator iter
= base_regs
.begin ();
5709 iter
!= base_regs
.end (); ++iter
)
5710 m_store
.purge_cluster (*iter
);
5712 /* Find any pointers to REG or its descendents; convert to poisoned. */
5713 poison_any_pointers_to_descendents (reg
, pkind
);
5715 /* Purge dynamic extents of any base regions in REG and below
5716 (e.g. VLAs and alloca stack regions). */
5717 for (auto iter
: m_dynamic_extents
)
5719 const region
*iter_reg
= iter
.first
;
5720 if (iter_reg
->descendent_of_p (reg
))
5721 unset_dynamic_extents (iter_reg
);
5725 /* Implementation of BindingVisitor.
5726 Update the bound svalues for regions below REG to use poisoned
5729 struct bad_pointer_finder
5731 bad_pointer_finder (const region
*reg
, enum poison_kind pkind
,
5732 region_model_manager
*mgr
)
5733 : m_reg (reg
), m_pkind (pkind
), m_mgr (mgr
), m_count (0)
5736 void on_binding (const binding_key
*, const svalue
*&sval
)
5738 if (const region_svalue
*ptr_sval
= sval
->dyn_cast_region_svalue ())
5740 const region
*ptr_dst
= ptr_sval
->get_pointee ();
5741 /* Poison ptrs to descendents of REG, but not to REG itself,
5742 otherwise double-free detection doesn't work (since sm-state
5743 for "free" is stored on the original ptr svalue). */
5744 if (ptr_dst
->descendent_of_p (m_reg
)
5745 && ptr_dst
!= m_reg
)
5747 sval
= m_mgr
->get_or_create_poisoned_svalue (m_pkind
,
5754 const region
*m_reg
;
5755 enum poison_kind m_pkind
;
5756 region_model_manager
*const m_mgr
;
5760 /* Find any pointers to REG or its descendents; convert them to
5761 poisoned values of kind PKIND.
5762 Return the number of pointers that were poisoned. */
5765 region_model::poison_any_pointers_to_descendents (const region
*reg
,
5766 enum poison_kind pkind
)
5768 bad_pointer_finder
bv (reg
, pkind
, m_mgr
);
5769 m_store
.for_each_binding (bv
);
5773 /* Attempt to merge THIS with OTHER_MODEL, writing the result
5774 to OUT_MODEL. Use POINT to distinguish values created as a
5775 result of merging. */
5778 region_model::can_merge_with_p (const region_model
&other_model
,
5779 const program_point
&point
,
5780 region_model
*out_model
,
5781 const extrinsic_state
*ext_state
,
5782 const program_state
*state_a
,
5783 const program_state
*state_b
) const
5785 gcc_assert (out_model
);
5786 gcc_assert (m_mgr
== other_model
.m_mgr
);
5787 gcc_assert (m_mgr
== out_model
->m_mgr
);
5789 if (m_current_frame
!= other_model
.m_current_frame
)
5791 out_model
->m_current_frame
= m_current_frame
;
5793 model_merger
m (this, &other_model
, point
, out_model
,
5794 ext_state
, state_a
, state_b
);
5796 if (!store::can_merge_p (&m_store
, &other_model
.m_store
,
5797 &out_model
->m_store
, m_mgr
->get_store_manager (),
5801 if (!m_dynamic_extents
.can_merge_with_p (other_model
.m_dynamic_extents
,
5802 &out_model
->m_dynamic_extents
))
5805 /* Merge constraints. */
5806 constraint_manager::merge (*m_constraints
,
5807 *other_model
.m_constraints
,
5808 out_model
->m_constraints
);
5813 /* Attempt to get the fndecl used at CALL, if known, or NULL_TREE
5817 region_model::get_fndecl_for_call (const gcall
*call
,
5818 region_model_context
*ctxt
)
5820 tree fn_ptr
= gimple_call_fn (call
);
5821 if (fn_ptr
== NULL_TREE
)
5823 const svalue
*fn_ptr_sval
= get_rvalue (fn_ptr
, ctxt
);
5824 if (const region_svalue
*fn_ptr_ptr
5825 = fn_ptr_sval
->dyn_cast_region_svalue ())
5827 const region
*reg
= fn_ptr_ptr
->get_pointee ();
5828 if (const function_region
*fn_reg
= reg
->dyn_cast_function_region ())
5830 tree fn_decl
= fn_reg
->get_fndecl ();
5831 cgraph_node
*node
= cgraph_node::get (fn_decl
);
5834 const cgraph_node
*ultimate_node
= node
->ultimate_alias_target ();
5836 return ultimate_node
->decl
;
5843 /* Would be much simpler to use a lambda here, if it were supported. */
5845 struct append_regions_cb_data
5847 const region_model
*model
;
5848 auto_vec
<const decl_region
*> *out
;
5851 /* Populate *OUT with all decl_regions in the current
5852 frame that have clusters within the store. */
5856 get_regions_for_current_frame (auto_vec
<const decl_region
*> *out
) const
5858 append_regions_cb_data data
;
5861 m_store
.for_each_cluster (append_regions_cb
, &data
);
5864 /* Implementation detail of get_regions_for_current_frame. */
5867 region_model::append_regions_cb (const region
*base_reg
,
5868 append_regions_cb_data
*cb_data
)
5870 if (base_reg
->get_parent_region () != cb_data
->model
->m_current_frame
)
5872 if (const decl_region
*decl_reg
= base_reg
->dyn_cast_decl_region ())
5873 cb_data
->out
->safe_push (decl_reg
);
5877 /* Abstract class for diagnostics related to the use of
5878 floating-point arithmetic where precision is needed. */
5880 class imprecise_floating_point_arithmetic
: public pending_diagnostic
5883 int get_controlling_option () const final override
5885 return OPT_Wanalyzer_imprecise_fp_arithmetic
;
5889 /* Concrete diagnostic to complain about uses of floating-point arithmetic
5890 in the size argument of malloc etc. */
5892 class float_as_size_arg
: public imprecise_floating_point_arithmetic
5895 float_as_size_arg (tree arg
) : m_arg (arg
)
5898 const char *get_kind () const final override
5900 return "float_as_size_arg_diagnostic";
5903 bool subclass_equal_p (const pending_diagnostic
&other
) const final override
5905 return same_tree_p (m_arg
, ((const float_as_size_arg
&) other
).m_arg
);
5908 bool emit (rich_location
*rich_loc
, logger
*) final override
5910 diagnostic_metadata m
;
5911 bool warned
= warning_meta (rich_loc
, m
, get_controlling_option (),
5912 "use of floating-point arithmetic here might"
5913 " yield unexpected results");
5915 inform (rich_loc
->get_loc (), "only use operands of an integer type"
5916 " inside the size argument");
5920 label_text
describe_final_event (const evdesc::final_event
&ev
) final
5924 return ev
.formatted_print ("operand %qE is of type %qT",
5925 m_arg
, TREE_TYPE (m_arg
));
5926 return ev
.formatted_print ("at least one operand of the size argument is"
5927 " of a floating-point type");
5934 /* Visitor to find uses of floating-point variables/constants in an svalue. */
5936 class contains_floating_point_visitor
: public visitor
5939 contains_floating_point_visitor (const svalue
*root_sval
) : m_result (NULL
)
5941 root_sval
->accept (this);
5944 const svalue
*get_svalue_to_report ()
5949 void visit_constant_svalue (const constant_svalue
*sval
) final override
5951 /* At the point the analyzer runs, constant integer operands in a floating
5952 point expression are already implictly converted to floating-points.
5953 Thus, we do prefer to report non-constants such that the diagnostic
5954 always reports a floating-point operand. */
5955 tree type
= sval
->get_type ();
5956 if (type
&& FLOAT_TYPE_P (type
) && !m_result
)
5960 void visit_conjured_svalue (const conjured_svalue
*sval
) final override
5962 tree type
= sval
->get_type ();
5963 if (type
&& FLOAT_TYPE_P (type
))
5967 void visit_initial_svalue (const initial_svalue
*sval
) final override
5969 tree type
= sval
->get_type ();
5970 if (type
&& FLOAT_TYPE_P (type
))
5975 /* Non-null if at least one floating-point operand was found. */
5976 const svalue
*m_result
;
5979 /* May complain about uses of floating-point operands in SIZE_IN_BYTES. */
5982 region_model::check_dynamic_size_for_floats (const svalue
*size_in_bytes
,
5983 region_model_context
*ctxt
) const
5987 contains_floating_point_visitor
v (size_in_bytes
);
5988 if (const svalue
*float_sval
= v
.get_svalue_to_report ())
5990 tree diag_arg
= get_representative_tree (float_sval
);
5991 ctxt
->warn (make_unique
<float_as_size_arg
> (diag_arg
));
5995 /* Return a region describing a heap-allocated block of memory.
5996 Use CTXT to complain about tainted sizes.
5998 Reuse an existing heap_allocated_region if it's not being referenced by
5999 this region_model; otherwise create a new one.
6001 Optionally (update_state_machine) transitions the pointer pointing to the
6002 heap_allocated_region from start to assumed non-null. */
6005 region_model::get_or_create_region_for_heap_alloc (const svalue
*size_in_bytes
,
6006 region_model_context
*ctxt
,
6007 bool update_state_machine
,
6008 const call_details
*cd
)
6010 /* Determine which regions are referenced in this region_model, so that
6011 we can reuse an existing heap_allocated_region if it's not in use on
6013 auto_bitmap base_regs_in_use
;
6014 get_referenced_base_regions (base_regs_in_use
);
6016 /* Don't reuse regions that are marked as TOUCHED. */
6017 for (store::cluster_map_t::iterator iter
= m_store
.begin ();
6018 iter
!= m_store
.end (); ++iter
)
6019 if ((*iter
).second
->touched_p ())
6021 const region
*base_reg
= (*iter
).first
;
6022 bitmap_set_bit (base_regs_in_use
, base_reg
->get_id ());
6026 = m_mgr
->get_or_create_region_for_heap_alloc (base_regs_in_use
);
6028 if (compat_types_p (size_in_bytes
->get_type (), size_type_node
))
6029 set_dynamic_extents (reg
, size_in_bytes
, ctxt
);
6031 if (update_state_machine
&& cd
)
6033 const svalue
*ptr_sval
6034 = m_mgr
->get_ptr_svalue (cd
->get_lhs_type (), reg
);
6035 transition_ptr_sval_non_null (ctxt
, ptr_sval
);
6041 /* Populate OUT_IDS with the set of IDs of those base regions which are
6042 reachable in this region_model. */
6045 region_model::get_referenced_base_regions (auto_bitmap
&out_ids
) const
6047 reachable_regions
reachable_regs (const_cast<region_model
*> (this));
6048 m_store
.for_each_cluster (reachable_regions::init_cluster_cb
,
6050 /* Get regions for locals that have explicitly bound values. */
6051 for (store::cluster_map_t::iterator iter
= m_store
.begin ();
6052 iter
!= m_store
.end (); ++iter
)
6054 const region
*base_reg
= (*iter
).first
;
6055 if (const region
*parent
= base_reg
->get_parent_region ())
6056 if (parent
->get_kind () == RK_FRAME
)
6057 reachable_regs
.add (base_reg
, false);
6060 bitmap_clear (out_ids
);
6061 for (auto iter_reg
: reachable_regs
)
6062 bitmap_set_bit (out_ids
, iter_reg
->get_id ());
6065 /* Return a new region describing a block of memory allocated within the
6067 Use CTXT to complain about tainted sizes. */
6070 region_model::create_region_for_alloca (const svalue
*size_in_bytes
,
6071 region_model_context
*ctxt
)
6073 const region
*reg
= m_mgr
->create_region_for_alloca (m_current_frame
);
6074 if (compat_types_p (size_in_bytes
->get_type (), size_type_node
))
6075 set_dynamic_extents (reg
, size_in_bytes
, ctxt
);
6079 /* Record that the size of REG is SIZE_IN_BYTES.
6080 Use CTXT to complain about tainted sizes. */
6083 region_model::set_dynamic_extents (const region
*reg
,
6084 const svalue
*size_in_bytes
,
6085 region_model_context
*ctxt
)
6087 assert_compat_types (size_in_bytes
->get_type (), size_type_node
);
6090 check_dynamic_size_for_taint (reg
->get_memory_space (), size_in_bytes
,
6092 check_dynamic_size_for_floats (size_in_bytes
, ctxt
);
6094 m_dynamic_extents
.put (reg
, size_in_bytes
);
6097 /* Get the recording of REG in bytes, or NULL if no dynamic size was
6101 region_model::get_dynamic_extents (const region
*reg
) const
6103 if (const svalue
* const *slot
= m_dynamic_extents
.get (reg
))
6108 /* Unset any recorded dynamic size of REG. */
6111 region_model::unset_dynamic_extents (const region
*reg
)
6113 m_dynamic_extents
.remove (reg
);
6116 /* A subclass of pending_diagnostic for complaining about uninitialized data
6117 being copied across a trust boundary to an untrusted output
6118 (e.g. copy_to_user infoleaks in the Linux kernel). */
6120 class exposure_through_uninit_copy
6121 : public pending_diagnostic_subclass
<exposure_through_uninit_copy
>
6124 exposure_through_uninit_copy (const region
*src_region
,
6125 const region
*dest_region
,
6126 const svalue
*copied_sval
)
6127 : m_src_region (src_region
),
6128 m_dest_region (dest_region
),
6129 m_copied_sval (copied_sval
)
6131 gcc_assert (m_copied_sval
->get_kind () == SK_POISONED
6132 || m_copied_sval
->get_kind () == SK_COMPOUND
);
6135 const char *get_kind () const final override
6137 return "exposure_through_uninit_copy";
6140 bool operator== (const exposure_through_uninit_copy
&other
) const
6142 return (m_src_region
== other
.m_src_region
6143 && m_dest_region
== other
.m_dest_region
6144 && m_copied_sval
== other
.m_copied_sval
);
6147 int get_controlling_option () const final override
6149 return OPT_Wanalyzer_exposure_through_uninit_copy
;
6152 bool emit (rich_location
*rich_loc
, logger
*) final override
6154 diagnostic_metadata m
;
6155 /* CWE-200: Exposure of Sensitive Information to an Unauthorized Actor. */
6157 enum memory_space mem_space
= get_src_memory_space ();
6162 warned
= warning_meta
6163 (rich_loc
, m
, get_controlling_option (),
6164 "potential exposure of sensitive information"
6165 " by copying uninitialized data across trust boundary");
6167 case MEMSPACE_STACK
:
6168 warned
= warning_meta
6169 (rich_loc
, m
, get_controlling_option (),
6170 "potential exposure of sensitive information"
6171 " by copying uninitialized data from stack across trust boundary");
6174 warned
= warning_meta
6175 (rich_loc
, m
, get_controlling_option (),
6176 "potential exposure of sensitive information"
6177 " by copying uninitialized data from heap across trust boundary");
6182 location_t loc
= rich_loc
->get_loc ();
6183 inform_number_of_uninit_bits (loc
);
6184 complain_about_uninit_ranges (loc
);
6186 if (mem_space
== MEMSPACE_STACK
)
6187 maybe_emit_fixit_hint ();
6192 label_text
describe_final_event (const evdesc::final_event
&) final override
6194 enum memory_space mem_space
= get_src_memory_space ();
6198 return label_text::borrow ("uninitialized data copied here");
6200 case MEMSPACE_STACK
:
6201 return label_text::borrow ("uninitialized data copied from stack here");
6204 return label_text::borrow ("uninitialized data copied from heap here");
6208 void mark_interesting_stuff (interesting_t
*interest
) final override
6211 interest
->add_region_creation (m_src_region
);
6215 enum memory_space
get_src_memory_space () const
6217 return m_src_region
? m_src_region
->get_memory_space () : MEMSPACE_UNKNOWN
;
6220 bit_size_t
calc_num_uninit_bits () const
6222 switch (m_copied_sval
->get_kind ())
6229 const poisoned_svalue
*poisoned_sval
6230 = as_a
<const poisoned_svalue
*> (m_copied_sval
);
6231 gcc_assert (poisoned_sval
->get_poison_kind () == POISON_KIND_UNINIT
);
6233 /* Give up if don't have type information. */
6234 if (m_copied_sval
->get_type () == NULL_TREE
)
6237 bit_size_t size_in_bits
;
6238 if (int_size_in_bits (m_copied_sval
->get_type (), &size_in_bits
))
6239 return size_in_bits
;
6241 /* Give up if we can't get the size of the type. */
6247 const compound_svalue
*compound_sval
6248 = as_a
<const compound_svalue
*> (m_copied_sval
);
6249 bit_size_t result
= 0;
6250 /* Find keys for uninit svals. */
6251 for (auto iter
: *compound_sval
)
6253 const svalue
*sval
= iter
.second
;
6254 if (const poisoned_svalue
*psval
6255 = sval
->dyn_cast_poisoned_svalue ())
6256 if (psval
->get_poison_kind () == POISON_KIND_UNINIT
)
6258 const binding_key
*key
= iter
.first
;
6259 const concrete_binding
*ckey
6260 = key
->dyn_cast_concrete_binding ();
6262 result
+= ckey
->get_size_in_bits ();
6270 void inform_number_of_uninit_bits (location_t loc
) const
6272 bit_size_t num_uninit_bits
= calc_num_uninit_bits ();
6273 if (num_uninit_bits
<= 0)
6275 if (num_uninit_bits
% BITS_PER_UNIT
== 0)
6277 /* Express in bytes. */
6278 byte_size_t num_uninit_bytes
= num_uninit_bits
/ BITS_PER_UNIT
;
6279 if (num_uninit_bytes
== 1)
6280 inform (loc
, "1 byte is uninitialized");
6283 "%wu bytes are uninitialized", num_uninit_bytes
.to_uhwi ());
6287 /* Express in bits. */
6288 if (num_uninit_bits
== 1)
6289 inform (loc
, "1 bit is uninitialized");
6292 "%wu bits are uninitialized", num_uninit_bits
.to_uhwi ());
6296 void complain_about_uninit_ranges (location_t loc
) const
6298 if (const compound_svalue
*compound_sval
6299 = m_copied_sval
->dyn_cast_compound_svalue ())
6301 /* Find keys for uninit svals. */
6302 auto_vec
<const concrete_binding
*> uninit_keys
;
6303 for (auto iter
: *compound_sval
)
6305 const svalue
*sval
= iter
.second
;
6306 if (const poisoned_svalue
*psval
6307 = sval
->dyn_cast_poisoned_svalue ())
6308 if (psval
->get_poison_kind () == POISON_KIND_UNINIT
)
6310 const binding_key
*key
= iter
.first
;
6311 const concrete_binding
*ckey
6312 = key
->dyn_cast_concrete_binding ();
6314 uninit_keys
.safe_push (ckey
);
6317 /* Complain about them in sorted order. */
6318 uninit_keys
.qsort (concrete_binding::cmp_ptr_ptr
);
6320 std::unique_ptr
<record_layout
> layout
;
6322 tree type
= m_copied_sval
->get_type ();
6323 if (type
&& TREE_CODE (type
) == RECORD_TYPE
)
6325 // (std::make_unique is C++14)
6326 layout
= std::unique_ptr
<record_layout
> (new record_layout (type
));
6333 const concrete_binding
*ckey
;
6334 FOR_EACH_VEC_ELT (uninit_keys
, i
, ckey
)
6336 bit_offset_t start_bit
= ckey
->get_start_bit_offset ();
6337 bit_offset_t next_bit
= ckey
->get_next_bit_offset ();
6338 complain_about_uninit_range (loc
, start_bit
, next_bit
,
6344 void complain_about_uninit_range (location_t loc
,
6345 bit_offset_t start_bit
,
6346 bit_offset_t next_bit
,
6347 const record_layout
*layout
) const
6351 while (start_bit
< next_bit
)
6353 if (const record_layout::item
*item
6354 = layout
->get_item_at (start_bit
))
6356 gcc_assert (start_bit
>= item
->get_start_bit_offset ());
6357 gcc_assert (start_bit
< item
->get_next_bit_offset ());
6358 if (item
->get_start_bit_offset () == start_bit
6359 && item
->get_next_bit_offset () <= next_bit
)
6360 complain_about_fully_uninit_item (*item
);
6362 complain_about_partially_uninit_item (*item
);
6363 start_bit
= item
->get_next_bit_offset ();
6371 if (start_bit
>= next_bit
)
6374 if (start_bit
% 8 == 0 && next_bit
% 8 == 0)
6376 /* Express in bytes. */
6377 byte_offset_t start_byte
= start_bit
/ 8;
6378 byte_offset_t last_byte
= (next_bit
/ 8) - 1;
6379 if (last_byte
== start_byte
)
6381 "byte %wu is uninitialized",
6382 start_byte
.to_uhwi ());
6385 "bytes %wu - %wu are uninitialized",
6386 start_byte
.to_uhwi (),
6387 last_byte
.to_uhwi ());
6391 /* Express in bits. */
6392 bit_offset_t last_bit
= next_bit
- 1;
6393 if (last_bit
== start_bit
)
6395 "bit %wu is uninitialized",
6396 start_bit
.to_uhwi ());
6399 "bits %wu - %wu are uninitialized",
6400 start_bit
.to_uhwi (),
6401 last_bit
.to_uhwi ());
6406 complain_about_fully_uninit_item (const record_layout::item
&item
)
6408 tree field
= item
.m_field
;
6409 bit_size_t num_bits
= item
.m_bit_range
.m_size_in_bits
;
6410 if (item
.m_is_padding
)
6412 if (num_bits
% 8 == 0)
6414 /* Express in bytes. */
6415 byte_size_t num_bytes
= num_bits
/ BITS_PER_UNIT
;
6417 inform (DECL_SOURCE_LOCATION (field
),
6418 "padding after field %qD is uninitialized (1 byte)",
6421 inform (DECL_SOURCE_LOCATION (field
),
6422 "padding after field %qD is uninitialized (%wu bytes)",
6423 field
, num_bytes
.to_uhwi ());
6427 /* Express in bits. */
6429 inform (DECL_SOURCE_LOCATION (field
),
6430 "padding after field %qD is uninitialized (1 bit)",
6433 inform (DECL_SOURCE_LOCATION (field
),
6434 "padding after field %qD is uninitialized (%wu bits)",
6435 field
, num_bits
.to_uhwi ());
6440 if (num_bits
% 8 == 0)
6442 /* Express in bytes. */
6443 byte_size_t num_bytes
= num_bits
/ BITS_PER_UNIT
;
6445 inform (DECL_SOURCE_LOCATION (field
),
6446 "field %qD is uninitialized (1 byte)", field
);
6448 inform (DECL_SOURCE_LOCATION (field
),
6449 "field %qD is uninitialized (%wu bytes)",
6450 field
, num_bytes
.to_uhwi ());
6454 /* Express in bits. */
6456 inform (DECL_SOURCE_LOCATION (field
),
6457 "field %qD is uninitialized (1 bit)", field
);
6459 inform (DECL_SOURCE_LOCATION (field
),
6460 "field %qD is uninitialized (%wu bits)",
6461 field
, num_bits
.to_uhwi ());
6467 complain_about_partially_uninit_item (const record_layout::item
&item
)
6469 tree field
= item
.m_field
;
6470 if (item
.m_is_padding
)
6471 inform (DECL_SOURCE_LOCATION (field
),
6472 "padding after field %qD is partially uninitialized",
6475 inform (DECL_SOURCE_LOCATION (field
),
6476 "field %qD is partially uninitialized",
6478 /* TODO: ideally we'd describe what parts are uninitialized. */
6481 void maybe_emit_fixit_hint () const
6483 if (tree decl
= m_src_region
->maybe_get_decl ())
6485 gcc_rich_location
hint_richloc (DECL_SOURCE_LOCATION (decl
));
6486 hint_richloc
.add_fixit_insert_after (" = {0}");
6487 inform (&hint_richloc
,
6488 "suggest forcing zero-initialization by"
6489 " providing a %<{0}%> initializer");
6494 const region
*m_src_region
;
6495 const region
*m_dest_region
;
6496 const svalue
*m_copied_sval
;
6499 /* Return true if any part of SVAL is uninitialized. */
6502 contains_uninit_p (const svalue
*sval
)
6504 struct uninit_finder
: public visitor
6507 uninit_finder () : m_found_uninit (false) {}
6508 void visit_poisoned_svalue (const poisoned_svalue
*sval
)
6510 if (sval
->get_poison_kind () == POISON_KIND_UNINIT
)
6511 m_found_uninit
= true;
6513 bool m_found_uninit
;
6519 return v
.m_found_uninit
;
6522 /* Function for use by plugins when simulating writing data through a
6523 pointer to an "untrusted" region DST_REG (and thus crossing a security
6524 boundary), such as copying data to user space in an OS kernel.
6526 Check that COPIED_SVAL is fully initialized. If not, complain about
6527 an infoleak to CTXT.
6529 SRC_REG can be NULL; if non-NULL it is used as a hint in the diagnostic
6530 as to where COPIED_SVAL came from. */
6533 region_model::maybe_complain_about_infoleak (const region
*dst_reg
,
6534 const svalue
*copied_sval
,
6535 const region
*src_reg
,
6536 region_model_context
*ctxt
)
6538 /* Check for exposure. */
6539 if (contains_uninit_p (copied_sval
))
6540 ctxt
->warn (make_unique
<exposure_through_uninit_copy
> (src_reg
,
6545 /* Set errno to a positive symbolic int, as if some error has occurred. */
6548 region_model::set_errno (const call_details
&cd
)
6550 const region
*errno_reg
= m_mgr
->get_errno_region ();
6551 conjured_purge
p (this, cd
.get_ctxt ());
6552 const svalue
*new_errno_sval
6553 = m_mgr
->get_or_create_conjured_svalue (integer_type_node
,
6554 cd
.get_call_stmt (),
6557 = m_mgr
->get_or_create_int_cst (integer_type_node
, 0);
6558 add_constraint (new_errno_sval
, GT_EXPR
, zero
, cd
.get_ctxt ());
6559 set_value (errno_reg
, new_errno_sval
, cd
.get_ctxt ());
6562 /* class noop_region_model_context : public region_model_context. */
6565 noop_region_model_context::add_note (std::unique_ptr
<pending_note
>)
6570 noop_region_model_context::add_event (std::unique_ptr
<checker_event
>)
6575 noop_region_model_context::bifurcate (std::unique_ptr
<custom_edge_info
>)
6580 noop_region_model_context::terminate_path ()
6584 /* class region_model_context_decorator : public region_model_context. */
6587 region_model_context_decorator::add_event (std::unique_ptr
<checker_event
> event
)
6590 m_inner
->add_event (std::move (event
));
6593 /* struct model_merger. */
6595 /* Dump a multiline representation of this merger to PP. */
6598 model_merger::dump_to_pp (pretty_printer
*pp
, bool simple
) const
6600 pp_string (pp
, "model A:");
6602 m_model_a
->dump_to_pp (pp
, simple
, true);
6605 pp_string (pp
, "model B:");
6607 m_model_b
->dump_to_pp (pp
, simple
, true);
6610 pp_string (pp
, "merged model:");
6612 m_merged_model
->dump_to_pp (pp
, simple
, true);
6616 /* Dump a multiline representation of this merger to FILE. */
6619 model_merger::dump (FILE *fp
, bool simple
) const
6622 pp_format_decoder (&pp
) = default_tree_printer
;
6623 pp_show_color (&pp
) = pp_show_color (global_dc
->printer
);
6624 pp
.buffer
->stream
= fp
;
6625 dump_to_pp (&pp
, simple
);
6629 /* Dump a multiline representation of this merger to stderr. */
6632 model_merger::dump (bool simple
) const
6634 dump (stderr
, simple
);
6637 /* Return true if it's OK to merge SVAL with other svalues. */
6640 model_merger::mergeable_svalue_p (const svalue
*sval
) const
6644 /* Reject merging svalues that have non-purgable sm-state,
6645 to avoid falsely reporting memory leaks by merging them
6646 with something else. For example, given a local var "p",
6647 reject the merger of a:
6648 store_a mapping "p" to a malloc-ed ptr
6650 store_b mapping "p" to a NULL ptr. */
6652 if (!m_state_a
->can_purge_p (*m_ext_state
, sval
))
6655 if (!m_state_b
->can_purge_p (*m_ext_state
, sval
))
6663 /* Dump RMODEL fully to stderr (i.e. without summarization). */
6666 debug (const region_model
&rmodel
)
6668 rmodel
.dump (false);
6671 /* class rejected_op_constraint : public rejected_constraint. */
6674 rejected_op_constraint::dump_to_pp (pretty_printer
*pp
) const
6676 region_model
m (m_model
);
6677 const svalue
*lhs_sval
= m
.get_rvalue (m_lhs
, NULL
);
6678 const svalue
*rhs_sval
= m
.get_rvalue (m_rhs
, NULL
);
6679 lhs_sval
->dump_to_pp (pp
, true);
6680 pp_printf (pp
, " %s ", op_symbol_code (m_op
));
6681 rhs_sval
->dump_to_pp (pp
, true);
6684 /* class rejected_default_case : public rejected_constraint. */
6687 rejected_default_case::dump_to_pp (pretty_printer
*pp
) const
6689 pp_string (pp
, "implicit default for enum");
6692 /* class rejected_ranges_constraint : public rejected_constraint. */
6695 rejected_ranges_constraint::dump_to_pp (pretty_printer
*pp
) const
6697 region_model
m (m_model
);
6698 const svalue
*sval
= m
.get_rvalue (m_expr
, NULL
);
6699 sval
->dump_to_pp (pp
, true);
6700 pp_string (pp
, " in ");
6701 m_ranges
->dump_to_pp (pp
, true);
6706 /* engine's ctor. */
6708 engine::engine (const supergraph
*sg
, logger
*logger
)
6709 : m_sg (sg
), m_mgr (logger
)
6713 /* Dump the managed objects by class to LOGGER, and the per-class totals. */
6716 engine::log_stats (logger
*logger
) const
6718 m_mgr
.log_stats (logger
, true);
6725 namespace selftest
{
6727 /* Build a constant tree of the given type from STR. */
6730 build_real_cst_from_string (tree type
, const char *str
)
6732 REAL_VALUE_TYPE real
;
6733 real_from_string (&real
, str
);
6734 return build_real (type
, real
);
6737 /* Append various "interesting" constants to OUT (e.g. NaN). */
6740 append_interesting_constants (auto_vec
<tree
> *out
)
6742 out
->safe_push (build_int_cst (integer_type_node
, 0));
6743 out
->safe_push (build_int_cst (integer_type_node
, 42));
6744 out
->safe_push (build_int_cst (unsigned_type_node
, 0));
6745 out
->safe_push (build_int_cst (unsigned_type_node
, 42));
6746 out
->safe_push (build_real_cst_from_string (float_type_node
, "QNaN"));
6747 out
->safe_push (build_real_cst_from_string (float_type_node
, "-QNaN"));
6748 out
->safe_push (build_real_cst_from_string (float_type_node
, "SNaN"));
6749 out
->safe_push (build_real_cst_from_string (float_type_node
, "-SNaN"));
6750 out
->safe_push (build_real_cst_from_string (float_type_node
, "0.0"));
6751 out
->safe_push (build_real_cst_from_string (float_type_node
, "-0.0"));
6752 out
->safe_push (build_real_cst_from_string (float_type_node
, "Inf"));
6753 out
->safe_push (build_real_cst_from_string (float_type_node
, "-Inf"));
6756 /* Verify that tree_cmp is a well-behaved comparator for qsort, even
6757 if the underlying constants aren't comparable. */
6760 test_tree_cmp_on_constants ()
6762 auto_vec
<tree
> csts
;
6763 append_interesting_constants (&csts
);
6765 /* Try sorting every triple. */
6766 const unsigned num
= csts
.length ();
6767 for (unsigned i
= 0; i
< num
; i
++)
6768 for (unsigned j
= 0; j
< num
; j
++)
6769 for (unsigned k
= 0; k
< num
; k
++)
6771 auto_vec
<tree
> v (3);
6772 v
.quick_push (csts
[i
]);
6773 v
.quick_push (csts
[j
]);
6774 v
.quick_push (csts
[k
]);
6779 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6782 assert_condition (const location
&loc
,
6783 region_model
&model
,
6784 const svalue
*lhs
, tree_code op
, const svalue
*rhs
,
6787 tristate actual
= model
.eval_condition (lhs
, op
, rhs
);
6788 ASSERT_EQ_AT (loc
, actual
, expected
);
6791 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6794 assert_condition (const location
&loc
,
6795 region_model
&model
,
6796 tree lhs
, tree_code op
, tree rhs
,
6799 tristate actual
= model
.eval_condition (lhs
, op
, rhs
, NULL
);
6800 ASSERT_EQ_AT (loc
, actual
, expected
);
6803 /* Implementation detail of ASSERT_DUMP_TREE_EQ. */
6806 assert_dump_tree_eq (const location
&loc
, tree t
, const char *expected
)
6808 auto_fix_quotes sentinel
;
6810 pp_format_decoder (&pp
) = default_tree_printer
;
6812 ASSERT_STREQ_AT (loc
, pp_formatted_text (&pp
), expected
);
6815 /* Assert that dump_tree (T) is EXPECTED. */
6817 #define ASSERT_DUMP_TREE_EQ(T, EXPECTED) \
6818 SELFTEST_BEGIN_STMT \
6819 assert_dump_tree_eq ((SELFTEST_LOCATION), (T), (EXPECTED)); \
6822 /* Implementation detail of ASSERT_DUMP_EQ. */
6825 assert_dump_eq (const location
&loc
,
6826 const region_model
&model
,
6828 const char *expected
)
6830 auto_fix_quotes sentinel
;
6832 pp_format_decoder (&pp
) = default_tree_printer
;
6834 model
.dump_to_pp (&pp
, summarize
, true);
6835 ASSERT_STREQ_AT (loc
, pp_formatted_text (&pp
), expected
);
6838 /* Assert that MODEL.dump_to_pp (SUMMARIZE) is EXPECTED. */
6840 #define ASSERT_DUMP_EQ(MODEL, SUMMARIZE, EXPECTED) \
6841 SELFTEST_BEGIN_STMT \
6842 assert_dump_eq ((SELFTEST_LOCATION), (MODEL), (SUMMARIZE), (EXPECTED)); \
6845 /* Smoketest for region_model::dump_to_pp. */
6850 region_model_manager mgr
;
6851 region_model
model (&mgr
);
6853 ASSERT_DUMP_EQ (model
, false,
6855 "m_called_unknown_fn: FALSE\n"
6856 "constraint_manager:\n"
6859 ASSERT_DUMP_EQ (model
, true,
6861 "m_called_unknown_fn: FALSE\n"
6862 "constraint_manager:\n"
6867 /* Helper function for selftests. Create a struct or union type named NAME,
6868 with the fields given by the FIELD_DECLS in FIELDS.
6869 If IS_STRUCT is true create a RECORD_TYPE (aka a struct), otherwise
6870 create a UNION_TYPE. */
6873 make_test_compound_type (const char *name
, bool is_struct
,
6874 const auto_vec
<tree
> *fields
)
6876 tree t
= make_node (is_struct
? RECORD_TYPE
: UNION_TYPE
);
6877 TYPE_NAME (t
) = get_identifier (name
);
6880 tree fieldlist
= NULL
;
6883 FOR_EACH_VEC_ELT (*fields
, i
, field
)
6885 gcc_assert (TREE_CODE (field
) == FIELD_DECL
);
6886 DECL_CONTEXT (field
) = t
;
6887 fieldlist
= chainon (field
, fieldlist
);
6889 fieldlist
= nreverse (fieldlist
);
6890 TYPE_FIELDS (t
) = fieldlist
;
6896 /* Selftest fixture for creating the type "struct coord {int x; int y; };". */
6902 auto_vec
<tree
> fields
;
6903 m_x_field
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
6904 get_identifier ("x"), integer_type_node
);
6905 fields
.safe_push (m_x_field
);
6906 m_y_field
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
6907 get_identifier ("y"), integer_type_node
);
6908 fields
.safe_push (m_y_field
);
6909 m_coord_type
= make_test_compound_type ("coord", true, &fields
);
6917 /* Verify usage of a struct. */
6924 tree c
= build_global_decl ("c", ct
.m_coord_type
);
6925 tree c_x
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_x_field
),
6926 c
, ct
.m_x_field
, NULL_TREE
);
6927 tree c_y
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_y_field
),
6928 c
, ct
.m_y_field
, NULL_TREE
);
6930 tree int_17
= build_int_cst (integer_type_node
, 17);
6931 tree int_m3
= build_int_cst (integer_type_node
, -3);
6933 region_model_manager mgr
;
6934 region_model
model (&mgr
);
6935 model
.set_value (c_x
, int_17
, NULL
);
6936 model
.set_value (c_y
, int_m3
, NULL
);
6938 /* Verify get_offset for "c.x". */
6940 const region
*c_x_reg
= model
.get_lvalue (c_x
, NULL
);
6941 region_offset offset
= c_x_reg
->get_offset (&mgr
);
6942 ASSERT_EQ (offset
.get_base_region (), model
.get_lvalue (c
, NULL
));
6943 ASSERT_EQ (offset
.get_bit_offset (), 0);
6946 /* Verify get_offset for "c.y". */
6948 const region
*c_y_reg
= model
.get_lvalue (c_y
, NULL
);
6949 region_offset offset
= c_y_reg
->get_offset (&mgr
);
6950 ASSERT_EQ (offset
.get_base_region (), model
.get_lvalue (c
, NULL
));
6951 ASSERT_EQ (offset
.get_bit_offset (), INT_TYPE_SIZE
);
6955 /* Verify usage of an array element. */
6960 tree tlen
= size_int (10);
6961 tree arr_type
= build_array_type (char_type_node
, build_index_type (tlen
));
6963 tree a
= build_global_decl ("a", arr_type
);
6965 region_model_manager mgr
;
6966 region_model
model (&mgr
);
6967 tree int_0
= build_int_cst (integer_type_node
, 0);
6968 tree a_0
= build4 (ARRAY_REF
, char_type_node
,
6969 a
, int_0
, NULL_TREE
, NULL_TREE
);
6970 tree char_A
= build_int_cst (char_type_node
, 'A');
6971 model
.set_value (a_0
, char_A
, NULL
);
6974 /* Verify that region_model::get_representative_tree works as expected. */
6977 test_get_representative_tree ()
6979 region_model_manager mgr
;
6983 tree string_cst
= build_string (4, "foo");
6984 region_model
m (&mgr
);
6985 const svalue
*str_sval
= m
.get_rvalue (string_cst
, NULL
);
6986 tree rep
= m
.get_representative_tree (str_sval
);
6987 ASSERT_EQ (rep
, string_cst
);
6990 /* String literal. */
6992 tree string_cst_ptr
= build_string_literal (4, "foo");
6993 region_model
m (&mgr
);
6994 const svalue
*str_sval
= m
.get_rvalue (string_cst_ptr
, NULL
);
6995 tree rep
= m
.get_representative_tree (str_sval
);
6996 ASSERT_DUMP_TREE_EQ (rep
, "&\"foo\"[0]");
6999 /* Value of an element within an array. */
7001 tree tlen
= size_int (10);
7002 tree arr_type
= build_array_type (char_type_node
, build_index_type (tlen
));
7003 tree a
= build_global_decl ("a", arr_type
);
7004 placeholder_svalue
test_sval (mgr
.alloc_symbol_id (),
7005 char_type_node
, "test value");
7007 /* Value of a[3]. */
7009 test_region_model_context ctxt
;
7010 region_model
model (&mgr
);
7011 tree int_3
= build_int_cst (integer_type_node
, 3);
7012 tree a_3
= build4 (ARRAY_REF
, char_type_node
,
7013 a
, int_3
, NULL_TREE
, NULL_TREE
);
7014 const region
*a_3_reg
= model
.get_lvalue (a_3
, &ctxt
);
7015 model
.set_value (a_3_reg
, &test_sval
, &ctxt
);
7016 tree rep
= model
.get_representative_tree (&test_sval
);
7017 ASSERT_DUMP_TREE_EQ (rep
, "a[3]");
7020 /* Value of a[0]. */
7022 test_region_model_context ctxt
;
7023 region_model
model (&mgr
);
7024 tree idx
= build_int_cst (integer_type_node
, 0);
7025 tree a_0
= build4 (ARRAY_REF
, char_type_node
,
7026 a
, idx
, NULL_TREE
, NULL_TREE
);
7027 const region
*a_0_reg
= model
.get_lvalue (a_0
, &ctxt
);
7028 model
.set_value (a_0_reg
, &test_sval
, &ctxt
);
7029 tree rep
= model
.get_representative_tree (&test_sval
);
7030 ASSERT_DUMP_TREE_EQ (rep
, "a[0]");
7034 /* Value of a field within a struct. */
7038 tree c
= build_global_decl ("c", ct
.m_coord_type
);
7039 tree c_x
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_x_field
),
7040 c
, ct
.m_x_field
, NULL_TREE
);
7041 tree c_y
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_y_field
),
7042 c
, ct
.m_y_field
, NULL_TREE
);
7044 test_region_model_context ctxt
;
7046 /* Value of initial field. */
7048 region_model
m (&mgr
);
7049 const region
*c_x_reg
= m
.get_lvalue (c_x
, &ctxt
);
7050 placeholder_svalue
test_sval_x (mgr
.alloc_symbol_id (),
7051 integer_type_node
, "test x val");
7052 m
.set_value (c_x_reg
, &test_sval_x
, &ctxt
);
7053 tree rep
= m
.get_representative_tree (&test_sval_x
);
7054 ASSERT_DUMP_TREE_EQ (rep
, "c.x");
7057 /* Value of non-initial field. */
7059 region_model
m (&mgr
);
7060 const region
*c_y_reg
= m
.get_lvalue (c_y
, &ctxt
);
7061 placeholder_svalue
test_sval_y (mgr
.alloc_symbol_id (),
7062 integer_type_node
, "test y val");
7063 m
.set_value (c_y_reg
, &test_sval_y
, &ctxt
);
7064 tree rep
= m
.get_representative_tree (&test_sval_y
);
7065 ASSERT_DUMP_TREE_EQ (rep
, "c.y");
7070 /* Verify that calling region_model::get_rvalue repeatedly on the same
7071 tree constant retrieves the same svalue *. */
7074 test_unique_constants ()
7076 tree int_0
= build_int_cst (integer_type_node
, 0);
7077 tree int_42
= build_int_cst (integer_type_node
, 42);
7079 test_region_model_context ctxt
;
7080 region_model_manager mgr
;
7081 region_model
model (&mgr
);
7082 ASSERT_EQ (model
.get_rvalue (int_0
, &ctxt
), model
.get_rvalue (int_0
, &ctxt
));
7083 ASSERT_EQ (model
.get_rvalue (int_42
, &ctxt
),
7084 model
.get_rvalue (int_42
, &ctxt
));
7085 ASSERT_NE (model
.get_rvalue (int_0
, &ctxt
), model
.get_rvalue (int_42
, &ctxt
));
7086 ASSERT_EQ (ctxt
.get_num_diagnostics (), 0);
7088 /* A "(const int)42" will be a different tree from "(int)42)"... */
7089 tree const_int_type_node
7090 = build_qualified_type (integer_type_node
, TYPE_QUAL_CONST
);
7091 tree const_int_42
= build_int_cst (const_int_type_node
, 42);
7092 ASSERT_NE (int_42
, const_int_42
);
7093 /* It should have a different const_svalue. */
7094 const svalue
*int_42_sval
= model
.get_rvalue (int_42
, &ctxt
);
7095 const svalue
*const_int_42_sval
= model
.get_rvalue (const_int_42
, &ctxt
);
7096 ASSERT_NE (int_42_sval
, const_int_42_sval
);
7097 /* But they should compare as equal. */
7098 ASSERT_CONDITION_TRUE (model
, int_42_sval
, EQ_EXPR
, const_int_42_sval
);
7099 ASSERT_CONDITION_FALSE (model
, int_42_sval
, NE_EXPR
, const_int_42_sval
);
7102 /* Verify that each type gets its own singleton unknown_svalue within a
7103 region_model_manager, and that NULL_TREE gets its own singleton. */
7106 test_unique_unknowns ()
7108 region_model_manager mgr
;
7109 const svalue
*unknown_int
7110 = mgr
.get_or_create_unknown_svalue (integer_type_node
);
7111 /* Repeated calls with the same type should get the same "unknown"
7113 const svalue
*unknown_int_2
7114 = mgr
.get_or_create_unknown_svalue (integer_type_node
);
7115 ASSERT_EQ (unknown_int
, unknown_int_2
);
7117 /* Different types (or the NULL type) should have different
7119 const svalue
*unknown_NULL_type
= mgr
.get_or_create_unknown_svalue (NULL
);
7120 ASSERT_NE (unknown_NULL_type
, unknown_int
);
7122 /* Repeated calls with NULL for the type should get the same "unknown"
7124 const svalue
*unknown_NULL_type_2
= mgr
.get_or_create_unknown_svalue (NULL
);
7125 ASSERT_EQ (unknown_NULL_type
, unknown_NULL_type_2
);
7128 /* Verify that initial_svalue are handled as expected. */
7131 test_initial_svalue_folding ()
7133 region_model_manager mgr
;
7134 tree x
= build_global_decl ("x", integer_type_node
);
7135 tree y
= build_global_decl ("y", integer_type_node
);
7137 test_region_model_context ctxt
;
7138 region_model
model (&mgr
);
7139 const svalue
*x_init
= model
.get_rvalue (x
, &ctxt
);
7140 const svalue
*y_init
= model
.get_rvalue (y
, &ctxt
);
7141 ASSERT_NE (x_init
, y_init
);
7142 const region
*x_reg
= model
.get_lvalue (x
, &ctxt
);
7143 ASSERT_EQ (x_init
, mgr
.get_or_create_initial_value (x_reg
));
7147 /* Verify that unary ops are folded as expected. */
7150 test_unaryop_svalue_folding ()
7152 region_model_manager mgr
;
7153 tree x
= build_global_decl ("x", integer_type_node
);
7154 tree y
= build_global_decl ("y", integer_type_node
);
7156 test_region_model_context ctxt
;
7157 region_model
model (&mgr
);
7158 const svalue
*x_init
= model
.get_rvalue (x
, &ctxt
);
7159 const svalue
*y_init
= model
.get_rvalue (y
, &ctxt
);
7160 const region
*x_reg
= model
.get_lvalue (x
, &ctxt
);
7161 ASSERT_EQ (x_init
, mgr
.get_or_create_initial_value (x_reg
));
7163 /* "(int)x" -> "x". */
7164 ASSERT_EQ (x_init
, mgr
.get_or_create_cast (integer_type_node
, x_init
));
7166 /* "(void *)x" -> something other than "x". */
7167 ASSERT_NE (x_init
, mgr
.get_or_create_cast (ptr_type_node
, x_init
));
7169 /* "!(x == y)" -> "x != y". */
7170 ASSERT_EQ (mgr
.get_or_create_unaryop
7171 (boolean_type_node
, TRUTH_NOT_EXPR
,
7172 mgr
.get_or_create_binop (boolean_type_node
, EQ_EXPR
,
7174 mgr
.get_or_create_binop (boolean_type_node
, NE_EXPR
,
7176 /* "!(x > y)" -> "x <= y". */
7177 ASSERT_EQ (mgr
.get_or_create_unaryop
7178 (boolean_type_node
, TRUTH_NOT_EXPR
,
7179 mgr
.get_or_create_binop (boolean_type_node
, GT_EXPR
,
7181 mgr
.get_or_create_binop (boolean_type_node
, LE_EXPR
,
7185 /* Verify that binops on constant svalues are folded. */
7188 test_binop_svalue_folding ()
7191 tree cst_int
[NUM_CSTS
];
7192 region_model_manager mgr
;
7193 const svalue
*cst_sval
[NUM_CSTS
];
7194 for (int i
= 0; i
< NUM_CSTS
; i
++)
7196 cst_int
[i
] = build_int_cst (integer_type_node
, i
);
7197 cst_sval
[i
] = mgr
.get_or_create_constant_svalue (cst_int
[i
]);
7198 ASSERT_EQ (cst_sval
[i
]->get_kind (), SK_CONSTANT
);
7199 ASSERT_EQ (cst_sval
[i
]->maybe_get_constant (), cst_int
[i
]);
7202 for (int i
= 0; i
< NUM_CSTS
; i
++)
7203 for (int j
= 0; j
< NUM_CSTS
; j
++)
7206 ASSERT_NE (cst_sval
[i
], cst_sval
[j
]);
7207 if (i
+ j
< NUM_CSTS
)
7210 = mgr
.get_or_create_binop (integer_type_node
, PLUS_EXPR
,
7211 cst_sval
[i
], cst_sval
[j
]);
7212 ASSERT_EQ (sum
, cst_sval
[i
+ j
]);
7216 const svalue
*difference
7217 = mgr
.get_or_create_binop (integer_type_node
, MINUS_EXPR
,
7218 cst_sval
[i
], cst_sval
[j
]);
7219 ASSERT_EQ (difference
, cst_sval
[i
- j
]);
7221 if (i
* j
< NUM_CSTS
)
7223 const svalue
*product
7224 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7225 cst_sval
[i
], cst_sval
[j
]);
7226 ASSERT_EQ (product
, cst_sval
[i
* j
]);
7228 const svalue
*eq
= mgr
.get_or_create_binop (integer_type_node
, EQ_EXPR
,
7229 cst_sval
[i
], cst_sval
[j
]);
7230 ASSERT_EQ (eq
, i
== j
? cst_sval
[1] : cst_sval
[0]);
7231 const svalue
*neq
= mgr
.get_or_create_binop (integer_type_node
, NE_EXPR
,
7232 cst_sval
[i
], cst_sval
[j
]);
7233 ASSERT_EQ (neq
, i
!= j
? cst_sval
[1] : cst_sval
[0]);
7237 tree x
= build_global_decl ("x", integer_type_node
);
7239 test_region_model_context ctxt
;
7240 region_model
model (&mgr
);
7241 const svalue
*x_init
= model
.get_rvalue (x
, &ctxt
);
7243 /* PLUS_EXPR folding. */
7244 const svalue
*x_init_plus_zero
7245 = mgr
.get_or_create_binop (integer_type_node
, PLUS_EXPR
,
7246 x_init
, cst_sval
[0]);
7247 ASSERT_EQ (x_init_plus_zero
, x_init
);
7248 const svalue
*zero_plus_x_init
7249 = mgr
.get_or_create_binop (integer_type_node
, PLUS_EXPR
,
7250 cst_sval
[0], x_init
);
7251 ASSERT_EQ (zero_plus_x_init
, x_init
);
7253 /* MULT_EXPR folding. */
7254 const svalue
*x_init_times_zero
7255 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7256 x_init
, cst_sval
[0]);
7257 ASSERT_EQ (x_init_times_zero
, cst_sval
[0]);
7258 const svalue
*zero_times_x_init
7259 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7260 cst_sval
[0], x_init
);
7261 ASSERT_EQ (zero_times_x_init
, cst_sval
[0]);
7263 const svalue
*x_init_times_one
7264 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7265 x_init
, cst_sval
[1]);
7266 ASSERT_EQ (x_init_times_one
, x_init
);
7267 const svalue
*one_times_x_init
7268 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7269 cst_sval
[1], x_init
);
7270 ASSERT_EQ (one_times_x_init
, x_init
);
7273 // TODO: do we want to use the match-and-simplify DSL for this?
7275 /* Verify that binops put any constants on the RHS. */
7276 const svalue
*four_times_x_init
7277 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7278 cst_sval
[4], x_init
);
7279 const svalue
*x_init_times_four
7280 = mgr
.get_or_create_binop (integer_type_node
, MULT_EXPR
,
7281 x_init
, cst_sval
[4]);
7282 ASSERT_EQ (four_times_x_init
, x_init_times_four
);
7283 const binop_svalue
*binop
= four_times_x_init
->dyn_cast_binop_svalue ();
7284 ASSERT_EQ (binop
->get_op (), MULT_EXPR
);
7285 ASSERT_EQ (binop
->get_arg0 (), x_init
);
7286 ASSERT_EQ (binop
->get_arg1 (), cst_sval
[4]);
7288 /* Verify that ((x + 1) + 1) == (x + 2). */
7289 const svalue
*x_init_plus_one
7290 = mgr
.get_or_create_binop (integer_type_node
, PLUS_EXPR
,
7291 x_init
, cst_sval
[1]);
7292 const svalue
*x_init_plus_two
7293 = mgr
.get_or_create_binop (integer_type_node
, PLUS_EXPR
,
7294 x_init
, cst_sval
[2]);
7295 const svalue
*x_init_plus_one_plus_one
7296 = mgr
.get_or_create_binop (integer_type_node
, PLUS_EXPR
,
7297 x_init_plus_one
, cst_sval
[1]);
7298 ASSERT_EQ (x_init_plus_one_plus_one
, x_init_plus_two
);
7300 /* Verify various binops on booleans. */
7302 const svalue
*sval_true
= mgr
.get_or_create_int_cst (boolean_type_node
, 1);
7303 const svalue
*sval_false
= mgr
.get_or_create_int_cst (boolean_type_node
, 0);
7304 const svalue
*sval_unknown
7305 = mgr
.get_or_create_unknown_svalue (boolean_type_node
);
7306 const placeholder_svalue
sval_placeholder (mgr
.alloc_symbol_id (),
7307 boolean_type_node
, "v");
7308 for (auto op
: {BIT_IOR_EXPR
, TRUTH_OR_EXPR
})
7310 ASSERT_EQ (mgr
.get_or_create_binop (boolean_type_node
, op
,
7311 sval_true
, sval_unknown
),
7313 ASSERT_EQ (mgr
.get_or_create_binop (boolean_type_node
, op
,
7314 sval_false
, sval_unknown
),
7316 ASSERT_EQ (mgr
.get_or_create_binop (boolean_type_node
, op
,
7317 sval_false
, &sval_placeholder
),
7320 for (auto op
: {BIT_AND_EXPR
, TRUTH_AND_EXPR
})
7322 ASSERT_EQ (mgr
.get_or_create_binop (boolean_type_node
, op
,
7323 sval_false
, sval_unknown
),
7325 ASSERT_EQ (mgr
.get_or_create_binop (boolean_type_node
, op
,
7326 sval_true
, sval_unknown
),
7328 ASSERT_EQ (mgr
.get_or_create_binop (boolean_type_node
, op
,
7329 sval_true
, &sval_placeholder
),
7335 /* Verify that sub_svalues are folded as expected. */
7338 test_sub_svalue_folding ()
7341 tree c
= build_global_decl ("c", ct
.m_coord_type
);
7342 tree c_x
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_x_field
),
7343 c
, ct
.m_x_field
, NULL_TREE
);
7345 region_model_manager mgr
;
7346 region_model
model (&mgr
);
7347 test_region_model_context ctxt
;
7348 const region
*c_x_reg
= model
.get_lvalue (c_x
, &ctxt
);
7350 /* Verify that sub_svalue of "unknown" simply
7351 yields an unknown. */
7353 const svalue
*unknown
= mgr
.get_or_create_unknown_svalue (ct
.m_coord_type
);
7354 const svalue
*sub
= mgr
.get_or_create_sub_svalue (TREE_TYPE (ct
.m_x_field
),
7356 ASSERT_EQ (sub
->get_kind (), SK_UNKNOWN
);
7357 ASSERT_EQ (sub
->get_type (), TREE_TYPE (ct
.m_x_field
));
7360 /* Get BIT within VAL as a symbolic value within MGR. */
7362 static const svalue
*
7363 get_bit (region_model_manager
*mgr
,
7365 unsigned HOST_WIDE_INT val
)
7367 const svalue
*inner_svalue
7368 = mgr
->get_or_create_int_cst (unsigned_type_node
, val
);
7369 return mgr
->get_or_create_bits_within (boolean_type_node
,
7374 /* Verify that bits_within_svalues are folded as expected. */
7377 test_bits_within_svalue_folding ()
7379 region_model_manager mgr
;
7381 const svalue
*zero
= mgr
.get_or_create_int_cst (boolean_type_node
, 0);
7382 const svalue
*one
= mgr
.get_or_create_int_cst (boolean_type_node
, 1);
7385 const unsigned val
= 0x0000;
7386 for (unsigned bit
= 0; bit
< 16; bit
++)
7387 ASSERT_EQ (get_bit (&mgr
, bit
, val
), zero
);
7391 const unsigned val
= 0x0001;
7392 ASSERT_EQ (get_bit (&mgr
, 0, val
), one
);
7393 for (unsigned bit
= 1; bit
< 16; bit
++)
7394 ASSERT_EQ (get_bit (&mgr
, bit
, val
), zero
);
7398 const unsigned val
= 0x8000;
7399 for (unsigned bit
= 0; bit
< 15; bit
++)
7400 ASSERT_EQ (get_bit (&mgr
, bit
, val
), zero
);
7401 ASSERT_EQ (get_bit (&mgr
, 15, val
), one
);
7405 const unsigned val
= 0xFFFF;
7406 for (unsigned bit
= 0; bit
< 16; bit
++)
7407 ASSERT_EQ (get_bit (&mgr
, bit
, val
), one
);
7411 /* Test that region::descendent_of_p works as expected. */
7414 test_descendent_of_p ()
7416 region_model_manager mgr
;
7417 const region
*stack
= mgr
.get_stack_region ();
7418 const region
*heap
= mgr
.get_heap_region ();
7419 const region
*code
= mgr
.get_code_region ();
7420 const region
*globals
= mgr
.get_globals_region ();
7422 /* descendent_of_p should return true when used on the region itself. */
7423 ASSERT_TRUE (stack
->descendent_of_p (stack
));
7424 ASSERT_FALSE (stack
->descendent_of_p (heap
));
7425 ASSERT_FALSE (stack
->descendent_of_p (code
));
7426 ASSERT_FALSE (stack
->descendent_of_p (globals
));
7428 tree x
= build_global_decl ("x", integer_type_node
);
7429 const region
*x_reg
= mgr
.get_region_for_global (x
);
7430 ASSERT_TRUE (x_reg
->descendent_of_p (globals
));
7432 /* A cast_region should be a descendent of the original region. */
7433 const region
*cast_reg
= mgr
.get_cast_region (x_reg
, ptr_type_node
);
7434 ASSERT_TRUE (cast_reg
->descendent_of_p (x_reg
));
7437 /* Verify that bit_range_region works as expected. */
7440 test_bit_range_regions ()
7442 tree x
= build_global_decl ("x", integer_type_node
);
7443 region_model_manager mgr
;
7444 const region
*x_reg
= mgr
.get_region_for_global (x
);
7446 = mgr
.get_bit_range (x_reg
, char_type_node
, bit_range (0, 8));
7448 = mgr
.get_bit_range (x_reg
, char_type_node
, bit_range (8, 8));
7449 ASSERT_TRUE (byte0
->descendent_of_p (x_reg
));
7450 ASSERT_TRUE (byte1
->descendent_of_p (x_reg
));
7451 ASSERT_NE (byte0
, byte1
);
7454 /* Verify that simple assignments work as expected. */
7459 tree int_0
= build_int_cst (integer_type_node
, 0);
7460 tree x
= build_global_decl ("x", integer_type_node
);
7461 tree y
= build_global_decl ("y", integer_type_node
);
7463 /* "x == 0", then use of y, then "y = 0;". */
7464 region_model_manager mgr
;
7465 region_model
model (&mgr
);
7466 ADD_SAT_CONSTRAINT (model
, x
, EQ_EXPR
, int_0
);
7467 ASSERT_CONDITION_UNKNOWN (model
, y
, EQ_EXPR
, int_0
);
7468 model
.set_value (model
.get_lvalue (y
, NULL
),
7469 model
.get_rvalue (int_0
, NULL
),
7471 ASSERT_CONDITION_TRUE (model
, y
, EQ_EXPR
, int_0
);
7472 ASSERT_CONDITION_TRUE (model
, y
, EQ_EXPR
, x
);
7475 /* Verify that compound assignments work as expected. */
7478 test_compound_assignment ()
7482 tree c
= build_global_decl ("c", ct
.m_coord_type
);
7483 tree c_x
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_x_field
),
7484 c
, ct
.m_x_field
, NULL_TREE
);
7485 tree c_y
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_y_field
),
7486 c
, ct
.m_y_field
, NULL_TREE
);
7487 tree d
= build_global_decl ("d", ct
.m_coord_type
);
7488 tree d_x
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_x_field
),
7489 d
, ct
.m_x_field
, NULL_TREE
);
7490 tree d_y
= build3 (COMPONENT_REF
, TREE_TYPE (ct
.m_y_field
),
7491 d
, ct
.m_y_field
, NULL_TREE
);
7493 tree int_17
= build_int_cst (integer_type_node
, 17);
7494 tree int_m3
= build_int_cst (integer_type_node
, -3);
7496 region_model_manager mgr
;
7497 region_model
model (&mgr
);
7498 model
.set_value (c_x
, int_17
, NULL
);
7499 model
.set_value (c_y
, int_m3
, NULL
);
7502 const svalue
*sval
= model
.get_rvalue (c
, NULL
);
7503 model
.set_value (model
.get_lvalue (d
, NULL
), sval
, NULL
);
7505 /* Check that the fields have the same svalues. */
7506 ASSERT_EQ (model
.get_rvalue (c_x
, NULL
), model
.get_rvalue (d_x
, NULL
));
7507 ASSERT_EQ (model
.get_rvalue (c_y
, NULL
), model
.get_rvalue (d_y
, NULL
));
7510 /* Verify the details of pushing and popping stack frames. */
7513 test_stack_frames ()
7515 tree int_42
= build_int_cst (integer_type_node
, 42);
7516 tree int_10
= build_int_cst (integer_type_node
, 10);
7517 tree int_5
= build_int_cst (integer_type_node
, 5);
7518 tree int_0
= build_int_cst (integer_type_node
, 0);
7520 auto_vec
<tree
> param_types
;
7521 tree parent_fndecl
= make_fndecl (integer_type_node
,
7524 allocate_struct_function (parent_fndecl
, true);
7526 tree child_fndecl
= make_fndecl (integer_type_node
,
7529 allocate_struct_function (child_fndecl
, true);
7531 /* "a" and "b" in the parent frame. */
7532 tree a
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7533 get_identifier ("a"),
7535 DECL_CONTEXT (a
) = parent_fndecl
;
7536 tree b
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7537 get_identifier ("b"),
7539 DECL_CONTEXT (b
) = parent_fndecl
;
7540 /* "x" and "y" in a child frame. */
7541 tree x
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7542 get_identifier ("x"),
7544 DECL_CONTEXT (x
) = child_fndecl
;
7545 tree y
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7546 get_identifier ("y"),
7548 DECL_CONTEXT (y
) = child_fndecl
;
7551 tree p
= build_global_decl ("p", ptr_type_node
);
7554 tree q
= build_global_decl ("q", ptr_type_node
);
7556 region_model_manager mgr
;
7557 test_region_model_context ctxt
;
7558 region_model
model (&mgr
);
7560 /* Push stack frame for "parent_fn". */
7561 const region
*parent_frame_reg
7562 = model
.push_frame (DECL_STRUCT_FUNCTION (parent_fndecl
),
7564 ASSERT_EQ (model
.get_current_frame (), parent_frame_reg
);
7565 ASSERT_TRUE (model
.region_exists_p (parent_frame_reg
));
7566 const region
*a_in_parent_reg
= model
.get_lvalue (a
, &ctxt
);
7567 model
.set_value (a_in_parent_reg
,
7568 model
.get_rvalue (int_42
, &ctxt
),
7570 ASSERT_EQ (a_in_parent_reg
->maybe_get_frame_region (), parent_frame_reg
);
7572 model
.add_constraint (b
, LT_EXPR
, int_10
, &ctxt
);
7573 ASSERT_EQ (model
.eval_condition (b
, LT_EXPR
, int_10
, &ctxt
),
7574 tristate (tristate::TS_TRUE
));
7576 /* Push stack frame for "child_fn". */
7577 const region
*child_frame_reg
7578 = model
.push_frame (DECL_STRUCT_FUNCTION (child_fndecl
), NULL
, &ctxt
);
7579 ASSERT_EQ (model
.get_current_frame (), child_frame_reg
);
7580 ASSERT_TRUE (model
.region_exists_p (child_frame_reg
));
7581 const region
*x_in_child_reg
= model
.get_lvalue (x
, &ctxt
);
7582 model
.set_value (x_in_child_reg
,
7583 model
.get_rvalue (int_0
, &ctxt
),
7585 ASSERT_EQ (x_in_child_reg
->maybe_get_frame_region (), child_frame_reg
);
7587 model
.add_constraint (y
, NE_EXPR
, int_5
, &ctxt
);
7588 ASSERT_EQ (model
.eval_condition (y
, NE_EXPR
, int_5
, &ctxt
),
7589 tristate (tristate::TS_TRUE
));
7591 /* Point a global pointer at a local in the child frame: p = &x. */
7592 const region
*p_in_globals_reg
= model
.get_lvalue (p
, &ctxt
);
7593 model
.set_value (p_in_globals_reg
,
7594 mgr
.get_ptr_svalue (ptr_type_node
, x_in_child_reg
),
7596 ASSERT_EQ (p_in_globals_reg
->maybe_get_frame_region (), NULL
);
7598 /* Point another global pointer at p: q = &p. */
7599 const region
*q_in_globals_reg
= model
.get_lvalue (q
, &ctxt
);
7600 model
.set_value (q_in_globals_reg
,
7601 mgr
.get_ptr_svalue (ptr_type_node
, p_in_globals_reg
),
7604 /* Test region::descendent_of_p. */
7605 ASSERT_TRUE (child_frame_reg
->descendent_of_p (child_frame_reg
));
7606 ASSERT_TRUE (x_in_child_reg
->descendent_of_p (child_frame_reg
));
7607 ASSERT_FALSE (a_in_parent_reg
->descendent_of_p (child_frame_reg
));
7609 /* Pop the "child_fn" frame from the stack. */
7610 model
.pop_frame (NULL
, NULL
, &ctxt
);
7611 ASSERT_FALSE (model
.region_exists_p (child_frame_reg
));
7612 ASSERT_TRUE (model
.region_exists_p (parent_frame_reg
));
7614 /* Verify that p (which was pointing at the local "x" in the popped
7615 frame) has been poisoned. */
7616 const svalue
*new_p_sval
= model
.get_rvalue (p
, NULL
);
7617 ASSERT_EQ (new_p_sval
->get_kind (), SK_POISONED
);
7618 ASSERT_EQ (new_p_sval
->dyn_cast_poisoned_svalue ()->get_poison_kind (),
7619 POISON_KIND_POPPED_STACK
);
7621 /* Verify that q still points to p, in spite of the region
7623 const svalue
*new_q_sval
= model
.get_rvalue (q
, &ctxt
);
7624 ASSERT_EQ (new_q_sval
->get_kind (), SK_REGION
);
7625 ASSERT_EQ (new_q_sval
->maybe_get_region (),
7626 model
.get_lvalue (p
, &ctxt
));
7628 /* Verify that top of stack has been updated. */
7629 ASSERT_EQ (model
.get_current_frame (), parent_frame_reg
);
7631 /* Verify locals in parent frame. */
7632 /* Verify "a" still has its value. */
7633 const svalue
*new_a_sval
= model
.get_rvalue (a
, &ctxt
);
7634 ASSERT_EQ (new_a_sval
->get_kind (), SK_CONSTANT
);
7635 ASSERT_EQ (new_a_sval
->dyn_cast_constant_svalue ()->get_constant (),
7637 /* Verify "b" still has its constraint. */
7638 ASSERT_EQ (model
.eval_condition (b
, LT_EXPR
, int_10
, &ctxt
),
7639 tristate (tristate::TS_TRUE
));
7642 /* Verify that get_representative_path_var works as expected, that
7643 we can map from regions to parms and back within a recursive call
7647 test_get_representative_path_var ()
7649 auto_vec
<tree
> param_types
;
7650 tree fndecl
= make_fndecl (integer_type_node
,
7653 allocate_struct_function (fndecl
, true);
7656 tree n
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7657 get_identifier ("n"),
7659 DECL_CONTEXT (n
) = fndecl
;
7661 region_model_manager mgr
;
7662 test_region_model_context ctxt
;
7663 region_model
model (&mgr
);
7665 /* Push 5 stack frames for "factorial", each with a param */
7666 auto_vec
<const region
*> parm_regs
;
7667 auto_vec
<const svalue
*> parm_svals
;
7668 for (int depth
= 0; depth
< 5; depth
++)
7670 const region
*frame_n_reg
7671 = model
.push_frame (DECL_STRUCT_FUNCTION (fndecl
), NULL
, &ctxt
);
7672 const region
*parm_n_reg
= model
.get_lvalue (path_var (n
, depth
), &ctxt
);
7673 parm_regs
.safe_push (parm_n_reg
);
7675 ASSERT_EQ (parm_n_reg
->get_parent_region (), frame_n_reg
);
7676 const svalue
*sval_n
= mgr
.get_or_create_initial_value (parm_n_reg
);
7677 parm_svals
.safe_push (sval_n
);
7680 /* Verify that we can recognize that the regions are the parms,
7682 for (int depth
= 0; depth
< 5; depth
++)
7686 ASSERT_EQ (model
.get_representative_path_var (parm_regs
[depth
],
7688 path_var (n
, depth
+ 1));
7690 /* ...and that we can lookup lvalues for locals for all frames,
7691 not just the top. */
7692 ASSERT_EQ (model
.get_lvalue (path_var (n
, depth
), NULL
),
7694 /* ...and that we can locate the svalues. */
7697 ASSERT_EQ (model
.get_representative_path_var (parm_svals
[depth
],
7699 path_var (n
, depth
+ 1));
7704 /* Ensure that region_model::operator== works as expected. */
7709 tree int_42
= build_int_cst (integer_type_node
, 42);
7710 tree int_17
= build_int_cst (integer_type_node
, 17);
7712 /* Verify that "empty" region_model instances are equal to each other. */
7713 region_model_manager mgr
;
7714 region_model
model0 (&mgr
);
7715 region_model
model1 (&mgr
);
7716 ASSERT_EQ (model0
, model1
);
7718 /* Verify that setting state in model1 makes the models non-equal. */
7719 tree x
= build_global_decl ("x", integer_type_node
);
7720 model0
.set_value (x
, int_42
, NULL
);
7721 ASSERT_EQ (model0
.get_rvalue (x
, NULL
)->maybe_get_constant (), int_42
);
7722 ASSERT_NE (model0
, model1
);
7724 /* Verify the copy-ctor. */
7725 region_model
model2 (model0
);
7726 ASSERT_EQ (model0
, model2
);
7727 ASSERT_EQ (model2
.get_rvalue (x
, NULL
)->maybe_get_constant (), int_42
);
7728 ASSERT_NE (model1
, model2
);
7730 /* Verify that models obtained from copy-ctor are independently editable
7731 w/o affecting the original model. */
7732 model2
.set_value (x
, int_17
, NULL
);
7733 ASSERT_NE (model0
, model2
);
7734 ASSERT_EQ (model2
.get_rvalue (x
, NULL
)->maybe_get_constant (), int_17
);
7735 ASSERT_EQ (model0
.get_rvalue (x
, NULL
)->maybe_get_constant (), int_42
);
7738 /* Verify that region models for
7745 test_canonicalization_2 ()
7747 tree int_42
= build_int_cst (integer_type_node
, 42);
7748 tree int_113
= build_int_cst (integer_type_node
, 113);
7749 tree x
= build_global_decl ("x", integer_type_node
);
7750 tree y
= build_global_decl ("y", integer_type_node
);
7752 region_model_manager mgr
;
7753 region_model
model0 (&mgr
);
7754 model0
.set_value (model0
.get_lvalue (x
, NULL
),
7755 model0
.get_rvalue (int_42
, NULL
),
7757 model0
.set_value (model0
.get_lvalue (y
, NULL
),
7758 model0
.get_rvalue (int_113
, NULL
),
7761 region_model
model1 (&mgr
);
7762 model1
.set_value (model1
.get_lvalue (y
, NULL
),
7763 model1
.get_rvalue (int_113
, NULL
),
7765 model1
.set_value (model1
.get_lvalue (x
, NULL
),
7766 model1
.get_rvalue (int_42
, NULL
),
7769 ASSERT_EQ (model0
, model1
);
7772 /* Verify that constraints for
7776 are equal after canonicalization. */
7779 test_canonicalization_3 ()
7781 tree int_3
= build_int_cst (integer_type_node
, 3);
7782 tree int_42
= build_int_cst (integer_type_node
, 42);
7783 tree x
= build_global_decl ("x", integer_type_node
);
7784 tree y
= build_global_decl ("y", integer_type_node
);
7786 region_model_manager mgr
;
7787 region_model
model0 (&mgr
);
7788 model0
.add_constraint (x
, GT_EXPR
, int_3
, NULL
);
7789 model0
.add_constraint (y
, GT_EXPR
, int_42
, NULL
);
7791 region_model
model1 (&mgr
);
7792 model1
.add_constraint (y
, GT_EXPR
, int_42
, NULL
);
7793 model1
.add_constraint (x
, GT_EXPR
, int_3
, NULL
);
7795 model0
.canonicalize ();
7796 model1
.canonicalize ();
7797 ASSERT_EQ (model0
, model1
);
7800 /* Verify that we can canonicalize a model containing NaN and other real
7804 test_canonicalization_4 ()
7806 auto_vec
<tree
> csts
;
7807 append_interesting_constants (&csts
);
7809 region_model_manager mgr
;
7810 region_model
model (&mgr
);
7812 for (tree cst
: csts
)
7813 model
.get_rvalue (cst
, NULL
);
7815 model
.canonicalize ();
7818 /* Assert that if we have two region_model instances
7819 with values VAL_A and VAL_B for EXPR that they are
7820 mergable. Write the merged model to *OUT_MERGED_MODEL,
7821 and the merged svalue ptr to *OUT_MERGED_SVALUE.
7822 If VAL_A or VAL_B are NULL_TREE, don't populate EXPR
7823 for that region_model. */
7826 assert_region_models_merge (tree expr
, tree val_a
, tree val_b
,
7827 region_model
*out_merged_model
,
7828 const svalue
**out_merged_svalue
)
7830 region_model_manager
*mgr
= out_merged_model
->get_manager ();
7831 program_point
point (program_point::origin (*mgr
));
7832 test_region_model_context ctxt
;
7833 region_model
model0 (mgr
);
7834 region_model
model1 (mgr
);
7836 model0
.set_value (model0
.get_lvalue (expr
, &ctxt
),
7837 model0
.get_rvalue (val_a
, &ctxt
),
7840 model1
.set_value (model1
.get_lvalue (expr
, &ctxt
),
7841 model1
.get_rvalue (val_b
, &ctxt
),
7844 /* They should be mergeable. */
7845 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, out_merged_model
));
7846 *out_merged_svalue
= out_merged_model
->get_rvalue (expr
, &ctxt
);
7849 /* Verify that we can merge region_model instances. */
7852 test_state_merging ()
7854 tree int_42
= build_int_cst (integer_type_node
, 42);
7855 tree int_113
= build_int_cst (integer_type_node
, 113);
7856 tree x
= build_global_decl ("x", integer_type_node
);
7857 tree y
= build_global_decl ("y", integer_type_node
);
7858 tree z
= build_global_decl ("z", integer_type_node
);
7859 tree p
= build_global_decl ("p", ptr_type_node
);
7861 tree addr_of_y
= build1 (ADDR_EXPR
, ptr_type_node
, y
);
7862 tree addr_of_z
= build1 (ADDR_EXPR
, ptr_type_node
, z
);
7864 auto_vec
<tree
> param_types
;
7865 tree test_fndecl
= make_fndecl (integer_type_node
, "test_fn", param_types
);
7866 allocate_struct_function (test_fndecl
, true);
7869 tree a
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7870 get_identifier ("a"),
7872 DECL_CONTEXT (a
) = test_fndecl
;
7873 tree addr_of_a
= build1 (ADDR_EXPR
, ptr_type_node
, a
);
7875 /* Param "q", a pointer. */
7876 tree q
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
7877 get_identifier ("q"),
7879 DECL_CONTEXT (q
) = test_fndecl
;
7881 region_model_manager mgr
;
7882 program_point
point (program_point::origin (mgr
));
7885 region_model
model0 (&mgr
);
7886 region_model
model1 (&mgr
);
7887 region_model
merged (&mgr
);
7888 /* Verify empty models can be merged. */
7889 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
7890 ASSERT_EQ (model0
, merged
);
7893 /* Verify that we can merge two contradictory constraints on the
7894 value for a global. */
7895 /* TODO: verify that the merged model doesn't have a value for
7898 region_model
model0 (&mgr
);
7899 region_model
model1 (&mgr
);
7900 region_model
merged (&mgr
);
7901 test_region_model_context ctxt
;
7902 model0
.add_constraint (x
, EQ_EXPR
, int_42
, &ctxt
);
7903 model1
.add_constraint (x
, EQ_EXPR
, int_113
, &ctxt
);
7904 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
7905 ASSERT_NE (model0
, merged
);
7906 ASSERT_NE (model1
, merged
);
7909 /* Verify handling of a PARM_DECL. */
7911 test_region_model_context ctxt
;
7912 region_model
model0 (&mgr
);
7913 region_model
model1 (&mgr
);
7914 ASSERT_EQ (model0
.get_stack_depth (), 0);
7915 model0
.push_frame (DECL_STRUCT_FUNCTION (test_fndecl
), NULL
, &ctxt
);
7916 ASSERT_EQ (model0
.get_stack_depth (), 1);
7917 model1
.push_frame (DECL_STRUCT_FUNCTION (test_fndecl
), NULL
, &ctxt
);
7919 placeholder_svalue
test_sval (mgr
.alloc_symbol_id (),
7920 integer_type_node
, "test sval");
7921 model0
.set_value (model0
.get_lvalue (a
, &ctxt
), &test_sval
, &ctxt
);
7922 model1
.set_value (model1
.get_lvalue (a
, &ctxt
), &test_sval
, &ctxt
);
7923 ASSERT_EQ (model0
, model1
);
7925 /* They should be mergeable, and the result should be the same. */
7926 region_model
merged (&mgr
);
7927 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
7928 ASSERT_EQ (model0
, merged
);
7929 /* In particular, "a" should have the placeholder value. */
7930 ASSERT_EQ (merged
.get_rvalue (a
, &ctxt
), &test_sval
);
7933 /* Verify handling of a global. */
7935 test_region_model_context ctxt
;
7936 region_model
model0 (&mgr
);
7937 region_model
model1 (&mgr
);
7939 placeholder_svalue
test_sval (mgr
.alloc_symbol_id (),
7940 integer_type_node
, "test sval");
7941 model0
.set_value (model0
.get_lvalue (x
, &ctxt
), &test_sval
, &ctxt
);
7942 model1
.set_value (model1
.get_lvalue (x
, &ctxt
), &test_sval
, &ctxt
);
7943 ASSERT_EQ (model0
, model1
);
7945 /* They should be mergeable, and the result should be the same. */
7946 region_model
merged (&mgr
);
7947 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
7948 ASSERT_EQ (model0
, merged
);
7949 /* In particular, "x" should have the placeholder value. */
7950 ASSERT_EQ (merged
.get_rvalue (x
, &ctxt
), &test_sval
);
7953 /* Use global-handling to verify various combinations of values. */
7955 /* Two equal constant values. */
7957 region_model
merged (&mgr
);
7958 const svalue
*merged_x_sval
;
7959 assert_region_models_merge (x
, int_42
, int_42
, &merged
, &merged_x_sval
);
7961 /* In particular, there should be a constant value for "x". */
7962 ASSERT_EQ (merged_x_sval
->get_kind (), SK_CONSTANT
);
7963 ASSERT_EQ (merged_x_sval
->dyn_cast_constant_svalue ()->get_constant (),
7967 /* Two non-equal constant values. */
7969 region_model
merged (&mgr
);
7970 const svalue
*merged_x_sval
;
7971 assert_region_models_merge (x
, int_42
, int_113
, &merged
, &merged_x_sval
);
7973 /* In particular, there should be a "widening" value for "x". */
7974 ASSERT_EQ (merged_x_sval
->get_kind (), SK_WIDENING
);
7977 /* Initial and constant. */
7979 region_model
merged (&mgr
);
7980 const svalue
*merged_x_sval
;
7981 assert_region_models_merge (x
, NULL_TREE
, int_113
, &merged
, &merged_x_sval
);
7983 /* In particular, there should be an unknown value for "x". */
7984 ASSERT_EQ (merged_x_sval
->get_kind (), SK_UNKNOWN
);
7987 /* Constant and initial. */
7989 region_model
merged (&mgr
);
7990 const svalue
*merged_x_sval
;
7991 assert_region_models_merge (x
, int_42
, NULL_TREE
, &merged
, &merged_x_sval
);
7993 /* In particular, there should be an unknown value for "x". */
7994 ASSERT_EQ (merged_x_sval
->get_kind (), SK_UNKNOWN
);
7997 /* Unknown and constant. */
8000 /* Pointers: NULL and NULL. */
8003 /* Pointers: NULL and non-NULL. */
8006 /* Pointers: non-NULL and non-NULL: ptr to a local. */
8008 region_model
model0 (&mgr
);
8009 model0
.push_frame (DECL_STRUCT_FUNCTION (test_fndecl
), NULL
, NULL
);
8010 model0
.set_value (model0
.get_lvalue (p
, NULL
),
8011 model0
.get_rvalue (addr_of_a
, NULL
), NULL
);
8013 region_model
model1 (model0
);
8014 ASSERT_EQ (model0
, model1
);
8016 /* They should be mergeable, and the result should be the same. */
8017 region_model
merged (&mgr
);
8018 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8019 ASSERT_EQ (model0
, merged
);
8022 /* Pointers: non-NULL and non-NULL: ptr to a global. */
8024 region_model
merged (&mgr
);
8025 /* p == &y in both input models. */
8026 const svalue
*merged_p_sval
;
8027 assert_region_models_merge (p
, addr_of_y
, addr_of_y
, &merged
,
8030 /* We should get p == &y in the merged model. */
8031 ASSERT_EQ (merged_p_sval
->get_kind (), SK_REGION
);
8032 const region_svalue
*merged_p_ptr
8033 = merged_p_sval
->dyn_cast_region_svalue ();
8034 const region
*merged_p_star_reg
= merged_p_ptr
->get_pointee ();
8035 ASSERT_EQ (merged_p_star_reg
, merged
.get_lvalue (y
, NULL
));
8038 /* Pointers: non-NULL ptrs to different globals: should be unknown. */
8040 region_model
merged (&mgr
);
8041 /* x == &y vs x == &z in the input models; these are actually casts
8042 of the ptrs to "int". */
8043 const svalue
*merged_x_sval
;
8045 assert_region_models_merge (x
, addr_of_y
, addr_of_z
, &merged
,
8048 /* We should get x == unknown in the merged model. */
8049 ASSERT_EQ (merged_x_sval
->get_kind (), SK_UNKNOWN
);
8052 /* Pointers: non-NULL and non-NULL: ptr to a heap region. */
8054 test_region_model_context ctxt
;
8055 region_model
model0 (&mgr
);
8056 tree size
= build_int_cst (size_type_node
, 1024);
8057 const svalue
*size_sval
= mgr
.get_or_create_constant_svalue (size
);
8058 const region
*new_reg
8059 = model0
.get_or_create_region_for_heap_alloc (size_sval
, &ctxt
);
8060 const svalue
*ptr_sval
= mgr
.get_ptr_svalue (ptr_type_node
, new_reg
);
8061 model0
.set_value (model0
.get_lvalue (p
, &ctxt
),
8064 region_model
model1 (model0
);
8066 ASSERT_EQ (model0
, model1
);
8068 region_model
merged (&mgr
);
8069 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8071 /* The merged model ought to be identical. */
8072 ASSERT_EQ (model0
, merged
);
8075 /* Two regions sharing the same placeholder svalue should continue sharing
8076 it after self-merger. */
8078 test_region_model_context ctxt
;
8079 region_model
model0 (&mgr
);
8080 placeholder_svalue
placeholder_sval (mgr
.alloc_symbol_id (),
8081 integer_type_node
, "test");
8082 model0
.set_value (model0
.get_lvalue (x
, &ctxt
),
8083 &placeholder_sval
, &ctxt
);
8084 model0
.set_value (model0
.get_lvalue (y
, &ctxt
), &placeholder_sval
, &ctxt
);
8085 region_model
model1 (model0
);
8087 /* They should be mergeable, and the result should be the same. */
8088 region_model
merged (&mgr
);
8089 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8090 ASSERT_EQ (model0
, merged
);
8092 /* In particular, we should have x == y. */
8093 ASSERT_EQ (merged
.eval_condition (x
, EQ_EXPR
, y
, &ctxt
),
8094 tristate (tristate::TS_TRUE
));
8098 region_model
model0 (&mgr
);
8099 region_model
model1 (&mgr
);
8100 test_region_model_context ctxt
;
8101 model0
.add_constraint (x
, EQ_EXPR
, int_42
, &ctxt
);
8102 model1
.add_constraint (x
, NE_EXPR
, int_42
, &ctxt
);
8103 region_model
merged (&mgr
);
8104 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8108 region_model
model0 (&mgr
);
8109 region_model
model1 (&mgr
);
8110 test_region_model_context ctxt
;
8111 model0
.add_constraint (x
, EQ_EXPR
, int_42
, &ctxt
);
8112 model1
.add_constraint (x
, NE_EXPR
, int_42
, &ctxt
);
8113 model1
.add_constraint (x
, EQ_EXPR
, int_113
, &ctxt
);
8114 region_model
merged (&mgr
);
8115 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8118 // TODO: what can't we merge? need at least one such test
8120 /* TODO: various things
8123 - every combination, but in particular
8129 test_region_model_context ctxt
;
8130 region_model
model0 (&mgr
);
8132 const region
*x_reg
= model0
.get_lvalue (x
, &ctxt
);
8133 const region
*x_as_ptr
= mgr
.get_cast_region (x_reg
, ptr_type_node
);
8134 model0
.set_value (x_as_ptr
, model0
.get_rvalue (addr_of_y
, &ctxt
), &ctxt
);
8136 region_model
model1 (model0
);
8137 ASSERT_EQ (model1
, model0
);
8139 /* They should be mergeable, and the result should be the same. */
8140 region_model
merged (&mgr
);
8141 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8144 /* Verify that we can merge a model in which a local in an older stack
8145 frame points to a local in a more recent stack frame. */
8147 region_model
model0 (&mgr
);
8148 model0
.push_frame (DECL_STRUCT_FUNCTION (test_fndecl
), NULL
, NULL
);
8149 const region
*q_in_first_frame
= model0
.get_lvalue (q
, NULL
);
8151 /* Push a second frame. */
8152 const region
*reg_2nd_frame
8153 = model0
.push_frame (DECL_STRUCT_FUNCTION (test_fndecl
), NULL
, NULL
);
8155 /* Have a pointer in the older frame point to a local in the
8156 more recent frame. */
8157 const svalue
*sval_ptr
= model0
.get_rvalue (addr_of_a
, NULL
);
8158 model0
.set_value (q_in_first_frame
, sval_ptr
, NULL
);
8160 /* Verify that it's pointing at the newer frame. */
8161 const region
*reg_pointee
= sval_ptr
->maybe_get_region ();
8162 ASSERT_EQ (reg_pointee
->get_parent_region (), reg_2nd_frame
);
8164 model0
.canonicalize ();
8166 region_model
model1 (model0
);
8167 ASSERT_EQ (model0
, model1
);
8169 /* They should be mergeable, and the result should be the same
8170 (after canonicalization, at least). */
8171 region_model
merged (&mgr
);
8172 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8173 merged
.canonicalize ();
8174 ASSERT_EQ (model0
, merged
);
8177 /* Verify that we can merge a model in which a local points to a global. */
8179 region_model
model0 (&mgr
);
8180 model0
.push_frame (DECL_STRUCT_FUNCTION (test_fndecl
), NULL
, NULL
);
8181 model0
.set_value (model0
.get_lvalue (q
, NULL
),
8182 model0
.get_rvalue (addr_of_y
, NULL
), NULL
);
8184 region_model
model1 (model0
);
8185 ASSERT_EQ (model0
, model1
);
8187 /* They should be mergeable, and the result should be the same
8188 (after canonicalization, at least). */
8189 region_model
merged (&mgr
);
8190 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8191 ASSERT_EQ (model0
, merged
);
8195 /* Verify that constraints are correctly merged when merging region_model
8199 test_constraint_merging ()
8201 tree int_0
= build_int_cst (integer_type_node
, 0);
8202 tree int_5
= build_int_cst (integer_type_node
, 5);
8203 tree x
= build_global_decl ("x", integer_type_node
);
8204 tree y
= build_global_decl ("y", integer_type_node
);
8205 tree z
= build_global_decl ("z", integer_type_node
);
8206 tree n
= build_global_decl ("n", integer_type_node
);
8208 region_model_manager mgr
;
8209 test_region_model_context ctxt
;
8211 /* model0: 0 <= (x == y) < n. */
8212 region_model
model0 (&mgr
);
8213 model0
.add_constraint (x
, EQ_EXPR
, y
, &ctxt
);
8214 model0
.add_constraint (x
, GE_EXPR
, int_0
, NULL
);
8215 model0
.add_constraint (x
, LT_EXPR
, n
, NULL
);
8217 /* model1: z != 5 && (0 <= x < n). */
8218 region_model
model1 (&mgr
);
8219 model1
.add_constraint (z
, NE_EXPR
, int_5
, NULL
);
8220 model1
.add_constraint (x
, GE_EXPR
, int_0
, NULL
);
8221 model1
.add_constraint (x
, LT_EXPR
, n
, NULL
);
8223 /* They should be mergeable; the merged constraints should
8224 be: (0 <= x < n). */
8225 program_point
point (program_point::origin (mgr
));
8226 region_model
merged (&mgr
);
8227 ASSERT_TRUE (model0
.can_merge_with_p (model1
, point
, &merged
));
8229 ASSERT_EQ (merged
.eval_condition (x
, GE_EXPR
, int_0
, &ctxt
),
8230 tristate (tristate::TS_TRUE
));
8231 ASSERT_EQ (merged
.eval_condition (x
, LT_EXPR
, n
, &ctxt
),
8232 tristate (tristate::TS_TRUE
));
8234 ASSERT_EQ (merged
.eval_condition (z
, NE_EXPR
, int_5
, &ctxt
),
8235 tristate (tristate::TS_UNKNOWN
));
8236 ASSERT_EQ (merged
.eval_condition (x
, LT_EXPR
, y
, &ctxt
),
8237 tristate (tristate::TS_UNKNOWN
));
8240 /* Verify that widening_svalue::eval_condition_without_cm works as
8244 test_widening_constraints ()
8246 region_model_manager mgr
;
8247 function_point
point (program_point::origin (mgr
).get_function_point ());
8248 tree int_0
= build_int_cst (integer_type_node
, 0);
8249 tree int_m1
= build_int_cst (integer_type_node
, -1);
8250 tree int_1
= build_int_cst (integer_type_node
, 1);
8251 tree int_256
= build_int_cst (integer_type_node
, 256);
8252 test_region_model_context ctxt
;
8253 const svalue
*int_0_sval
= mgr
.get_or_create_constant_svalue (int_0
);
8254 const svalue
*int_1_sval
= mgr
.get_or_create_constant_svalue (int_1
);
8255 const svalue
*w_zero_then_one_sval
8256 = mgr
.get_or_create_widening_svalue (integer_type_node
, point
,
8257 int_0_sval
, int_1_sval
);
8258 const widening_svalue
*w_zero_then_one
8259 = w_zero_then_one_sval
->dyn_cast_widening_svalue ();
8260 ASSERT_EQ (w_zero_then_one
->get_direction (),
8261 widening_svalue::DIR_ASCENDING
);
8262 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LT_EXPR
, int_m1
),
8263 tristate::TS_FALSE
);
8264 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LT_EXPR
, int_0
),
8265 tristate::TS_FALSE
);
8266 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LT_EXPR
, int_1
),
8267 tristate::TS_UNKNOWN
);
8268 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LT_EXPR
, int_256
),
8269 tristate::TS_UNKNOWN
);
8271 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LE_EXPR
, int_m1
),
8272 tristate::TS_FALSE
);
8273 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LE_EXPR
, int_0
),
8274 tristate::TS_UNKNOWN
);
8275 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LE_EXPR
, int_1
),
8276 tristate::TS_UNKNOWN
);
8277 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (LE_EXPR
, int_256
),
8278 tristate::TS_UNKNOWN
);
8280 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GT_EXPR
, int_m1
),
8282 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GT_EXPR
, int_0
),
8283 tristate::TS_UNKNOWN
);
8284 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GT_EXPR
, int_1
),
8285 tristate::TS_UNKNOWN
);
8286 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GT_EXPR
, int_256
),
8287 tristate::TS_UNKNOWN
);
8289 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GE_EXPR
, int_m1
),
8291 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GE_EXPR
, int_0
),
8293 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GE_EXPR
, int_1
),
8294 tristate::TS_UNKNOWN
);
8295 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (GE_EXPR
, int_256
),
8296 tristate::TS_UNKNOWN
);
8298 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (EQ_EXPR
, int_m1
),
8299 tristate::TS_FALSE
);
8300 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (EQ_EXPR
, int_0
),
8301 tristate::TS_UNKNOWN
);
8302 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (EQ_EXPR
, int_1
),
8303 tristate::TS_UNKNOWN
);
8304 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (EQ_EXPR
, int_256
),
8305 tristate::TS_UNKNOWN
);
8307 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (NE_EXPR
, int_m1
),
8309 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (NE_EXPR
, int_0
),
8310 tristate::TS_UNKNOWN
);
8311 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (NE_EXPR
, int_1
),
8312 tristate::TS_UNKNOWN
);
8313 ASSERT_EQ (w_zero_then_one
->eval_condition_without_cm (NE_EXPR
, int_256
),
8314 tristate::TS_UNKNOWN
);
8317 /* Verify merging constraints for states simulating successive iterations
8320 for (i = 0; i < 256; i++)
8327 i_11 = PHI <i_15(2), i_23(3)>
8337 and thus these ops (and resultant states):
8340 add_constraint (i_11 <= 255) [for the true edge]
8341 {i_11: 0} [constraint was a no-op]
8345 {i_11: WIDENED (at phi, 0, 1)}
8346 add_constraint (i_11 <= 255) [for the true edge]
8347 {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}
8349 {i_23: (WIDENED (at phi, 0, 1) + 1); WIDENED <= 255}
8350 i_11 = PHI(); merge with state at phi above
8351 {i_11: WIDENED (at phi, 0, 1); WIDENED <= 256}
8352 [changing meaning of "WIDENED" here]
8354 T: {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}; cache hit
8361 region_model_manager mgr
;
8362 program_point
point (program_point::origin (mgr
));
8364 tree int_0
= build_int_cst (integer_type_node
, 0);
8365 tree int_1
= build_int_cst (integer_type_node
, 1);
8366 tree int_256
= build_int_cst (integer_type_node
, 256);
8367 tree int_257
= build_int_cst (integer_type_node
, 257);
8368 tree i
= build_global_decl ("i", integer_type_node
);
8370 test_region_model_context ctxt
;
8373 region_model
model0 (&mgr
);
8374 model0
.set_value (i
, int_0
, &ctxt
);
8377 region_model
model1 (&mgr
);
8378 model1
.set_value (i
, int_1
, &ctxt
);
8380 /* Should merge "i" to a widened value. */
8381 region_model
model2 (&mgr
);
8382 ASSERT_TRUE (model1
.can_merge_with_p (model0
, point
, &model2
));
8383 const svalue
*merged_i
= model2
.get_rvalue (i
, &ctxt
);
8384 ASSERT_EQ (merged_i
->get_kind (), SK_WIDENING
);
8385 const widening_svalue
*w
= merged_i
->dyn_cast_widening_svalue ();
8386 ASSERT_EQ (w
->get_direction (), widening_svalue::DIR_ASCENDING
);
8388 /* Add constraint: i < 256 */
8389 model2
.add_constraint (i
, LT_EXPR
, int_256
, &ctxt
);
8390 ASSERT_EQ (model2
.eval_condition (i
, LT_EXPR
, int_256
, &ctxt
),
8391 tristate (tristate::TS_TRUE
));
8392 ASSERT_EQ (model2
.eval_condition (i
, GE_EXPR
, int_0
, &ctxt
),
8393 tristate (tristate::TS_TRUE
));
8395 /* Try merging with the initial state. */
8396 region_model
model3 (&mgr
);
8397 ASSERT_TRUE (model2
.can_merge_with_p (model0
, point
, &model3
));
8398 /* Merging the merged value with the initial value should be idempotent,
8399 so that the analysis converges. */
8400 ASSERT_EQ (model3
.get_rvalue (i
, &ctxt
), merged_i
);
8401 /* Merger of 0 and a widening value with constraint < CST
8402 should retain the constraint, even though it was implicit
8404 ASSERT_EQ (model3
.eval_condition (i
, LT_EXPR
, int_256
, &ctxt
),
8405 tristate (tristate::TS_TRUE
));
8406 /* ...and we should have equality: the analysis should have converged. */
8407 ASSERT_EQ (model3
, model2
);
8409 /* "i_23 = i_11 + 1;" */
8410 region_model
model4 (model3
);
8411 ASSERT_EQ (model4
, model2
);
8412 model4
.set_value (i
, build2 (PLUS_EXPR
, integer_type_node
, i
, int_1
), &ctxt
);
8413 const svalue
*plus_one
= model4
.get_rvalue (i
, &ctxt
);
8414 ASSERT_EQ (plus_one
->get_kind (), SK_BINOP
);
8416 /* Try merging with the "i: 1" state. */
8417 region_model
model5 (&mgr
);
8418 ASSERT_TRUE (model4
.can_merge_with_p (model1
, point
, &model5
));
8419 ASSERT_EQ (model5
.get_rvalue (i
, &ctxt
), plus_one
);
8420 ASSERT_EQ (model5
, model4
);
8422 /* "i_11 = PHI();" merge with state at phi above.
8423 For i, we should have a merger of WIDENING with WIDENING + 1,
8424 and this should be WIDENING again. */
8425 region_model
model6 (&mgr
);
8426 ASSERT_TRUE (model5
.can_merge_with_p (model2
, point
, &model6
));
8427 const svalue
*merged_widening
= model6
.get_rvalue (i
, &ctxt
);
8428 ASSERT_EQ (merged_widening
->get_kind (), SK_WIDENING
);
8430 ASSERT_CONDITION_TRUE (model6
, i
, LT_EXPR
, int_257
);
8433 /* Verify that if we mark a pointer to a malloc-ed region as non-NULL,
8434 all cast pointers to that region are also known to be non-NULL. */
8437 test_malloc_constraints ()
8439 region_model_manager mgr
;
8440 region_model
model (&mgr
);
8441 tree p
= build_global_decl ("p", ptr_type_node
);
8442 tree char_star
= build_pointer_type (char_type_node
);
8443 tree q
= build_global_decl ("q", char_star
);
8444 tree null_ptr
= build_int_cst (ptr_type_node
, 0);
8446 const svalue
*size_in_bytes
8447 = mgr
.get_or_create_unknown_svalue (size_type_node
);
8449 = model
.get_or_create_region_for_heap_alloc (size_in_bytes
, NULL
);
8450 const svalue
*sval
= mgr
.get_ptr_svalue (ptr_type_node
, reg
);
8451 model
.set_value (model
.get_lvalue (p
, NULL
), sval
, NULL
);
8452 model
.set_value (q
, p
, NULL
);
8454 ASSERT_CONDITION_UNKNOWN (model
, p
, NE_EXPR
, null_ptr
);
8455 ASSERT_CONDITION_UNKNOWN (model
, p
, EQ_EXPR
, null_ptr
);
8456 ASSERT_CONDITION_UNKNOWN (model
, q
, NE_EXPR
, null_ptr
);
8457 ASSERT_CONDITION_UNKNOWN (model
, q
, EQ_EXPR
, null_ptr
);
8459 model
.add_constraint (p
, NE_EXPR
, null_ptr
, NULL
);
8461 ASSERT_CONDITION_TRUE (model
, p
, NE_EXPR
, null_ptr
);
8462 ASSERT_CONDITION_FALSE (model
, p
, EQ_EXPR
, null_ptr
);
8463 ASSERT_CONDITION_TRUE (model
, q
, NE_EXPR
, null_ptr
);
8464 ASSERT_CONDITION_FALSE (model
, q
, EQ_EXPR
, null_ptr
);
8467 /* Smoketest of getting and setting the value of a variable. */
8473 tree i
= build_global_decl ("i", integer_type_node
);
8475 tree int_17
= build_int_cst (integer_type_node
, 17);
8476 tree int_m3
= build_int_cst (integer_type_node
, -3);
8478 region_model_manager mgr
;
8479 region_model
model (&mgr
);
8481 const region
*i_reg
= model
.get_lvalue (i
, NULL
);
8482 ASSERT_EQ (i_reg
->get_kind (), RK_DECL
);
8484 /* Reading "i" should give a symbolic "initial value". */
8485 const svalue
*sval_init
= model
.get_rvalue (i
, NULL
);
8486 ASSERT_EQ (sval_init
->get_kind (), SK_INITIAL
);
8487 ASSERT_EQ (sval_init
->dyn_cast_initial_svalue ()->get_region (), i_reg
);
8488 /* ..and doing it again should give the same "initial value". */
8489 ASSERT_EQ (model
.get_rvalue (i
, NULL
), sval_init
);
8492 model
.set_value (i
, int_17
, NULL
);
8493 ASSERT_EQ (model
.get_rvalue (i
, NULL
),
8494 model
.get_rvalue (int_17
, NULL
));
8497 model
.set_value (i
, int_m3
, NULL
);
8498 ASSERT_EQ (model
.get_rvalue (i
, NULL
),
8499 model
.get_rvalue (int_m3
, NULL
));
8501 /* Verify get_offset for "i". */
8503 region_offset offset
= i_reg
->get_offset (&mgr
);
8504 ASSERT_EQ (offset
.get_base_region (), i_reg
);
8505 ASSERT_EQ (offset
.get_bit_offset (), 0);
8512 /* "int arr[10];" */
8513 tree tlen
= size_int (10);
8515 = build_array_type (integer_type_node
, build_index_type (tlen
));
8516 tree arr
= build_global_decl ("arr", arr_type
);
8519 tree i
= build_global_decl ("i", integer_type_node
);
8521 tree int_0
= build_int_cst (integer_type_node
, 0);
8522 tree int_1
= build_int_cst (integer_type_node
, 1);
8524 tree arr_0
= build4 (ARRAY_REF
, integer_type_node
,
8525 arr
, int_0
, NULL_TREE
, NULL_TREE
);
8526 tree arr_1
= build4 (ARRAY_REF
, integer_type_node
,
8527 arr
, int_1
, NULL_TREE
, NULL_TREE
);
8528 tree arr_i
= build4 (ARRAY_REF
, integer_type_node
,
8529 arr
, i
, NULL_TREE
, NULL_TREE
);
8531 tree int_17
= build_int_cst (integer_type_node
, 17);
8532 tree int_42
= build_int_cst (integer_type_node
, 42);
8533 tree int_m3
= build_int_cst (integer_type_node
, -3);
8535 region_model_manager mgr
;
8536 region_model
model (&mgr
);
8537 /* "arr[0] = 17;". */
8538 model
.set_value (arr_0
, int_17
, NULL
);
8539 /* "arr[1] = -3;". */
8540 model
.set_value (arr_1
, int_m3
, NULL
);
8542 ASSERT_EQ (model
.get_rvalue (arr_0
, NULL
), model
.get_rvalue (int_17
, NULL
));
8543 ASSERT_EQ (model
.get_rvalue (arr_1
, NULL
), model
.get_rvalue (int_m3
, NULL
));
8545 /* Overwrite a pre-existing binding: "arr[1] = 42;". */
8546 model
.set_value (arr_1
, int_42
, NULL
);
8547 ASSERT_EQ (model
.get_rvalue (arr_1
, NULL
), model
.get_rvalue (int_42
, NULL
));
8549 /* Verify get_offset for "arr[0]". */
8551 const region
*arr_0_reg
= model
.get_lvalue (arr_0
, NULL
);
8552 region_offset offset
= arr_0_reg
->get_offset (&mgr
);
8553 ASSERT_EQ (offset
.get_base_region (), model
.get_lvalue (arr
, NULL
));
8554 ASSERT_EQ (offset
.get_bit_offset (), 0);
8557 /* Verify get_offset for "arr[1]". */
8559 const region
*arr_1_reg
= model
.get_lvalue (arr_1
, NULL
);
8560 region_offset offset
= arr_1_reg
->get_offset (&mgr
);
8561 ASSERT_EQ (offset
.get_base_region (), model
.get_lvalue (arr
, NULL
));
8562 ASSERT_EQ (offset
.get_bit_offset (), INT_TYPE_SIZE
);
8565 /* Verify get_offset for "arr[i]". */
8567 const region
*arr_i_reg
= model
.get_lvalue (arr_i
, NULL
);
8568 region_offset offset
= arr_i_reg
->get_offset (&mgr
);
8569 ASSERT_EQ (offset
.get_base_region (), model
.get_lvalue (arr
, NULL
));
8570 ASSERT_EQ (offset
.get_symbolic_byte_offset ()->get_kind (), SK_BINOP
);
8573 /* "arr[i] = i;" - this should remove the earlier bindings. */
8574 model
.set_value (arr_i
, i
, NULL
);
8575 ASSERT_EQ (model
.get_rvalue (arr_i
, NULL
), model
.get_rvalue (i
, NULL
));
8576 ASSERT_EQ (model
.get_rvalue (arr_0
, NULL
)->get_kind (), SK_UNKNOWN
);
8578 /* "arr[0] = 17;" - this should remove the arr[i] binding. */
8579 model
.set_value (arr_0
, int_17
, NULL
);
8580 ASSERT_EQ (model
.get_rvalue (arr_0
, NULL
), model
.get_rvalue (int_17
, NULL
));
8581 ASSERT_EQ (model
.get_rvalue (arr_i
, NULL
)->get_kind (), SK_UNKNOWN
);
8584 /* Smoketest of dereferencing a pointer via MEM_REF. */
8594 tree x
= build_global_decl ("x", integer_type_node
);
8595 tree int_star
= build_pointer_type (integer_type_node
);
8596 tree p
= build_global_decl ("p", int_star
);
8598 tree int_17
= build_int_cst (integer_type_node
, 17);
8599 tree addr_of_x
= build1 (ADDR_EXPR
, int_star
, x
);
8600 tree offset_0
= build_int_cst (integer_type_node
, 0);
8601 tree star_p
= build2 (MEM_REF
, integer_type_node
, p
, offset_0
);
8603 region_model_manager mgr
;
8604 region_model
model (&mgr
);
8607 model
.set_value (x
, int_17
, NULL
);
8610 model
.set_value (p
, addr_of_x
, NULL
);
8612 const svalue
*sval
= model
.get_rvalue (star_p
, NULL
);
8613 ASSERT_EQ (sval
->maybe_get_constant (), int_17
);
8616 /* Test for a POINTER_PLUS_EXPR followed by a MEM_REF.
8617 Analogous to this code:
8618 void test_6 (int a[10])
8620 __analyzer_eval (a[3] == 42); [should be UNKNOWN]
8622 __analyzer_eval (a[3] == 42); [should be TRUE]
8624 from data-model-1.c, which looks like this at the gimple level:
8625 # __analyzer_eval (a[3] == 42); [should be UNKNOWN]
8626 int *_1 = a_10(D) + 12; # POINTER_PLUS_EXPR
8627 int _2 = *_1; # MEM_REF
8628 _Bool _3 = _2 == 42;
8630 __analyzer_eval (_4);
8633 int *_5 = a_10(D) + 12; # POINTER_PLUS_EXPR
8636 # __analyzer_eval (a[3] == 42); [should be TRUE]
8637 int *_6 = a_10(D) + 12; # POINTER_PLUS_EXPR
8638 int _7 = *_6; # MEM_REF
8639 _Bool _8 = _7 == 42;
8641 __analyzer_eval (_9); */
8644 test_POINTER_PLUS_EXPR_then_MEM_REF ()
8646 tree int_star
= build_pointer_type (integer_type_node
);
8647 tree a
= build_global_decl ("a", int_star
);
8648 tree offset_12
= build_int_cst (size_type_node
, 12);
8649 tree pointer_plus_expr
= build2 (POINTER_PLUS_EXPR
, int_star
, a
, offset_12
);
8650 tree offset_0
= build_int_cst (integer_type_node
, 0);
8651 tree mem_ref
= build2 (MEM_REF
, integer_type_node
,
8652 pointer_plus_expr
, offset_0
);
8653 region_model_manager mgr
;
8654 region_model
m (&mgr
);
8656 tree int_42
= build_int_cst (integer_type_node
, 42);
8657 m
.set_value (mem_ref
, int_42
, NULL
);
8658 ASSERT_EQ (m
.get_rvalue (mem_ref
, NULL
)->maybe_get_constant (), int_42
);
8661 /* Verify that malloc works. */
8666 tree int_star
= build_pointer_type (integer_type_node
);
8667 tree p
= build_global_decl ("p", int_star
);
8668 tree n
= build_global_decl ("n", integer_type_node
);
8669 tree n_times_4
= build2 (MULT_EXPR
, size_type_node
,
8670 n
, build_int_cst (size_type_node
, 4));
8672 region_model_manager mgr
;
8673 test_region_model_context ctxt
;
8674 region_model
model (&mgr
);
8676 /* "p = malloc (n * 4);". */
8677 const svalue
*size_sval
= model
.get_rvalue (n_times_4
, &ctxt
);
8679 = model
.get_or_create_region_for_heap_alloc (size_sval
, &ctxt
);
8680 const svalue
*ptr
= mgr
.get_ptr_svalue (int_star
, reg
);
8681 model
.set_value (model
.get_lvalue (p
, &ctxt
), ptr
, &ctxt
);
8682 ASSERT_EQ (model
.get_capacity (reg
), size_sval
);
8685 /* Verify that alloca works. */
8690 auto_vec
<tree
> param_types
;
8691 tree fndecl
= make_fndecl (integer_type_node
,
8694 allocate_struct_function (fndecl
, true);
8697 tree int_star
= build_pointer_type (integer_type_node
);
8698 tree p
= build_global_decl ("p", int_star
);
8699 tree n
= build_global_decl ("n", integer_type_node
);
8700 tree n_times_4
= build2 (MULT_EXPR
, size_type_node
,
8701 n
, build_int_cst (size_type_node
, 4));
8703 region_model_manager mgr
;
8704 test_region_model_context ctxt
;
8705 region_model
model (&mgr
);
8707 /* Push stack frame. */
8708 const region
*frame_reg
8709 = model
.push_frame (DECL_STRUCT_FUNCTION (fndecl
),
8711 /* "p = alloca (n * 4);". */
8712 const svalue
*size_sval
= model
.get_rvalue (n_times_4
, &ctxt
);
8713 const region
*reg
= model
.create_region_for_alloca (size_sval
, &ctxt
);
8714 ASSERT_EQ (reg
->get_parent_region (), frame_reg
);
8715 const svalue
*ptr
= mgr
.get_ptr_svalue (int_star
, reg
);
8716 model
.set_value (model
.get_lvalue (p
, &ctxt
), ptr
, &ctxt
);
8717 ASSERT_EQ (model
.get_capacity (reg
), size_sval
);
8719 /* Verify that the pointers to the alloca region are replaced by
8720 poisoned values when the frame is popped. */
8721 model
.pop_frame (NULL
, NULL
, &ctxt
);
8722 ASSERT_EQ (model
.get_rvalue (p
, NULL
)->get_kind (), SK_POISONED
);
8725 /* Verify that svalue::involves_p works. */
8730 region_model_manager mgr
;
8731 tree int_star
= build_pointer_type (integer_type_node
);
8732 tree p
= build_global_decl ("p", int_star
);
8733 tree q
= build_global_decl ("q", int_star
);
8735 test_region_model_context ctxt
;
8736 region_model
model (&mgr
);
8737 const svalue
*p_init
= model
.get_rvalue (p
, &ctxt
);
8738 const svalue
*q_init
= model
.get_rvalue (q
, &ctxt
);
8740 ASSERT_TRUE (p_init
->involves_p (p_init
));
8741 ASSERT_FALSE (p_init
->involves_p (q_init
));
8743 const region
*star_p_reg
= mgr
.get_symbolic_region (p_init
);
8744 const region
*star_q_reg
= mgr
.get_symbolic_region (q_init
);
8746 const svalue
*init_star_p
= mgr
.get_or_create_initial_value (star_p_reg
);
8747 const svalue
*init_star_q
= mgr
.get_or_create_initial_value (star_q_reg
);
8749 ASSERT_TRUE (init_star_p
->involves_p (p_init
));
8750 ASSERT_FALSE (p_init
->involves_p (init_star_p
));
8751 ASSERT_FALSE (init_star_p
->involves_p (q_init
));
8752 ASSERT_TRUE (init_star_q
->involves_p (q_init
));
8753 ASSERT_FALSE (init_star_q
->involves_p (p_init
));
8756 /* Run all of the selftests within this file. */
8759 analyzer_region_model_cc_tests ()
8761 test_tree_cmp_on_constants ();
8765 test_get_representative_tree ();
8766 test_unique_constants ();
8767 test_unique_unknowns ();
8768 test_initial_svalue_folding ();
8769 test_unaryop_svalue_folding ();
8770 test_binop_svalue_folding ();
8771 test_sub_svalue_folding ();
8772 test_bits_within_svalue_folding ();
8773 test_descendent_of_p ();
8774 test_bit_range_regions ();
8776 test_compound_assignment ();
8777 test_stack_frames ();
8778 test_get_representative_path_var ();
8780 test_canonicalization_2 ();
8781 test_canonicalization_3 ();
8782 test_canonicalization_4 ();
8783 test_state_merging ();
8784 test_constraint_merging ();
8785 test_widening_constraints ();
8786 test_iteration_1 ();
8787 test_malloc_constraints ();
8791 test_POINTER_PLUS_EXPR_then_MEM_REF ();
8797 } // namespace selftest
8799 #endif /* CHECKING_P */
8803 #endif /* #if ENABLE_ANALYZER */