c++: decltype of (by-value captured reference) [PR79620]
[official-gcc.git] / gcc / analyzer / region-model.cc
blobdc8344065202708f87de4dcf0b5bac1f3b9bf378
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)
10 any later version.
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/>. */
21 #include "config.h"
22 #define INCLUDE_MEMORY
23 #define INCLUDE_ALGORITHM
24 #include "system.h"
25 #include "coretypes.h"
26 #include "make-unique.h"
27 #include "tree.h"
28 #include "function.h"
29 #include "basic-block.h"
30 #include "gimple.h"
31 #include "gimple-iterator.h"
32 #include "diagnostic-core.h"
33 #include "graphviz.h"
34 #include "options.h"
35 #include "cgraph.h"
36 #include "tree-dfa.h"
37 #include "stringpool.h"
38 #include "convert.h"
39 #include "target.h"
40 #include "fold-const.h"
41 #include "tree-pretty-print.h"
42 #include "diagnostic-color.h"
43 #include "diagnostic-metadata.h"
44 #include "bitmap.h"
45 #include "selftest.h"
46 #include "analyzer/analyzer.h"
47 #include "analyzer/analyzer-logging.h"
48 #include "ordered-hash-map.h"
49 #include "options.h"
50 #include "cgraph.h"
51 #include "cfg.h"
52 #include "analyzer/supergraph.h"
53 #include "sbitmap.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"
69 #include "attribs.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"
75 #include "calls.h"
76 #include "is-a.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"
83 #if ENABLE_ANALYZER
85 namespace ana {
87 auto_vec<pop_frame_callback> region_model::pop_frame_callbacks;
89 /* Dump T to PP in language-independent form, for debugging/logging/dumping
90 purposes. */
92 void
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. */
101 void
102 dump_quoted_tree (pretty_printer *pp, tree t)
104 pp_begin_quote (pp, pp_show_color (pp));
105 dump_tree (pp, t);
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
115 garbled output.
117 Ideally pp_printf could be made to be reentrant, but in the meantime
118 this function provides a workaround. */
120 void
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)
135 m_hash_map.empty ();
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);
142 return *this;
145 /* Equality operator for region_to_value_map. */
147 bool
148 region_to_value_map::operator== (const region_to_value_map &other) const
150 if (m_hash_map.elements () != other.m_hash_map.elements ())
151 return false;
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)
159 return false;
160 if (sval != *other_slot)
161 return false;
164 return true;
167 /* Dump this object to PP. */
169 void
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);
177 if (multiline)
178 pp_newline (pp);
179 else
180 pp_string (pp, " {");
181 unsigned i;
182 const region *reg;
183 FOR_EACH_VEC_ELT (regs, i, reg)
185 if (multiline)
186 pp_string (pp, " ");
187 else if (i > 0)
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);
193 if (multiline)
194 pp_newline (pp);
196 if (!multiline)
197 pp_string (pp, "}");
200 /* Dump this object to stderr. */
202 DEBUG_FUNCTION void
203 region_to_value_map::dump (bool simple) const
205 pretty_printer pp;
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);
210 pp_newline (&pp);
211 pp_flush (&pp);
215 /* Attempt to merge THIS with OTHER, writing the result
216 to OUT.
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. */
223 bool
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);
232 if (other_slot)
234 if (iter_sval == *other_slot)
235 out->put (iter_reg, iter_sval);
236 else
237 return false;
240 return true;
243 /* Purge any state involving SVAL. */
245 void
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),
266 m_dynamic_extents ()
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. */
290 region_model &
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;
305 return *this;
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. */
314 bool
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)
321 return false;
323 if (*m_constraints != *other.m_constraints)
324 return false;
326 if (m_current_frame != other.m_current_frame)
327 return false;
329 if (m_dynamic_extents != other.m_dynamic_extents)
330 return false;
332 gcc_checking_assert (hash () == other.hash ());
334 return true;
337 /* Generate a hash value for this region_model. */
339 hashval_t
340 region_model::hash () const
342 hashval_t result = m_store.hash ();
343 result ^= m_constraints->hash ();
344 return result;
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. */
351 void
352 region_model::dump_to_pp (pretty_printer *pp, bool simple,
353 bool multiline) const
355 /* Dump stack. */
356 pp_printf (pp, "stack depth: %i", get_stack_depth ());
357 if (multiline)
358 pp_newline (pp);
359 else
360 pp_string (pp, " {");
361 for (const frame_region *iter_frame = m_current_frame; iter_frame;
362 iter_frame = iter_frame->get_calling_frame ())
364 if (multiline)
365 pp_string (pp, " ");
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);
370 if (multiline)
371 pp_newline (pp);
373 if (!multiline)
374 pp_string (pp, "}");
376 /* Dump store. */
377 if (!multiline)
378 pp_string (pp, ", {");
379 m_store.dump_to_pp (pp, simple, multiline,
380 m_mgr->get_store_manager ());
381 if (!multiline)
382 pp_string (pp, "}");
384 /* Dump constraints. */
385 pp_string (pp, "constraint_manager:");
386 if (multiline)
387 pp_newline (pp);
388 else
389 pp_string (pp, " {");
390 m_constraints->dump_to_pp (pp, multiline);
391 if (!multiline)
392 pp_string (pp, "}");
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. */
404 void
405 region_model::dump (FILE *fp, bool simple, bool multiline) const
407 pretty_printer pp;
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);
412 pp_newline (&pp);
413 pp_flush (&pp);
416 /* Dump a multiline representation of this model to stderr. */
418 DEBUG_FUNCTION void
419 region_model::dump (bool simple) const
421 dump (stderr, simple, true);
424 /* Dump a multiline representation of this model to stderr. */
426 DEBUG_FUNCTION void
427 region_model::debug () const
429 dump (true);
432 /* Assert that this object is valid. */
434 void
435 region_model::validate () const
437 m_store.validate ();
440 /* Canonicalize the store and constraints, to maximize the chance of
441 equality between region_model instances. */
443 void
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. */
452 bool
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. */
462 void
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
469 poisoned values. */
471 class poisoned_value_diagnostic
472 : public pending_diagnostic_subclass<poisoned_value_diagnostic>
474 public:
475 poisoned_value_diagnostic (tree expr, enum poison_kind pkind,
476 const region *src_region,
477 tree check_expr)
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
499 switch (m_pkind)
501 default:
502 gcc_unreachable ();
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
517 switch (m_pkind)
519 default:
520 gcc_unreachable ();
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",
527 m_expr);
529 break;
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",
536 m_expr);
538 break;
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",
545 m_expr);
547 break;
548 case POISON_KIND_POPPED_STACK:
550 /* TODO: which CWE? */
551 return warning_at
552 (rich_loc, get_controlling_option (),
553 "dereferencing pointer %qE to within stale stack frame",
554 m_expr);
556 break;
560 label_text describe_final_event (const evdesc::final_event &ev) final override
562 switch (m_pkind)
564 default:
565 gcc_unreachable ();
566 case POISON_KIND_UNINIT:
567 return ev.formatted_print ("use of uninitialized value %qE here",
568 m_expr);
569 case POISON_KIND_FREED:
570 return ev.formatted_print ("use after %<free%> of %qE here",
571 m_expr);
572 case POISON_KIND_DELETED:
573 return ev.formatted_print ("use after %<delete%> of %qE here",
574 m_expr);
575 case POISON_KIND_POPPED_STACK:
576 return ev.formatted_print
577 ("dereferencing pointer %qE to within stale stack frame",
578 m_expr);
582 void mark_interesting_stuff (interesting_t *interest) final override
584 if (m_src_region)
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)
601 const final override
603 if (!m_check_expr)
604 return true;
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. */
611 return true;
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
615 same way). */
616 const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();
617 if (!fspval)
618 return false;
619 if (fspval->get_poison_kind () != m_pkind)
620 return false;
621 return true;
624 private:
625 tree m_expr;
626 enum poison_kind m_pkind;
627 const region *m_src_region;
628 tree m_check_expr;
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>
637 public:
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);
669 private:
670 const gassign *m_assign;
671 tree m_count_cst;
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>
680 public:
681 shift_count_overflow_diagnostic (const gassign *assign,
682 int operand_precision,
683 tree count_cst)
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);
717 private:
718 const gassign *m_assign;
719 int m_operand_precision;
720 tree m_count_cst;
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. */
728 const svalue *
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),
739 assign,
740 get_lvalue (lhs, ctxt),
744 tree rhs1 = gimple_assign_rhs1 (assign);
745 enum tree_code op = gimple_assign_rhs_code (assign);
746 switch (op)
748 default:
749 return NULL;
751 case POINTER_PLUS_EXPR:
753 /* e.g. "_1 = a_10(D) + 12;" */
754 tree ptr = rhs1;
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);
766 return sval_binop;
768 break;
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);
782 return sval_binop;
784 break;
786 /* Assignments of the form
787 set_value (lvalue (LHS), rvalue (EXPR))
788 for various EXPR.
789 We already have the lvalue for the LHS above, as "lhs_reg". */
790 case ADDR_EXPR: /* LHS = &RHS; */
791 case BIT_FIELD_REF:
792 case COMPONENT_REF: /* LHS = op0.op1; */
793 case MEM_REF:
794 case REAL_CST:
795 case COMPLEX_CST:
796 case VECTOR_CST:
797 case INTEGER_CST:
798 case ARRAY_REF:
799 case SSA_NAME: /* LHS = VAR; */
800 case VAR_DECL: /* LHS = VAR; */
801 case PARM_DECL:/* LHS = VAR; */
802 case REALPART_EXPR:
803 case IMAGPART_EXPR:
804 return get_rvalue (rhs1, ctxt);
806 case ABS_EXPR:
807 case ABSU_EXPR:
808 case CONJ_EXPR:
809 case BIT_NOT_EXPR:
810 case FIX_TRUNC_EXPR:
811 case FLOAT_EXPR:
812 case NEGATE_EXPR:
813 case NOP_EXPR:
814 case VIEW_CONVERT_EXPR:
816 /* Unary ops. */
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);
820 return sval_unaryop;
823 case EQ_EXPR:
824 case GE_EXPR:
825 case LE_EXPR:
826 case NE_EXPR:
827 case GT_EXPR:
828 case LT_EXPR:
829 case UNORDERED_EXPR:
830 case ORDERED_EXPR:
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);
841 if (t.is_known ())
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);
850 return sval_binop;
852 break;
854 case PLUS_EXPR:
855 case MINUS_EXPR:
856 case MULT_EXPR:
857 case MULT_HIGHPART_EXPR:
858 case TRUNC_DIV_EXPR:
859 case CEIL_DIV_EXPR:
860 case FLOOR_DIV_EXPR:
861 case ROUND_DIV_EXPR:
862 case TRUNC_MOD_EXPR:
863 case CEIL_MOD_EXPR:
864 case FLOOR_MOD_EXPR:
865 case ROUND_MOD_EXPR:
866 case RDIV_EXPR:
867 case EXACT_DIV_EXPR:
868 case LSHIFT_EXPR:
869 case RSHIFT_EXPR:
870 case LROTATE_EXPR:
871 case RROTATE_EXPR:
872 case BIT_IOR_EXPR:
873 case BIT_XOR_EXPR:
874 case BIT_AND_EXPR:
875 case MIN_EXPR:
876 case MAX_EXPR:
877 case COMPLEX_EXPR:
879 /* Binary ops. */
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
889 the operand." */
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)
895 ctxt->warn
896 (make_unique<shift_count_negative_diagnostic>
897 (assign, rhs2_cst));
898 else if (compare_tree_int (rhs2_cst,
899 TYPE_PRECISION (TREE_TYPE (rhs1)))
900 >= 0)
901 ctxt->warn
902 (make_unique<shift_count_overflow_diagnostic>
903 (assign,
904 int (TYPE_PRECISION (TREE_TYPE (rhs1))),
905 rhs2_cst));
909 const svalue *sval_binop
910 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
911 rhs1_sval, rhs2_sval);
912 return sval_binop;
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:
919 case VEC_COND_EXPR:
920 case VEC_PERM_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
943 of the form:
944 ((A OR-IF B) OR-IF C)
945 and:
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)
957 into:
958 ((A OR 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:
963 tmp = A | B;
964 if (tmp)
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:
974 tmp = A | B;
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. */
978 static bool
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)
985 return false;
986 if (TREE_CODE (lhs) != SSA_NAME)
987 return false;
988 if (SSA_NAME_VAR (lhs) != NULL_TREE)
989 return false;
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;
994 gimple *use_stmt;
995 if (!single_imm_use (lhs, &use_op, &use_stmt))
996 return false;
997 const gassign *use_assign = dyn_cast <const gassign *> (use_stmt);
998 if (!use_assign)
999 return false;
1000 enum tree_code op = gimple_assign_rhs_code (use_assign);
1001 if (!(op == BIT_IOR_EXPR ||op == BIT_AND_EXPR))
1002 return false;
1003 if (!(gimple_assign_rhs1 (use_assign) != lhs
1004 && gimple_assign_rhs2 (use_assign) == lhs))
1005 return false;
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 ();
1014 if (!other_arg_cst)
1015 return false;
1016 switch (op)
1018 default:
1019 gcc_unreachable ();
1020 case BIT_IOR_EXPR:
1021 if (zerop (other_arg_cst))
1022 return false;
1023 break;
1024 case BIT_AND_EXPR:
1025 if (!zerop (other_arg_cst))
1026 return false;
1027 break;
1030 /* All tests passed. We appear to be in a stmt that generates a boolean
1031 temporary with a value that won't matter. */
1032 return true;
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
1042 something like:
1044 _1 = .DEFERRED_INIT (4, 2, &"len"[0]);
1045 len = _1;
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. */
1052 static bool
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)
1059 return false;
1060 tree lhs = gimple_assign_lhs (assign_stmt);
1061 if (TREE_CODE (lhs) != VAR_DECL)
1062 return false;
1063 tree rhs = gimple_assign_rhs1 (assign_stmt);
1064 if (TREE_CODE (rhs) != SSA_NAME)
1065 return false;
1066 const gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
1067 const gcall *call = dyn_cast <const gcall *> (def_stmt);
1068 if (!call)
1069 return false;
1070 if (gimple_call_internal_p (call)
1071 && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1072 return true;
1073 return false;
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. */
1081 const svalue *
1082 region_model::check_for_poison (const svalue *sval,
1083 tree expr,
1084 const region *src_region,
1085 region_model_context *ctxt) const
1087 if (!ctxt)
1088 return sval;
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
1095 to initialize. */
1096 if (pkind == POISON_KIND_UNINIT
1097 && sval->get_type ()
1098 && is_empty_type (sval->get_type ()))
1099 return sval;
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))
1108 return sval;
1110 /* Special case to avoid false positive on
1111 -ftrivial-auto-var-init=. */
1112 if (due_to_ifn_deferred_init_p (assign_stmt))
1113 return sval;
1116 /* If we have an SSA name for a temporary, we don't want to print
1117 '<unknown>'.
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)
1133 check_expr = expr;
1134 else
1135 check_expr = NULL;
1136 if (ctxt->warn (make_unique<poisoned_value_diagnostic> (diag_arg,
1137 pkind,
1138 src_region,
1139 check_expr)))
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 ());
1147 return sval;
1150 return sval;
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. */
1157 const region *
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))
1164 expr = decl;
1165 else
1166 return NULL;
1168 return get_lvalue (expr, NULL);
1171 /* Update this model for the ASSIGN stmt, using CTXT to report any
1172 diagnostics. */
1174 void
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)
1184 for some SVALUE. */
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);
1190 return;
1193 enum tree_code op = gimple_assign_rhs_code (assign);
1194 switch (op)
1196 default:
1198 if (0)
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);
1205 break;
1207 case CONSTRUCTOR:
1209 if (TREE_CLOBBER_P (rhs1))
1211 /* e.g. "x ={v} {CLOBBER};" */
1212 clobber_region (lhs_reg);
1214 else
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);
1220 unsigned ix;
1221 tree index;
1222 tree val;
1223 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs1), ix, index, val)
1225 gcc_assert (TREE_CODE (TREE_TYPE (rhs1)) == VECTOR_TYPE);
1226 if (!index)
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,
1234 TREE_TYPE (val),
1235 index_sval);
1236 const svalue *val_sval = get_rvalue (val, ctxt);
1237 set_value (sub_reg, val_sval, ctxt);
1241 break;
1243 case STRING_CST:
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);
1250 break;
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
1256 side effects. */
1258 void
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))
1265 default:
1266 /* No-op for now. */
1267 break;
1269 case GIMPLE_ASSIGN:
1271 const gassign *assign = as_a <const gassign *> (stmt);
1272 on_assignment (assign, ctxt);
1274 break;
1276 case GIMPLE_ASM:
1278 const gasm *asm_stmt = as_a <const gasm *> (stmt);
1279 on_asm_stmt (asm_stmt, ctxt);
1281 break;
1283 case GIMPLE_CALL:
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);
1291 break;
1293 case GIMPLE_RETURN:
1295 const greturn *return_ = as_a <const greturn *> (stmt);
1296 on_return (return_, ctxt);
1298 break;
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. */
1305 void
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)
1315 return;
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)
1321 return;
1322 const tree arg1_value = TREE_VALUE (arg1_tree_list);
1323 if (!arg1_value)
1324 return;
1326 unsigned format_arg_idx = TREE_INT_CST_LOW (arg1_value) - 1;
1327 if (cd.num_args () <= format_arg_idx)
1328 return;
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
1334 public:
1335 annotating_ctxt (const call_details &cd,
1336 unsigned fmt_param_idx)
1337 : annotating_context (cd.get_ctxt ()),
1338 m_cd (cd),
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>
1347 public:
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,
1364 "format");
1367 bool operator== (const reason_format_attr &other) const
1369 return m_arg_details == other.m_arg_details;
1372 private:
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));
1379 private:
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. */
1395 void
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
1407 integer constant.
1408 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1409 the state-merger code from merging success and failure outcomes. */
1411 void
1412 region_model::update_for_int_cst_return (const call_details &cd,
1413 int retval,
1414 bool unmergeable)
1416 if (!cd.get_lhs_type ())
1417 return;
1418 if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1419 return;
1420 const svalue *result
1421 = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), retval);
1422 if (unmergeable)
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. */
1431 void
1432 region_model::update_for_zero_return (const call_details &cd,
1433 bool unmergeable)
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. */
1442 void
1443 region_model::update_for_nonzero_return (const call_details &cd)
1445 if (!cd.get_lhs_type ())
1446 return;
1447 if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1448 return;
1449 cd.set_any_lhs_with_defaults ();
1450 const svalue *zero
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
1462 constant.
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
1479 the upper bound. */
1481 return NULL;
1484 /* Attempt to get an upper bound for the size of a copy when simulating a
1485 copy function.
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. */
1494 const svalue *
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. */
1518 return NULL;
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
1527 assumption(s). */
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
1546 if not NULL.
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
1583 attributes. */
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)
1592 return NULL;
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 ();
1598 return NULL;
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
1610 fndecl it is). */
1612 bool
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. */
1631 if (ctxt)
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. */
1644 if (!callee_fndecl)
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
1679 to purge state. */
1681 void
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);
1692 return;
1694 /* Was this fndecl referenced by
1695 __attribute__((malloc(FOO)))? */
1696 if (lookup_attribute ("*dealloc", DECL_ATTRIBUTES (callee_fndecl)))
1698 impl_deallocation_call (cd);
1699 return;
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.
1715 For example, in:
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. */
1728 void
1729 region_model::purge_state_involving (const svalue *sval,
1730 region_model_context *ctxt)
1732 if (!sval->can_have_associated_state_p ())
1733 return;
1734 m_store.purge_state_involving (sval, m_mgr);
1735 m_constraints->purge_state_involving (sval);
1736 m_dynamic_extents.purge_state_involving (sval);
1737 if (ctxt)
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>
1746 public:
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));
1770 private:
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"
1782 attribute. */
1784 void
1785 region_model::check_function_attr_access (const gcall *call,
1786 tree callee_fndecl,
1787 region_model_context *ctxt,
1788 rdwr_map &rdwr_idx) const
1790 gcc_assert (call);
1791 gcc_assert (callee_fndecl);
1792 gcc_assert (ctxt);
1794 tree fntype = TREE_TYPE (callee_fndecl);
1795 gcc_assert (fntype);
1797 unsigned argno = 0;
1799 for (tree iter = TYPE_ARG_TYPES (fntype); iter;
1800 iter = TREE_CHAIN (iter), ++argno)
1802 const attr_access* access = rdwr_idx.get (argno);
1803 if (!access)
1804 continue;
1806 /* Ignore any duplicate entry in the map for the size argument. */
1807 if (access->ptrarg != argno)
1808 continue;
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
1817 public:
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),
1823 m_access (access)
1826 void add_annotations () final override
1828 add_note (make_unique<reason_attr_access>
1829 (m_callee_fndecl, m_access));
1831 private:
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)). */
1852 void
1853 region_model::
1854 check_one_function_attr_null_terminated_string_arg (const gcall *call,
1855 tree callee_fndecl,
1856 region_model_context *ctxt,
1857 rdwr_map &rdwr_idx,
1858 tree attr)
1860 gcc_assert (call);
1861 gcc_assert (callee_fndecl);
1862 gcc_assert (ctxt);
1863 gcc_assert (attr);
1865 tree arg = TREE_VALUE (attr);
1866 if (!arg)
1867 return;
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),
1889 NULL_TREE,
1890 limit_sval,
1891 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
1897 terminator. */
1898 check_for_null_terminated_string_arg (cd_checked,
1899 arg_idx);
1901 else
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),
1906 NULL_TREE,
1907 limit_sval,
1908 ctxt);
1910 return;
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, ....). */
1926 void
1927 region_model::
1928 check_function_attr_null_terminated_string_arg (const gcall *call,
1929 tree callee_fndecl,
1930 region_model_context *ctxt,
1931 rdwr_map &rdwr_idx)
1933 gcc_assert (call);
1934 gcc_assert (callee_fndecl);
1935 gcc_assert (ctxt);
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);
1945 if (!attr)
1946 return;
1948 check_one_function_attr_null_terminated_string_arg (call, callee_fndecl,
1949 ctxt, rdwr_idx,
1950 attr);
1954 /* Check CALL a call to external function CALLEE_FNDECL for any
1955 function attributes, complaining to CTXT about any issues. */
1957 void
1958 region_model::check_function_attrs (const gcall *call,
1959 tree callee_fndecl,
1960 region_model_context *ctxt)
1962 gcc_assert (call);
1963 gcc_assert (callee_fndecl);
1964 gcc_assert (ctxt);
1966 tree fntype = TREE_TYPE (callee_fndecl);
1967 if (!fntype)
1968 return;
1970 if (!TYPE_ATTRIBUTES (fntype))
1971 return;
1973 /* Initialize a map of attribute access specifications for arguments
1974 to the function call. */
1975 rdwr_map rdwr_idx;
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,
1980 ctxt, rdwr_idx);
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,
1987 recursively.
1989 Set all reachable regions to new unknown values and purge sm-state
1990 from their values, and from values that point to them. */
1992 void
1993 region_model::handle_unrecognized_call (const gcall *call,
1994 region_model_context *ctxt)
1996 tree fndecl = get_fndecl_for_call (call, ctxt);
1998 if (fndecl && 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
2006 unknown calls. */
2007 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2008 &reachable_regs);
2010 /* Params that are pointers. */
2011 tree iter_param_types = NULL_TREE;
2012 if (fndecl)
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);
2040 if (ctxt)
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);
2048 if (ctxt)
2049 ctxt->on_unknown_change (sval, true);
2050 if (uncertainty)
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,
2058 or previously. */
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 ();
2067 ++iter)
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. */
2086 void
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
2094 unknown calls. */
2095 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2096 &reachable_regs);
2098 if (extra_sval)
2099 reachable_regs.handle_sval (extra_sval);
2101 if (uncertainty)
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)
2121 out->add (*iter);
2124 /* Update this model for the RETURN_STMT, using CTXT to report any
2125 diagnostics. */
2127 void
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);
2134 if (lhs && rhs)
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. */
2148 void
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),
2154 ctxt);
2156 /* Create a setjmp_svalue for this call and store it in BUF_REG's
2157 region. */
2158 if (buf_reg)
2160 setjmp_record r (enode, call);
2161 const svalue *sval
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. */
2181 void
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;
2211 else
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
2221 return. */
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. */
2235 void
2236 region_model::handle_phi (const gphi *phi,
2237 tree lhs, tree rhs,
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))
2245 return;
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);
2252 if (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. */
2261 const region *
2262 region_model::get_lvalue_1 (path_var pv, region_model_context *ctxt) const
2264 tree expr = pv.m_tree;
2266 gcc_assert (expr);
2268 switch (TREE_CODE (expr))
2270 default:
2271 return m_mgr->get_region_for_unexpected_tree_code (ctxt, expr,
2272 dump_location_t ());
2274 case ARRAY_REF:
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)),
2283 index_sval);
2285 break;
2287 case BIT_FIELD_REF:
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);
2299 break;
2301 case MEM_REF:
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,
2309 TREE_TYPE (expr),
2310 offset_sval);
2312 break;
2314 case FUNCTION_DECL:
2315 return m_mgr->get_region_for_fndecl (expr);
2317 case LABEL_DECL:
2318 return m_mgr->get_region_for_label (expr);
2320 case VAR_DECL:
2321 /* Handle globals. */
2322 if (is_global_var (expr))
2323 return m_mgr->get_region_for_global (expr);
2325 /* Fall through. */
2327 case SSA_NAME:
2328 case PARM_DECL:
2329 case RESULT_DECL:
2331 gcc_assert (TREE_CODE (expr) == SSA_NAME
2332 || TREE_CODE (expr) == PARM_DECL
2333 || VAR_P (expr)
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);
2338 gcc_assert (frame);
2339 return frame->get_region_for_local (m_mgr, expr, ctxt);
2342 case COMPONENT_REF:
2344 /* obj.field */
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);
2350 break;
2352 case STRING_CST:
2353 return m_mgr->get_region_for_string (expr);
2357 /* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op. */
2359 static void
2360 assert_compat_types (tree src_type, tree dst_type)
2362 if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2364 #if CHECKING_P
2365 if (!(useless_type_conversion_p (src_type, dst_type)))
2366 internal_error ("incompatible types: %qT and %qT", src_type, dst_type);
2367 #endif
2371 /* Return true if SRC_TYPE can be converted to DST_TYPE as a no-op. */
2373 bool
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)))
2378 return false;
2379 return true;
2382 /* Get the region for PV within this region_model,
2383 emitting any diagnostics to CTXT. */
2385 const region *
2386 region_model::get_lvalue (path_var pv, region_model_context *ctxt) const
2388 if (pv.m_tree == NULL_TREE)
2389 return NULL;
2391 const region *result_reg = get_lvalue_1 (pv, ctxt);
2392 assert_compat_types (result_reg->get_type (), TREE_TYPE (pv.m_tree));
2393 return result_reg;
2396 /* Get the region for EXPR within this region_model (assuming the most
2397 recent stack frame if it's a local). */
2399 const region *
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. */
2410 const svalue *
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))
2417 default:
2418 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2420 case ADDR_EXPR:
2422 /* "&EXPR". */
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);
2428 break;
2430 case BIT_FIELD_REF:
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);
2444 case VAR_DECL:
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));
2451 /* Fall through. */
2452 case PARM_DECL:
2453 case SSA_NAME:
2454 case RESULT_DECL:
2455 case ARRAY_REF:
2457 const region *reg = get_lvalue (pv, ctxt);
2458 return get_store_value (reg, ctxt);
2461 case REALPART_EXPR:
2462 case IMAGPART_EXPR:
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),
2470 arg_sval);
2471 return sval_unaryop;
2474 case INTEGER_CST:
2475 case REAL_CST:
2476 case COMPLEX_CST:
2477 case VECTOR_CST:
2478 case STRING_CST:
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);
2491 return sval_binop;
2494 /* Binary ops. */
2495 case PLUS_EXPR:
2496 case MULT_EXPR:
2497 case BIT_AND_EXPR:
2498 case BIT_IOR_EXPR:
2499 case BIT_XOR_EXPR:
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);
2509 return sval_binop;
2512 case COMPONENT_REF:
2513 case MEM_REF:
2515 const region *ref_reg = get_lvalue (pv, ctxt);
2516 return get_store_value (ref_reg, ctxt);
2518 case OBJ_TYPE_REF:
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. */
2529 const svalue *
2530 region_model::get_rvalue (path_var pv, region_model_context *ctxt) const
2532 if (pv.m_tree == NULL_TREE)
2533 return NULL;
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);
2541 return result_sval;
2544 /* Get the value of EXPR within this region_model (assuming the most
2545 recent stack frame if it's a local). */
2547 const svalue *
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). */
2557 bool
2558 region_model::called_from_main_p () const
2560 if (!m_current_frame)
2561 return false;
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). */
2572 const svalue *
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
2594 of the decl. */
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. */
2606 const svalue *
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))
2621 return sval;
2623 const svalue *sval
2624 = m_store.get_any_binding (m_mgr->get_store_manager (), reg);
2625 if (sval)
2627 if (reg->get_type ())
2628 sval = m_mgr->get_or_create_cast (reg->get_type (), sval);
2629 return 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,
2642 byte_offset_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,
2655 byte_offset_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
2662 that above). */
2664 /* Handle globals. */
2665 if (reg->get_base_region ()->get_parent_region ()->get_kind ()
2666 == RK_GLOBALS)
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. */
2676 bool
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
2683 by it. */
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)
2687 return true;
2688 return false;
2691 return true;
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. */
2699 const region *
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 ())
2722 default:
2723 break;
2725 case SK_REGION:
2727 const region_svalue *region_sval
2728 = as_a <const region_svalue *> (ptr_sval);
2729 return region_sval->get_pointee ();
2732 case SK_BINOP:
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);
2748 default:
2749 break;
2752 break;
2754 case SK_POISONED:
2756 if (ctxt)
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. */
2762 if (!ptr)
2763 ptr = ptr_tree;
2764 if (ptr)
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));
2774 break;
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. */
2786 const svalue *
2787 region_model::get_rvalue_for_bits (tree type,
2788 const region *reg,
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>
2802 public:
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;
2826 bool warned;
2827 switch (m_reg->get_kind ())
2829 default:
2830 warned = warning_at (rich_loc, get_controlling_option (),
2831 "write to %<const%> object %qE", m_decl);
2832 break;
2833 case RK_FUNCTION:
2834 warned = warning_at (rich_loc, get_controlling_option (),
2835 "write to function %qE", m_decl);
2836 break;
2837 case RK_LABEL:
2838 warned = warning_at (rich_loc, get_controlling_option (),
2839 "write to label %qE", m_decl);
2840 break;
2842 if (warned)
2843 inform (DECL_SOURCE_LOCATION (m_decl), "declared here");
2844 return warned;
2847 label_text describe_final_event (const evdesc::final_event &ev) final override
2849 switch (m_reg->get_kind ())
2851 default:
2852 return ev.formatted_print ("write to %<const%> object %qE here", m_decl);
2853 case RK_FUNCTION:
2854 return ev.formatted_print ("write to function %qE here", m_decl);
2855 case RK_LABEL:
2856 return ev.formatted_print ("write to label %qE here", m_decl);
2860 private:
2861 const region *m_reg;
2862 tree m_decl;
2865 /* A subclass of pending_diagnostic for complaining about writes to
2866 string literals. */
2868 class write_to_string_literal_diagnostic
2869 : public pending_diagnostic_subclass<write_to_string_literal_diagnostic>
2871 public:
2872 write_to_string_literal_diagnostic (const region *reg)
2873 : m_reg (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");
2904 private:
2905 const region *m_reg;
2908 /* Use CTXT to warn If DEST_REG is a region that shouldn't be written to. */
2910 void
2911 region_model::check_for_writable_region (const region* dest_reg,
2912 region_model_context *ctxt) const
2914 /* Fail gracefully if CTXT is NULL. */
2915 if (!ctxt)
2916 return;
2918 const region *base_reg = dest_reg->get_base_region ();
2919 switch (base_reg->get_kind ())
2921 default:
2922 break;
2923 case RK_FUNCTION:
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));
2930 break;
2931 case RK_LABEL:
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));
2938 break;
2939 case RK_DECL:
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));
2951 break;
2952 case RK_STRING:
2953 ctxt->warn (make_unique<write_to_string_literal_diagnostic> (dest_reg));
2954 break;
2958 /* Get the capacity of REG in bytes. */
2960 const svalue *
2961 region_model::get_capacity (const region *reg) const
2963 switch (reg->get_kind ())
2965 default:
2966 break;
2967 case RK_DECL:
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);
2977 else
2979 tree size = decl_init_size (decl, false);
2980 if (size)
2981 return get_rvalue (size, NULL);
2984 break;
2985 case RK_SIZED:
2986 /* Look through sized regions to get at the capacity
2987 of the underlying regions. */
2988 return get_capacity (reg->get_parent_region ());
2989 case RK_STRING:
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));
2997 break;
3000 if (const svalue *recorded = get_dynamic_extents (reg))
3001 return recorded;
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. */
3012 bool
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. */
3019 if (!ctxt)
3020 return false;
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;
3027 switch (dir)
3029 default:
3030 gcc_unreachable ();
3031 case DIR_READ:
3032 /* Currently a no-op. */
3033 break;
3034 case DIR_WRITE:
3035 check_for_writable_region (reg, ctxt);
3036 break;
3038 return oob_access_detected;
3041 /* If CTXT is non-NULL, use it to warn about any problems writing to REG. */
3043 void
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. */
3054 bool
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>
3066 public:
3067 dubious_allocation_size (const region *lhs, const region *rhs,
3068 const gimple *stmt)
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;
3098 m.add_cwe (131);
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
3106 override
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
3115 before. */
3116 if (m_expr)
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));
3123 else
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));
3136 void
3137 add_region_creation_events (const region *,
3138 tree capacity,
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);
3153 private:
3154 const region *m_lhs;
3155 const region *m_rhs;
3156 const tree m_expr;
3157 const gimple *m_stmt;
3158 bool m_has_allocation_event;
3161 /* Return true on dubious allocation sizes for constant sizes. */
3163 static bool
3164 capacity_compatible_with_type (tree cst, tree pointee_size_tree,
3165 bool is_struct)
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);
3173 if (is_struct)
3174 return alloc_size == 0 || alloc_size >= pointee_size;
3175 return alloc_size % pointee_size == 0;
3178 static bool
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
3192 public:
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 ())
3223 case MULT_EXPR:
3224 if (result_set.contains (arg0) && result_set.contains (arg1))
3225 result_set.add (sval);
3226 break;
3227 case PLUS_EXPR:
3228 case MINUS_EXPR:
3229 if (result_set.contains (arg0) || result_set.contains (arg1))
3230 result_set.add (sval);
3231 break;
3232 default:
3233 break;
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);
3274 private:
3275 void check_constant (tree cst, const svalue *sval)
3277 switch (TREE_CODE (cst))
3279 default:
3280 /* Assume all unhandled operands are compatible. */
3281 break;
3282 case INTEGER_CST:
3283 if (!capacity_compatible_with_type (cst, m_size_cst))
3284 result_set.add (sval);
3285 break;
3289 tree m_size_cst;
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. */
3299 static bool
3300 struct_or_union_with_inheritance_p (tree struc)
3302 tree iter = TYPE_FIELDS (struc);
3303 if (iter == NULL_TREE)
3304 return false;
3305 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (iter)))
3306 return true;
3308 tree last_field;
3309 while (iter != NULL_TREE)
3311 last_field = iter;
3312 iter = DECL_CHAIN (iter);
3315 if (last_field != NULL_TREE
3316 && TREE_CODE (TREE_TYPE (last_field)) == ARRAY_TYPE)
3317 return true;
3319 return false;
3322 /* Return true if the lhs and rhs of an assignment have different types. */
3324 static bool
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));
3340 return false;
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. */
3347 void
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)
3352 return;
3353 /* Only report warnings on assignments that actually change the type. */
3354 if (!is_any_cast_p (ctxt->get_stmt ()))
3355 return;
3357 tree pointer_type = lhs_reg->get_type ();
3358 if (pointer_type == NULL_TREE || !POINTER_TYPE_P (pointer_type))
3359 return;
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)
3365 return;
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))
3371 return;
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))
3379 return;
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,
3392 is_struct))
3393 ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg, rhs_reg,
3394 cst_cap,
3395 ctxt->get_stmt ()));
3397 break;
3398 default:
3400 if (!is_struct)
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,
3407 rhs_reg,
3408 expr,
3409 ctxt->get_stmt ()));
3412 break;
3417 /* Set the value of the region given by LHS_REG to the value given
3418 by RHS_SVAL.
3419 Use CTXT to report any warnings associated with writing to LHS_REG. */
3421 void
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 ())
3430 return;
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. */
3442 void
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. */
3455 static void
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. */
3466 struct fragment
3468 fragment ()
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.
3490 Return a tristate:
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 ())
3515 case SK_CONSTANT:
3517 tree cst
3518 = as_a <const constant_svalue *> (m_sval)->get_constant ();
3519 switch (TREE_CODE (cst))
3521 case STRING_CST:
3522 return string_cst_has_null_terminator (cst,
3523 rel_start_read_offset_hwi,
3524 available_bytes_hwi,
3525 out_bytes_read);
3526 case INTEGER_CST:
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
3531 INTEGER_CST. */
3532 if (zerop (cst))
3534 *out_bytes_read = 1;
3535 return tristate (true);
3537 else
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;
3546 default:
3547 gcc_unreachable ();
3548 break;
3551 break;
3553 case SK_INITIAL:
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,
3563 out_bytes_read);
3565 return tristate::TS_UNKNOWN;
3567 break;
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,
3580 available_bytes)),
3581 inner_sval);
3582 return f.has_null_terminator (start_read_offset, out_bytes_read);
3585 break;
3587 default:
3588 // TODO: it may be possible to handle other cases here.
3589 break;
3591 return tristate::TS_UNKNOWN;
3594 static tristate
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
3631 public:
3632 iterable_cluster (const binding_cluster *cluster)
3634 if (!cluster)
3635 return;
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));
3648 else
3649 m_symbolic_bindings.safe_push (key);
3651 m_fragments.qsort (fragment::cmp_ptrs);
3654 bool
3655 get_fragment_for_byte (byte_offset_t byte, fragment *out_frag) const
3657 /* TODO: binary search rather than linear. */
3658 unsigned iter_idx;
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];
3664 return true;
3667 return false;
3670 bool has_symbolic_bindings_p () const
3672 return !m_symbolic_bindings.is_empty ();
3675 private:
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. */
3683 const svalue *
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,
3699 NULL_TREE,
3700 index_sval);
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,
3704 NULL_TREE,
3705 byte_size_sval);
3707 /* Simulate reading those bytes from the store. */
3708 const svalue *sval = get_store_value (read_reg, ctxt);
3709 return sval;
3712 static tree
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,
3717 char_type_node,
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.
3733 Algorithm
3734 =========
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.
3746 Finish
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
3750 Continue
3751 If unknown:
3752 Result is unknown
3753 Finish
3756 const svalue *
3757 region_model::scan_for_null_terminator (const region *reg,
3758 tree expr,
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 ())
3767 if (out_sval)
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))
3774 if (out_sval)
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);
3795 if (out_sval)
3796 *out_sval = sval;
3797 return m_mgr->get_or_create_int_cst (size_type_node,
3798 num_bytes_read);
3802 const binding_cluster *cluster = m_store.get_cluster (base_reg);
3803 iterable_cluster c (cluster);
3804 binding_map result;
3806 while (1)
3808 fragment f;
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 ())
3816 if (out_sval)
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);
3826 if (out_sval)
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 ())
3839 if (out_sval)
3840 *out_sval = m_mgr->get_or_create_compound_svalue (NULL_TREE,
3841 result);
3842 return m_mgr->get_or_create_int_cst (size_type_node,
3843 dst_byte_offset);
3846 else
3847 break;
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 ())
3855 if (out_sval)
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);
3866 tree byte_expr
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 ())
3872 if (out_sval)
3873 *out_sval = get_store_value (reg, nullptr);
3874 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3876 else
3877 return nullptr;
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). */
3897 const svalue *
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,
3902 arg_idx,
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). */
3930 const svalue *
3931 region_model::check_for_null_terminated_string_arg (const call_details &cd,
3932 unsigned arg_idx,
3933 bool include_terminator,
3934 const svalue **out_sval) const
3936 class null_terminator_check_event : public custom_event
3938 public:
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);
3955 else
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);
3963 private:
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>
3970 public:
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;
3991 private:
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
3999 public:
4000 annotating_ctxt (const call_details &cd,
4001 unsigned arg_idx)
4002 : annotating_context (cd.get_ctxt ()),
4003 m_cd (cd),
4004 m_arg_idx (arg_idx)
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,
4015 arg_details));
4016 add_note (make_unique <null_terminator_check_decl_note> (arg_details));
4018 private:
4019 const call_details &m_cd;
4020 unsigned m_arg_idx;
4023 /* Use this ctxt below so that any diagnostics that get added
4024 get annotated. */
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),
4034 out_sval,
4035 &my_ctxt))
4037 if (include_terminator)
4038 return num_bytes_read_sval;
4039 else
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,
4044 MINUS_EXPR,
4045 num_bytes_read_sval,
4046 one);
4049 else
4050 return nullptr;
4053 /* Remove all bindings overlapping REG within the store. */
4055 void
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. */
4063 void
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). */
4073 void
4074 region_model::fill_region (const region *reg,
4075 const svalue *sval,
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);
4082 /* Zero-fill REG.
4083 Use CTXT to report any warnings associated with the write
4084 (e.g. out-of-bounds). */
4086 void
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). */
4098 void
4099 region_model::write_bytes (const region *dest_reg,
4100 const svalue *num_bytes_sval,
4101 const svalue *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). */
4113 const svalue *
4114 region_model::read_bytes (const region *src_reg,
4115 tree src_ptr_expr,
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,
4132 etc). */
4134 void
4135 region_model::copy_bytes (const region *dest_reg,
4136 const region *src_reg,
4137 tree src_ptr_expr,
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. */
4148 void
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
4159 this model. */
4161 tristate
4162 region_model::eval_condition (const svalue *lhs,
4163 enum tree_code op,
4164 const svalue *rhs) const
4166 gcc_assert (lhs);
4167 gcc_assert (rhs);
4169 /* For now, make no attempt to capture constraints on floating-point
4170 values. */
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 ();
4181 if (lhs == rhs)
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;
4191 switch (op)
4193 case EQ_EXPR:
4194 case GE_EXPR:
4195 case LE_EXPR:
4196 return tristate::TS_TRUE;
4198 case NE_EXPR:
4199 case GT_EXPR:
4200 case LT_EXPR:
4201 return tristate::TS_FALSE;
4203 default:
4204 /* For other ops, use the logic below. */
4205 break;
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 ())
4215 return res;
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);
4224 else
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 ())
4244 switch (op)
4246 default:
4247 gcc_unreachable ();
4249 case EQ_EXPR:
4250 case GE_EXPR:
4251 case LE_EXPR:
4252 return tristate::TS_FALSE;
4254 case NE_EXPR:
4255 case GT_EXPR:
4256 case LT_EXPR:
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 ())
4272 return lhs_ts;
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),
4283 rhs);
4284 if (lhs_ts.is_known ())
4285 return lhs_ts;
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 ())
4297 return res;
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 ())
4304 return res;
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 ())
4312 return res;
4315 /* Handle comparisons between two svalues with more than one operand. */
4316 if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4318 switch (op)
4320 default:
4321 break;
4322 case EQ_EXPR:
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);
4327 if (res.is_true ())
4328 return res;
4330 break;
4331 case LE_EXPR:
4333 tristate res = structural_equality (lhs, rhs);
4334 if (res.is_true ())
4335 return res;
4337 break;
4338 case GE_EXPR:
4340 tristate res = structural_equality (lhs, rhs);
4341 if (res.is_true ())
4342 return res;
4343 res = symbolic_greater_than (binop, rhs);
4344 if (res.is_true ())
4345 return res;
4347 break;
4348 case GT_EXPR:
4350 tristate res = symbolic_greater_than (binop, rhs);
4351 if (res.is_true ())
4352 return res;
4354 break;
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. */
4391 tristate
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. */
4408 static bool
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 ();
4414 if (!type)
4415 return false;
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. */
4431 tristate
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 (),
4441 GT_EXPR,
4442 bin_b->get_arg1 ()).is_true ()
4443 && eval_condition (bin_a->get_arg0 (),
4444 GE_EXPR,
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.
4466 For example,
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. */
4477 tristate
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. */
4481 if (a == b)
4482 return tristate (tristate::TS_TRUE);
4484 switch (a->get_kind ())
4486 default:
4487 return tristate::unknown ();
4488 /* SK_CONJURED and SK_INITIAL are already handled
4489 by the referential equality above. */
4490 case SK_CONSTANT:
4492 tree a_cst = a->maybe_get_constant ();
4493 tree b_cst = b->maybe_get_constant ();
4494 if (a_cst && b_cst)
4495 return tristate (tree_int_cst_equal (a_cst, b_cst));
4497 return tristate (tristate::TS_FALSE);
4498 case SK_UNARYOP:
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 (),
4503 un_b->get_type ())
4504 && un_a->get_op () == un_b->get_op ()
4505 && structural_equality (un_a->get_arg (),
4506 un_b->get_arg ()));
4508 return tristate (tristate::TS_FALSE);
4509 case SK_BINOP:
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 (),
4515 bin_b->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))
4525 OP : == or !=
4526 RHS: zero
4527 and (with a cast):
4528 LHS: CAST([long]int, ((bool)INNER_LHS INNER_OP INNER_RHS))
4529 OP : == or !=
4530 RHS: zero
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
4541 something like:
4542 LHS: CAST(long int, (&HEAP_ALLOCATED_REGION(8)!=(int *)0B))
4543 OP : NE_EXPR
4544 RHS: zero
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.
4549 if (p && q)
4550 becoming gimple like this:
4551 _1 = p_6 == 0B;
4552 _2 = q_8 == 0B
4553 _3 = _1 | _2
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))
4557 == 0
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)
4561 and:
4562 (&HEAP_ALLOCATED_REGION(10)!=(int *)0B). */
4564 bool
4565 region_model::add_constraints_from_binop (const svalue *outer_lhs,
4566 enum tree_code outer_op,
4567 const svalue *outer_rhs,
4568 bool *out,
4569 region_model_context *ctxt)
4571 while (const svalue *cast = outer_lhs->maybe_undo_cast ())
4572 outer_lhs = cast;
4573 const binop_svalue *binop_sval = outer_lhs->dyn_cast_binop_svalue ();
4574 if (!binop_sval)
4575 return false;
4576 if (!outer_rhs->all_zeroes_p ())
4577 return false;
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)
4584 return false;
4586 /* We have either
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;
4591 switch (inner_op)
4593 default:
4594 return false;
4596 case EQ_EXPR:
4597 case NE_EXPR:
4598 case GE_EXPR:
4599 case GT_EXPR:
4600 case LE_EXPR:
4601 case LT_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. */
4606 if (!is_true)
4607 inner_op = invert_tree_comparison (inner_op, false /* honor_nans */);
4608 *out = add_constraint (inner_lhs, inner_op, inner_rhs, ctxt);
4609 return true;
4611 break;
4613 case BIT_AND_EXPR:
4614 if (is_true)
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;
4623 return true;
4625 return false;
4627 case BIT_IOR_EXPR:
4628 if (!is_true)
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;
4638 return true;
4640 return false;
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. */
4649 bool
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
4654 values. */
4655 if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
4656 return true;
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. */
4669 bool
4670 region_model::add_constraint (const svalue *lhs,
4671 enum tree_code op,
4672 const svalue *rhs,
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 ())
4679 return true;
4681 /* Reject a constraint that would contradict existing knowledge, as
4682 unsatisfiable. */
4683 if (t_cond.is_false ())
4684 return false;
4686 bool out;
4687 if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt))
4688 return out;
4690 /* Attempt to store the constraint. */
4691 if (!m_constraints->add_constraint (lhs, op, rhs))
4692 return false;
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. */
4698 if (ctxt)
4699 ctxt->on_condition (lhs, op, rhs);
4701 /* If we have &REGION == 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 ());
4708 return true;
4711 /* As above, but when returning false, if OUT is non-NULL, write a
4712 new rejected_constraint to *OUT. */
4714 bool
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);
4720 if (!sat && out)
4721 *out = make_unique <rejected_op_constraint> (*this, lhs, op, rhs);
4722 return sat;
4725 /* Determine what is known about the condition "LHS OP RHS" within
4726 this model.
4727 Use CTXT for reporting any diagnostics associated with the accesses. */
4729 tristate
4730 region_model::eval_condition (tree lhs,
4731 enum tree_code op,
4732 tree rhs,
4733 region_model_context *ctxt) const
4735 /* For now, make no attempt to model constraints on floating-point
4736 values. */
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
4746 regions. */
4748 path_var
4749 region_model::get_representative_path_var_1 (const svalue *sval,
4750 svalue_set *visited) const
4752 gcc_assert (sval);
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);
4759 else
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);
4772 return result;
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,
4787 sval->get_type (),
4788 pv.m_tree),
4789 pv.m_stack_depth);
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,
4801 sval->get_type (),
4802 parent_pv.m_tree,
4803 field_reg->get_field (),
4804 NULL_TREE),
4805 parent_pv.m_stack_depth);
4808 /* Handle binops. */
4809 if (const binop_svalue *binop_sval = sval->dyn_cast_binop_svalue ())
4810 if (path_var lhs_pv
4811 = get_representative_path_var (binop_sval->get_arg0 (), visited))
4812 if (path_var rhs_pv
4813 = get_representative_path_var (binop_sval->get_arg1 (), visited))
4814 return path_var (build2 (binop_sval->get_op (),
4815 sval->get_type (),
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);
4823 return pvs[0];
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
4828 regions
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. */
4834 path_var
4835 region_model::get_representative_path_var (const svalue *sval,
4836 svalue_set *visited) const
4838 if (sval == NULL)
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);
4849 return result;
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. */
4858 tree
4859 region_model::get_representative_tree (const svalue *sval) const
4861 svalue_set visited;
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);
4871 tree
4872 region_model::get_representative_tree (const region *reg) const
4874 svalue_set visited;
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
4887 the NULL path_var.
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
4891 svalues. */
4893 path_var
4894 region_model::get_representative_path_var_1 (const region *reg,
4895 svalue_set *visited) const
4897 switch (reg->get_kind ())
4899 default:
4900 gcc_unreachable ();
4902 case RK_FRAME:
4903 case RK_GLOBALS:
4904 case RK_CODE:
4905 case RK_HEAP:
4906 case RK_STACK:
4907 case RK_THREAD_LOCAL:
4908 case RK_ROOT:
4909 /* Regions that represent memory spaces are not expressible as trees. */
4910 return path_var (NULL_TREE, 0);
4912 case RK_FUNCTION:
4914 const function_region *function_reg
4915 = as_a <const function_region *> (reg);
4916 return path_var (function_reg->get_fndecl (), 0);
4918 case RK_LABEL:
4920 const label_region *label_reg = as_a <const label_region *> (reg);
4921 return path_var (label_reg->get_label (), 0);
4924 case RK_SYMBOLIC:
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);
4930 if (!pointer_pv)
4931 return path_var (NULL_TREE, 0);
4932 tree offset = build_int_cst (pointer->get_type (), 0);
4933 return path_var (build2 (MEM_REF,
4934 reg->get_type (),
4935 pointer_pv.m_tree,
4936 offset),
4937 pointer_pv.m_stack_depth);
4939 case RK_DECL:
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 ());
4944 case RK_FIELD:
4946 const field_region *field_reg = as_a <const field_region *> (reg);
4947 path_var parent_pv
4948 = get_representative_path_var (reg->get_parent_region (), visited);
4949 if (!parent_pv)
4950 return path_var (NULL_TREE, 0);
4951 return path_var (build3 (COMPONENT_REF,
4952 reg->get_type (),
4953 parent_pv.m_tree,
4954 field_reg->get_field (),
4955 NULL_TREE),
4956 parent_pv.m_stack_depth);
4959 case RK_ELEMENT:
4961 const element_region *element_reg
4962 = as_a <const element_region *> (reg);
4963 path_var parent_pv
4964 = get_representative_path_var (reg->get_parent_region (), visited);
4965 if (!parent_pv)
4966 return path_var (NULL_TREE, 0);
4967 path_var index_pv
4968 = get_representative_path_var (element_reg->get_index (), visited);
4969 if (!index_pv)
4970 return path_var (NULL_TREE, 0);
4971 return path_var (build4 (ARRAY_REF,
4972 reg->get_type (),
4973 parent_pv.m_tree, index_pv.m_tree,
4974 NULL_TREE, NULL_TREE),
4975 parent_pv.m_stack_depth);
4978 case RK_OFFSET:
4980 const offset_region *offset_reg
4981 = as_a <const offset_region *> (reg);
4982 path_var parent_pv
4983 = get_representative_path_var (reg->get_parent_region (), visited);
4984 if (!parent_pv)
4985 return path_var (NULL_TREE, 0);
4986 path_var offset_pv
4987 = get_representative_path_var (offset_reg->get_byte_offset (),
4988 visited);
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 ()),
4993 parent_pv.m_tree);
4994 return path_var (build2 (MEM_REF,
4995 reg->get_type (),
4996 addr_parent, offset_pv.m_tree),
4997 parent_pv.m_stack_depth);
5000 case RK_SIZED:
5001 return path_var (NULL_TREE, 0);
5003 case RK_CAST:
5005 path_var parent_pv
5006 = get_representative_path_var (reg->get_parent_region (), visited);
5007 if (!parent_pv)
5008 return path_var (NULL_TREE, 0);
5009 return path_var (build1 (NOP_EXPR,
5010 reg->get_type (),
5011 parent_pv.m_tree),
5012 parent_pv.m_stack_depth);
5015 case RK_HEAP_ALLOCATED:
5016 case RK_ALLOCA:
5017 /* No good way to express heap-allocated/alloca regions as trees. */
5018 return path_var (NULL_TREE, 0);
5020 case RK_STRING:
5022 const string_region *string_reg = as_a <const string_region *> (reg);
5023 return path_var (string_reg->get_string_cst (), 0);
5026 case RK_VAR_ARG:
5027 case RK_ERRNO:
5028 case RK_UNKNOWN:
5029 return path_var (NULL_TREE, 0);
5033 /* Attempt to return a path_var that represents REG, or return
5034 the NULL path_var.
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
5038 svalues.
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. */
5044 path_var
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 ());
5054 return result;
5057 /* Update this model for any phis in SNODE, assuming we came from
5058 LAST_CFG_SUPEREDGE. */
5060 void
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
5086 otherwise.
5087 When returning false, if OUT is non-NULL, write a new rejected_constraint
5088 to it.
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
5093 impossible.
5095 For call superedges, push frame information and store arguments
5096 into parameters.
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). */
5105 bool
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)
5114 default:
5115 break;
5117 case SUPEREDGE_CALL:
5119 const call_superedge *call_edge = as_a <const call_superedge *> (&edge);
5120 update_for_call_superedge (*call_edge, ctxt);
5122 break;
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);
5130 break;
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. */
5135 break;
5138 if (last_stmt == NULL)
5139 return true;
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,
5154 ctxt, out);
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);
5168 return true;
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
5174 caller's frame. */
5176 void
5177 region_model::update_for_gcall (const gcall *call_stmt,
5178 region_model_context *ctxt,
5179 function *callee)
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));
5191 if(!callee)
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). */
5205 void
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
5211 *caller* frame. */
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
5217 call */
5219 void
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 */
5230 void
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. */
5241 bool
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))
5250 return false;
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);
5256 if (!caller_reg)
5257 continue;
5258 const svalue *summary_sval = kv.second;
5259 const svalue *caller_sval = r.convert_svalue_from_summary (summary_sval);
5260 if (!caller_sval)
5261 continue;
5262 m_dynamic_extents.put (caller_reg, caller_sval);
5265 return true;
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
5276 to it. */
5278 bool
5279 region_model::
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
5298 INT_CST. */
5300 static bool
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
5310 gimplifier). */
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);
5316 gcc_assert (low);
5317 tree high = CASE_HIGH (label);
5318 if (!high)
5319 high = low;
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;
5331 else
5332 /* This case contains INT_CST. */
5333 return true;
5335 /* Not found. */
5336 return false;
5339 /* Return true iff SWITCH_STMT (which must be on an enum value)
5340 has nondefault cases handling all values in the enum. */
5342 static bool
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);
5350 enum_val_iter;
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)))
5358 return false;
5360 return true;
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
5371 to it. */
5373 bool
5374 region_model::
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). */
5390 ctxt
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))
5403 if (out)
5404 *out = make_unique <rejected_default_case> (*this);
5405 return false;
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);
5412 if (!sat && out)
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);
5416 return sat;
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). */
5427 bool
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))
5444 return false;
5447 return true;
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
5457 to it. */
5459 bool
5460 region_model::
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
5474 the EH edge. */
5475 if (tree lhs = gimple_call_lhs (call))
5476 return add_constraint (lhs, EQ_EXPR, null_pointer_node, ctxt, out);
5477 return true;
5479 return true;
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
5486 the region.
5487 If NONNULL is true, then assume that PARAM must be non-NULL. */
5489 void
5490 region_model::on_top_level_param (tree param,
5491 bool nonnull,
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);
5501 if (nonnull)
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
5511 for a call to FUN.
5513 If ARG_SVALS is non-NULL, use it to populate the parameters
5514 in the new frame.
5515 Otherwise, the params have their initial_svalues.
5517 Return the frame_region for the new frame. */
5519 const region *
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);
5524 if (arg_svals)
5526 /* Arguments supplied from a caller frame. */
5527 tree fndecl = fun->decl;
5528 unsigned idx = 0;
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 ())
5536 break;
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,
5552 va_arg_idx);
5553 set_value (var_arg_reg, arg_sval, ctxt);
5556 else
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))
5574 : false);
5575 if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
5576 on_top_level_param (parm_default_ssa, non_null, ctxt);
5577 else
5578 on_top_level_param (iter_parm, non_null, ctxt);
5579 parm_idx++;
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. */
5591 function *
5592 region_model::get_current_function () const
5594 const frame_region *frame = get_current_frame ();
5595 gcc_assert (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
5605 into *OUT_RESULT.
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. */
5615 void
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. */
5627 if (ctxt)
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;
5634 if (result
5635 && TREE_TYPE (result) != void_type_node
5636 && eval_return_svalue)
5638 retval = get_rvalue (result, ctxt);
5639 if (out_result)
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 ();
5666 if (frame)
5667 return frame->get_stack_depth ();
5668 else
5669 return 0;
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 ();
5679 gcc_assert (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 ();
5685 gcc_assert (frame);
5687 return 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. */
5695 void
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
5727 values instead. */
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,
5748 sval->get_type ());
5749 ++m_count;
5754 const region *m_reg;
5755 enum poison_kind m_pkind;
5756 region_model_manager *const m_mgr;
5757 int m_count;
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);
5770 return bv.m_count;
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. */
5777 bool
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)
5790 return false;
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 (),
5798 &m))
5799 return false;
5801 if (!m_dynamic_extents.can_merge_with_p (other_model.m_dynamic_extents,
5802 &out_model->m_dynamic_extents))
5803 return false;
5805 /* Merge constraints. */
5806 constraint_manager::merge (*m_constraints,
5807 *other_model.m_constraints,
5808 out_model->m_constraints);
5810 return true;
5813 /* Attempt to get the fndecl used at CALL, if known, or NULL_TREE
5814 otherwise. */
5816 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)
5822 return 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);
5832 if (!node)
5833 return NULL_TREE;
5834 const cgraph_node *ultimate_node = node->ultimate_alias_target ();
5835 if (ultimate_node)
5836 return ultimate_node->decl;
5840 return NULL_TREE;
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. */
5854 void
5855 region_model::
5856 get_regions_for_current_frame (auto_vec<const decl_region *> *out) const
5858 append_regions_cb_data data;
5859 data.model = this;
5860 data.out = out;
5861 m_store.for_each_cluster (append_regions_cb, &data);
5864 /* Implementation detail of get_regions_for_current_frame. */
5866 void
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)
5871 return;
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
5882 public:
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
5894 public:
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");
5914 if (warned)
5915 inform (rich_loc->get_loc (), "only use operands of an integer type"
5916 " inside the size argument");
5917 return warned;
5920 label_text describe_final_event (const evdesc::final_event &ev) final
5921 override
5923 if (m_arg)
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");
5930 private:
5931 tree m_arg;
5934 /* Visitor to find uses of floating-point variables/constants in an svalue. */
5936 class contains_floating_point_visitor : public visitor
5938 public:
5939 contains_floating_point_visitor (const svalue *root_sval) : m_result (NULL)
5941 root_sval->accept (this);
5944 const svalue *get_svalue_to_report ()
5946 return m_result;
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)
5957 m_result = sval;
5960 void visit_conjured_svalue (const conjured_svalue *sval) final override
5962 tree type = sval->get_type ();
5963 if (type && FLOAT_TYPE_P (type))
5964 m_result = sval;
5967 void visit_initial_svalue (const initial_svalue *sval) final override
5969 tree type = sval->get_type ();
5970 if (type && FLOAT_TYPE_P (type))
5971 m_result = sval;
5974 private:
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. */
5981 void
5982 region_model::check_dynamic_size_for_floats (const svalue *size_in_bytes,
5983 region_model_context *ctxt) const
5985 gcc_assert (ctxt);
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. */
6004 const region *
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
6012 this path. */
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 ());
6025 const region *reg
6026 = m_mgr->get_or_create_region_for_heap_alloc (base_regs_in_use);
6027 if (size_in_bytes)
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);
6038 return reg;
6041 /* Populate OUT_IDS with the set of IDs of those base regions which are
6042 reachable in this region_model. */
6044 void
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,
6049 &reachable_regs);
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
6066 current frame.
6067 Use CTXT to complain about tainted sizes. */
6069 const region *
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);
6076 return reg;
6079 /* Record that the size of REG is SIZE_IN_BYTES.
6080 Use CTXT to complain about tainted sizes. */
6082 void
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);
6088 if (ctxt)
6090 check_dynamic_size_for_taint (reg->get_memory_space (), size_in_bytes,
6091 ctxt);
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
6098 recorded. */
6100 const svalue *
6101 region_model::get_dynamic_extents (const region *reg) const
6103 if (const svalue * const *slot = m_dynamic_extents.get (reg))
6104 return *slot;
6105 return NULL;
6108 /* Unset any recorded dynamic size of REG. */
6110 void
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>
6123 public:
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. */
6156 m.add_cwe (200);
6157 enum memory_space mem_space = get_src_memory_space ();
6158 bool warned;
6159 switch (mem_space)
6161 default:
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");
6166 break;
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");
6172 break;
6173 case MEMSPACE_HEAP:
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");
6178 break;
6180 if (warned)
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 ();
6189 return warned;
6192 label_text describe_final_event (const evdesc::final_event &) final override
6194 enum memory_space mem_space = get_src_memory_space ();
6195 switch (mem_space)
6197 default:
6198 return label_text::borrow ("uninitialized data copied here");
6200 case MEMSPACE_STACK:
6201 return label_text::borrow ("uninitialized data copied from stack here");
6203 case MEMSPACE_HEAP:
6204 return label_text::borrow ("uninitialized data copied from heap here");
6208 void mark_interesting_stuff (interesting_t *interest) final override
6210 if (m_src_region)
6211 interest->add_region_creation (m_src_region);
6214 private:
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 ())
6224 default:
6225 gcc_unreachable ();
6226 break;
6227 case SK_POISONED:
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)
6235 return 0;
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. */
6242 return 0;
6244 break;
6245 case SK_COMPOUND:
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 ();
6261 gcc_assert (ckey);
6262 result += ckey->get_size_in_bits ();
6265 return result;
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)
6274 return;
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");
6281 else
6282 inform (loc,
6283 "%wu bytes are uninitialized", num_uninit_bytes.to_uhwi ());
6285 else
6287 /* Express in bits. */
6288 if (num_uninit_bits == 1)
6289 inform (loc, "1 bit is uninitialized");
6290 else
6291 inform (loc,
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 ();
6313 gcc_assert (ckey);
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));
6328 if (0)
6329 layout->dump ();
6332 unsigned i;
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,
6339 layout.get ());
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
6349 if (layout)
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);
6361 else
6362 complain_about_partially_uninit_item (*item);
6363 start_bit = item->get_next_bit_offset ();
6364 continue;
6366 else
6367 break;
6371 if (start_bit >= next_bit)
6372 return;
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)
6380 inform (loc,
6381 "byte %wu is uninitialized",
6382 start_byte.to_uhwi ());
6383 else
6384 inform (loc,
6385 "bytes %wu - %wu are uninitialized",
6386 start_byte.to_uhwi (),
6387 last_byte.to_uhwi ());
6389 else
6391 /* Express in bits. */
6392 bit_offset_t last_bit = next_bit - 1;
6393 if (last_bit == start_bit)
6394 inform (loc,
6395 "bit %wu is uninitialized",
6396 start_bit.to_uhwi ());
6397 else
6398 inform (loc,
6399 "bits %wu - %wu are uninitialized",
6400 start_bit.to_uhwi (),
6401 last_bit.to_uhwi ());
6405 static void
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;
6416 if (num_bytes == 1)
6417 inform (DECL_SOURCE_LOCATION (field),
6418 "padding after field %qD is uninitialized (1 byte)",
6419 field);
6420 else
6421 inform (DECL_SOURCE_LOCATION (field),
6422 "padding after field %qD is uninitialized (%wu bytes)",
6423 field, num_bytes.to_uhwi ());
6425 else
6427 /* Express in bits. */
6428 if (num_bits == 1)
6429 inform (DECL_SOURCE_LOCATION (field),
6430 "padding after field %qD is uninitialized (1 bit)",
6431 field);
6432 else
6433 inform (DECL_SOURCE_LOCATION (field),
6434 "padding after field %qD is uninitialized (%wu bits)",
6435 field, num_bits.to_uhwi ());
6438 else
6440 if (num_bits % 8 == 0)
6442 /* Express in bytes. */
6443 byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
6444 if (num_bytes == 1)
6445 inform (DECL_SOURCE_LOCATION (field),
6446 "field %qD is uninitialized (1 byte)", field);
6447 else
6448 inform (DECL_SOURCE_LOCATION (field),
6449 "field %qD is uninitialized (%wu bytes)",
6450 field, num_bytes.to_uhwi ());
6452 else
6454 /* Express in bits. */
6455 if (num_bits == 1)
6456 inform (DECL_SOURCE_LOCATION (field),
6457 "field %qD is uninitialized (1 bit)", field);
6458 else
6459 inform (DECL_SOURCE_LOCATION (field),
6460 "field %qD is uninitialized (%wu bits)",
6461 field, num_bits.to_uhwi ());
6466 static void
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",
6473 field);
6474 else
6475 inform (DECL_SOURCE_LOCATION (field),
6476 "field %qD is partially uninitialized",
6477 field);
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");
6493 private:
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. */
6501 static bool
6502 contains_uninit_p (const svalue *sval)
6504 struct uninit_finder : public visitor
6506 public:
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;
6516 uninit_finder v;
6517 sval->accept (&v);
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. */
6532 void
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,
6541 dst_reg,
6542 copied_sval));
6545 /* Set errno to a positive symbolic int, as if some error has occurred. */
6547 void
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 (),
6555 errno_reg, p);
6556 const svalue *zero
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. */
6564 void
6565 noop_region_model_context::add_note (std::unique_ptr<pending_note>)
6569 void
6570 noop_region_model_context::add_event (std::unique_ptr<checker_event>)
6574 void
6575 noop_region_model_context::bifurcate (std::unique_ptr<custom_edge_info>)
6579 void
6580 noop_region_model_context::terminate_path ()
6584 /* class region_model_context_decorator : public region_model_context. */
6586 void
6587 region_model_context_decorator::add_event (std::unique_ptr<checker_event> event)
6589 if (m_inner)
6590 m_inner->add_event (std::move (event));
6593 /* struct model_merger. */
6595 /* Dump a multiline representation of this merger to PP. */
6597 void
6598 model_merger::dump_to_pp (pretty_printer *pp, bool simple) const
6600 pp_string (pp, "model A:");
6601 pp_newline (pp);
6602 m_model_a->dump_to_pp (pp, simple, true);
6603 pp_newline (pp);
6605 pp_string (pp, "model B:");
6606 pp_newline (pp);
6607 m_model_b->dump_to_pp (pp, simple, true);
6608 pp_newline (pp);
6610 pp_string (pp, "merged model:");
6611 pp_newline (pp);
6612 m_merged_model->dump_to_pp (pp, simple, true);
6613 pp_newline (pp);
6616 /* Dump a multiline representation of this merger to FILE. */
6618 void
6619 model_merger::dump (FILE *fp, bool simple) const
6621 pretty_printer pp;
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);
6626 pp_flush (&pp);
6629 /* Dump a multiline representation of this merger to stderr. */
6631 DEBUG_FUNCTION void
6632 model_merger::dump (bool simple) const
6634 dump (stderr, simple);
6637 /* Return true if it's OK to merge SVAL with other svalues. */
6639 bool
6640 model_merger::mergeable_svalue_p (const svalue *sval) const
6642 if (m_ext_state)
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
6649 with:
6650 store_b mapping "p" to a NULL ptr. */
6651 if (m_state_a)
6652 if (!m_state_a->can_purge_p (*m_ext_state, sval))
6653 return false;
6654 if (m_state_b)
6655 if (!m_state_b->can_purge_p (*m_ext_state, sval))
6656 return false;
6658 return true;
6661 } // namespace ana
6663 /* Dump RMODEL fully to stderr (i.e. without summarization). */
6665 DEBUG_FUNCTION void
6666 debug (const region_model &rmodel)
6668 rmodel.dump (false);
6671 /* class rejected_op_constraint : public rejected_constraint. */
6673 void
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. */
6686 void
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. */
6694 void
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);
6704 /* class engine. */
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. */
6715 void
6716 engine::log_stats (logger *logger) const
6718 m_mgr.log_stats (logger, true);
6721 namespace ana {
6723 #if CHECKING_P
6725 namespace selftest {
6727 /* Build a constant tree of the given type from STR. */
6729 static tree
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). */
6739 static void
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. */
6759 static void
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]);
6775 v.qsort (tree_cmp);
6779 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6781 void
6782 assert_condition (const location &loc,
6783 region_model &model,
6784 const svalue *lhs, tree_code op, const svalue *rhs,
6785 tristate expected)
6787 tristate actual = model.eval_condition (lhs, op, rhs);
6788 ASSERT_EQ_AT (loc, actual, expected);
6791 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6793 void
6794 assert_condition (const location &loc,
6795 region_model &model,
6796 tree lhs, tree_code op, tree rhs,
6797 tristate expected)
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. */
6805 static void
6806 assert_dump_tree_eq (const location &loc, tree t, const char *expected)
6808 auto_fix_quotes sentinel;
6809 pretty_printer pp;
6810 pp_format_decoder (&pp) = default_tree_printer;
6811 dump_tree (&pp, t);
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)); \
6820 SELFTEST_END_STMT
6822 /* Implementation detail of ASSERT_DUMP_EQ. */
6824 static void
6825 assert_dump_eq (const location &loc,
6826 const region_model &model,
6827 bool summarize,
6828 const char *expected)
6830 auto_fix_quotes sentinel;
6831 pretty_printer pp;
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)); \
6843 SELFTEST_END_STMT
6845 /* Smoketest for region_model::dump_to_pp. */
6847 static void
6848 test_dump ()
6850 region_model_manager mgr;
6851 region_model model (&mgr);
6853 ASSERT_DUMP_EQ (model, false,
6854 "stack depth: 0\n"
6855 "m_called_unknown_fn: FALSE\n"
6856 "constraint_manager:\n"
6857 " equiv classes:\n"
6858 " constraints:\n");
6859 ASSERT_DUMP_EQ (model, true,
6860 "stack depth: 0\n"
6861 "m_called_unknown_fn: FALSE\n"
6862 "constraint_manager:\n"
6863 " equiv classes:\n"
6864 " constraints:\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. */
6872 static tree
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);
6878 TYPE_SIZE (t) = 0;
6880 tree fieldlist = NULL;
6881 int i;
6882 tree field;
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;
6892 layout_type (t);
6893 return t;
6896 /* Selftest fixture for creating the type "struct coord {int x; int y; };". */
6898 struct coord_test
6900 coord_test ()
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);
6912 tree m_x_field;
6913 tree m_y_field;
6914 tree m_coord_type;
6917 /* Verify usage of a struct. */
6919 static void
6920 test_struct ()
6922 coord_test ct;
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. */
6957 static void
6958 test_array_1 ()
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. */
6976 static void
6977 test_get_representative_tree ()
6979 region_model_manager mgr;
6981 /* STRING_CST. */
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. */
7036 coord_test ct;
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 *. */
7073 static void
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. */
7105 static void
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"
7112 svalue. */
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
7118 unknown_svalues. */
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"
7123 svalue. */
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. */
7130 static void
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. */
7149 static void
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,
7173 x_init, y_init)),
7174 mgr.get_or_create_binop (boolean_type_node, NE_EXPR,
7175 x_init, y_init));
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,
7180 x_init, y_init)),
7181 mgr.get_or_create_binop (boolean_type_node, LE_EXPR,
7182 x_init, y_init));
7185 /* Verify that binops on constant svalues are folded. */
7187 static void
7188 test_binop_svalue_folding ()
7190 #define NUM_CSTS 10
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++)
7205 if (i != j)
7206 ASSERT_NE (cst_sval[i], cst_sval[j]);
7207 if (i + j < NUM_CSTS)
7209 const svalue *sum
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]);
7214 if (i - j >= 0)
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]);
7234 // etc
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);
7272 // etc
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),
7312 sval_true);
7313 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7314 sval_false, sval_unknown),
7315 sval_unknown);
7316 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7317 sval_false, &sval_placeholder),
7318 &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),
7324 sval_false);
7325 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7326 sval_true, sval_unknown),
7327 sval_unknown);
7328 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7329 sval_true, &sval_placeholder),
7330 &sval_placeholder);
7335 /* Verify that sub_svalues are folded as expected. */
7337 static void
7338 test_sub_svalue_folding ()
7340 coord_test ct;
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),
7355 unknown, c_x_reg);
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,
7364 bit_offset_t bit,
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,
7370 bit_range (bit, 1),
7371 inner_svalue);
7374 /* Verify that bits_within_svalues are folded as expected. */
7376 static void
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. */
7413 static void
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. */
7439 static void
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);
7445 const region *byte0
7446 = mgr.get_bit_range (x_reg, char_type_node, bit_range (0, 8));
7447 const region *byte1
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. */
7456 static void
7457 test_assignment ()
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),
7470 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. */
7477 static void
7478 test_compound_assignment ()
7480 coord_test ct;
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);
7501 /* Copy c to d. */
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. */
7512 static void
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,
7522 "parent_fn",
7523 param_types);
7524 allocate_struct_function (parent_fndecl, true);
7526 tree child_fndecl = make_fndecl (integer_type_node,
7527 "child_fn",
7528 param_types);
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"),
7534 integer_type_node);
7535 DECL_CONTEXT (a) = parent_fndecl;
7536 tree b = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7537 get_identifier ("b"),
7538 integer_type_node);
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"),
7543 integer_type_node);
7544 DECL_CONTEXT (x) = child_fndecl;
7545 tree y = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7546 get_identifier ("y"),
7547 integer_type_node);
7548 DECL_CONTEXT (y) = child_fndecl;
7550 /* "p" global. */
7551 tree p = build_global_decl ("p", ptr_type_node);
7553 /* "q" global. */
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),
7563 NULL, &ctxt);
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),
7569 &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),
7584 &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),
7595 &ctxt);
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),
7602 &ctxt);
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
7622 renumbering. */
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 (),
7636 int_42);
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
7644 stack. */
7646 static void
7647 test_get_representative_path_var ()
7649 auto_vec <tree> param_types;
7650 tree fndecl = make_fndecl (integer_type_node,
7651 "factorial",
7652 param_types);
7653 allocate_struct_function (fndecl, true);
7655 /* Parm "n". */
7656 tree n = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7657 get_identifier ("n"),
7658 integer_type_node);
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,
7681 at every depth. */
7682 for (int depth = 0; depth < 5; depth++)
7685 svalue_set visited;
7686 ASSERT_EQ (model.get_representative_path_var (parm_regs[depth],
7687 &visited),
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),
7693 parm_regs[depth]);
7694 /* ...and that we can locate the svalues. */
7696 svalue_set visited;
7697 ASSERT_EQ (model.get_representative_path_var (parm_svals[depth],
7698 &visited),
7699 path_var (n, depth + 1));
7704 /* Ensure that region_model::operator== works as expected. */
7706 static void
7707 test_equality_1 ()
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
7739 x = 42; y = 113;
7741 y = 113; x = 42;
7742 are equal. */
7744 static void
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),
7756 NULL);
7757 model0.set_value (model0.get_lvalue (y, NULL),
7758 model0.get_rvalue (int_113, NULL),
7759 NULL);
7761 region_model model1 (&mgr);
7762 model1.set_value (model1.get_lvalue (y, NULL),
7763 model1.get_rvalue (int_113, NULL),
7764 NULL);
7765 model1.set_value (model1.get_lvalue (x, NULL),
7766 model1.get_rvalue (int_42, NULL),
7767 NULL);
7769 ASSERT_EQ (model0, model1);
7772 /* Verify that constraints for
7773 x > 3 && y > 42
7775 y > 42 && x > 3
7776 are equal after canonicalization. */
7778 static void
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
7801 constants. */
7803 static void
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. */
7825 static void
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);
7835 if (val_a)
7836 model0.set_value (model0.get_lvalue (expr, &ctxt),
7837 model0.get_rvalue (val_a, &ctxt),
7838 &ctxt);
7839 if (val_b)
7840 model1.set_value (model1.get_lvalue (expr, &ctxt),
7841 model1.get_rvalue (val_b, &ctxt),
7842 &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. */
7851 static void
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);
7868 /* Param "a". */
7869 tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7870 get_identifier ("a"),
7871 integer_type_node);
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"),
7878 ptr_type_node);
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
7896 the global */
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 (),
7964 int_42);
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. */
7998 // TODO
8000 /* Pointers: NULL and NULL. */
8001 // TODO
8003 /* Pointers: NULL and non-NULL. */
8004 // TODO
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,
8028 &merged_p_sval);
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;
8044 // TODO:
8045 assert_region_models_merge (x, addr_of_y, addr_of_z, &merged,
8046 &merged_x_sval);
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),
8062 ptr_sval, &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
8121 - heap regions
8122 - value merging:
8123 - every combination, but in particular
8124 - pairs of regions
8127 /* Views. */
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
8196 instances. */
8198 static void
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
8241 expected. */
8243 static void
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),
8281 tristate::TS_TRUE);
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),
8290 tristate::TS_TRUE);
8291 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_0),
8292 tristate::TS_TRUE);
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),
8308 tristate::TS_TRUE);
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
8318 of a loop.
8319 Simulate:
8320 for (i = 0; i < 256; i++)
8321 [...body...]
8322 i.e. this gimple:.
8323 i_15 = 0;
8324 goto <bb 4>;
8326 <bb 4> :
8327 i_11 = PHI <i_15(2), i_23(3)>
8328 if (i_11 <= 255)
8329 goto <bb 3>;
8330 else
8331 goto [AFTER LOOP]
8333 <bb 3> :
8334 [LOOP BODY]
8335 i_23 = i_11 + 1;
8337 and thus these ops (and resultant states):
8338 i_11 = PHI()
8339 {i_11: 0}
8340 add_constraint (i_11 <= 255) [for the true edge]
8341 {i_11: 0} [constraint was a no-op]
8342 i_23 = i_11 + 1;
8343 {i_22: 1}
8344 i_11 = PHI()
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}
8348 i_23 = i_11 + 1;
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]
8353 if (i_11 <= 255)
8354 T: {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}; cache hit
8355 F: {i_11: 256}
8358 static void
8359 test_iteration_1 ()
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;
8372 /* model0: i: 0. */
8373 region_model model0 (&mgr);
8374 model0.set_value (i, int_0, &ctxt);
8376 /* model1: i: 1. */
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
8403 for the 0 case. */
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. */
8436 static void
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);
8448 const region *reg
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. */
8469 static void
8470 test_var ()
8472 /* "int i;" */
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);
8491 /* "i = 17;". */
8492 model.set_value (i, int_17, NULL);
8493 ASSERT_EQ (model.get_rvalue (i, NULL),
8494 model.get_rvalue (int_17, NULL));
8496 /* "i = -3;". */
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);
8509 static void
8510 test_array_2 ()
8512 /* "int arr[10];" */
8513 tree tlen = size_int (10);
8514 tree arr_type
8515 = build_array_type (integer_type_node, build_index_type (tlen));
8516 tree arr = build_global_decl ("arr", arr_type);
8518 /* "int i;" */
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. */
8586 static void
8587 test_mem_ref ()
8590 x = 17;
8591 p = &x;
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);
8606 /* "x = 17;". */
8607 model.set_value (x, int_17, NULL);
8609 /* "p = &x;". */
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]
8621 a[3] = 42;
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;
8629 int _4 = (int) _3;
8630 __analyzer_eval (_4);
8632 # a[3] = 42;
8633 int *_5 = a_10(D) + 12; # POINTER_PLUS_EXPR
8634 *_5 = 42; # MEM_REF
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;
8640 int _9 = (int) _8;
8641 __analyzer_eval (_9); */
8643 static void
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. */
8663 static void
8664 test_malloc ()
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);
8678 const region *reg
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. */
8687 static void
8688 test_alloca ()
8690 auto_vec <tree> param_types;
8691 tree fndecl = make_fndecl (integer_type_node,
8692 "test_fn",
8693 param_types);
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),
8710 NULL, &ctxt);
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. */
8727 static void
8728 test_involves_p ()
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. */
8758 void
8759 analyzer_region_model_cc_tests ()
8761 test_tree_cmp_on_constants ();
8762 test_dump ();
8763 test_struct ();
8764 test_array_1 ();
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 ();
8775 test_assignment ();
8776 test_compound_assignment ();
8777 test_stack_frames ();
8778 test_get_representative_path_var ();
8779 test_equality_1 ();
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 ();
8788 test_var ();
8789 test_array_2 ();
8790 test_mem_ref ();
8791 test_POINTER_PLUS_EXPR_then_MEM_REF ();
8792 test_malloc ();
8793 test_alloca ();
8794 test_involves_p ();
8797 } // namespace selftest
8799 #endif /* CHECKING_P */
8801 } // namespace ana
8803 #endif /* #if ENABLE_ANALYZER */