analyzer: deal with -fshort-enums
[official-gcc.git] / gcc / analyzer / region-model.cc
blob6a7a8bc9f48845ad9731bebf664c78cc1ef17fa4
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 "bitmap.h"
44 #include "selftest.h"
45 #include "analyzer/analyzer.h"
46 #include "analyzer/analyzer-logging.h"
47 #include "ordered-hash-map.h"
48 #include "options.h"
49 #include "cgraph.h"
50 #include "cfg.h"
51 #include "analyzer/supergraph.h"
52 #include "sbitmap.h"
53 #include "analyzer/call-string.h"
54 #include "analyzer/program-point.h"
55 #include "analyzer/store.h"
56 #include "analyzer/region-model.h"
57 #include "analyzer/constraint-manager.h"
58 #include "diagnostic-event-id.h"
59 #include "analyzer/sm.h"
60 #include "diagnostic-event-id.h"
61 #include "analyzer/sm.h"
62 #include "analyzer/pending-diagnostic.h"
63 #include "analyzer/region-model-reachability.h"
64 #include "analyzer/analyzer-selftests.h"
65 #include "analyzer/program-state.h"
66 #include "analyzer/call-summary.h"
67 #include "stor-layout.h"
68 #include "attribs.h"
69 #include "tree-object-size.h"
70 #include "gimple-ssa.h"
71 #include "tree-phinodes.h"
72 #include "tree-ssa-operands.h"
73 #include "ssa-iterators.h"
74 #include "calls.h"
75 #include "is-a.h"
76 #include "gcc-rich-location.h"
77 #include "analyzer/checker-event.h"
78 #include "analyzer/checker-path.h"
79 #include "analyzer/feasible-graph.h"
80 #include "analyzer/record-layout.h"
81 #include "diagnostic-format-sarif.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 (diagnostic_emission_context &ctxt) final override
517 switch (m_pkind)
519 default:
520 gcc_unreachable ();
521 case POISON_KIND_UNINIT:
523 ctxt.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
524 return ctxt.warn ("use of uninitialized value %qE",
525 m_expr);
527 break;
528 case POISON_KIND_FREED:
530 ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
531 return ctxt.warn ("use after %<free%> of %qE",
532 m_expr);
534 break;
535 case POISON_KIND_DELETED:
537 ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
538 return ctxt.warn ("use after %<delete%> of %qE",
539 m_expr);
541 break;
542 case POISON_KIND_POPPED_STACK:
544 /* TODO: which CWE? */
545 return ctxt.warn
546 ("dereferencing pointer %qE to within stale stack frame",
547 m_expr);
549 break;
553 label_text describe_final_event (const evdesc::final_event &ev) final override
555 switch (m_pkind)
557 default:
558 gcc_unreachable ();
559 case POISON_KIND_UNINIT:
560 return ev.formatted_print ("use of uninitialized value %qE here",
561 m_expr);
562 case POISON_KIND_FREED:
563 return ev.formatted_print ("use after %<free%> of %qE here",
564 m_expr);
565 case POISON_KIND_DELETED:
566 return ev.formatted_print ("use after %<delete%> of %qE here",
567 m_expr);
568 case POISON_KIND_POPPED_STACK:
569 return ev.formatted_print
570 ("dereferencing pointer %qE to within stale stack frame",
571 m_expr);
575 void mark_interesting_stuff (interesting_t *interest) final override
577 if (m_src_region)
578 interest->add_region_creation (m_src_region);
581 /* Attempt to suppress false positives.
582 Reject paths where the value of the underlying region isn't poisoned.
583 This can happen due to state merging when exploring the exploded graph,
584 where the more precise analysis during feasibility analysis finds that
585 the region is in fact valid.
586 To do this we need to get the value from the fgraph. Unfortunately
587 we can't simply query the state of m_src_region (from the enode),
588 since it might be a different region in the fnode state (e.g. with
589 heap-allocated regions, the numbering could be different).
590 Hence we access m_check_expr, if available. */
592 bool check_valid_fpath_p (const feasible_node &fnode,
593 const gimple *emission_stmt)
594 const final override
596 if (!m_check_expr)
597 return true;
599 /* We've reached the enode, but not necessarily the right function_point.
600 Try to get the state at the correct stmt. */
601 region_model emission_model (fnode.get_model ().get_manager());
602 if (!fnode.get_state_at_stmt (emission_stmt, &emission_model))
603 /* Couldn't get state; accept this diagnostic. */
604 return true;
606 const svalue *fsval = emission_model.get_rvalue (m_check_expr, NULL);
607 /* Check to see if the expr is also poisoned in FNODE (and in the
608 same way). */
609 const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();
610 if (!fspval)
611 return false;
612 if (fspval->get_poison_kind () != m_pkind)
613 return false;
614 return true;
617 private:
618 tree m_expr;
619 enum poison_kind m_pkind;
620 const region *m_src_region;
621 tree m_check_expr;
624 /* A subclass of pending_diagnostic for complaining about shifts
625 by negative counts. */
627 class shift_count_negative_diagnostic
628 : public pending_diagnostic_subclass<shift_count_negative_diagnostic>
630 public:
631 shift_count_negative_diagnostic (const gassign *assign, tree count_cst)
632 : m_assign (assign), m_count_cst (count_cst)
635 const char *get_kind () const final override
637 return "shift_count_negative_diagnostic";
640 bool operator== (const shift_count_negative_diagnostic &other) const
642 return (m_assign == other.m_assign
643 && same_tree_p (m_count_cst, other.m_count_cst));
646 int get_controlling_option () const final override
648 return OPT_Wanalyzer_shift_count_negative;
651 bool emit (diagnostic_emission_context &ctxt) final override
653 return ctxt.warn ("shift by negative count (%qE)", m_count_cst);
656 label_text describe_final_event (const evdesc::final_event &ev) final override
658 return ev.formatted_print ("shift by negative amount here (%qE)", m_count_cst);
661 private:
662 const gassign *m_assign;
663 tree m_count_cst;
666 /* A subclass of pending_diagnostic for complaining about shifts
667 by counts >= the width of the operand type. */
669 class shift_count_overflow_diagnostic
670 : public pending_diagnostic_subclass<shift_count_overflow_diagnostic>
672 public:
673 shift_count_overflow_diagnostic (const gassign *assign,
674 int operand_precision,
675 tree count_cst)
676 : m_assign (assign), m_operand_precision (operand_precision),
677 m_count_cst (count_cst)
680 const char *get_kind () const final override
682 return "shift_count_overflow_diagnostic";
685 bool operator== (const shift_count_overflow_diagnostic &other) const
687 return (m_assign == other.m_assign
688 && m_operand_precision == other.m_operand_precision
689 && same_tree_p (m_count_cst, other.m_count_cst));
692 int get_controlling_option () const final override
694 return OPT_Wanalyzer_shift_count_overflow;
697 bool emit (diagnostic_emission_context &ctxt) final override
699 return ctxt.warn ("shift by count (%qE) >= precision of type (%qi)",
700 m_count_cst, m_operand_precision);
703 label_text describe_final_event (const evdesc::final_event &ev) final override
705 return ev.formatted_print ("shift by count %qE here", m_count_cst);
708 private:
709 const gassign *m_assign;
710 int m_operand_precision;
711 tree m_count_cst;
714 /* If ASSIGN is a stmt that can be modelled via
715 set_value (lhs_reg, SVALUE, CTXT)
716 for some SVALUE, get the SVALUE.
717 Otherwise return NULL. */
719 const svalue *
720 region_model::get_gassign_result (const gassign *assign,
721 region_model_context *ctxt)
723 tree lhs = gimple_assign_lhs (assign);
725 if (gimple_has_volatile_ops (assign)
726 && !gimple_clobber_p (assign))
728 conjured_purge p (this, ctxt);
729 return m_mgr->get_or_create_conjured_svalue (TREE_TYPE (lhs),
730 assign,
731 get_lvalue (lhs, ctxt),
735 tree rhs1 = gimple_assign_rhs1 (assign);
736 enum tree_code op = gimple_assign_rhs_code (assign);
737 switch (op)
739 default:
740 return NULL;
742 case POINTER_PLUS_EXPR:
744 /* e.g. "_1 = a_10(D) + 12;" */
745 tree ptr = rhs1;
746 tree offset = gimple_assign_rhs2 (assign);
748 const svalue *ptr_sval = get_rvalue (ptr, ctxt);
749 const svalue *offset_sval = get_rvalue (offset, ctxt);
750 /* Quoting tree.def, "the second operand [of a POINTER_PLUS_EXPR]
751 is an integer of type sizetype". */
752 offset_sval = m_mgr->get_or_create_cast (size_type_node, offset_sval);
754 const svalue *sval_binop
755 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
756 ptr_sval, offset_sval);
757 return sval_binop;
759 break;
761 case POINTER_DIFF_EXPR:
763 /* e.g. "_1 = p_2(D) - q_3(D);". */
764 tree rhs2 = gimple_assign_rhs2 (assign);
765 const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
766 const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
768 // TODO: perhaps fold to zero if they're known to be equal?
770 const svalue *sval_binop
771 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
772 rhs1_sval, rhs2_sval);
773 return sval_binop;
775 break;
777 /* Assignments of the form
778 set_value (lvalue (LHS), rvalue (EXPR))
779 for various EXPR.
780 We already have the lvalue for the LHS above, as "lhs_reg". */
781 case ADDR_EXPR: /* LHS = &RHS; */
782 case BIT_FIELD_REF:
783 case COMPONENT_REF: /* LHS = op0.op1; */
784 case MEM_REF:
785 case REAL_CST:
786 case COMPLEX_CST:
787 case VECTOR_CST:
788 case INTEGER_CST:
789 case ARRAY_REF:
790 case SSA_NAME: /* LHS = VAR; */
791 case VAR_DECL: /* LHS = VAR; */
792 case PARM_DECL:/* LHS = VAR; */
793 case REALPART_EXPR:
794 case IMAGPART_EXPR:
795 return get_rvalue (rhs1, ctxt);
797 case ABS_EXPR:
798 case ABSU_EXPR:
799 case CONJ_EXPR:
800 case BIT_NOT_EXPR:
801 case FIX_TRUNC_EXPR:
802 case FLOAT_EXPR:
803 case NEGATE_EXPR:
804 case NOP_EXPR:
805 case VIEW_CONVERT_EXPR:
807 /* Unary ops. */
808 const svalue *rhs_sval = get_rvalue (rhs1, ctxt);
809 const svalue *sval_unaryop
810 = m_mgr->get_or_create_unaryop (TREE_TYPE (lhs), op, rhs_sval);
811 return sval_unaryop;
814 case EQ_EXPR:
815 case GE_EXPR:
816 case LE_EXPR:
817 case NE_EXPR:
818 case GT_EXPR:
819 case LT_EXPR:
820 case UNORDERED_EXPR:
821 case ORDERED_EXPR:
823 tree rhs2 = gimple_assign_rhs2 (assign);
825 const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
826 const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
828 if (TREE_TYPE (lhs) == boolean_type_node)
830 /* Consider constraints between svalues. */
831 tristate t = eval_condition (rhs1_sval, op, rhs2_sval);
832 if (t.is_known ())
833 return m_mgr->get_or_create_constant_svalue
834 (t.is_true () ? boolean_true_node : boolean_false_node);
837 /* Otherwise, generate a symbolic binary op. */
838 const svalue *sval_binop
839 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
840 rhs1_sval, rhs2_sval);
841 return sval_binop;
843 break;
845 case PLUS_EXPR:
846 case MINUS_EXPR:
847 case MULT_EXPR:
848 case MULT_HIGHPART_EXPR:
849 case TRUNC_DIV_EXPR:
850 case CEIL_DIV_EXPR:
851 case FLOOR_DIV_EXPR:
852 case ROUND_DIV_EXPR:
853 case TRUNC_MOD_EXPR:
854 case CEIL_MOD_EXPR:
855 case FLOOR_MOD_EXPR:
856 case ROUND_MOD_EXPR:
857 case RDIV_EXPR:
858 case EXACT_DIV_EXPR:
859 case LSHIFT_EXPR:
860 case RSHIFT_EXPR:
861 case LROTATE_EXPR:
862 case RROTATE_EXPR:
863 case BIT_IOR_EXPR:
864 case BIT_XOR_EXPR:
865 case BIT_AND_EXPR:
866 case MIN_EXPR:
867 case MAX_EXPR:
868 case COMPLEX_EXPR:
870 /* Binary ops. */
871 tree rhs2 = gimple_assign_rhs2 (assign);
873 const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
874 const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
876 if (ctxt && (op == LSHIFT_EXPR || op == RSHIFT_EXPR))
878 /* "INT34-C. Do not shift an expression by a negative number of bits
879 or by greater than or equal to the number of bits that exist in
880 the operand." */
881 if (const tree rhs2_cst = rhs2_sval->maybe_get_constant ())
882 if (TREE_CODE (rhs2_cst) == INTEGER_CST
883 && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
885 if (tree_int_cst_sgn (rhs2_cst) < 0)
886 ctxt->warn
887 (make_unique<shift_count_negative_diagnostic>
888 (assign, rhs2_cst));
889 else if (compare_tree_int (rhs2_cst,
890 TYPE_PRECISION (TREE_TYPE (rhs1)))
891 >= 0)
892 ctxt->warn
893 (make_unique<shift_count_overflow_diagnostic>
894 (assign,
895 int (TYPE_PRECISION (TREE_TYPE (rhs1))),
896 rhs2_cst));
900 const svalue *sval_binop
901 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
902 rhs1_sval, rhs2_sval);
903 return sval_binop;
906 /* Vector expressions. In theory we could implement these elementwise,
907 but for now, simply return unknown values. */
908 case VEC_DUPLICATE_EXPR:
909 case VEC_SERIES_EXPR:
910 case VEC_COND_EXPR:
911 case VEC_PERM_EXPR:
912 case VEC_WIDEN_MULT_HI_EXPR:
913 case VEC_WIDEN_MULT_LO_EXPR:
914 case VEC_WIDEN_MULT_EVEN_EXPR:
915 case VEC_WIDEN_MULT_ODD_EXPR:
916 case VEC_UNPACK_HI_EXPR:
917 case VEC_UNPACK_LO_EXPR:
918 case VEC_UNPACK_FLOAT_HI_EXPR:
919 case VEC_UNPACK_FLOAT_LO_EXPR:
920 case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
921 case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
922 case VEC_PACK_TRUNC_EXPR:
923 case VEC_PACK_SAT_EXPR:
924 case VEC_PACK_FIX_TRUNC_EXPR:
925 case VEC_PACK_FLOAT_EXPR:
926 case VEC_WIDEN_LSHIFT_HI_EXPR:
927 case VEC_WIDEN_LSHIFT_LO_EXPR:
928 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (lhs));
932 /* Workaround for discarding certain false positives from
933 -Wanalyzer-use-of-uninitialized-value
934 of the form:
935 ((A OR-IF B) OR-IF C)
936 and:
937 ((A AND-IF B) AND-IF C)
938 where evaluating B is redundant, but could involve simple accesses of
939 uninitialized locals.
941 When optimization is turned on the FE can immediately fold compound
942 conditionals. Specifically, c_parser_condition parses this condition:
943 ((A OR-IF B) OR-IF C)
944 and calls c_fully_fold on the condition.
945 Within c_fully_fold, fold_truth_andor is called, which bails when
946 optimization is off, but if any optimization is turned on can convert the
947 ((A OR-IF B) OR-IF C)
948 into:
949 ((A OR B) OR_IF C)
950 for sufficiently simple B
951 i.e. the inner OR-IF becomes an OR.
952 At gimplification time the inner OR becomes BIT_IOR_EXPR (in gimplify_expr),
953 giving this for the inner condition:
954 tmp = A | B;
955 if (tmp)
956 thus effectively synthesizing a redundant access of B when optimization
957 is turned on, when compared to:
958 if (A) goto L1; else goto L4;
959 L1: if (B) goto L2; else goto L4;
960 L2: if (C) goto L3; else goto L4;
961 for the unoptimized case.
963 Return true if CTXT appears to be handling such a short-circuitable stmt,
964 such as the def-stmt for B for the:
965 tmp = A | B;
966 case above, for the case where A is true and thus B would have been
967 short-circuited without optimization, using MODEL for the value of A. */
969 static bool
970 within_short_circuited_stmt_p (const region_model *model,
971 const gassign *assign_stmt)
973 /* We must have an assignment to a temporary of _Bool type. */
974 tree lhs = gimple_assign_lhs (assign_stmt);
975 if (TREE_TYPE (lhs) != boolean_type_node)
976 return false;
977 if (TREE_CODE (lhs) != SSA_NAME)
978 return false;
979 if (SSA_NAME_VAR (lhs) != NULL_TREE)
980 return false;
982 /* The temporary bool must be used exactly once: as the second arg of
983 a BIT_IOR_EXPR or BIT_AND_EXPR. */
984 use_operand_p use_op;
985 gimple *use_stmt;
986 if (!single_imm_use (lhs, &use_op, &use_stmt))
987 return false;
988 const gassign *use_assign = dyn_cast <const gassign *> (use_stmt);
989 if (!use_assign)
990 return false;
991 enum tree_code op = gimple_assign_rhs_code (use_assign);
992 if (!(op == BIT_IOR_EXPR ||op == BIT_AND_EXPR))
993 return false;
994 if (!(gimple_assign_rhs1 (use_assign) != lhs
995 && gimple_assign_rhs2 (use_assign) == lhs))
996 return false;
998 /* The first arg of the bitwise stmt must have a known value in MODEL
999 that implies that the value of the second arg doesn't matter, i.e.
1000 1 for bitwise or, 0 for bitwise and. */
1001 tree other_arg = gimple_assign_rhs1 (use_assign);
1002 /* Use a NULL ctxt here to avoid generating warnings. */
1003 const svalue *other_arg_sval = model->get_rvalue (other_arg, NULL);
1004 tree other_arg_cst = other_arg_sval->maybe_get_constant ();
1005 if (!other_arg_cst)
1006 return false;
1007 switch (op)
1009 default:
1010 gcc_unreachable ();
1011 case BIT_IOR_EXPR:
1012 if (zerop (other_arg_cst))
1013 return false;
1014 break;
1015 case BIT_AND_EXPR:
1016 if (!zerop (other_arg_cst))
1017 return false;
1018 break;
1021 /* All tests passed. We appear to be in a stmt that generates a boolean
1022 temporary with a value that won't matter. */
1023 return true;
1026 /* Workaround for discarding certain false positives from
1027 -Wanalyzer-use-of-uninitialized-value
1028 seen with -ftrivial-auto-var-init=.
1030 -ftrivial-auto-var-init= will generate calls to IFN_DEFERRED_INIT.
1032 If the address of the var is taken, gimplification will give us
1033 something like:
1035 _1 = .DEFERRED_INIT (4, 2, &"len"[0]);
1036 len = _1;
1038 The result of DEFERRED_INIT will be an uninit value; we don't
1039 want to emit a false positive for "len = _1;"
1041 Return true if ASSIGN_STMT is such a stmt. */
1043 static bool
1044 due_to_ifn_deferred_init_p (const gassign *assign_stmt)
1047 /* We must have an assignment to a decl from an SSA name that's the
1048 result of a IFN_DEFERRED_INIT call. */
1049 if (gimple_assign_rhs_code (assign_stmt) != SSA_NAME)
1050 return false;
1051 tree lhs = gimple_assign_lhs (assign_stmt);
1052 if (TREE_CODE (lhs) != VAR_DECL)
1053 return false;
1054 tree rhs = gimple_assign_rhs1 (assign_stmt);
1055 if (TREE_CODE (rhs) != SSA_NAME)
1056 return false;
1057 const gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
1058 const gcall *call = dyn_cast <const gcall *> (def_stmt);
1059 if (!call)
1060 return false;
1061 if (gimple_call_internal_p (call)
1062 && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1063 return true;
1064 return false;
1067 /* Check for SVAL being poisoned, adding a warning to CTXT.
1068 Return SVAL, or, if a warning is added, another value, to avoid
1069 repeatedly complaining about the same poisoned value in followup code.
1070 SRC_REGION is a hint about where SVAL came from, and can be NULL. */
1072 const svalue *
1073 region_model::check_for_poison (const svalue *sval,
1074 tree expr,
1075 const region *src_region,
1076 region_model_context *ctxt) const
1078 if (!ctxt)
1079 return sval;
1081 if (const poisoned_svalue *poisoned_sval = sval->dyn_cast_poisoned_svalue ())
1083 enum poison_kind pkind = poisoned_sval->get_poison_kind ();
1085 /* Ignore uninitialized uses of empty types; there's nothing
1086 to initialize. */
1087 if (pkind == POISON_KIND_UNINIT
1088 && sval->get_type ()
1089 && is_empty_type (sval->get_type ()))
1090 return sval;
1092 if (pkind == POISON_KIND_UNINIT)
1093 if (const gimple *curr_stmt = ctxt->get_stmt ())
1094 if (const gassign *assign_stmt
1095 = dyn_cast <const gassign *> (curr_stmt))
1097 /* Special case to avoid certain false positives. */
1098 if (within_short_circuited_stmt_p (this, assign_stmt))
1099 return sval;
1101 /* Special case to avoid false positive on
1102 -ftrivial-auto-var-init=. */
1103 if (due_to_ifn_deferred_init_p (assign_stmt))
1104 return sval;
1107 /* If we have an SSA name for a temporary, we don't want to print
1108 '<unknown>'.
1109 Poisoned values are shared by type, and so we can't reconstruct
1110 the tree other than via the def stmts, using
1111 fixup_tree_for_diagnostic. */
1112 tree diag_arg = fixup_tree_for_diagnostic (expr);
1113 if (src_region == NULL && pkind == POISON_KIND_UNINIT)
1114 src_region = get_region_for_poisoned_expr (expr);
1116 /* Can we reliably get the poisoned value from "expr"?
1117 This is for use by poisoned_value_diagnostic::check_valid_fpath_p.
1118 Unfortunately, we might not have a reliable value for EXPR.
1119 Hence we only query its value now, and only use it if we get the
1120 poisoned value back again. */
1121 tree check_expr = expr;
1122 const svalue *foo_sval = get_rvalue (expr, NULL);
1123 if (foo_sval == sval)
1124 check_expr = expr;
1125 else
1126 check_expr = NULL;
1127 if (ctxt->warn (make_unique<poisoned_value_diagnostic> (diag_arg,
1128 pkind,
1129 src_region,
1130 check_expr)))
1132 /* We only want to report use of a poisoned value at the first
1133 place it gets used; return an unknown value to avoid generating
1134 a chain of followup warnings. */
1135 sval = m_mgr->get_or_create_unknown_svalue (sval->get_type ());
1138 return sval;
1141 return sval;
1144 /* Attempt to get a region for describing EXPR, the source of region of
1145 a poisoned_svalue for use in a poisoned_value_diagnostic.
1146 Return NULL if there is no good region to use. */
1148 const region *
1149 region_model::get_region_for_poisoned_expr (tree expr) const
1151 if (TREE_CODE (expr) == SSA_NAME)
1153 tree decl = SSA_NAME_VAR (expr);
1154 if (decl && DECL_P (decl))
1155 expr = decl;
1156 else
1157 return NULL;
1159 return get_lvalue (expr, NULL);
1162 /* Update this model for the ASSIGN stmt, using CTXT to report any
1163 diagnostics. */
1165 void
1166 region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
1168 tree lhs = gimple_assign_lhs (assign);
1169 tree rhs1 = gimple_assign_rhs1 (assign);
1171 const region *lhs_reg = get_lvalue (lhs, ctxt);
1173 /* Any writes other than to the stack are treated
1174 as externally visible. */
1175 if (ctxt)
1177 enum memory_space memspace = lhs_reg->get_memory_space ();
1178 if (memspace != MEMSPACE_STACK)
1179 ctxt->maybe_did_work ();
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);
1280 if (ctxt)
1281 ctxt->maybe_did_work ();
1283 break;
1285 case GIMPLE_CALL:
1287 /* Track whether we have a gcall to a function that's not recognized by
1288 anything, for which we don't have a function body, or for which we
1289 don't know the fndecl. */
1290 const gcall *call = as_a <const gcall *> (stmt);
1291 *out_unknown_side_effects = on_call_pre (call, ctxt);
1293 break;
1295 case GIMPLE_RETURN:
1297 const greturn *return_ = as_a <const greturn *> (stmt);
1298 on_return (return_, ctxt);
1300 break;
1304 /* Given a call CD with function attribute FORMAT_ATTR, check that the
1305 format arg to the call is a valid null-terminated string. */
1307 void
1308 region_model::check_call_format_attr (const call_details &cd,
1309 tree format_attr) const
1311 /* We assume that FORMAT_ATTR has already been validated. */
1313 /* arg0 of the attribute should be kind of format strings
1314 that this function expects (e.g. "printf"). */
1315 const tree arg0_tree_list = TREE_VALUE (format_attr);
1316 if (!arg0_tree_list)
1317 return;
1319 /* arg1 of the attribute should be the 1-based parameter index
1320 to treat as the format string. */
1321 const tree arg1_tree_list = TREE_CHAIN (arg0_tree_list);
1322 if (!arg1_tree_list)
1323 return;
1324 const tree arg1_value = TREE_VALUE (arg1_tree_list);
1325 if (!arg1_value)
1326 return;
1328 unsigned format_arg_idx = TREE_INT_CST_LOW (arg1_value) - 1;
1329 if (cd.num_args () <= format_arg_idx)
1330 return;
1332 /* Subclass of annotating_context that
1333 adds a note about the format attr to any saved diagnostics. */
1334 class annotating_ctxt : public annotating_context
1336 public:
1337 annotating_ctxt (const call_details &cd,
1338 unsigned fmt_param_idx)
1339 : annotating_context (cd.get_ctxt ()),
1340 m_cd (cd),
1341 m_fmt_param_idx (fmt_param_idx)
1344 void add_annotations () final override
1346 class reason_format_attr
1347 : public pending_note_subclass<reason_format_attr>
1349 public:
1350 reason_format_attr (const call_arg_details &arg_details)
1351 : m_arg_details (arg_details)
1355 const char *get_kind () const final override
1357 return "reason_format_attr";
1360 void emit () const final override
1362 inform (DECL_SOURCE_LOCATION (m_arg_details.m_called_fndecl),
1363 "parameter %i of %qD marked as a format string"
1364 " via %qs attribute",
1365 m_arg_details.m_arg_idx + 1, m_arg_details.m_called_fndecl,
1366 "format");
1369 bool operator== (const reason_format_attr &other) const
1371 return m_arg_details == other.m_arg_details;
1374 private:
1375 call_arg_details m_arg_details;
1378 call_arg_details arg_details (m_cd, m_fmt_param_idx);
1379 add_note (make_unique<reason_format_attr> (arg_details));
1381 private:
1382 const call_details &m_cd;
1383 unsigned m_fmt_param_idx;
1386 annotating_ctxt my_ctxt (cd, format_arg_idx);
1387 call_details my_cd (cd, &my_ctxt);
1388 my_cd.check_for_null_terminated_string_arg (format_arg_idx);
1391 /* Ensure that all arguments at the call described by CD are checked
1392 for poisoned values, by calling get_rvalue on each argument.
1394 Check that calls to functions with "format" attribute have valid
1395 null-terminated strings for their format argument. */
1397 void
1398 region_model::check_call_args (const call_details &cd) const
1400 for (unsigned arg_idx = 0; arg_idx < cd.num_args (); arg_idx++)
1401 cd.get_arg_svalue (arg_idx);
1403 /* Handle attribute "format". */
1404 if (tree format_attr = cd.lookup_function_attribute ("format"))
1405 check_call_format_attr (cd, format_attr);
1408 /* Update this model for an outcome of a call that returns a specific
1409 integer constant.
1410 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1411 the state-merger code from merging success and failure outcomes. */
1413 void
1414 region_model::update_for_int_cst_return (const call_details &cd,
1415 int retval,
1416 bool unmergeable)
1418 if (!cd.get_lhs_type ())
1419 return;
1420 if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1421 return;
1422 const svalue *result
1423 = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), retval);
1424 if (unmergeable)
1425 result = m_mgr->get_or_create_unmergeable (result);
1426 set_value (cd.get_lhs_region (), result, cd.get_ctxt ());
1429 /* Update this model for an outcome of a call that returns zero.
1430 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1431 the state-merger code from merging success and failure outcomes. */
1433 void
1434 region_model::update_for_zero_return (const call_details &cd,
1435 bool unmergeable)
1437 update_for_int_cst_return (cd, 0, unmergeable);
1440 /* Update this model for an outcome of a call that returns non-zero.
1441 Specifically, assign an svalue to the LHS, and add a constraint that
1442 that svalue is non-zero. */
1444 void
1445 region_model::update_for_nonzero_return (const call_details &cd)
1447 if (!cd.get_lhs_type ())
1448 return;
1449 if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1450 return;
1451 cd.set_any_lhs_with_defaults ();
1452 const svalue *zero
1453 = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
1454 const svalue *result
1455 = get_store_value (cd.get_lhs_region (), cd.get_ctxt ());
1456 add_constraint (result, NE_EXPR, zero, cd.get_ctxt ());
1459 /* Subroutine of region_model::maybe_get_copy_bounds.
1460 The Linux kernel commonly uses
1461 min_t([unsigned] long, VAR, sizeof(T));
1462 to set an upper bound on the size of a copy_to_user.
1463 Attempt to simplify such sizes by trying to get the upper bound as a
1464 constant.
1465 Return the simplified svalue if possible, or NULL otherwise. */
1467 static const svalue *
1468 maybe_simplify_upper_bound (const svalue *num_bytes_sval,
1469 region_model_manager *mgr)
1471 tree type = num_bytes_sval->get_type ();
1472 while (const svalue *raw = num_bytes_sval->maybe_undo_cast ())
1473 num_bytes_sval = raw;
1474 if (const binop_svalue *binop_sval = num_bytes_sval->dyn_cast_binop_svalue ())
1475 if (binop_sval->get_op () == MIN_EXPR)
1476 if (binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT)
1478 return mgr->get_or_create_cast (type, binop_sval->get_arg1 ());
1479 /* TODO: we might want to also capture the constraint
1480 when recording the diagnostic, or note that we're using
1481 the upper bound. */
1483 return NULL;
1486 /* Attempt to get an upper bound for the size of a copy when simulating a
1487 copy function.
1489 NUM_BYTES_SVAL is the symbolic value for the size of the copy.
1490 Use it if it's constant, otherwise try to simplify it. Failing
1491 that, use the size of SRC_REG if constant.
1493 Return a symbolic value for an upper limit on the number of bytes
1494 copied, or NULL if no such value could be determined. */
1496 const svalue *
1497 region_model::maybe_get_copy_bounds (const region *src_reg,
1498 const svalue *num_bytes_sval)
1500 if (num_bytes_sval->maybe_get_constant ())
1501 return num_bytes_sval;
1503 if (const svalue *simplified
1504 = maybe_simplify_upper_bound (num_bytes_sval, m_mgr))
1505 num_bytes_sval = simplified;
1507 if (num_bytes_sval->maybe_get_constant ())
1508 return num_bytes_sval;
1510 /* For now, try just guessing the size as the capacity of the
1511 base region of the src.
1512 This is a hack; we might get too large a value. */
1513 const region *src_base_reg = src_reg->get_base_region ();
1514 num_bytes_sval = get_capacity (src_base_reg);
1516 if (num_bytes_sval->maybe_get_constant ())
1517 return num_bytes_sval;
1519 /* Non-constant: give up. */
1520 return NULL;
1523 /* Get any known_function for FNDECL for call CD.
1525 The call must match all assumptions made by the known_function (such as
1526 e.g. "argument 1's type must be a pointer type").
1528 Return NULL if no known_function is found, or it does not match the
1529 assumption(s). */
1531 const known_function *
1532 region_model::get_known_function (tree fndecl, const call_details &cd) const
1534 known_function_manager *known_fn_mgr = m_mgr->get_known_function_manager ();
1535 return known_fn_mgr->get_match (fndecl, cd);
1538 /* Get any known_function for IFN, or NULL. */
1540 const known_function *
1541 region_model::get_known_function (enum internal_fn ifn) const
1543 known_function_manager *known_fn_mgr = m_mgr->get_known_function_manager ();
1544 return known_fn_mgr->get_internal_fn (ifn);
1547 /* Get any builtin_known_function for CALL and emit any warning to CTXT
1548 if not NULL.
1550 The call must match all assumptions made by the known_function (such as
1551 e.g. "argument 1's type must be a pointer type").
1553 Return NULL if no builtin_known_function is found, or it does
1554 not match the assumption(s).
1556 Internally calls get_known_function to find a known_function and cast it
1557 to a builtin_known_function.
1559 For instance, calloc is a C builtin, defined in gcc/builtins.def
1560 by the DEF_LIB_BUILTIN macro. Such builtins are recognized by the
1561 analyzer by their name, so that even in C++ or if the user redeclares
1562 them but mismatch their signature, they are still recognized as builtins.
1564 Cases when a supposed builtin is not flagged as one by the FE:
1566 The C++ FE does not recognize calloc as a builtin if it has not been
1567 included from a standard header, but the C FE does. Hence in C++ if
1568 CALL comes from a calloc and stdlib is not included,
1569 gcc/tree.h:fndecl_built_in_p (CALL) would be false.
1571 In C code, a __SIZE_TYPE__ calloc (__SIZE_TYPE__, __SIZE_TYPE__) user
1572 declaration has obviously a mismatching signature from the standard, and
1573 its function_decl tree won't be unified by
1574 gcc/c-decl.cc:match_builtin_function_types.
1576 Yet in both cases the analyzer should treat the calls as a builtin calloc
1577 so that extra attributes unspecified by the standard but added by GCC
1578 (e.g. sprintf attributes in gcc/builtins.def), useful for the detection of
1579 dangerous behavior, are indeed processed.
1581 Therefore for those cases when a "builtin flag" is not added by the FE,
1582 builtins' kf are derived from builtin_known_function, whose method
1583 builtin_known_function::builtin_decl returns the builtin's
1584 function_decl tree as defined in gcc/builtins.def, with all the extra
1585 attributes. */
1587 const builtin_known_function *
1588 region_model::get_builtin_kf (const gcall *call,
1589 region_model_context *ctxt /* = NULL */) const
1591 region_model *mut_this = const_cast <region_model *> (this);
1592 tree callee_fndecl = mut_this->get_fndecl_for_call (call, ctxt);
1593 if (! callee_fndecl)
1594 return NULL;
1596 call_details cd (call, mut_this, ctxt);
1597 if (const known_function *kf = get_known_function (callee_fndecl, cd))
1598 return kf->dyn_cast_builtin_kf ();
1600 return NULL;
1603 /* Update this model for the CALL stmt, using CTXT to report any
1604 diagnostics - the first half.
1606 Updates to the region_model that should be made *before* sm-states
1607 are updated are done here; other updates to the region_model are done
1608 in region_model::on_call_post.
1610 Return true if the function call has unknown side effects (it wasn't
1611 recognized and we don't have a body for it, or are unable to tell which
1612 fndecl it is). */
1614 bool
1615 region_model::on_call_pre (const gcall *call, region_model_context *ctxt)
1617 call_details cd (call, this, ctxt);
1619 /* Special-case for IFN_DEFERRED_INIT.
1620 We want to report uninitialized variables with -fanalyzer (treating
1621 -ftrivial-auto-var-init= as purely a mitigation feature).
1622 Handle IFN_DEFERRED_INIT by treating it as no-op: don't touch the
1623 lhs of the call, so that it is still uninitialized from the point of
1624 view of the analyzer. */
1625 if (gimple_call_internal_p (call)
1626 && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1627 return false; /* No side effects. */
1629 /* Get svalues for all of the arguments at the callsite, to ensure that we
1630 complain about any uninitialized arguments. This might lead to
1631 duplicates if any of the handling below also looks up the svalues,
1632 but the deduplication code should deal with that. */
1633 if (ctxt)
1634 check_call_args (cd);
1636 tree callee_fndecl = get_fndecl_for_call (call, ctxt);
1638 if (gimple_call_internal_p (call))
1639 if (const known_function *kf
1640 = get_known_function (gimple_call_internal_fn (call)))
1642 kf->impl_call_pre (cd);
1643 return false; /* No further side effects. */
1646 if (!callee_fndecl)
1648 cd.set_any_lhs_with_defaults ();
1649 return true; /* Unknown side effects. */
1652 if (const known_function *kf = get_known_function (callee_fndecl, cd))
1654 kf->impl_call_pre (cd);
1655 return false; /* No further side effects. */
1658 cd.set_any_lhs_with_defaults ();
1660 const int callee_fndecl_flags = flags_from_decl_or_type (callee_fndecl);
1661 if (callee_fndecl_flags & (ECF_CONST | ECF_PURE))
1662 return false; /* No side effects. */
1664 if (fndecl_built_in_p (callee_fndecl))
1665 return true; /* Unknown side effects. */
1667 if (!fndecl_has_gimple_body_p (callee_fndecl))
1668 return true; /* Unknown side effects. */
1670 return false; /* No side effects. */
1673 /* Update this model for the CALL stmt, using CTXT to report any
1674 diagnostics - the second half.
1676 Updates to the region_model that should be made *after* sm-states
1677 are updated are done here; other updates to the region_model are done
1678 in region_model::on_call_pre.
1680 If UNKNOWN_SIDE_EFFECTS is true, also call handle_unrecognized_call
1681 to purge state. */
1683 void
1684 region_model::on_call_post (const gcall *call,
1685 bool unknown_side_effects,
1686 region_model_context *ctxt)
1688 if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
1690 call_details cd (call, this, ctxt);
1691 if (const known_function *kf = get_known_function (callee_fndecl, cd))
1693 kf->impl_call_post (cd);
1694 return;
1696 /* Was this fndecl referenced by
1697 __attribute__((malloc(FOO)))? */
1698 if (lookup_attribute ("*dealloc", DECL_ATTRIBUTES (callee_fndecl)))
1700 impl_deallocation_call (cd);
1701 return;
1705 if (unknown_side_effects)
1707 handle_unrecognized_call (call, ctxt);
1708 if (ctxt)
1709 ctxt->maybe_did_work ();
1713 /* Purge state involving SVAL from this region_model, using CTXT
1714 (if non-NULL) to purge other state in a program_state.
1716 For example, if we're at the def-stmt of an SSA name, then we need to
1717 purge any state for svalues that involve that SSA name. This avoids
1718 false positives in loops, since a symbolic value referring to the
1719 SSA name will be referring to the previous value of that SSA name.
1721 For example, in:
1722 while ((e = hashmap_iter_next(&iter))) {
1723 struct oid2strbuf *e_strbuf = (struct oid2strbuf *)e;
1724 free (e_strbuf->value);
1726 at the def-stmt of e_8:
1727 e_8 = hashmap_iter_next (&iter);
1728 we should purge the "freed" state of:
1729 INIT_VAL(CAST_REG(‘struct oid2strbuf’, (*INIT_VAL(e_8))).value)
1730 which is the "e_strbuf->value" value from the previous iteration,
1731 or we will erroneously report a double-free - the "e_8" within it
1732 refers to the previous value. */
1734 void
1735 region_model::purge_state_involving (const svalue *sval,
1736 region_model_context *ctxt)
1738 if (!sval->can_have_associated_state_p ())
1739 return;
1740 m_store.purge_state_involving (sval, m_mgr);
1741 m_constraints->purge_state_involving (sval);
1742 m_dynamic_extents.purge_state_involving (sval);
1743 if (ctxt)
1744 ctxt->purge_state_involving (sval);
1747 /* A pending_note subclass for adding a note about an
1748 __attribute__((access, ...)) to a diagnostic. */
1750 class reason_attr_access : public pending_note_subclass<reason_attr_access>
1752 public:
1753 reason_attr_access (tree callee_fndecl, const attr_access &access)
1754 : m_callee_fndecl (callee_fndecl),
1755 m_ptr_argno (access.ptrarg),
1756 m_access_str (TREE_STRING_POINTER (access.to_external_string ()))
1760 const char *get_kind () const final override { return "reason_attr_access"; }
1762 void emit () const final override
1764 inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
1765 "parameter %i of %qD marked with attribute %qs",
1766 m_ptr_argno + 1, m_callee_fndecl, m_access_str);
1769 bool operator== (const reason_attr_access &other) const
1771 return (m_callee_fndecl == other.m_callee_fndecl
1772 && m_ptr_argno == other.m_ptr_argno
1773 && !strcmp (m_access_str, other.m_access_str));
1776 private:
1777 tree m_callee_fndecl;
1778 unsigned m_ptr_argno;
1779 const char *m_access_str;
1782 /* Check CALL a call to external function CALLEE_FNDECL based on
1783 any __attribute__ ((access, ....) on the latter, complaining to
1784 CTXT about any issues.
1786 Currently we merely call check_region_for_write on any regions
1787 pointed to by arguments marked with a "write_only" or "read_write"
1788 attribute. */
1790 void
1791 region_model::check_function_attr_access (const gcall *call,
1792 tree callee_fndecl,
1793 region_model_context *ctxt,
1794 rdwr_map &rdwr_idx) const
1796 gcc_assert (call);
1797 gcc_assert (callee_fndecl);
1798 gcc_assert (ctxt);
1800 tree fntype = TREE_TYPE (callee_fndecl);
1801 gcc_assert (fntype);
1803 unsigned argno = 0;
1805 for (tree iter = TYPE_ARG_TYPES (fntype); iter;
1806 iter = TREE_CHAIN (iter), ++argno)
1808 const attr_access* access = rdwr_idx.get (argno);
1809 if (!access)
1810 continue;
1812 /* Ignore any duplicate entry in the map for the size argument. */
1813 if (access->ptrarg != argno)
1814 continue;
1816 if (access->mode == access_write_only
1817 || access->mode == access_read_write)
1819 /* Subclass of annotating_context that
1820 adds a note about the attr access to any saved diagnostics. */
1821 class annotating_ctxt : public annotating_context
1823 public:
1824 annotating_ctxt (tree callee_fndecl,
1825 const attr_access &access,
1826 region_model_context *ctxt)
1827 : annotating_context (ctxt),
1828 m_callee_fndecl (callee_fndecl),
1829 m_access (access)
1832 void add_annotations () final override
1834 add_note (make_unique<reason_attr_access>
1835 (m_callee_fndecl, m_access));
1837 private:
1838 tree m_callee_fndecl;
1839 const attr_access &m_access;
1842 /* Use this ctxt below so that any diagnostics get the
1843 note added to them. */
1844 annotating_ctxt my_ctxt (callee_fndecl, *access, ctxt);
1846 tree ptr_tree = gimple_call_arg (call, access->ptrarg);
1847 const svalue *ptr_sval = get_rvalue (ptr_tree, &my_ctxt);
1848 const region *reg = deref_rvalue (ptr_sval, ptr_tree, &my_ctxt);
1849 check_region_for_write (reg, nullptr, &my_ctxt);
1850 /* We don't use the size arg for now. */
1855 /* Subroutine of region_model::check_function_attr_null_terminated_string_arg,
1856 checking one instance of __attribute__((null_terminated_string_arg)). */
1858 void
1859 region_model::
1860 check_one_function_attr_null_terminated_string_arg (const gcall *call,
1861 tree callee_fndecl,
1862 region_model_context *ctxt,
1863 rdwr_map &rdwr_idx,
1864 tree attr)
1866 gcc_assert (call);
1867 gcc_assert (callee_fndecl);
1868 gcc_assert (ctxt);
1869 gcc_assert (attr);
1871 tree arg = TREE_VALUE (attr);
1872 if (!arg)
1873 return;
1875 /* Convert from 1-based to 0-based index. */
1876 unsigned int arg_idx = TREE_INT_CST_LOW (TREE_VALUE (arg)) - 1;
1878 /* If there's also an "access" attribute on the ptr param
1879 for reading with a size param specified, then that size
1880 limits the size of the possible read from the pointer. */
1881 if (const attr_access* access = rdwr_idx.get (arg_idx))
1882 if ((access->mode == access_read_only
1883 || access->mode == access_read_write)
1884 && access->sizarg != UINT_MAX)
1886 call_details cd_checked (call, this, ctxt);
1887 const svalue *limit_sval
1888 = cd_checked.get_arg_svalue (access->sizarg);
1889 const svalue *ptr_sval
1890 = cd_checked.get_arg_svalue (arg_idx);
1891 /* Try reading all of the bytes expressed by the size param,
1892 but without emitting warnings (via a null context). */
1893 const svalue *limited_sval
1894 = read_bytes (deref_rvalue (ptr_sval, NULL_TREE, nullptr),
1895 NULL_TREE,
1896 limit_sval,
1897 nullptr);
1898 if (limited_sval->get_kind () == SK_POISONED)
1900 /* Reading up to the truncation limit caused issues.
1901 Assume that the string is meant to be terminated
1902 before then, so perform a *checked* check for the
1903 terminator. */
1904 check_for_null_terminated_string_arg (cd_checked,
1905 arg_idx);
1907 else
1909 /* Reading up to the truncation limit seems OK; repeat
1910 the read, but with checking enabled. */
1911 read_bytes (deref_rvalue (ptr_sval, NULL_TREE, ctxt),
1912 NULL_TREE,
1913 limit_sval,
1914 ctxt);
1916 return;
1919 /* Otherwise, we don't have an access-attribute limiting the read.
1920 Simulate a read up to the null terminator (if any). */
1922 call_details cd (call, this, ctxt);
1923 check_for_null_terminated_string_arg (cd, arg_idx);
1926 /* Check CALL a call to external function CALLEE_FNDECL for any uses
1927 of __attribute__ ((null_terminated_string_arg)), compaining
1928 to CTXT about any issues.
1930 Use RDWR_IDX for tracking uses of __attribute__ ((access, ....). */
1932 void
1933 region_model::
1934 check_function_attr_null_terminated_string_arg (const gcall *call,
1935 tree callee_fndecl,
1936 region_model_context *ctxt,
1937 rdwr_map &rdwr_idx)
1939 gcc_assert (call);
1940 gcc_assert (callee_fndecl);
1941 gcc_assert (ctxt);
1943 tree fntype = TREE_TYPE (callee_fndecl);
1944 gcc_assert (fntype);
1946 /* A function declaration can specify multiple attribute
1947 null_terminated_string_arg, each with one argument. */
1948 for (tree attr = TYPE_ATTRIBUTES (fntype); attr; attr = TREE_CHAIN (attr))
1950 attr = lookup_attribute ("null_terminated_string_arg", attr);
1951 if (!attr)
1952 return;
1954 check_one_function_attr_null_terminated_string_arg (call, callee_fndecl,
1955 ctxt, rdwr_idx,
1956 attr);
1960 /* Check CALL a call to external function CALLEE_FNDECL for any
1961 function attributes, complaining to CTXT about any issues. */
1963 void
1964 region_model::check_function_attrs (const gcall *call,
1965 tree callee_fndecl,
1966 region_model_context *ctxt)
1968 gcc_assert (call);
1969 gcc_assert (callee_fndecl);
1970 gcc_assert (ctxt);
1972 tree fntype = TREE_TYPE (callee_fndecl);
1973 if (!fntype)
1974 return;
1976 if (!TYPE_ATTRIBUTES (fntype))
1977 return;
1979 /* Initialize a map of attribute access specifications for arguments
1980 to the function call. */
1981 rdwr_map rdwr_idx;
1982 init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype));
1984 check_function_attr_access (call, callee_fndecl, ctxt, rdwr_idx);
1985 check_function_attr_null_terminated_string_arg (call, callee_fndecl,
1986 ctxt, rdwr_idx);
1989 /* Handle a call CALL to a function with unknown behavior.
1991 Traverse the regions in this model, determining what regions are
1992 reachable from pointer arguments to CALL and from global variables,
1993 recursively.
1995 Set all reachable regions to new unknown values and purge sm-state
1996 from their values, and from values that point to them. */
1998 void
1999 region_model::handle_unrecognized_call (const gcall *call,
2000 region_model_context *ctxt)
2002 tree fndecl = get_fndecl_for_call (call, ctxt);
2004 if (fndecl && ctxt)
2005 check_function_attrs (call, fndecl, ctxt);
2007 reachable_regions reachable_regs (this);
2009 /* Determine the reachable regions and their mutability. */
2011 /* Add globals and regions that already escaped in previous
2012 unknown calls. */
2013 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2014 &reachable_regs);
2016 /* Params that are pointers. */
2017 tree iter_param_types = NULL_TREE;
2018 if (fndecl)
2019 iter_param_types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
2020 for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
2022 /* Track expected param type, where available. */
2023 tree param_type = NULL_TREE;
2024 if (iter_param_types)
2026 param_type = TREE_VALUE (iter_param_types);
2027 gcc_assert (param_type);
2028 iter_param_types = TREE_CHAIN (iter_param_types);
2031 tree parm = gimple_call_arg (call, arg_idx);
2032 const svalue *parm_sval = get_rvalue (parm, ctxt);
2033 reachable_regs.handle_parm (parm_sval, param_type);
2037 uncertainty_t *uncertainty = ctxt ? ctxt->get_uncertainty () : NULL;
2039 /* Purge sm-state for the svalues that were reachable,
2040 both in non-mutable and mutable form. */
2041 for (svalue_set::iterator iter
2042 = reachable_regs.begin_reachable_svals ();
2043 iter != reachable_regs.end_reachable_svals (); ++iter)
2045 const svalue *sval = (*iter);
2046 if (ctxt)
2047 ctxt->on_unknown_change (sval, false);
2049 for (svalue_set::iterator iter
2050 = reachable_regs.begin_mutable_svals ();
2051 iter != reachable_regs.end_mutable_svals (); ++iter)
2053 const svalue *sval = (*iter);
2054 if (ctxt)
2055 ctxt->on_unknown_change (sval, true);
2056 if (uncertainty)
2057 uncertainty->on_mutable_sval_at_unknown_call (sval);
2060 /* Mark any clusters that have escaped. */
2061 reachable_regs.mark_escaped_clusters (ctxt);
2063 /* Update bindings for all clusters that have escaped, whether above,
2064 or previously. */
2065 m_store.on_unknown_fncall (call, m_mgr->get_store_manager (),
2066 conjured_purge (this, ctxt));
2068 /* Purge dynamic extents from any regions that have escaped mutably:
2069 realloc could have been called on them. */
2070 for (hash_set<const region *>::iterator
2071 iter = reachable_regs.begin_mutable_base_regs ();
2072 iter != reachable_regs.end_mutable_base_regs ();
2073 ++iter)
2075 const region *base_reg = (*iter);
2076 unset_dynamic_extents (base_reg);
2080 /* Traverse the regions in this model, determining what regions are
2081 reachable from the store and populating *OUT.
2083 If EXTRA_SVAL is non-NULL, treat it as an additional "root"
2084 for reachability (for handling return values from functions when
2085 analyzing return of the only function on the stack).
2087 If UNCERTAINTY is non-NULL, treat any svalues that were recorded
2088 within it as being maybe-bound as additional "roots" for reachability.
2090 Find svalues that haven't leaked. */
2092 void
2093 region_model::get_reachable_svalues (svalue_set *out,
2094 const svalue *extra_sval,
2095 const uncertainty_t *uncertainty)
2097 reachable_regions reachable_regs (this);
2099 /* Add globals and regions that already escaped in previous
2100 unknown calls. */
2101 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2102 &reachable_regs);
2104 if (extra_sval)
2105 reachable_regs.handle_sval (extra_sval);
2107 if (uncertainty)
2108 for (uncertainty_t::iterator iter
2109 = uncertainty->begin_maybe_bound_svals ();
2110 iter != uncertainty->end_maybe_bound_svals (); ++iter)
2111 reachable_regs.handle_sval (*iter);
2113 /* Get regions for locals that have explicitly bound values. */
2114 for (store::cluster_map_t::iterator iter = m_store.begin ();
2115 iter != m_store.end (); ++iter)
2117 const region *base_reg = (*iter).first;
2118 if (const region *parent = base_reg->get_parent_region ())
2119 if (parent->get_kind () == RK_FRAME)
2120 reachable_regs.add (base_reg, false);
2123 /* Populate *OUT based on the values that were reachable. */
2124 for (svalue_set::iterator iter
2125 = reachable_regs.begin_reachable_svals ();
2126 iter != reachable_regs.end_reachable_svals (); ++iter)
2127 out->add (*iter);
2130 /* Update this model for the RETURN_STMT, using CTXT to report any
2131 diagnostics. */
2133 void
2134 region_model::on_return (const greturn *return_stmt, region_model_context *ctxt)
2136 tree callee = get_current_function ()->decl;
2137 tree lhs = DECL_RESULT (callee);
2138 tree rhs = gimple_return_retval (return_stmt);
2140 if (lhs && rhs)
2142 const svalue *sval = get_rvalue (rhs, ctxt);
2143 const region *ret_reg = get_lvalue (lhs, ctxt);
2144 set_value (ret_reg, sval, ctxt);
2148 /* Update this model for a call and return of setjmp/sigsetjmp at CALL within
2149 ENODE, using CTXT to report any diagnostics.
2151 This is for the initial direct invocation of setjmp/sigsetjmp (which returns
2152 0), as opposed to any second return due to longjmp/sigsetjmp. */
2154 void
2155 region_model::on_setjmp (const gcall *call, const exploded_node *enode,
2156 region_model_context *ctxt)
2158 const svalue *buf_ptr = get_rvalue (gimple_call_arg (call, 0), ctxt);
2159 const region *buf_reg = deref_rvalue (buf_ptr, gimple_call_arg (call, 0),
2160 ctxt);
2162 /* Create a setjmp_svalue for this call and store it in BUF_REG's
2163 region. */
2164 if (buf_reg)
2166 setjmp_record r (enode, call);
2167 const svalue *sval
2168 = m_mgr->get_or_create_setjmp_svalue (r, buf_reg->get_type ());
2169 set_value (buf_reg, sval, ctxt);
2172 /* Direct calls to setjmp return 0. */
2173 if (tree lhs = gimple_call_lhs (call))
2175 const svalue *new_sval
2176 = m_mgr->get_or_create_int_cst (TREE_TYPE (lhs), 0);
2177 const region *lhs_reg = get_lvalue (lhs, ctxt);
2178 set_value (lhs_reg, new_sval, ctxt);
2182 /* Update this region_model for rewinding from a "longjmp" at LONGJMP_CALL
2183 to a "setjmp" at SETJMP_CALL where the final stack depth should be
2184 SETJMP_STACK_DEPTH. Pop any stack frames. Leak detection is *not*
2185 done, and should be done by the caller. */
2187 void
2188 region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
2189 int setjmp_stack_depth, region_model_context *ctxt)
2191 /* Evaluate the val, using the frame of the "longjmp". */
2192 tree fake_retval = gimple_call_arg (longjmp_call, 1);
2193 const svalue *fake_retval_sval = get_rvalue (fake_retval, ctxt);
2195 /* Pop any frames until we reach the stack depth of the function where
2196 setjmp was called. */
2197 gcc_assert (get_stack_depth () >= setjmp_stack_depth);
2198 while (get_stack_depth () > setjmp_stack_depth)
2199 pop_frame (NULL, NULL, ctxt, false);
2201 gcc_assert (get_stack_depth () == setjmp_stack_depth);
2203 /* Assign to LHS of "setjmp" in new_state. */
2204 if (tree lhs = gimple_call_lhs (setjmp_call))
2206 /* Passing 0 as the val to longjmp leads to setjmp returning 1. */
2207 const svalue *zero_sval
2208 = m_mgr->get_or_create_int_cst (TREE_TYPE (fake_retval), 0);
2209 tristate eq_zero = eval_condition (fake_retval_sval, EQ_EXPR, zero_sval);
2210 /* If we have 0, use 1. */
2211 if (eq_zero.is_true ())
2213 const svalue *one_sval
2214 = m_mgr->get_or_create_int_cst (TREE_TYPE (fake_retval), 1);
2215 fake_retval_sval = one_sval;
2217 else
2219 /* Otherwise note that the value is nonzero. */
2220 m_constraints->add_constraint (fake_retval_sval, NE_EXPR, zero_sval);
2223 /* Decorate the return value from setjmp as being unmergeable,
2224 so that we don't attempt to merge states with it as zero
2225 with states in which it's nonzero, leading to a clean distinction
2226 in the exploded_graph betweeen the first return and the second
2227 return. */
2228 fake_retval_sval = m_mgr->get_or_create_unmergeable (fake_retval_sval);
2230 const region *lhs_reg = get_lvalue (lhs, ctxt);
2231 set_value (lhs_reg, fake_retval_sval, ctxt);
2235 /* Update this region_model for a phi stmt of the form
2236 LHS = PHI <...RHS...>.
2237 where RHS is for the appropriate edge.
2238 Get state from OLD_STATE so that all of the phi stmts for a basic block
2239 are effectively handled simultaneously. */
2241 void
2242 region_model::handle_phi (const gphi *phi,
2243 tree lhs, tree rhs,
2244 const region_model &old_state,
2245 hash_set<const svalue *> &svals_changing_meaning,
2246 region_model_context *ctxt)
2248 /* For now, don't bother tracking the .MEM SSA names. */
2249 if (tree var = SSA_NAME_VAR (lhs))
2250 if (TREE_CODE (var) == VAR_DECL)
2251 if (VAR_DECL_IS_VIRTUAL_OPERAND (var))
2252 return;
2254 const svalue *src_sval = old_state.get_rvalue (rhs, ctxt);
2255 const region *dst_reg = old_state.get_lvalue (lhs, ctxt);
2257 const svalue *sval = old_state.get_rvalue (lhs, nullptr);
2258 if (sval->get_kind () == SK_WIDENING)
2259 svals_changing_meaning.add (sval);
2261 set_value (dst_reg, src_sval, ctxt);
2263 if (ctxt)
2264 ctxt->on_phi (phi, rhs);
2267 /* Implementation of region_model::get_lvalue; the latter adds type-checking.
2269 Get the id of the region for PV within this region_model,
2270 emitting any diagnostics to CTXT. */
2272 const region *
2273 region_model::get_lvalue_1 (path_var pv, region_model_context *ctxt) const
2275 tree expr = pv.m_tree;
2277 gcc_assert (expr);
2279 switch (TREE_CODE (expr))
2281 default:
2282 return m_mgr->get_region_for_unexpected_tree_code (ctxt, expr,
2283 dump_location_t ());
2285 case ARRAY_REF:
2287 tree array = TREE_OPERAND (expr, 0);
2288 tree index = TREE_OPERAND (expr, 1);
2290 const region *array_reg = get_lvalue (array, ctxt);
2291 const svalue *index_sval = get_rvalue (index, ctxt);
2292 return m_mgr->get_element_region (array_reg,
2293 TREE_TYPE (TREE_TYPE (array)),
2294 index_sval);
2296 break;
2298 case BIT_FIELD_REF:
2300 tree inner_expr = TREE_OPERAND (expr, 0);
2301 const region *inner_reg = get_lvalue (inner_expr, ctxt);
2302 tree num_bits = TREE_OPERAND (expr, 1);
2303 tree first_bit_offset = TREE_OPERAND (expr, 2);
2304 gcc_assert (TREE_CODE (num_bits) == INTEGER_CST);
2305 gcc_assert (TREE_CODE (first_bit_offset) == INTEGER_CST);
2306 bit_range bits (TREE_INT_CST_LOW (first_bit_offset),
2307 TREE_INT_CST_LOW (num_bits));
2308 return m_mgr->get_bit_range (inner_reg, TREE_TYPE (expr), bits);
2310 break;
2312 case MEM_REF:
2314 tree ptr = TREE_OPERAND (expr, 0);
2315 tree offset = TREE_OPERAND (expr, 1);
2316 const svalue *ptr_sval = get_rvalue (ptr, ctxt);
2317 const svalue *offset_sval = get_rvalue (offset, ctxt);
2318 const region *star_ptr = deref_rvalue (ptr_sval, ptr, ctxt);
2319 return m_mgr->get_offset_region (star_ptr,
2320 TREE_TYPE (expr),
2321 offset_sval);
2323 break;
2325 case FUNCTION_DECL:
2326 return m_mgr->get_region_for_fndecl (expr);
2328 case LABEL_DECL:
2329 return m_mgr->get_region_for_label (expr);
2331 case VAR_DECL:
2332 /* Handle globals. */
2333 if (is_global_var (expr))
2334 return m_mgr->get_region_for_global (expr);
2336 /* Fall through. */
2338 case SSA_NAME:
2339 case PARM_DECL:
2340 case RESULT_DECL:
2342 gcc_assert (TREE_CODE (expr) == SSA_NAME
2343 || TREE_CODE (expr) == PARM_DECL
2344 || VAR_P (expr)
2345 || TREE_CODE (expr) == RESULT_DECL);
2347 int stack_index = pv.m_stack_depth;
2348 const frame_region *frame = get_frame_at_index (stack_index);
2349 gcc_assert (frame);
2350 return frame->get_region_for_local (m_mgr, expr, ctxt);
2353 case COMPONENT_REF:
2355 /* obj.field */
2356 tree obj = TREE_OPERAND (expr, 0);
2357 tree field = TREE_OPERAND (expr, 1);
2358 const region *obj_reg = get_lvalue (obj, ctxt);
2359 return m_mgr->get_field_region (obj_reg, field);
2361 break;
2363 case STRING_CST:
2364 return m_mgr->get_region_for_string (expr);
2368 /* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op. */
2370 static void
2371 assert_compat_types (tree src_type, tree dst_type)
2373 if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2375 #if CHECKING_P
2376 if (!(useless_type_conversion_p (src_type, dst_type)))
2377 internal_error ("incompatible types: %qT and %qT", src_type, dst_type);
2378 #endif
2382 /* Return true if SRC_TYPE can be converted to DST_TYPE as a no-op. */
2384 bool
2385 compat_types_p (tree src_type, tree dst_type)
2387 if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2388 if (!(useless_type_conversion_p (src_type, dst_type)))
2389 return false;
2390 return true;
2393 /* Get the region for PV within this region_model,
2394 emitting any diagnostics to CTXT. */
2396 const region *
2397 region_model::get_lvalue (path_var pv, region_model_context *ctxt) const
2399 if (pv.m_tree == NULL_TREE)
2400 return NULL;
2402 const region *result_reg = get_lvalue_1 (pv, ctxt);
2403 assert_compat_types (result_reg->get_type (), TREE_TYPE (pv.m_tree));
2404 return result_reg;
2407 /* Get the region for EXPR within this region_model (assuming the most
2408 recent stack frame if it's a local). */
2410 const region *
2411 region_model::get_lvalue (tree expr, region_model_context *ctxt) const
2413 return get_lvalue (path_var (expr, get_stack_depth () - 1), ctxt);
2416 /* Implementation of region_model::get_rvalue; the latter adds type-checking.
2418 Get the value of PV within this region_model,
2419 emitting any diagnostics to CTXT. */
2421 const svalue *
2422 region_model::get_rvalue_1 (path_var pv, region_model_context *ctxt) const
2424 gcc_assert (pv.m_tree);
2426 switch (TREE_CODE (pv.m_tree))
2428 default:
2429 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2431 case ADDR_EXPR:
2433 /* "&EXPR". */
2434 tree expr = pv.m_tree;
2435 tree op0 = TREE_OPERAND (expr, 0);
2436 const region *expr_reg = get_lvalue (op0, ctxt);
2437 return m_mgr->get_ptr_svalue (TREE_TYPE (expr), expr_reg);
2439 break;
2441 case BIT_FIELD_REF:
2443 tree expr = pv.m_tree;
2444 tree op0 = TREE_OPERAND (expr, 0);
2445 const region *reg = get_lvalue (op0, ctxt);
2446 tree num_bits = TREE_OPERAND (expr, 1);
2447 tree first_bit_offset = TREE_OPERAND (expr, 2);
2448 gcc_assert (TREE_CODE (num_bits) == INTEGER_CST);
2449 gcc_assert (TREE_CODE (first_bit_offset) == INTEGER_CST);
2450 bit_range bits (TREE_INT_CST_LOW (first_bit_offset),
2451 TREE_INT_CST_LOW (num_bits));
2452 return get_rvalue_for_bits (TREE_TYPE (expr), reg, bits, ctxt);
2455 case VAR_DECL:
2456 if (DECL_HARD_REGISTER (pv.m_tree))
2458 /* If it has a hard register, it doesn't have a memory region
2459 and can't be referred to as an lvalue. */
2460 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2462 /* Fall through. */
2463 case PARM_DECL:
2464 case SSA_NAME:
2465 case RESULT_DECL:
2466 case ARRAY_REF:
2468 const region *reg = get_lvalue (pv, ctxt);
2469 return get_store_value (reg, ctxt);
2472 case REALPART_EXPR:
2473 case IMAGPART_EXPR:
2474 case VIEW_CONVERT_EXPR:
2476 tree expr = pv.m_tree;
2477 tree arg = TREE_OPERAND (expr, 0);
2478 const svalue *arg_sval = get_rvalue (arg, ctxt);
2479 const svalue *sval_unaryop
2480 = m_mgr->get_or_create_unaryop (TREE_TYPE (expr), TREE_CODE (expr),
2481 arg_sval);
2482 return sval_unaryop;
2485 case INTEGER_CST:
2486 case REAL_CST:
2487 case COMPLEX_CST:
2488 case VECTOR_CST:
2489 case STRING_CST:
2490 return m_mgr->get_or_create_constant_svalue (pv.m_tree);
2492 case POINTER_PLUS_EXPR:
2494 tree expr = pv.m_tree;
2495 tree ptr = TREE_OPERAND (expr, 0);
2496 tree offset = TREE_OPERAND (expr, 1);
2497 const svalue *ptr_sval = get_rvalue (ptr, ctxt);
2498 const svalue *offset_sval = get_rvalue (offset, ctxt);
2499 const svalue *sval_binop
2500 = m_mgr->get_or_create_binop (TREE_TYPE (expr), POINTER_PLUS_EXPR,
2501 ptr_sval, offset_sval);
2502 return sval_binop;
2505 /* Binary ops. */
2506 case PLUS_EXPR:
2507 case MULT_EXPR:
2508 case BIT_AND_EXPR:
2509 case BIT_IOR_EXPR:
2510 case BIT_XOR_EXPR:
2512 tree expr = pv.m_tree;
2513 tree arg0 = TREE_OPERAND (expr, 0);
2514 tree arg1 = TREE_OPERAND (expr, 1);
2515 const svalue *arg0_sval = get_rvalue (arg0, ctxt);
2516 const svalue *arg1_sval = get_rvalue (arg1, ctxt);
2517 const svalue *sval_binop
2518 = m_mgr->get_or_create_binop (TREE_TYPE (expr), TREE_CODE (expr),
2519 arg0_sval, arg1_sval);
2520 return sval_binop;
2523 case COMPONENT_REF:
2524 case MEM_REF:
2526 const region *ref_reg = get_lvalue (pv, ctxt);
2527 return get_store_value (ref_reg, ctxt);
2529 case OBJ_TYPE_REF:
2531 tree expr = OBJ_TYPE_REF_EXPR (pv.m_tree);
2532 return get_rvalue (expr, ctxt);
2537 /* Get the value of PV within this region_model,
2538 emitting any diagnostics to CTXT. */
2540 const svalue *
2541 region_model::get_rvalue (path_var pv, region_model_context *ctxt) const
2543 if (pv.m_tree == NULL_TREE)
2544 return NULL;
2546 const svalue *result_sval = get_rvalue_1 (pv, ctxt);
2548 assert_compat_types (result_sval->get_type (), TREE_TYPE (pv.m_tree));
2550 result_sval = check_for_poison (result_sval, pv.m_tree, NULL, ctxt);
2552 return result_sval;
2555 /* Get the value of EXPR within this region_model (assuming the most
2556 recent stack frame if it's a local). */
2558 const svalue *
2559 region_model::get_rvalue (tree expr, region_model_context *ctxt) const
2561 return get_rvalue (path_var (expr, get_stack_depth () - 1), ctxt);
2564 /* Return true if this model is on a path with "main" as the entrypoint
2565 (as opposed to one in which we're merely analyzing a subset of the
2566 path through the code). */
2568 bool
2569 region_model::called_from_main_p () const
2571 if (!m_current_frame)
2572 return false;
2573 /* Determine if the oldest stack frame in this model is for "main". */
2574 const frame_region *frame0 = get_frame_at_index (0);
2575 gcc_assert (frame0);
2576 return id_equal (DECL_NAME (frame0->get_function ()->decl), "main");
2579 /* Subroutine of region_model::get_store_value for when REG is (or is within)
2580 a global variable that hasn't been touched since the start of this path
2581 (or was implicitly touched due to a call to an unknown function). */
2583 const svalue *
2584 region_model::get_initial_value_for_global (const region *reg) const
2586 /* Get the decl that REG is for (or is within). */
2587 const decl_region *base_reg
2588 = reg->get_base_region ()->dyn_cast_decl_region ();
2589 gcc_assert (base_reg);
2590 tree decl = base_reg->get_decl ();
2592 /* Special-case: to avoid having to explicitly update all previously
2593 untracked globals when calling an unknown fn, they implicitly have
2594 an unknown value if an unknown call has occurred, unless this is
2595 static to-this-TU and hasn't escaped. Globals that have escaped
2596 are explicitly tracked, so we shouldn't hit this case for them. */
2597 if (m_store.called_unknown_fn_p ()
2598 && TREE_PUBLIC (decl)
2599 && !TREE_READONLY (decl))
2600 return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
2602 /* If we are on a path from the entrypoint from "main" and we have a
2603 global decl defined in this TU that hasn't been touched yet, then
2604 the initial value of REG can be taken from the initialization value
2605 of the decl. */
2606 if (called_from_main_p () || TREE_READONLY (decl))
2607 return reg->get_initial_value_at_main (m_mgr);
2609 /* Otherwise, return INIT_VAL(REG). */
2610 return m_mgr->get_or_create_initial_value (reg);
2613 /* Get a value for REG, looking it up in the store, or otherwise falling
2614 back to "initial" or "unknown" values.
2615 Use CTXT to report any warnings associated with reading from REG. */
2617 const svalue *
2618 region_model::get_store_value (const region *reg,
2619 region_model_context *ctxt) const
2621 /* Getting the value of an empty region gives an unknown_svalue. */
2622 if (reg->empty_p ())
2623 return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
2625 bool check_poisoned = true;
2626 if (check_region_for_read (reg, ctxt))
2627 check_poisoned = false;
2629 /* Special-case: handle var_decls in the constant pool. */
2630 if (const decl_region *decl_reg = reg->dyn_cast_decl_region ())
2631 if (const svalue *sval = decl_reg->maybe_get_constant_value (m_mgr))
2632 return sval;
2634 const svalue *sval
2635 = m_store.get_any_binding (m_mgr->get_store_manager (), reg);
2636 if (sval)
2638 if (reg->get_type ())
2639 sval = m_mgr->get_or_create_cast (reg->get_type (), sval);
2640 return sval;
2643 /* Special-case: read at a constant index within a STRING_CST. */
2644 if (const offset_region *offset_reg = reg->dyn_cast_offset_region ())
2645 if (tree byte_offset_cst
2646 = offset_reg->get_byte_offset ()->maybe_get_constant ())
2647 if (const string_region *str_reg
2648 = reg->get_parent_region ()->dyn_cast_string_region ())
2650 tree string_cst = str_reg->get_string_cst ();
2651 if (const svalue *char_sval
2652 = m_mgr->maybe_get_char_from_string_cst (string_cst,
2653 byte_offset_cst))
2654 return m_mgr->get_or_create_cast (reg->get_type (), char_sval);
2657 /* Special-case: read the initial char of a STRING_CST. */
2658 if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
2659 if (const string_region *str_reg
2660 = cast_reg->get_original_region ()->dyn_cast_string_region ())
2662 tree string_cst = str_reg->get_string_cst ();
2663 tree byte_offset_cst = build_int_cst (integer_type_node, 0);
2664 if (const svalue *char_sval
2665 = m_mgr->maybe_get_char_from_string_cst (string_cst,
2666 byte_offset_cst))
2667 return m_mgr->get_or_create_cast (reg->get_type (), char_sval);
2670 /* Otherwise we implicitly have the initial value of the region
2671 (if the cluster had been touched, binding_cluster::get_any_binding,
2672 would have returned UNKNOWN, and we would already have returned
2673 that above). */
2675 /* Handle globals. */
2676 if (reg->get_base_region ()->get_parent_region ()->get_kind ()
2677 == RK_GLOBALS)
2678 return get_initial_value_for_global (reg);
2680 return m_mgr->get_or_create_initial_value (reg, check_poisoned);
2683 /* Return false if REG does not exist, true if it may do.
2684 This is for detecting regions within the stack that don't exist anymore
2685 after frames are popped. */
2687 bool
2688 region_model::region_exists_p (const region *reg) const
2690 /* If within a stack frame, check that the stack frame is live. */
2691 if (const frame_region *enclosing_frame = reg->maybe_get_frame_region ())
2693 /* Check that the current frame is the enclosing frame, or is called
2694 by it. */
2695 for (const frame_region *iter_frame = get_current_frame (); iter_frame;
2696 iter_frame = iter_frame->get_calling_frame ())
2697 if (iter_frame == enclosing_frame)
2698 return true;
2699 return false;
2702 return true;
2705 /* Get a region for referencing PTR_SVAL, creating a region if need be, and
2706 potentially generating warnings via CTXT.
2707 PTR_SVAL must be of pointer type.
2708 PTR_TREE if non-NULL can be used when emitting diagnostics. */
2710 const region *
2711 region_model::deref_rvalue (const svalue *ptr_sval, tree ptr_tree,
2712 region_model_context *ctxt,
2713 bool add_nonnull_constraint) const
2715 gcc_assert (ptr_sval);
2716 gcc_assert (POINTER_TYPE_P (ptr_sval->get_type ()));
2718 /* If we're dereferencing PTR_SVAL, assume that it is non-NULL; add this
2719 as a constraint. This suppresses false positives from
2720 -Wanalyzer-null-dereference for the case where we later have an
2721 if (PTR_SVAL) that would occur if we considered the false branch
2722 and transitioned the malloc state machine from start->null. */
2723 if (add_nonnull_constraint)
2725 tree null_ptr_cst = build_int_cst (ptr_sval->get_type (), 0);
2726 const svalue *null_ptr
2727 = m_mgr->get_or_create_constant_svalue (null_ptr_cst);
2728 m_constraints->add_constraint (ptr_sval, NE_EXPR, null_ptr);
2731 switch (ptr_sval->get_kind ())
2733 default:
2734 break;
2736 case SK_REGION:
2738 const region_svalue *region_sval
2739 = as_a <const region_svalue *> (ptr_sval);
2740 return region_sval->get_pointee ();
2743 case SK_BINOP:
2745 const binop_svalue *binop_sval
2746 = as_a <const binop_svalue *> (ptr_sval);
2747 switch (binop_sval->get_op ())
2749 case POINTER_PLUS_EXPR:
2751 /* If we have a symbolic value expressing pointer arithmentic,
2752 try to convert it to a suitable region. */
2753 const region *parent_region
2754 = deref_rvalue (binop_sval->get_arg0 (), NULL_TREE, ctxt);
2755 const svalue *offset = binop_sval->get_arg1 ();
2756 tree type= TREE_TYPE (ptr_sval->get_type ());
2757 return m_mgr->get_offset_region (parent_region, type, offset);
2759 default:
2760 break;
2763 break;
2765 case SK_POISONED:
2767 if (ctxt)
2769 tree ptr = get_representative_tree (ptr_sval);
2770 /* If we can't get a representative tree for PTR_SVAL
2771 (e.g. if it hasn't been bound into the store), then
2772 fall back on PTR_TREE, if non-NULL. */
2773 if (!ptr)
2774 ptr = ptr_tree;
2775 if (ptr)
2777 const poisoned_svalue *poisoned_sval
2778 = as_a <const poisoned_svalue *> (ptr_sval);
2779 enum poison_kind pkind = poisoned_sval->get_poison_kind ();
2780 ctxt->warn (::make_unique<poisoned_value_diagnostic>
2781 (ptr, pkind, nullptr, nullptr));
2785 break;
2788 return m_mgr->get_symbolic_region (ptr_sval);
2791 /* Attempt to get BITS within any value of REG, as TYPE.
2792 In particular, extract values from compound_svalues for the case
2793 where there's a concrete binding at BITS.
2794 Return an unknown svalue if we can't handle the given case.
2795 Use CTXT to report any warnings associated with reading from REG. */
2797 const svalue *
2798 region_model::get_rvalue_for_bits (tree type,
2799 const region *reg,
2800 const bit_range &bits,
2801 region_model_context *ctxt) const
2803 const svalue *sval = get_store_value (reg, ctxt);
2804 return m_mgr->get_or_create_bits_within (type, bits, sval);
2807 /* A subclass of pending_diagnostic for complaining about writes to
2808 constant regions of memory. */
2810 class write_to_const_diagnostic
2811 : public pending_diagnostic_subclass<write_to_const_diagnostic>
2813 public:
2814 write_to_const_diagnostic (const region *reg, tree decl)
2815 : m_reg (reg), m_decl (decl)
2818 const char *get_kind () const final override
2820 return "write_to_const_diagnostic";
2823 bool operator== (const write_to_const_diagnostic &other) const
2825 return (m_reg == other.m_reg
2826 && m_decl == other.m_decl);
2829 int get_controlling_option () const final override
2831 return OPT_Wanalyzer_write_to_const;
2834 bool emit (diagnostic_emission_context &ctxt) final override
2836 auto_diagnostic_group d;
2837 bool warned;
2838 switch (m_reg->get_kind ())
2840 default:
2841 warned = ctxt.warn ("write to %<const%> object %qE", m_decl);
2842 break;
2843 case RK_FUNCTION:
2844 warned = ctxt.warn ("write to function %qE", m_decl);
2845 break;
2846 case RK_LABEL:
2847 warned = ctxt.warn ("write to label %qE", m_decl);
2848 break;
2850 if (warned)
2851 inform (DECL_SOURCE_LOCATION (m_decl), "declared here");
2852 return warned;
2855 label_text describe_final_event (const evdesc::final_event &ev) final override
2857 switch (m_reg->get_kind ())
2859 default:
2860 return ev.formatted_print ("write to %<const%> object %qE here", m_decl);
2861 case RK_FUNCTION:
2862 return ev.formatted_print ("write to function %qE here", m_decl);
2863 case RK_LABEL:
2864 return ev.formatted_print ("write to label %qE here", m_decl);
2868 private:
2869 const region *m_reg;
2870 tree m_decl;
2873 /* A subclass of pending_diagnostic for complaining about writes to
2874 string literals. */
2876 class write_to_string_literal_diagnostic
2877 : public pending_diagnostic_subclass<write_to_string_literal_diagnostic>
2879 public:
2880 write_to_string_literal_diagnostic (const region *reg)
2881 : m_reg (reg)
2884 const char *get_kind () const final override
2886 return "write_to_string_literal_diagnostic";
2889 bool operator== (const write_to_string_literal_diagnostic &other) const
2891 return m_reg == other.m_reg;
2894 int get_controlling_option () const final override
2896 return OPT_Wanalyzer_write_to_string_literal;
2899 bool emit (diagnostic_emission_context &ctxt) final override
2901 return ctxt.warn ("write to string literal");
2902 /* Ideally we would show the location of the STRING_CST as well,
2903 but it is not available at this point. */
2906 label_text describe_final_event (const evdesc::final_event &ev) final override
2908 return ev.formatted_print ("write to string literal here");
2911 private:
2912 const region *m_reg;
2915 /* Use CTXT to warn If DEST_REG is a region that shouldn't be written to. */
2917 void
2918 region_model::check_for_writable_region (const region* dest_reg,
2919 region_model_context *ctxt) const
2921 /* Fail gracefully if CTXT is NULL. */
2922 if (!ctxt)
2923 return;
2925 const region *base_reg = dest_reg->get_base_region ();
2926 switch (base_reg->get_kind ())
2928 default:
2929 break;
2930 case RK_FUNCTION:
2932 const function_region *func_reg = as_a <const function_region *> (base_reg);
2933 tree fndecl = func_reg->get_fndecl ();
2934 ctxt->warn (make_unique<write_to_const_diagnostic>
2935 (func_reg, fndecl));
2937 break;
2938 case RK_LABEL:
2940 const label_region *label_reg = as_a <const label_region *> (base_reg);
2941 tree label = label_reg->get_label ();
2942 ctxt->warn (make_unique<write_to_const_diagnostic>
2943 (label_reg, label));
2945 break;
2946 case RK_DECL:
2948 const decl_region *decl_reg = as_a <const decl_region *> (base_reg);
2949 tree decl = decl_reg->get_decl ();
2950 /* Warn about writes to const globals.
2951 Don't warn for writes to const locals, and params in particular,
2952 since we would warn in push_frame when setting them up (e.g the
2953 "this" param is "T* const"). */
2954 if (TREE_READONLY (decl)
2955 && is_global_var (decl))
2956 ctxt->warn (make_unique<write_to_const_diagnostic> (dest_reg, decl));
2958 break;
2959 case RK_STRING:
2960 ctxt->warn (make_unique<write_to_string_literal_diagnostic> (dest_reg));
2961 break;
2965 /* Get the capacity of REG in bytes. */
2967 const svalue *
2968 region_model::get_capacity (const region *reg) const
2970 switch (reg->get_kind ())
2972 default:
2973 break;
2974 case RK_DECL:
2976 const decl_region *decl_reg = as_a <const decl_region *> (reg);
2977 tree decl = decl_reg->get_decl ();
2978 if (TREE_CODE (decl) == SSA_NAME)
2980 tree type = TREE_TYPE (decl);
2981 tree size = TYPE_SIZE (type);
2982 return get_rvalue (size, NULL);
2984 else
2986 tree size = decl_init_size (decl, false);
2987 if (size)
2988 return get_rvalue (size, NULL);
2991 break;
2992 case RK_SIZED:
2993 /* Look through sized regions to get at the capacity
2994 of the underlying regions. */
2995 return get_capacity (reg->get_parent_region ());
2996 case RK_STRING:
2998 /* "Capacity" here means "size". */
2999 const string_region *string_reg = as_a <const string_region *> (reg);
3000 tree string_cst = string_reg->get_string_cst ();
3001 return m_mgr->get_or_create_int_cst (size_type_node,
3002 TREE_STRING_LENGTH (string_cst));
3004 break;
3007 if (const svalue *recorded = get_dynamic_extents (reg))
3008 return recorded;
3010 return m_mgr->get_or_create_unknown_svalue (sizetype);
3013 /* If CTXT is non-NULL, use it to warn about any problems accessing REG,
3014 using DIR to determine if this access is a read or write.
3015 Return TRUE if an OOB access was detected.
3016 If SVAL_HINT is non-NULL, use it as a hint in diagnostics
3017 about the value that would be written to REG. */
3019 bool
3020 region_model::check_region_access (const region *reg,
3021 enum access_direction dir,
3022 const svalue *sval_hint,
3023 region_model_context *ctxt) const
3025 /* Fail gracefully if CTXT is NULL. */
3026 if (!ctxt)
3027 return false;
3029 bool oob_access_detected = false;
3030 check_region_for_taint (reg, dir, ctxt);
3031 if (!check_region_bounds (reg, dir, sval_hint, ctxt))
3032 oob_access_detected = true;
3034 switch (dir)
3036 default:
3037 gcc_unreachable ();
3038 case DIR_READ:
3039 /* Currently a no-op. */
3040 break;
3041 case DIR_WRITE:
3042 check_for_writable_region (reg, ctxt);
3043 break;
3045 return oob_access_detected;
3048 /* If CTXT is non-NULL, use it to warn about any problems writing to REG. */
3050 void
3051 region_model::check_region_for_write (const region *dest_reg,
3052 const svalue *sval_hint,
3053 region_model_context *ctxt) const
3055 check_region_access (dest_reg, DIR_WRITE, sval_hint, ctxt);
3058 /* If CTXT is non-NULL, use it to warn about any problems reading from REG.
3059 Returns TRUE if an OOB read was detected. */
3061 bool
3062 region_model::check_region_for_read (const region *src_reg,
3063 region_model_context *ctxt) const
3065 return check_region_access (src_reg, DIR_READ, NULL, ctxt);
3068 /* Concrete subclass for casts of pointers that lead to trailing bytes. */
3070 class dubious_allocation_size
3071 : public pending_diagnostic_subclass<dubious_allocation_size>
3073 public:
3074 dubious_allocation_size (const region *lhs, const region *rhs,
3075 const gimple *stmt)
3076 : m_lhs (lhs), m_rhs (rhs), m_expr (NULL_TREE), m_stmt (stmt),
3077 m_has_allocation_event (false)
3080 dubious_allocation_size (const region *lhs, const region *rhs,
3081 tree expr, const gimple *stmt)
3082 : m_lhs (lhs), m_rhs (rhs), m_expr (expr), m_stmt (stmt),
3083 m_has_allocation_event (false)
3086 const char *get_kind () const final override
3088 return "dubious_allocation_size";
3091 bool operator== (const dubious_allocation_size &other) const
3093 return (m_stmt == other.m_stmt
3094 && pending_diagnostic::same_tree_p (m_expr, other.m_expr));
3097 int get_controlling_option () const final override
3099 return OPT_Wanalyzer_allocation_size;
3102 bool emit (diagnostic_emission_context &ctxt) final override
3104 ctxt.add_cwe (131);
3106 return ctxt.warn ("allocated buffer size is not a multiple"
3107 " of the pointee's size");
3110 label_text describe_final_event (const evdesc::final_event &ev) final
3111 override
3113 tree pointee_type = TREE_TYPE (m_lhs->get_type ());
3114 if (m_has_allocation_event)
3115 return ev.formatted_print ("assigned to %qT here;"
3116 " %<sizeof (%T)%> is %qE",
3117 m_lhs->get_type (), pointee_type,
3118 size_in_bytes (pointee_type));
3119 /* Fallback: Typically, we should always see an allocation_event
3120 before. */
3121 if (m_expr)
3123 if (TREE_CODE (m_expr) == INTEGER_CST)
3124 return ev.formatted_print ("allocated %E 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));
3128 else
3129 return ev.formatted_print ("allocated %qE bytes and assigned to"
3130 " %qT here; %<sizeof (%T)%> is %qE",
3131 m_expr, m_lhs->get_type (), pointee_type,
3132 size_in_bytes (pointee_type));
3135 return ev.formatted_print ("allocated and assigned to %qT here;"
3136 " %<sizeof (%T)%> is %qE",
3137 m_lhs->get_type (), pointee_type,
3138 size_in_bytes (pointee_type));
3141 void
3142 add_region_creation_events (const region *,
3143 tree capacity,
3144 const event_loc_info &loc_info,
3145 checker_path &emission_path) final override
3147 emission_path.add_event
3148 (make_unique<region_creation_event_allocation_size> (capacity, loc_info));
3150 m_has_allocation_event = true;
3153 void mark_interesting_stuff (interesting_t *interest) final override
3155 interest->add_region_creation (m_rhs);
3158 private:
3159 const region *m_lhs;
3160 const region *m_rhs;
3161 const tree m_expr;
3162 const gimple *m_stmt;
3163 bool m_has_allocation_event;
3166 /* Return true on dubious allocation sizes for constant sizes. */
3168 static bool
3169 capacity_compatible_with_type (tree cst, tree pointee_size_tree,
3170 bool is_struct)
3172 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
3173 gcc_assert (TREE_CODE (pointee_size_tree) == INTEGER_CST);
3175 unsigned HOST_WIDE_INT pointee_size = TREE_INT_CST_LOW (pointee_size_tree);
3176 unsigned HOST_WIDE_INT alloc_size = TREE_INT_CST_LOW (cst);
3178 if (is_struct)
3179 return alloc_size == 0 || alloc_size >= pointee_size;
3180 return alloc_size % pointee_size == 0;
3183 static bool
3184 capacity_compatible_with_type (tree cst, tree pointee_size_tree)
3186 return capacity_compatible_with_type (cst, pointee_size_tree, false);
3189 /* Checks whether SVAL could be a multiple of SIZE_CST.
3191 It works by visiting all svalues inside SVAL until it reaches
3192 atomic nodes. From those, it goes back up again and adds each
3193 node that is not a multiple of SIZE_CST to the RESULT_SET. */
3195 class size_visitor : public visitor
3197 public:
3198 size_visitor (tree size_cst, const svalue *root_sval, constraint_manager *cm)
3199 : m_size_cst (size_cst), m_root_sval (root_sval), m_cm (cm)
3201 m_root_sval->accept (this);
3204 bool is_dubious_capacity ()
3206 return result_set.contains (m_root_sval);
3209 void visit_constant_svalue (const constant_svalue *sval) final override
3211 check_constant (sval->get_constant (), sval);
3214 void visit_unaryop_svalue (const unaryop_svalue *sval) final override
3216 if (CONVERT_EXPR_CODE_P (sval->get_op ())
3217 && result_set.contains (sval->get_arg ()))
3218 result_set.add (sval);
3221 void visit_binop_svalue (const binop_svalue *sval) final override
3223 const svalue *arg0 = sval->get_arg0 ();
3224 const svalue *arg1 = sval->get_arg1 ();
3226 switch (sval->get_op ())
3228 case MULT_EXPR:
3229 if (result_set.contains (arg0) && result_set.contains (arg1))
3230 result_set.add (sval);
3231 break;
3232 case PLUS_EXPR:
3233 case MINUS_EXPR:
3234 if (result_set.contains (arg0) || result_set.contains (arg1))
3235 result_set.add (sval);
3236 break;
3237 default:
3238 break;
3242 void visit_unmergeable_svalue (const unmergeable_svalue *sval) final override
3244 if (result_set.contains (sval->get_arg ()))
3245 result_set.add (sval);
3248 void visit_widening_svalue (const widening_svalue *sval) final override
3250 const svalue *base = sval->get_base_svalue ();
3251 const svalue *iter = sval->get_iter_svalue ();
3253 if (result_set.contains (base) || result_set.contains (iter))
3254 result_set.add (sval);
3257 void visit_initial_svalue (const initial_svalue *sval) final override
3259 equiv_class_id id = equiv_class_id::null ();
3260 if (m_cm->get_equiv_class_by_svalue (sval, &id))
3262 if (tree cst = id.get_obj (*m_cm).get_any_constant ())
3263 check_constant (cst, sval);
3265 else if (!m_cm->sval_constrained_p (sval))
3267 result_set.add (sval);
3271 void visit_conjured_svalue (const conjured_svalue *sval) final override
3273 equiv_class_id id = equiv_class_id::null ();
3274 if (m_cm->get_equiv_class_by_svalue (sval, &id))
3275 if (tree cst = id.get_obj (*m_cm).get_any_constant ())
3276 check_constant (cst, sval);
3279 private:
3280 void check_constant (tree cst, const svalue *sval)
3282 switch (TREE_CODE (cst))
3284 default:
3285 /* Assume all unhandled operands are compatible. */
3286 break;
3287 case INTEGER_CST:
3288 if (!capacity_compatible_with_type (cst, m_size_cst))
3289 result_set.add (sval);
3290 break;
3294 tree m_size_cst;
3295 const svalue *m_root_sval;
3296 constraint_manager *m_cm;
3297 svalue_set result_set; /* Used as a mapping of svalue*->bool. */
3300 /* Return true if a struct or union either uses the inheritance pattern,
3301 where the first field is a base struct, or the flexible array member
3302 pattern, where the last field is an array without a specified size. */
3304 static bool
3305 struct_or_union_with_inheritance_p (tree struc)
3307 tree iter = TYPE_FIELDS (struc);
3308 if (iter == NULL_TREE)
3309 return false;
3310 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (iter)))
3311 return true;
3313 tree last_field;
3314 while (iter != NULL_TREE)
3316 last_field = iter;
3317 iter = DECL_CHAIN (iter);
3320 if (last_field != NULL_TREE
3321 && TREE_CODE (TREE_TYPE (last_field)) == ARRAY_TYPE)
3322 return true;
3324 return false;
3327 /* Return true if the lhs and rhs of an assignment have different types. */
3329 static bool
3330 is_any_cast_p (const gimple *stmt)
3332 if (const gassign *assign = dyn_cast <const gassign *> (stmt))
3333 return gimple_assign_cast_p (assign)
3334 || !pending_diagnostic::same_tree_p (
3335 TREE_TYPE (gimple_assign_lhs (assign)),
3336 TREE_TYPE (gimple_assign_rhs1 (assign)));
3337 else if (const gcall *call = dyn_cast <const gcall *> (stmt))
3339 tree lhs = gimple_call_lhs (call);
3340 return lhs != NULL_TREE && !pending_diagnostic::same_tree_p (
3341 TREE_TYPE (gimple_call_lhs (call)),
3342 gimple_call_return_type (call));
3345 return false;
3348 /* On pointer assignments, check whether the buffer size of
3349 RHS_SVAL is compatible with the type of the LHS_REG.
3350 Use a non-null CTXT to report allocation size warnings. */
3352 void
3353 region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval,
3354 region_model_context *ctxt) const
3356 if (!ctxt || ctxt->get_stmt () == NULL)
3357 return;
3358 /* Only report warnings on assignments that actually change the type. */
3359 if (!is_any_cast_p (ctxt->get_stmt ()))
3360 return;
3362 tree pointer_type = lhs_reg->get_type ();
3363 if (pointer_type == NULL_TREE || !POINTER_TYPE_P (pointer_type))
3364 return;
3366 tree pointee_type = TREE_TYPE (pointer_type);
3367 /* Make sure that the type on the left-hand size actually has a size. */
3368 if (pointee_type == NULL_TREE || VOID_TYPE_P (pointee_type)
3369 || TYPE_SIZE_UNIT (pointee_type) == NULL_TREE)
3370 return;
3372 /* Bail out early on pointers to structs where we can
3373 not deduce whether the buffer size is compatible. */
3374 bool is_struct = RECORD_OR_UNION_TYPE_P (pointee_type);
3375 if (is_struct && struct_or_union_with_inheritance_p (pointee_type))
3376 return;
3378 tree pointee_size_tree = size_in_bytes (pointee_type);
3379 /* We give up if the type size is not known at compile-time or the
3380 type size is always compatible regardless of the buffer size. */
3381 if (TREE_CODE (pointee_size_tree) != INTEGER_CST
3382 || integer_zerop (pointee_size_tree)
3383 || integer_onep (pointee_size_tree))
3384 return;
3386 const region *rhs_reg = deref_rvalue (rhs_sval, NULL_TREE, ctxt, false);
3387 const svalue *capacity = get_capacity (rhs_reg);
3388 switch (capacity->get_kind ())
3390 case svalue_kind::SK_CONSTANT:
3392 const constant_svalue *cst_cap_sval
3393 = as_a <const constant_svalue *> (capacity);
3394 tree cst_cap = cst_cap_sval->get_constant ();
3395 if (TREE_CODE (cst_cap) == INTEGER_CST
3396 && !capacity_compatible_with_type (cst_cap, pointee_size_tree,
3397 is_struct))
3398 ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg, rhs_reg,
3399 cst_cap,
3400 ctxt->get_stmt ()));
3402 break;
3403 default:
3405 if (!is_struct)
3407 size_visitor v (pointee_size_tree, capacity, m_constraints);
3408 if (v.is_dubious_capacity ())
3410 tree expr = get_representative_tree (capacity);
3411 ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg,
3412 rhs_reg,
3413 expr,
3414 ctxt->get_stmt ()));
3417 break;
3422 /* Set the value of the region given by LHS_REG to the value given
3423 by RHS_SVAL.
3424 Use CTXT to report any warnings associated with writing to LHS_REG. */
3426 void
3427 region_model::set_value (const region *lhs_reg, const svalue *rhs_sval,
3428 region_model_context *ctxt)
3430 gcc_assert (lhs_reg);
3431 gcc_assert (rhs_sval);
3433 /* Setting the value of an empty region is a no-op. */
3434 if (lhs_reg->empty_p ())
3435 return;
3437 check_region_size (lhs_reg, rhs_sval, ctxt);
3439 check_region_for_write (lhs_reg, rhs_sval, ctxt);
3441 m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
3442 ctxt ? ctxt->get_uncertainty () : NULL);
3445 /* Set the value of the region given by LHS to the value given by RHS. */
3447 void
3448 region_model::set_value (tree lhs, tree rhs, region_model_context *ctxt)
3450 const region *lhs_reg = get_lvalue (lhs, ctxt);
3451 const svalue *rhs_sval = get_rvalue (rhs, ctxt);
3452 gcc_assert (lhs_reg);
3453 gcc_assert (rhs_sval);
3454 set_value (lhs_reg, rhs_sval, ctxt);
3457 /* Issue a note specifying that a particular function parameter is expected
3458 to be a valid null-terminated string. */
3460 static void
3461 inform_about_expected_null_terminated_string_arg (const call_arg_details &ad)
3463 // TODO: ideally we'd underline the param here
3464 inform (DECL_SOURCE_LOCATION (ad.m_called_fndecl),
3465 "argument %d of %qD must be a pointer to a null-terminated string",
3466 ad.m_arg_idx + 1, ad.m_called_fndecl);
3469 /* A binding of a specific svalue at a concrete byte range. */
3471 struct fragment
3473 fragment ()
3474 : m_byte_range (0, 0), m_sval (nullptr)
3478 fragment (const byte_range &bytes, const svalue *sval)
3479 : m_byte_range (bytes), m_sval (sval)
3483 static int cmp_ptrs (const void *p1, const void *p2)
3485 const fragment *f1 = (const fragment *)p1;
3486 const fragment *f2 = (const fragment *)p2;
3487 return byte_range::cmp (f1->m_byte_range, f2->m_byte_range);
3490 /* Determine if there is a zero terminator somewhere in the
3491 bytes of this fragment, starting at START_READ_OFFSET (which
3492 is absolute to the start of the cluster as a whole), and stopping
3493 at the end of this fragment.
3495 Return a tristate:
3496 - true if there definitely is a zero byte, writing to *OUT_BYTES_READ
3497 the number of bytes from that would be read, including the zero byte.
3498 - false if there definitely isn't a zero byte
3499 - unknown if we don't know. */
3500 tristate has_null_terminator (byte_offset_t start_read_offset,
3501 byte_offset_t *out_bytes_read) const
3503 byte_offset_t rel_start_read_offset
3504 = start_read_offset - m_byte_range.get_start_byte_offset ();
3505 gcc_assert (rel_start_read_offset >= 0);
3506 byte_offset_t available_bytes
3507 = (m_byte_range.get_next_byte_offset () - start_read_offset);
3508 gcc_assert (available_bytes >= 0);
3510 if (rel_start_read_offset > INT_MAX)
3511 return tristate::TS_UNKNOWN;
3512 HOST_WIDE_INT rel_start_read_offset_hwi = rel_start_read_offset.slow ();
3514 if (available_bytes > INT_MAX)
3515 return tristate::TS_UNKNOWN;
3516 HOST_WIDE_INT available_bytes_hwi = available_bytes.slow ();
3518 switch (m_sval->get_kind ())
3520 case SK_CONSTANT:
3522 tree cst
3523 = as_a <const constant_svalue *> (m_sval)->get_constant ();
3524 switch (TREE_CODE (cst))
3526 case STRING_CST:
3527 return string_cst_has_null_terminator (cst,
3528 rel_start_read_offset_hwi,
3529 available_bytes_hwi,
3530 out_bytes_read);
3531 case INTEGER_CST:
3532 if (rel_start_read_offset_hwi == 0
3533 && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (cst))))
3535 /* Model accesses to the initial byte of a 1-byte
3536 INTEGER_CST. */
3537 if (zerop (cst))
3539 *out_bytes_read = 1;
3540 return tristate (true);
3542 else
3544 *out_bytes_read = available_bytes;
3545 return tristate (false);
3548 /* Treat any other access to an INTEGER_CST as unknown. */
3549 return tristate::TS_UNKNOWN;
3551 default:
3552 gcc_unreachable ();
3553 break;
3556 break;
3558 case SK_INITIAL:
3560 const initial_svalue *initial_sval = (const initial_svalue *)m_sval;
3561 const region *reg = initial_sval->get_region ();
3562 if (const string_region *string_reg = reg->dyn_cast_string_region ())
3564 tree string_cst = string_reg->get_string_cst ();
3565 return string_cst_has_null_terminator (string_cst,
3566 rel_start_read_offset_hwi,
3567 available_bytes_hwi,
3568 out_bytes_read);
3570 return tristate::TS_UNKNOWN;
3572 break;
3574 case SK_BITS_WITHIN:
3576 const bits_within_svalue *bits_within_sval
3577 = (const bits_within_svalue *)m_sval;
3578 byte_range bytes (0, 0);
3579 if (bits_within_sval->get_bits ().as_byte_range (&bytes))
3581 const svalue *inner_sval = bits_within_sval->get_inner_svalue ();
3582 fragment f (byte_range
3583 (start_read_offset - bytes.get_start_bit_offset (),
3584 std::max<byte_size_t> (bytes.m_size_in_bytes,
3585 available_bytes)),
3586 inner_sval);
3587 return f.has_null_terminator (start_read_offset, out_bytes_read);
3590 break;
3592 default:
3593 // TODO: it may be possible to handle other cases here.
3594 break;
3596 return tristate::TS_UNKNOWN;
3599 static tristate
3600 string_cst_has_null_terminator (tree string_cst,
3601 HOST_WIDE_INT rel_start_read_offset_hwi,
3602 HOST_WIDE_INT available_bytes_hwi,
3603 byte_offset_t *out_bytes_read)
3605 /* Look for the first 0 byte within STRING_CST
3606 from START_READ_OFFSET onwards. */
3607 const HOST_WIDE_INT num_bytes_to_search
3608 = std::min<HOST_WIDE_INT> ((TREE_STRING_LENGTH (string_cst)
3609 - rel_start_read_offset_hwi),
3610 available_bytes_hwi);
3611 const char *start = (TREE_STRING_POINTER (string_cst)
3612 + rel_start_read_offset_hwi);
3613 if (num_bytes_to_search >= 0)
3614 if (const void *p = memchr (start, 0,
3615 num_bytes_to_search))
3617 *out_bytes_read = (const char *)p - start + 1;
3618 return tristate (true);
3621 *out_bytes_read = available_bytes_hwi;
3622 return tristate (false);
3625 byte_range m_byte_range;
3626 const svalue *m_sval;
3629 /* A frozen copy of a single base region's binding_cluster within a store,
3630 optimized for traversal of the concrete parts in byte order.
3631 This only captures concrete bindings, and is an implementation detail
3632 of region_model::scan_for_null_terminator. */
3634 class iterable_cluster
3636 public:
3637 iterable_cluster (const binding_cluster *cluster)
3639 if (!cluster)
3640 return;
3641 for (auto iter : *cluster)
3643 const binding_key *key = iter.first;
3644 const svalue *sval = iter.second;
3646 if (const concrete_binding *concrete_key
3647 = key->dyn_cast_concrete_binding ())
3649 byte_range fragment_bytes (0, 0);
3650 if (concrete_key->get_byte_range (&fragment_bytes))
3651 m_fragments.safe_push (fragment (fragment_bytes, sval));
3653 else
3654 m_symbolic_bindings.safe_push (key);
3656 m_fragments.qsort (fragment::cmp_ptrs);
3659 bool
3660 get_fragment_for_byte (byte_offset_t byte, fragment *out_frag) const
3662 /* TODO: binary search rather than linear. */
3663 unsigned iter_idx;
3664 for (iter_idx = 0; iter_idx < m_fragments.length (); iter_idx++)
3666 if (m_fragments[iter_idx].m_byte_range.contains_p (byte))
3668 *out_frag = m_fragments[iter_idx];
3669 return true;
3672 return false;
3675 bool has_symbolic_bindings_p () const
3677 return !m_symbolic_bindings.is_empty ();
3680 private:
3681 auto_vec<fragment> m_fragments;
3682 auto_vec<const binding_key *> m_symbolic_bindings;
3685 /* Simulate reading the bytes at BYTES from BASE_REG.
3686 Complain to CTXT about any issues with the read e.g. out-of-bounds. */
3688 const svalue *
3689 region_model::get_store_bytes (const region *base_reg,
3690 const byte_range &bytes,
3691 region_model_context *ctxt) const
3693 /* Shortcut reading all of a string_region. */
3694 if (bytes.get_start_byte_offset () == 0)
3695 if (const string_region *string_reg = base_reg->dyn_cast_string_region ())
3696 if (bytes.m_size_in_bytes
3697 == TREE_STRING_LENGTH (string_reg->get_string_cst ()))
3698 return m_mgr->get_or_create_initial_value (base_reg);
3700 const svalue *index_sval
3701 = m_mgr->get_or_create_int_cst (size_type_node,
3702 bytes.get_start_byte_offset ());
3703 const region *offset_reg = m_mgr->get_offset_region (base_reg,
3704 NULL_TREE,
3705 index_sval);
3706 const svalue *byte_size_sval
3707 = m_mgr->get_or_create_int_cst (size_type_node, bytes.m_size_in_bytes);
3708 const region *read_reg = m_mgr->get_sized_region (offset_reg,
3709 NULL_TREE,
3710 byte_size_sval);
3712 /* Simulate reading those bytes from the store. */
3713 const svalue *sval = get_store_value (read_reg, ctxt);
3714 return sval;
3717 static tree
3718 get_tree_for_byte_offset (tree ptr_expr, byte_offset_t byte_offset)
3720 gcc_assert (ptr_expr);
3721 return fold_build2 (MEM_REF,
3722 char_type_node,
3723 ptr_expr, wide_int_to_tree (size_type_node, byte_offset));
3726 /* Simulate a series of reads of REG until we find a 0 byte
3727 (equivalent to calling strlen).
3729 Complain to CTXT and return NULL if:
3730 - the buffer pointed to isn't null-terminated
3731 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3732 - any of the reads aren't within the bounds of the underlying base region
3734 Otherwise, return a svalue for the number of bytes read (strlen + 1),
3735 and, if OUT_SVAL is non-NULL, write to *OUT_SVAL with an svalue
3736 representing the content of REG up to and including the terminator.
3738 Algorithm
3739 =========
3741 Get offset for first byte to read.
3742 Find the binding (if any) that contains it.
3743 Find the size in bits of that binding.
3744 Round to the nearest byte (which way???)
3745 Or maybe give up if we have a partial binding there.
3746 Get the svalue from the binding.
3747 Determine the strlen (if any) of that svalue.
3748 Does it have a 0-terminator within it?
3749 If so, we have a partial read up to and including that terminator
3750 Read those bytes from the store; add to the result in the correct place.
3751 Finish
3752 If not, we have a full read of that svalue
3753 Read those bytes from the store; add to the result in the correct place.
3754 Update read/write offsets
3755 Continue
3756 If unknown:
3757 Result is unknown
3758 Finish
3761 const svalue *
3762 region_model::scan_for_null_terminator (const region *reg,
3763 tree expr,
3764 const svalue **out_sval,
3765 region_model_context *ctxt) const
3767 store_manager *store_mgr = m_mgr->get_store_manager ();
3769 region_offset offset = reg->get_offset (m_mgr);
3770 if (offset.symbolic_p ())
3772 if (out_sval)
3773 *out_sval = get_store_value (reg, nullptr);
3774 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3776 byte_offset_t src_byte_offset;
3777 if (!offset.get_concrete_byte_offset (&src_byte_offset))
3779 if (out_sval)
3780 *out_sval = get_store_value (reg, nullptr);
3781 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3783 const byte_offset_t initial_src_byte_offset = src_byte_offset;
3784 byte_offset_t dst_byte_offset = 0;
3786 const region *base_reg = reg->get_base_region ();
3788 if (const string_region *str_reg = base_reg->dyn_cast_string_region ())
3790 tree string_cst = str_reg->get_string_cst ();
3791 if (const void *p = memchr (TREE_STRING_POINTER (string_cst),
3793 TREE_STRING_LENGTH (string_cst)))
3795 size_t num_bytes_read
3796 = (const char *)p - TREE_STRING_POINTER (string_cst) + 1;
3797 /* Simulate the read. */
3798 byte_range bytes_to_read (0, num_bytes_read);
3799 const svalue *sval = get_store_bytes (reg, bytes_to_read, ctxt);
3800 if (out_sval)
3801 *out_sval = sval;
3802 return m_mgr->get_or_create_int_cst (size_type_node,
3803 num_bytes_read);
3807 const binding_cluster *cluster = m_store.get_cluster (base_reg);
3808 iterable_cluster c (cluster);
3809 binding_map result;
3811 while (1)
3813 fragment f;
3814 if (c.get_fragment_for_byte (src_byte_offset, &f))
3816 byte_offset_t fragment_bytes_read;
3817 tristate is_terminated
3818 = f.has_null_terminator (src_byte_offset, &fragment_bytes_read);
3819 if (is_terminated.is_unknown ())
3821 if (out_sval)
3822 *out_sval = get_store_value (reg, nullptr);
3823 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3826 /* Simulate reading those bytes from the store. */
3827 byte_range bytes_to_read (src_byte_offset, fragment_bytes_read);
3828 const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
3829 check_for_poison (sval, expr, nullptr, ctxt);
3831 if (out_sval)
3833 byte_range bytes_to_write (dst_byte_offset, fragment_bytes_read);
3834 const binding_key *key
3835 = store_mgr->get_concrete_binding (bytes_to_write);
3836 result.put (key, sval);
3839 src_byte_offset += fragment_bytes_read;
3840 dst_byte_offset += fragment_bytes_read;
3842 if (is_terminated.is_true ())
3844 if (out_sval)
3845 *out_sval = m_mgr->get_or_create_compound_svalue (NULL_TREE,
3846 result);
3847 return m_mgr->get_or_create_int_cst (size_type_node,
3848 dst_byte_offset);
3851 else
3852 break;
3855 /* No binding for this base_region, or no binding at src_byte_offset
3856 (or a symbolic binding). */
3858 if (c.has_symbolic_bindings_p ())
3860 if (out_sval)
3861 *out_sval = get_store_value (reg, nullptr);
3862 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3865 /* TODO: the various special-cases seen in
3866 region_model::get_store_value. */
3868 /* Simulate reading from this byte, then give up. */
3869 byte_range bytes_to_read (src_byte_offset, 1);
3870 const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
3871 tree byte_expr
3872 = (expr
3873 ? get_tree_for_byte_offset (expr,
3874 src_byte_offset - initial_src_byte_offset)
3875 : NULL_TREE);
3876 check_for_poison (sval, byte_expr, nullptr, ctxt);
3877 if (base_reg->can_have_initial_svalue_p ())
3879 if (out_sval)
3880 *out_sval = get_store_value (reg, nullptr);
3881 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3883 else
3884 return nullptr;
3887 /* Check that argument ARG_IDX (0-based) to the call described by CD
3888 is a pointer to a valid null-terminated string.
3890 Simulate scanning through the buffer, reading until we find a 0 byte
3891 (equivalent to calling strlen).
3893 Complain and return NULL if:
3894 - the buffer pointed to isn't null-terminated
3895 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3896 - any of the reads aren't within the bounds of the underlying base region
3898 Otherwise, return a svalue for strlen of the buffer (*not* including
3899 the null terminator).
3901 TODO: we should also complain if:
3902 - the pointer is NULL (or could be). */
3904 const svalue *
3905 region_model::check_for_null_terminated_string_arg (const call_details &cd,
3906 unsigned arg_idx) const
3908 return check_for_null_terminated_string_arg (cd,
3909 arg_idx,
3910 false, /* include_terminator */
3911 nullptr); // out_sval
3915 /* Check that argument ARG_IDX (0-based) to the call described by CD
3916 is a pointer to a valid null-terminated string.
3918 Simulate scanning through the buffer, reading until we find a 0 byte
3919 (equivalent to calling strlen).
3921 Complain and return NULL if:
3922 - the buffer pointed to isn't null-terminated
3923 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3924 - any of the reads aren't within the bounds of the underlying base region
3926 Otherwise, return a svalue. This will be the number of bytes read
3927 (including the null terminator) if INCLUDE_TERMINATOR is true, or strlen
3928 of the buffer (not including the null terminator) if it is false.
3930 Also, when returning an svalue, if OUT_SVAL is non-NULL, write to
3931 *OUT_SVAL with an svalue representing the content of the buffer up to
3932 and including the terminator.
3934 TODO: we should also complain if:
3935 - the pointer is NULL (or could be). */
3937 const svalue *
3938 region_model::check_for_null_terminated_string_arg (const call_details &cd,
3939 unsigned arg_idx,
3940 bool include_terminator,
3941 const svalue **out_sval) const
3943 class null_terminator_check_event : public custom_event
3945 public:
3946 null_terminator_check_event (const event_loc_info &loc_info,
3947 const call_arg_details &arg_details)
3948 : custom_event (loc_info),
3949 m_arg_details (arg_details)
3953 label_text get_desc (bool can_colorize) const final override
3955 if (m_arg_details.m_arg_expr)
3956 return make_label_text (can_colorize,
3957 "while looking for null terminator"
3958 " for argument %i (%qE) of %qD...",
3959 m_arg_details.m_arg_idx + 1,
3960 m_arg_details.m_arg_expr,
3961 m_arg_details.m_called_fndecl);
3962 else
3963 return make_label_text (can_colorize,
3964 "while looking for null terminator"
3965 " for argument %i of %qD...",
3966 m_arg_details.m_arg_idx + 1,
3967 m_arg_details.m_called_fndecl);
3970 private:
3971 const call_arg_details m_arg_details;
3974 class null_terminator_check_decl_note
3975 : public pending_note_subclass<null_terminator_check_decl_note>
3977 public:
3978 null_terminator_check_decl_note (const call_arg_details &arg_details)
3979 : m_arg_details (arg_details)
3983 const char *get_kind () const final override
3985 return "null_terminator_check_decl_note";
3988 void emit () const final override
3990 inform_about_expected_null_terminated_string_arg (m_arg_details);
3993 bool operator== (const null_terminator_check_decl_note &other) const
3995 return m_arg_details == other.m_arg_details;
3998 private:
3999 const call_arg_details m_arg_details;
4002 /* Subclass of decorated_region_model_context that
4003 adds the above event and note to any saved diagnostics. */
4004 class annotating_ctxt : public annotating_context
4006 public:
4007 annotating_ctxt (const call_details &cd,
4008 unsigned arg_idx)
4009 : annotating_context (cd.get_ctxt ()),
4010 m_cd (cd),
4011 m_arg_idx (arg_idx)
4014 void add_annotations () final override
4016 call_arg_details arg_details (m_cd, m_arg_idx);
4017 event_loc_info loc_info (m_cd.get_location (),
4018 m_cd.get_model ()->get_current_function ()->decl,
4019 m_cd.get_model ()->get_stack_depth ());
4021 add_event (make_unique<null_terminator_check_event> (loc_info,
4022 arg_details));
4023 add_note (make_unique <null_terminator_check_decl_note> (arg_details));
4025 private:
4026 const call_details &m_cd;
4027 unsigned m_arg_idx;
4030 /* Use this ctxt below so that any diagnostics that get added
4031 get annotated. */
4032 annotating_ctxt my_ctxt (cd, arg_idx);
4034 const svalue *arg_sval = cd.get_arg_svalue (arg_idx);
4035 const region *buf_reg
4036 = deref_rvalue (arg_sval, cd.get_arg_tree (arg_idx), &my_ctxt);
4038 if (const svalue *num_bytes_read_sval
4039 = scan_for_null_terminator (buf_reg,
4040 cd.get_arg_tree (arg_idx),
4041 out_sval,
4042 &my_ctxt))
4044 if (include_terminator)
4045 return num_bytes_read_sval;
4046 else
4048 /* strlen is (bytes_read - 1). */
4049 const svalue *one = m_mgr->get_or_create_int_cst (size_type_node, 1);
4050 return m_mgr->get_or_create_binop (size_type_node,
4051 MINUS_EXPR,
4052 num_bytes_read_sval,
4053 one);
4056 else
4057 return nullptr;
4060 /* Remove all bindings overlapping REG within the store. */
4062 void
4063 region_model::clobber_region (const region *reg)
4065 m_store.clobber_region (m_mgr->get_store_manager(), reg);
4068 /* Remove any bindings for REG within the store. */
4070 void
4071 region_model::purge_region (const region *reg)
4073 m_store.purge_region (m_mgr->get_store_manager(), reg);
4076 /* Fill REG with SVAL.
4077 Use CTXT to report any warnings associated with the write
4078 (e.g. out-of-bounds). */
4080 void
4081 region_model::fill_region (const region *reg,
4082 const svalue *sval,
4083 region_model_context *ctxt)
4085 check_region_for_write (reg, nullptr, ctxt);
4086 m_store.fill_region (m_mgr->get_store_manager(), reg, sval);
4089 /* Zero-fill REG.
4090 Use CTXT to report any warnings associated with the write
4091 (e.g. out-of-bounds). */
4093 void
4094 region_model::zero_fill_region (const region *reg,
4095 region_model_context *ctxt)
4097 check_region_for_write (reg, nullptr, ctxt);
4098 m_store.zero_fill_region (m_mgr->get_store_manager(), reg);
4101 /* Copy NUM_BYTES_SVAL of SVAL to DEST_REG.
4102 Use CTXT to report any warnings associated with the copy
4103 (e.g. out-of-bounds writes). */
4105 void
4106 region_model::write_bytes (const region *dest_reg,
4107 const svalue *num_bytes_sval,
4108 const svalue *sval,
4109 region_model_context *ctxt)
4111 const region *sized_dest_reg
4112 = m_mgr->get_sized_region (dest_reg, NULL_TREE, num_bytes_sval);
4113 set_value (sized_dest_reg, sval, ctxt);
4116 /* Read NUM_BYTES_SVAL from SRC_REG.
4117 Use CTXT to report any warnings associated with the copy
4118 (e.g. out-of-bounds reads, copying of uninitialized values, etc). */
4120 const svalue *
4121 region_model::read_bytes (const region *src_reg,
4122 tree src_ptr_expr,
4123 const svalue *num_bytes_sval,
4124 region_model_context *ctxt) const
4126 if (num_bytes_sval->get_kind () == SK_UNKNOWN)
4127 return m_mgr->get_or_create_unknown_svalue (NULL_TREE);
4128 const region *sized_src_reg
4129 = m_mgr->get_sized_region (src_reg, NULL_TREE, num_bytes_sval);
4130 const svalue *src_contents_sval = get_store_value (sized_src_reg, ctxt);
4131 check_for_poison (src_contents_sval, src_ptr_expr,
4132 sized_src_reg, ctxt);
4133 return src_contents_sval;
4136 /* Copy NUM_BYTES_SVAL bytes from SRC_REG to DEST_REG.
4137 Use CTXT to report any warnings associated with the copy
4138 (e.g. out-of-bounds reads/writes, copying of uninitialized values,
4139 etc). */
4141 void
4142 region_model::copy_bytes (const region *dest_reg,
4143 const region *src_reg,
4144 tree src_ptr_expr,
4145 const svalue *num_bytes_sval,
4146 region_model_context *ctxt)
4148 const svalue *data_sval
4149 = read_bytes (src_reg, src_ptr_expr, num_bytes_sval, ctxt);
4150 write_bytes (dest_reg, num_bytes_sval, data_sval, ctxt);
4153 /* Mark REG as having unknown content. */
4155 void
4156 region_model::mark_region_as_unknown (const region *reg,
4157 uncertainty_t *uncertainty)
4159 svalue_set maybe_live_values;
4160 m_store.mark_region_as_unknown (m_mgr->get_store_manager(), reg,
4161 uncertainty, &maybe_live_values);
4162 m_store.on_maybe_live_values (maybe_live_values);
4165 /* Determine what is known about the condition "LHS_SVAL OP RHS_SVAL" within
4166 this model. */
4168 tristate
4169 region_model::eval_condition (const svalue *lhs,
4170 enum tree_code op,
4171 const svalue *rhs) const
4173 gcc_assert (lhs);
4174 gcc_assert (rhs);
4176 /* For now, make no attempt to capture constraints on floating-point
4177 values. */
4178 if ((lhs->get_type () && FLOAT_TYPE_P (lhs->get_type ()))
4179 || (rhs->get_type () && FLOAT_TYPE_P (rhs->get_type ())))
4180 return tristate::unknown ();
4182 /* See what we know based on the values. */
4184 /* Unwrap any unmergeable values. */
4185 lhs = lhs->unwrap_any_unmergeable ();
4186 rhs = rhs->unwrap_any_unmergeable ();
4188 if (lhs == rhs)
4190 /* If we have the same svalue, then we have equality
4191 (apart from NaN-handling).
4192 TODO: should this definitely be the case for poisoned values? */
4193 /* Poisoned and unknown values are "unknowable". */
4194 if (lhs->get_kind () == SK_POISONED
4195 || lhs->get_kind () == SK_UNKNOWN)
4196 return tristate::TS_UNKNOWN;
4198 switch (op)
4200 case EQ_EXPR:
4201 case GE_EXPR:
4202 case LE_EXPR:
4203 return tristate::TS_TRUE;
4205 case NE_EXPR:
4206 case GT_EXPR:
4207 case LT_EXPR:
4208 return tristate::TS_FALSE;
4210 default:
4211 /* For other ops, use the logic below. */
4212 break;
4216 /* If we have a pair of region_svalues, compare them. */
4217 if (const region_svalue *lhs_ptr = lhs->dyn_cast_region_svalue ())
4218 if (const region_svalue *rhs_ptr = rhs->dyn_cast_region_svalue ())
4220 tristate res = region_svalue::eval_condition (lhs_ptr, op, rhs_ptr);
4221 if (res.is_known ())
4222 return res;
4223 /* Otherwise, only known through constraints. */
4226 if (const constant_svalue *cst_lhs = lhs->dyn_cast_constant_svalue ())
4228 /* If we have a pair of constants, compare them. */
4229 if (const constant_svalue *cst_rhs = rhs->dyn_cast_constant_svalue ())
4230 return constant_svalue::eval_condition (cst_lhs, op, cst_rhs);
4231 else
4233 /* When we have one constant, put it on the RHS. */
4234 std::swap (lhs, rhs);
4235 op = swap_tree_comparison (op);
4238 gcc_assert (lhs->get_kind () != SK_CONSTANT);
4240 /* Handle comparison against zero. */
4241 if (const constant_svalue *cst_rhs = rhs->dyn_cast_constant_svalue ())
4242 if (zerop (cst_rhs->get_constant ()))
4244 if (const region_svalue *ptr = lhs->dyn_cast_region_svalue ())
4246 /* A region_svalue is a non-NULL pointer, except in certain
4247 special cases (see the comment for region::non_null_p). */
4248 const region *pointee = ptr->get_pointee ();
4249 if (pointee->non_null_p ())
4251 switch (op)
4253 default:
4254 gcc_unreachable ();
4256 case EQ_EXPR:
4257 case GE_EXPR:
4258 case LE_EXPR:
4259 return tristate::TS_FALSE;
4261 case NE_EXPR:
4262 case GT_EXPR:
4263 case LT_EXPR:
4264 return tristate::TS_TRUE;
4268 else if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4270 /* Treat offsets from a non-NULL pointer as being non-NULL. This
4271 isn't strictly true, in that eventually ptr++ will wrap
4272 around and be NULL, but it won't occur in practise and thus
4273 can be used to suppress effectively false positives that we
4274 shouldn't warn for. */
4275 if (binop->get_op () == POINTER_PLUS_EXPR)
4277 tristate lhs_ts = eval_condition (binop->get_arg0 (), op, rhs);
4278 if (lhs_ts.is_known ())
4279 return lhs_ts;
4282 else if (const unaryop_svalue *unaryop
4283 = lhs->dyn_cast_unaryop_svalue ())
4285 if (unaryop->get_op () == NEGATE_EXPR)
4287 /* e.g. "-X <= 0" is equivalent to X >= 0". */
4288 tristate lhs_ts = eval_condition (unaryop->get_arg (),
4289 swap_tree_comparison (op),
4290 rhs);
4291 if (lhs_ts.is_known ())
4292 return lhs_ts;
4297 /* Handle rejection of equality for comparisons of the initial values of
4298 "external" values (such as params) with the address of locals. */
4299 if (const initial_svalue *init_lhs = lhs->dyn_cast_initial_svalue ())
4300 if (const region_svalue *rhs_ptr = rhs->dyn_cast_region_svalue ())
4302 tristate res = compare_initial_and_pointer (init_lhs, rhs_ptr);
4303 if (res.is_known ())
4304 return res;
4306 if (const initial_svalue *init_rhs = rhs->dyn_cast_initial_svalue ())
4307 if (const region_svalue *lhs_ptr = lhs->dyn_cast_region_svalue ())
4309 tristate res = compare_initial_and_pointer (init_rhs, lhs_ptr);
4310 if (res.is_known ())
4311 return res;
4314 if (const widening_svalue *widen_lhs = lhs->dyn_cast_widening_svalue ())
4315 if (tree rhs_cst = rhs->maybe_get_constant ())
4317 tristate res = widen_lhs->eval_condition_without_cm (op, rhs_cst);
4318 if (res.is_known ())
4319 return res;
4322 /* Handle comparisons between two svalues with more than one operand. */
4323 if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4325 switch (op)
4327 default:
4328 break;
4329 case EQ_EXPR:
4331 /* TODO: binops can be equal even if they are not structurally
4332 equal in case of commutative operators. */
4333 tristate res = structural_equality (lhs, rhs);
4334 if (res.is_true ())
4335 return res;
4337 break;
4338 case LE_EXPR:
4340 tristate res = structural_equality (lhs, rhs);
4341 if (res.is_true ())
4342 return res;
4344 break;
4345 case GE_EXPR:
4347 tristate res = structural_equality (lhs, rhs);
4348 if (res.is_true ())
4349 return res;
4350 res = symbolic_greater_than (binop, rhs);
4351 if (res.is_true ())
4352 return res;
4354 break;
4355 case GT_EXPR:
4357 tristate res = symbolic_greater_than (binop, rhs);
4358 if (res.is_true ())
4359 return res;
4361 break;
4365 /* Attempt to unwrap cast if there is one, and the types match. */
4366 tree lhs_type = lhs->get_type ();
4367 tree rhs_type = rhs->get_type ();
4368 if (lhs_type && rhs_type)
4370 const unaryop_svalue *lhs_un_op = dyn_cast <const unaryop_svalue *> (lhs);
4371 const unaryop_svalue *rhs_un_op = dyn_cast <const unaryop_svalue *> (rhs);
4372 if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
4373 && rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
4374 && lhs_type == rhs_type)
4375 return eval_condition (lhs_un_op->get_arg (),
4377 rhs_un_op->get_arg ());
4379 else if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
4380 && lhs_type == rhs_type)
4381 return eval_condition (lhs_un_op->get_arg (), op, rhs);
4383 else if (rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
4384 && lhs_type == rhs_type)
4385 return eval_condition (lhs, op, rhs_un_op->get_arg ());
4388 /* Otherwise, try constraints.
4389 Cast to const to ensure we don't change the constraint_manager as we
4390 do this (e.g. by creating equivalence classes). */
4391 const constraint_manager *constraints = m_constraints;
4392 return constraints->eval_condition (lhs, op, rhs);
4395 /* Subroutine of region_model::eval_condition, for rejecting
4396 equality of INIT_VAL(PARM) with &LOCAL. */
4398 tristate
4399 region_model::compare_initial_and_pointer (const initial_svalue *init,
4400 const region_svalue *ptr) const
4402 const region *pointee = ptr->get_pointee ();
4404 /* If we have a pointer to something within a stack frame, it can't be the
4405 initial value of a param. */
4406 if (pointee->maybe_get_frame_region ())
4407 if (init->initial_value_of_param_p ())
4408 return tristate::TS_FALSE;
4410 return tristate::TS_UNKNOWN;
4413 /* Return true if SVAL is definitely positive. */
4415 static bool
4416 is_positive_svalue (const svalue *sval)
4418 if (tree cst = sval->maybe_get_constant ())
4419 return !zerop (cst) && get_range_pos_neg (cst) == 1;
4420 tree type = sval->get_type ();
4421 if (!type)
4422 return false;
4423 /* Consider a binary operation size_t + int. The analyzer wraps the int in
4424 an unaryop_svalue, converting it to a size_t, but in the dynamic execution
4425 the result is smaller than the first operand. Thus, we have to look if
4426 the argument of the unaryop_svalue is also positive. */
4427 if (const unaryop_svalue *un_op = dyn_cast <const unaryop_svalue *> (sval))
4428 return CONVERT_EXPR_CODE_P (un_op->get_op ()) && TYPE_UNSIGNED (type)
4429 && is_positive_svalue (un_op->get_arg ());
4430 return TYPE_UNSIGNED (type);
4433 /* Return true if A is definitely larger than B.
4435 Limitation: does not account for integer overflows and does not try to
4436 return false, so it can not be used negated. */
4438 tristate
4439 region_model::symbolic_greater_than (const binop_svalue *bin_a,
4440 const svalue *b) const
4442 if (bin_a->get_op () == PLUS_EXPR || bin_a->get_op () == MULT_EXPR)
4444 /* Eliminate the right-hand side of both svalues. */
4445 if (const binop_svalue *bin_b = dyn_cast <const binop_svalue *> (b))
4446 if (bin_a->get_op () == bin_b->get_op ()
4447 && eval_condition (bin_a->get_arg1 (),
4448 GT_EXPR,
4449 bin_b->get_arg1 ()).is_true ()
4450 && eval_condition (bin_a->get_arg0 (),
4451 GE_EXPR,
4452 bin_b->get_arg0 ()).is_true ())
4453 return tristate (tristate::TS_TRUE);
4455 /* Otherwise, try to remove a positive offset or factor from BIN_A. */
4456 if (is_positive_svalue (bin_a->get_arg1 ())
4457 && eval_condition (bin_a->get_arg0 (),
4458 GE_EXPR, b).is_true ())
4459 return tristate (tristate::TS_TRUE);
4461 return tristate::unknown ();
4464 /* Return true if A and B are equal structurally.
4466 Structural equality means that A and B are equal if the svalues A and B have
4467 the same nodes at the same positions in the tree and the leafs are equal.
4468 Equality for conjured_svalues and initial_svalues is determined by comparing
4469 the pointers while constants are compared by value. That behavior is useful
4470 to check for binaryop_svlaues that evaluate to the same concrete value but
4471 might use one operand with a different type but the same constant value.
4473 For example,
4474 binop_svalue (mult_expr,
4475 initial_svalue (‘size_t’, decl_region (..., 'some_var')),
4476 constant_svalue (‘size_t’, 4))
4478 binop_svalue (mult_expr,
4479 initial_svalue (‘size_t’, decl_region (..., 'some_var'),
4480 constant_svalue (‘sizetype’, 4))
4481 are structurally equal. A concrete C code example, where this occurs, can
4482 be found in test7 of out-of-bounds-5.c. */
4484 tristate
4485 region_model::structural_equality (const svalue *a, const svalue *b) const
4487 /* If A and B are referentially equal, they are also structurally equal. */
4488 if (a == b)
4489 return tristate (tristate::TS_TRUE);
4491 switch (a->get_kind ())
4493 default:
4494 return tristate::unknown ();
4495 /* SK_CONJURED and SK_INITIAL are already handled
4496 by the referential equality above. */
4497 case SK_CONSTANT:
4499 tree a_cst = a->maybe_get_constant ();
4500 tree b_cst = b->maybe_get_constant ();
4501 if (a_cst && b_cst)
4502 return tristate (tree_int_cst_equal (a_cst, b_cst));
4504 return tristate (tristate::TS_FALSE);
4505 case SK_UNARYOP:
4507 const unaryop_svalue *un_a = as_a <const unaryop_svalue *> (a);
4508 if (const unaryop_svalue *un_b = dyn_cast <const unaryop_svalue *> (b))
4509 return tristate (pending_diagnostic::same_tree_p (un_a->get_type (),
4510 un_b->get_type ())
4511 && un_a->get_op () == un_b->get_op ()
4512 && structural_equality (un_a->get_arg (),
4513 un_b->get_arg ()));
4515 return tristate (tristate::TS_FALSE);
4516 case SK_BINOP:
4518 const binop_svalue *bin_a = as_a <const binop_svalue *> (a);
4519 if (const binop_svalue *bin_b = dyn_cast <const binop_svalue *> (b))
4520 return tristate (bin_a->get_op () == bin_b->get_op ()
4521 && structural_equality (bin_a->get_arg0 (),
4522 bin_b->get_arg0 ())
4523 && structural_equality (bin_a->get_arg1 (),
4524 bin_b->get_arg1 ()));
4526 return tristate (tristate::TS_FALSE);
4530 /* Handle various constraints of the form:
4531 LHS: ((bool)INNER_LHS INNER_OP INNER_RHS))
4532 OP : == or !=
4533 RHS: zero
4534 and (with a cast):
4535 LHS: CAST([long]int, ((bool)INNER_LHS INNER_OP INNER_RHS))
4536 OP : == or !=
4537 RHS: zero
4538 by adding constraints for INNER_LHS INNEROP INNER_RHS.
4540 Return true if this function can fully handle the constraint; if
4541 so, add the implied constraint(s) and write true to *OUT if they
4542 are consistent with existing constraints, or write false to *OUT
4543 if they contradicts existing constraints.
4545 Return false for cases that this function doeesn't know how to handle.
4547 For example, if we're checking a stored conditional, we'll have
4548 something like:
4549 LHS: CAST(long int, (&HEAP_ALLOCATED_REGION(8)!=(int *)0B))
4550 OP : NE_EXPR
4551 RHS: zero
4552 which this function can turn into an add_constraint of:
4553 (&HEAP_ALLOCATED_REGION(8) != (int *)0B)
4555 Similarly, optimized && and || conditionals lead to e.g.
4556 if (p && q)
4557 becoming gimple like this:
4558 _1 = p_6 == 0B;
4559 _2 = q_8 == 0B
4560 _3 = _1 | _2
4561 On the "_3 is false" branch we can have constraints of the form:
4562 ((&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
4563 | (&HEAP_ALLOCATED_REGION(10)!=(int *)0B))
4564 == 0
4565 which implies that both _1 and _2 are false,
4566 which this function can turn into a pair of add_constraints of
4567 (&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
4568 and:
4569 (&HEAP_ALLOCATED_REGION(10)!=(int *)0B). */
4571 bool
4572 region_model::add_constraints_from_binop (const svalue *outer_lhs,
4573 enum tree_code outer_op,
4574 const svalue *outer_rhs,
4575 bool *out,
4576 region_model_context *ctxt)
4578 while (const svalue *cast = outer_lhs->maybe_undo_cast ())
4579 outer_lhs = cast;
4580 const binop_svalue *binop_sval = outer_lhs->dyn_cast_binop_svalue ();
4581 if (!binop_sval)
4582 return false;
4583 if (!outer_rhs->all_zeroes_p ())
4584 return false;
4586 const svalue *inner_lhs = binop_sval->get_arg0 ();
4587 enum tree_code inner_op = binop_sval->get_op ();
4588 const svalue *inner_rhs = binop_sval->get_arg1 ();
4590 if (outer_op != NE_EXPR && outer_op != EQ_EXPR)
4591 return false;
4593 /* We have either
4594 - "OUTER_LHS != false" (i.e. OUTER is true), or
4595 - "OUTER_LHS == false" (i.e. OUTER is false). */
4596 bool is_true = outer_op == NE_EXPR;
4598 switch (inner_op)
4600 default:
4601 return false;
4603 case EQ_EXPR:
4604 case NE_EXPR:
4605 case GE_EXPR:
4606 case GT_EXPR:
4607 case LE_EXPR:
4608 case LT_EXPR:
4610 /* ...and "(inner_lhs OP inner_rhs) == 0"
4611 then (inner_lhs OP inner_rhs) must have the same
4612 logical value as LHS. */
4613 if (!is_true)
4614 inner_op = invert_tree_comparison (inner_op, false /* honor_nans */);
4615 *out = add_constraint (inner_lhs, inner_op, inner_rhs, ctxt);
4616 return true;
4618 break;
4620 case BIT_AND_EXPR:
4621 if (is_true)
4623 /* ...and "(inner_lhs & inner_rhs) != 0"
4624 then both inner_lhs and inner_rhs must be true. */
4625 const svalue *false_sval
4626 = m_mgr->get_or_create_constant_svalue (boolean_false_node);
4627 bool sat1 = add_constraint (inner_lhs, NE_EXPR, false_sval, ctxt);
4628 bool sat2 = add_constraint (inner_rhs, NE_EXPR, false_sval, ctxt);
4629 *out = sat1 && sat2;
4630 return true;
4632 return false;
4634 case BIT_IOR_EXPR:
4635 if (!is_true)
4637 /* ...and "(inner_lhs | inner_rhs) == 0"
4638 i.e. "(inner_lhs | inner_rhs)" is false
4639 then both inner_lhs and inner_rhs must be false. */
4640 const svalue *false_sval
4641 = m_mgr->get_or_create_constant_svalue (boolean_false_node);
4642 bool sat1 = add_constraint (inner_lhs, EQ_EXPR, false_sval, ctxt);
4643 bool sat2 = add_constraint (inner_rhs, EQ_EXPR, false_sval, ctxt);
4644 *out = sat1 && sat2;
4645 return true;
4647 return false;
4651 /* Attempt to add the constraint "LHS OP RHS" to this region_model.
4652 If it is consistent with existing constraints, add it, and return true.
4653 Return false if it contradicts existing constraints.
4654 Use CTXT for reporting any diagnostics associated with the accesses. */
4656 bool
4657 region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
4658 region_model_context *ctxt)
4660 /* For now, make no attempt to capture constraints on floating-point
4661 values. */
4662 if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
4663 return true;
4665 const svalue *lhs_sval = get_rvalue (lhs, ctxt);
4666 const svalue *rhs_sval = get_rvalue (rhs, ctxt);
4668 return add_constraint (lhs_sval, op, rhs_sval, ctxt);
4671 static bool
4672 unusable_in_infinite_loop_constraint_p (const svalue *sval)
4674 if (sval->get_kind () == SK_WIDENING)
4675 return true;
4676 return false;
4679 /* Attempt to add the constraint "LHS OP RHS" to this region_model.
4680 If it is consistent with existing constraints, add it, and return true.
4681 Return false if it contradicts existing constraints.
4682 Use CTXT for reporting any diagnostics associated with the accesses. */
4684 bool
4685 region_model::add_constraint (const svalue *lhs,
4686 enum tree_code op,
4687 const svalue *rhs,
4688 region_model_context *ctxt)
4690 const bool checking_for_infinite_loop
4691 = ctxt ? ctxt->checking_for_infinite_loop_p () : false;
4693 if (checking_for_infinite_loop)
4695 if (unusable_in_infinite_loop_constraint_p (lhs)
4696 || unusable_in_infinite_loop_constraint_p (rhs))
4698 gcc_assert (ctxt);
4699 ctxt->on_unusable_in_infinite_loop ();
4700 return false;
4704 tristate t_cond = eval_condition (lhs, op, rhs);
4706 /* If we already have the condition, do nothing. */
4707 if (t_cond.is_true ())
4708 return true;
4710 /* Reject a constraint that would contradict existing knowledge, as
4711 unsatisfiable. */
4712 if (t_cond.is_false ())
4713 return false;
4715 if (checking_for_infinite_loop)
4717 /* Here, we don't have a definite true/false value, so bail out
4718 when checking for infinite loops. */
4719 gcc_assert (ctxt);
4720 ctxt->on_unusable_in_infinite_loop ();
4721 return false;
4724 bool out;
4725 if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt))
4726 return out;
4728 /* Attempt to store the constraint. */
4729 if (!m_constraints->add_constraint (lhs, op, rhs))
4730 return false;
4732 /* Notify the context, if any. This exists so that the state machines
4733 in a program_state can be notified about the condition, and so can
4734 set sm-state for e.g. unchecked->checked, both for cfg-edges, and
4735 when synthesizing constraints as above. */
4736 if (ctxt)
4737 ctxt->on_condition (lhs, op, rhs);
4739 /* If we have &REGION == NULL, then drop dynamic extents for REGION (for
4740 the case where REGION is heap-allocated and thus could be NULL). */
4741 if (tree rhs_cst = rhs->maybe_get_constant ())
4742 if (op == EQ_EXPR && zerop (rhs_cst))
4743 if (const region_svalue *region_sval = lhs->dyn_cast_region_svalue ())
4744 unset_dynamic_extents (region_sval->get_pointee ());
4746 return true;
4749 /* As above, but when returning false, if OUT is non-NULL, write a
4750 new rejected_constraint to *OUT. */
4752 bool
4753 region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
4754 region_model_context *ctxt,
4755 std::unique_ptr<rejected_constraint> *out)
4757 bool sat = add_constraint (lhs, op, rhs, ctxt);
4758 if (!sat && out)
4759 *out = make_unique <rejected_op_constraint> (*this, lhs, op, rhs);
4760 return sat;
4763 /* Determine what is known about the condition "LHS OP RHS" within
4764 this model.
4765 Use CTXT for reporting any diagnostics associated with the accesses. */
4767 tristate
4768 region_model::eval_condition (tree lhs,
4769 enum tree_code op,
4770 tree rhs,
4771 region_model_context *ctxt) const
4773 /* For now, make no attempt to model constraints on floating-point
4774 values. */
4775 if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
4776 return tristate::unknown ();
4778 return eval_condition (get_rvalue (lhs, ctxt), op, get_rvalue (rhs, ctxt));
4781 /* Implementation of region_model::get_representative_path_var.
4782 Attempt to return a path_var that represents SVAL, or return NULL_TREE.
4783 Use VISITED to prevent infinite mutual recursion with the overload for
4784 regions. */
4786 path_var
4787 region_model::get_representative_path_var_1 (const svalue *sval,
4788 svalue_set *visited) const
4790 gcc_assert (sval);
4792 /* Prevent infinite recursion. */
4793 if (visited->contains (sval))
4795 if (sval->get_kind () == SK_CONSTANT)
4796 return path_var (sval->maybe_get_constant (), 0);
4797 else
4798 return path_var (NULL_TREE, 0);
4800 visited->add (sval);
4802 /* Handle casts by recursion into get_representative_path_var. */
4803 if (const svalue *cast_sval = sval->maybe_undo_cast ())
4805 path_var result = get_representative_path_var (cast_sval, visited);
4806 tree orig_type = sval->get_type ();
4807 /* If necessary, wrap the result in a cast. */
4808 if (result.m_tree && orig_type)
4809 result.m_tree = build1 (NOP_EXPR, orig_type, result.m_tree);
4810 return result;
4813 auto_vec<path_var> pvs;
4814 m_store.get_representative_path_vars (this, visited, sval, &pvs);
4816 if (tree cst = sval->maybe_get_constant ())
4817 pvs.safe_push (path_var (cst, 0));
4819 /* Handle string literals and various other pointers. */
4820 if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
4822 const region *reg = ptr_sval->get_pointee ();
4823 if (path_var pv = get_representative_path_var (reg, visited))
4824 return path_var (build1 (ADDR_EXPR,
4825 sval->get_type (),
4826 pv.m_tree),
4827 pv.m_stack_depth);
4830 /* If we have a sub_svalue, look for ways to represent the parent. */
4831 if (const sub_svalue *sub_sval = sval->dyn_cast_sub_svalue ())
4833 const svalue *parent_sval = sub_sval->get_parent ();
4834 const region *subreg = sub_sval->get_subregion ();
4835 if (path_var parent_pv
4836 = get_representative_path_var (parent_sval, visited))
4837 if (const field_region *field_reg = subreg->dyn_cast_field_region ())
4838 return path_var (build3 (COMPONENT_REF,
4839 sval->get_type (),
4840 parent_pv.m_tree,
4841 field_reg->get_field (),
4842 NULL_TREE),
4843 parent_pv.m_stack_depth);
4846 /* Handle binops. */
4847 if (const binop_svalue *binop_sval = sval->dyn_cast_binop_svalue ())
4848 if (path_var lhs_pv
4849 = get_representative_path_var (binop_sval->get_arg0 (), visited))
4850 if (path_var rhs_pv
4851 = get_representative_path_var (binop_sval->get_arg1 (), visited))
4852 return path_var (build2 (binop_sval->get_op (),
4853 sval->get_type (),
4854 lhs_pv.m_tree, rhs_pv.m_tree),
4855 lhs_pv.m_stack_depth);
4857 if (pvs.length () < 1)
4858 return path_var (NULL_TREE, 0);
4860 pvs.qsort (readability_comparator);
4861 return pvs[0];
4864 /* Attempt to return a path_var that represents SVAL, or return NULL_TREE.
4865 Use VISITED to prevent infinite mutual recursion with the overload for
4866 regions
4868 This function defers to get_representative_path_var_1 to do the work;
4869 it adds verification that get_representative_path_var_1 returned a tree
4870 of the correct type. */
4872 path_var
4873 region_model::get_representative_path_var (const svalue *sval,
4874 svalue_set *visited) const
4876 if (sval == NULL)
4877 return path_var (NULL_TREE, 0);
4879 tree orig_type = sval->get_type ();
4881 path_var result = get_representative_path_var_1 (sval, visited);
4883 /* Verify that the result has the same type as SVAL, if any. */
4884 if (result.m_tree && orig_type)
4885 gcc_assert (TREE_TYPE (result.m_tree) == orig_type);
4887 return result;
4890 /* Attempt to return a tree that represents SVAL, or return NULL_TREE.
4892 Strip off any top-level cast, to avoid messages like
4893 double-free of '(void *)ptr'
4894 from analyzer diagnostics. */
4896 tree
4897 region_model::get_representative_tree (const svalue *sval) const
4899 svalue_set visited;
4900 tree expr = get_representative_path_var (sval, &visited).m_tree;
4902 /* Strip off any top-level cast. */
4903 if (expr && TREE_CODE (expr) == NOP_EXPR)
4904 expr = TREE_OPERAND (expr, 0);
4906 return fixup_tree_for_diagnostic (expr);
4909 tree
4910 region_model::get_representative_tree (const region *reg) const
4912 svalue_set visited;
4913 tree expr = get_representative_path_var (reg, &visited).m_tree;
4915 /* Strip off any top-level cast. */
4916 if (expr && TREE_CODE (expr) == NOP_EXPR)
4917 expr = TREE_OPERAND (expr, 0);
4919 return fixup_tree_for_diagnostic (expr);
4922 /* Implementation of region_model::get_representative_path_var.
4924 Attempt to return a path_var that represents REG, or return
4925 the NULL path_var.
4926 For example, a region for a field of a local would be a path_var
4927 wrapping a COMPONENT_REF.
4928 Use VISITED to prevent infinite mutual recursion with the overload for
4929 svalues. */
4931 path_var
4932 region_model::get_representative_path_var_1 (const region *reg,
4933 svalue_set *visited) const
4935 switch (reg->get_kind ())
4937 default:
4938 gcc_unreachable ();
4940 case RK_FRAME:
4941 case RK_GLOBALS:
4942 case RK_CODE:
4943 case RK_HEAP:
4944 case RK_STACK:
4945 case RK_THREAD_LOCAL:
4946 case RK_ROOT:
4947 /* Regions that represent memory spaces are not expressible as trees. */
4948 return path_var (NULL_TREE, 0);
4950 case RK_FUNCTION:
4952 const function_region *function_reg
4953 = as_a <const function_region *> (reg);
4954 return path_var (function_reg->get_fndecl (), 0);
4956 case RK_LABEL:
4958 const label_region *label_reg = as_a <const label_region *> (reg);
4959 return path_var (label_reg->get_label (), 0);
4962 case RK_SYMBOLIC:
4964 const symbolic_region *symbolic_reg
4965 = as_a <const symbolic_region *> (reg);
4966 const svalue *pointer = symbolic_reg->get_pointer ();
4967 path_var pointer_pv = get_representative_path_var (pointer, visited);
4968 if (!pointer_pv)
4969 return path_var (NULL_TREE, 0);
4970 tree offset = build_int_cst (pointer->get_type (), 0);
4971 return path_var (build2 (MEM_REF,
4972 reg->get_type (),
4973 pointer_pv.m_tree,
4974 offset),
4975 pointer_pv.m_stack_depth);
4977 case RK_DECL:
4979 const decl_region *decl_reg = as_a <const decl_region *> (reg);
4980 return path_var (decl_reg->get_decl (), decl_reg->get_stack_depth ());
4982 case RK_FIELD:
4984 const field_region *field_reg = as_a <const field_region *> (reg);
4985 path_var parent_pv
4986 = get_representative_path_var (reg->get_parent_region (), visited);
4987 if (!parent_pv)
4988 return path_var (NULL_TREE, 0);
4989 return path_var (build3 (COMPONENT_REF,
4990 reg->get_type (),
4991 parent_pv.m_tree,
4992 field_reg->get_field (),
4993 NULL_TREE),
4994 parent_pv.m_stack_depth);
4997 case RK_ELEMENT:
4999 const element_region *element_reg
5000 = as_a <const element_region *> (reg);
5001 path_var parent_pv
5002 = get_representative_path_var (reg->get_parent_region (), visited);
5003 if (!parent_pv)
5004 return path_var (NULL_TREE, 0);
5005 path_var index_pv
5006 = get_representative_path_var (element_reg->get_index (), visited);
5007 if (!index_pv)
5008 return path_var (NULL_TREE, 0);
5009 return path_var (build4 (ARRAY_REF,
5010 reg->get_type (),
5011 parent_pv.m_tree, index_pv.m_tree,
5012 NULL_TREE, NULL_TREE),
5013 parent_pv.m_stack_depth);
5016 case RK_OFFSET:
5018 const offset_region *offset_reg
5019 = as_a <const offset_region *> (reg);
5020 path_var parent_pv
5021 = get_representative_path_var (reg->get_parent_region (), visited);
5022 if (!parent_pv)
5023 return path_var (NULL_TREE, 0);
5024 path_var offset_pv
5025 = get_representative_path_var (offset_reg->get_byte_offset (),
5026 visited);
5027 if (!offset_pv || TREE_CODE (offset_pv.m_tree) != INTEGER_CST)
5028 return path_var (NULL_TREE, 0);
5029 tree addr_parent = build1 (ADDR_EXPR,
5030 build_pointer_type (reg->get_type ()),
5031 parent_pv.m_tree);
5032 return path_var (build2 (MEM_REF,
5033 reg->get_type (),
5034 addr_parent, offset_pv.m_tree),
5035 parent_pv.m_stack_depth);
5038 case RK_SIZED:
5039 return path_var (NULL_TREE, 0);
5041 case RK_CAST:
5043 path_var parent_pv
5044 = get_representative_path_var (reg->get_parent_region (), visited);
5045 if (!parent_pv)
5046 return path_var (NULL_TREE, 0);
5047 return path_var (build1 (NOP_EXPR,
5048 reg->get_type (),
5049 parent_pv.m_tree),
5050 parent_pv.m_stack_depth);
5053 case RK_HEAP_ALLOCATED:
5054 case RK_ALLOCA:
5055 /* No good way to express heap-allocated/alloca regions as trees. */
5056 return path_var (NULL_TREE, 0);
5058 case RK_STRING:
5060 const string_region *string_reg = as_a <const string_region *> (reg);
5061 return path_var (string_reg->get_string_cst (), 0);
5064 case RK_VAR_ARG:
5065 case RK_ERRNO:
5066 case RK_UNKNOWN:
5067 case RK_PRIVATE:
5068 return path_var (NULL_TREE, 0);
5072 /* Attempt to return a path_var that represents REG, or return
5073 the NULL path_var.
5074 For example, a region for a field of a local would be a path_var
5075 wrapping a COMPONENT_REF.
5076 Use VISITED to prevent infinite mutual recursion with the overload for
5077 svalues.
5079 This function defers to get_representative_path_var_1 to do the work;
5080 it adds verification that get_representative_path_var_1 returned a tree
5081 of the correct type. */
5083 path_var
5084 region_model::get_representative_path_var (const region *reg,
5085 svalue_set *visited) const
5087 path_var result = get_representative_path_var_1 (reg, visited);
5089 /* Verify that the result has the same type as REG, if any. */
5090 if (result.m_tree && reg->get_type ())
5091 gcc_assert (TREE_TYPE (result.m_tree) == reg->get_type ());
5093 return result;
5096 /* Update this model for any phis in SNODE, assuming we came from
5097 LAST_CFG_SUPEREDGE. */
5099 void
5100 region_model::update_for_phis (const supernode *snode,
5101 const cfg_superedge *last_cfg_superedge,
5102 region_model_context *ctxt)
5104 gcc_assert (last_cfg_superedge);
5106 /* Copy this state and pass it to handle_phi so that all of the phi stmts
5107 are effectively handled simultaneously. */
5108 const region_model old_state (*this);
5110 hash_set<const svalue *> svals_changing_meaning;
5112 for (gphi_iterator gpi = const_cast<supernode *>(snode)->start_phis ();
5113 !gsi_end_p (gpi); gsi_next (&gpi))
5115 gphi *phi = gpi.phi ();
5117 tree src = last_cfg_superedge->get_phi_arg (phi);
5118 tree lhs = gimple_phi_result (phi);
5120 /* Update next_state based on phi and old_state. */
5121 handle_phi (phi, lhs, src, old_state, svals_changing_meaning, ctxt);
5124 for (auto iter : svals_changing_meaning)
5125 m_constraints->purge_state_involving (iter);
5128 /* Attempt to update this model for taking EDGE (where the last statement
5129 was LAST_STMT), returning true if the edge can be taken, false
5130 otherwise.
5131 When returning false, if OUT is non-NULL, write a new rejected_constraint
5132 to it.
5134 For CFG superedges where LAST_STMT is a conditional or a switch
5135 statement, attempt to add the relevant conditions for EDGE to this
5136 model, returning true if they are feasible, or false if they are
5137 impossible.
5139 For call superedges, push frame information and store arguments
5140 into parameters.
5142 For return superedges, pop frame information and store return
5143 values into any lhs.
5145 Rejection of call/return superedges happens elsewhere, in
5146 program_point::on_edge (i.e. based on program point, rather
5147 than program state). */
5149 bool
5150 region_model::maybe_update_for_edge (const superedge &edge,
5151 const gimple *last_stmt,
5152 region_model_context *ctxt,
5153 std::unique_ptr<rejected_constraint> *out)
5155 /* Handle frame updates for interprocedural edges. */
5156 switch (edge.m_kind)
5158 default:
5159 break;
5161 case SUPEREDGE_CALL:
5163 const call_superedge *call_edge = as_a <const call_superedge *> (&edge);
5164 update_for_call_superedge (*call_edge, ctxt);
5166 break;
5168 case SUPEREDGE_RETURN:
5170 const return_superedge *return_edge
5171 = as_a <const return_superedge *> (&edge);
5172 update_for_return_superedge (*return_edge, ctxt);
5174 break;
5176 case SUPEREDGE_INTRAPROCEDURAL_CALL:
5177 /* This is a no-op for call summaries; we should already
5178 have handled the effect of the call summary at the call stmt. */
5179 break;
5182 if (last_stmt == NULL)
5183 return true;
5185 /* Apply any constraints for conditionals/switch/computed-goto statements. */
5187 if (const gcond *cond_stmt = dyn_cast <const gcond *> (last_stmt))
5189 const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (&edge);
5190 return apply_constraints_for_gcond (*cfg_sedge, cond_stmt, ctxt, out);
5193 if (const gswitch *switch_stmt = dyn_cast <const gswitch *> (last_stmt))
5195 const switch_cfg_superedge *switch_sedge
5196 = as_a <const switch_cfg_superedge *> (&edge);
5197 return apply_constraints_for_gswitch (*switch_sedge, switch_stmt,
5198 ctxt, out);
5201 if (const ggoto *goto_stmt = dyn_cast <const ggoto *> (last_stmt))
5203 const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (&edge);
5204 return apply_constraints_for_ggoto (*cfg_sedge, goto_stmt, ctxt);
5207 /* Apply any constraints due to an exception being thrown. */
5208 if (const cfg_superedge *cfg_sedge = dyn_cast <const cfg_superedge *> (&edge))
5209 if (cfg_sedge->get_flags () & EDGE_EH)
5210 return apply_constraints_for_exception (last_stmt, ctxt, out);
5212 return true;
5215 /* Push a new frame_region on to the stack region.
5216 Populate the frame_region with child regions for the function call's
5217 parameters, using values from the arguments at the callsite in the
5218 caller's frame. */
5220 void
5221 region_model::update_for_gcall (const gcall *call_stmt,
5222 region_model_context *ctxt,
5223 function *callee)
5225 /* Build a vec of argument svalues, using the current top
5226 frame for resolving tree expressions. */
5227 auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt));
5229 for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
5231 tree arg = gimple_call_arg (call_stmt, i);
5232 arg_svals.quick_push (get_rvalue (arg, ctxt));
5235 if(!callee)
5237 /* Get the function * from the gcall. */
5238 tree fn_decl = get_fndecl_for_call (call_stmt,ctxt);
5239 callee = DECL_STRUCT_FUNCTION (fn_decl);
5242 push_frame (callee, &arg_svals, ctxt);
5245 /* Pop the top-most frame_region from the stack, and copy the return
5246 region's values (if any) into the region for the lvalue of the LHS of
5247 the call (if any). */
5249 void
5250 region_model::update_for_return_gcall (const gcall *call_stmt,
5251 region_model_context *ctxt)
5253 /* Get the lvalue for the result of the call, passing it to pop_frame,
5254 so that pop_frame can determine the region with respect to the
5255 *caller* frame. */
5256 tree lhs = gimple_call_lhs (call_stmt);
5257 pop_frame (lhs, NULL, ctxt);
5260 /* Extract calling information from the superedge and update the model for the
5261 call */
5263 void
5264 region_model::update_for_call_superedge (const call_superedge &call_edge,
5265 region_model_context *ctxt)
5267 const gcall *call_stmt = call_edge.get_call_stmt ();
5268 update_for_gcall (call_stmt, ctxt, call_edge.get_callee_function ());
5271 /* Extract calling information from the return superedge and update the model
5272 for the returning call */
5274 void
5275 region_model::update_for_return_superedge (const return_superedge &return_edge,
5276 region_model_context *ctxt)
5278 const gcall *call_stmt = return_edge.get_call_stmt ();
5279 update_for_return_gcall (call_stmt, ctxt);
5282 /* Attempt to to use R to replay SUMMARY into this object.
5283 Return true if it is possible. */
5285 bool
5286 region_model::replay_call_summary (call_summary_replay &r,
5287 const region_model &summary)
5289 gcc_assert (summary.get_stack_depth () == 1);
5291 m_store.replay_call_summary (r, summary.m_store);
5293 if (r.get_ctxt ())
5294 r.get_ctxt ()->maybe_did_work ();
5296 if (!m_constraints->replay_call_summary (r, *summary.m_constraints))
5297 return false;
5299 for (auto kv : summary.m_dynamic_extents)
5301 const region *summary_reg = kv.first;
5302 const region *caller_reg = r.convert_region_from_summary (summary_reg);
5303 if (!caller_reg)
5304 continue;
5305 const svalue *summary_sval = kv.second;
5306 const svalue *caller_sval = r.convert_svalue_from_summary (summary_sval);
5307 if (!caller_sval)
5308 continue;
5309 m_dynamic_extents.put (caller_reg, caller_sval);
5312 return true;
5315 /* Given a true or false edge guarded by conditional statement COND_STMT,
5316 determine appropriate constraints for the edge to be taken.
5318 If they are feasible, add the constraints and return true.
5320 Return false if the constraints contradict existing knowledge
5321 (and so the edge should not be taken).
5322 When returning false, if OUT is non-NULL, write a new rejected_constraint
5323 to it. */
5325 bool
5326 region_model::
5327 apply_constraints_for_gcond (const cfg_superedge &sedge,
5328 const gcond *cond_stmt,
5329 region_model_context *ctxt,
5330 std::unique_ptr<rejected_constraint> *out)
5332 ::edge cfg_edge = sedge.get_cfg_edge ();
5333 gcc_assert (cfg_edge != NULL);
5334 gcc_assert (cfg_edge->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE));
5336 enum tree_code op = gimple_cond_code (cond_stmt);
5337 tree lhs = gimple_cond_lhs (cond_stmt);
5338 tree rhs = gimple_cond_rhs (cond_stmt);
5339 if (cfg_edge->flags & EDGE_FALSE_VALUE)
5340 op = invert_tree_comparison (op, false /* honor_nans */);
5341 return add_constraint (lhs, op, rhs, ctxt, out);
5344 /* Return true iff SWITCH_STMT has a non-default label that contains
5345 INT_CST. */
5347 static bool
5348 has_nondefault_case_for_value_p (const gswitch *switch_stmt, tree int_cst)
5350 /* We expect the initial label to be the default; skip it. */
5351 gcc_assert (CASE_LOW (gimple_switch_label (switch_stmt, 0)) == NULL);
5352 unsigned min_idx = 1;
5353 unsigned max_idx = gimple_switch_num_labels (switch_stmt) - 1;
5355 /* Binary search: try to find the label containing INT_CST.
5356 This requires the cases to be sorted by CASE_LOW (done by the
5357 gimplifier). */
5358 while (max_idx >= min_idx)
5360 unsigned case_idx = (min_idx + max_idx) / 2;
5361 tree label = gimple_switch_label (switch_stmt, case_idx);
5362 tree low = CASE_LOW (label);
5363 gcc_assert (low);
5364 tree high = CASE_HIGH (label);
5365 if (!high)
5366 high = low;
5367 if (tree_int_cst_compare (int_cst, low) < 0)
5369 /* INT_CST is below the range of this label. */
5370 gcc_assert (case_idx > 0);
5371 max_idx = case_idx - 1;
5373 else if (tree_int_cst_compare (int_cst, high) > 0)
5375 /* INT_CST is above the range of this case. */
5376 min_idx = case_idx + 1;
5378 else
5379 /* This case contains INT_CST. */
5380 return true;
5382 /* Not found. */
5383 return false;
5386 /* Return true iff SWITCH_STMT (which must be on an enum value)
5387 has nondefault cases handling all values in the enum. */
5389 static bool
5390 has_nondefault_cases_for_all_enum_values_p (const gswitch *switch_stmt,
5391 tree type)
5393 gcc_assert (switch_stmt);
5394 gcc_assert (TREE_CODE (type) == ENUMERAL_TYPE);
5396 for (tree enum_val_iter = TYPE_VALUES (type);
5397 enum_val_iter;
5398 enum_val_iter = TREE_CHAIN (enum_val_iter))
5400 tree enum_val = TREE_VALUE (enum_val_iter);
5401 gcc_assert (TREE_CODE (enum_val) == CONST_DECL);
5402 gcc_assert (TREE_CODE (DECL_INITIAL (enum_val)) == INTEGER_CST);
5403 if (!has_nondefault_case_for_value_p (switch_stmt,
5404 DECL_INITIAL (enum_val)))
5405 return false;
5407 return true;
5410 /* Given an EDGE guarded by SWITCH_STMT, determine appropriate constraints
5411 for the edge to be taken.
5413 If they are feasible, add the constraints and return true.
5415 Return false if the constraints contradict existing knowledge
5416 (and so the edge should not be taken).
5417 When returning false, if OUT is non-NULL, write a new rejected_constraint
5418 to it. */
5420 bool
5421 region_model::
5422 apply_constraints_for_gswitch (const switch_cfg_superedge &edge,
5423 const gswitch *switch_stmt,
5424 region_model_context *ctxt,
5425 std::unique_ptr<rejected_constraint> *out)
5427 tree index = gimple_switch_index (switch_stmt);
5428 const svalue *index_sval = get_rvalue (index, ctxt);
5429 bool check_index_type = true;
5431 /* With -fshort-enum, there may be a type cast. */
5432 if (ctxt && index_sval->get_kind () == SK_UNARYOP
5433 && TREE_CODE (index_sval->get_type ()) == INTEGER_TYPE)
5435 const unaryop_svalue *unaryop = as_a <const unaryop_svalue *> (index_sval);
5436 if (unaryop->get_op () == NOP_EXPR
5437 && is_a <const initial_svalue *> (unaryop->get_arg ()))
5438 if (const initial_svalue *initvalop = (as_a <const initial_svalue *>
5439 (unaryop->get_arg ())))
5440 if (TREE_CODE (initvalop->get_type ()) == ENUMERAL_TYPE)
5442 index_sval = initvalop;
5443 check_index_type = false;
5447 /* If we're switching based on an enum type, assume that the user is only
5448 working with values from the enum. Hence if this is an
5449 implicitly-created "default", assume it doesn't get followed.
5450 This fixes numerous "uninitialized" false positives where we otherwise
5451 consider jumping past the initialization cases. */
5453 if (/* Don't check during feasibility-checking (when ctxt is NULL). */
5454 ctxt
5455 /* Must be an enum value. */
5456 && index_sval->get_type ()
5457 && (!check_index_type
5458 || TREE_CODE (TREE_TYPE (index)) == ENUMERAL_TYPE)
5459 && TREE_CODE (index_sval->get_type ()) == ENUMERAL_TYPE
5460 /* If we have a constant, then we can check it directly. */
5461 && index_sval->get_kind () != SK_CONSTANT
5462 && edge.implicitly_created_default_p ()
5463 && has_nondefault_cases_for_all_enum_values_p (switch_stmt,
5464 index_sval->get_type ())
5465 /* Don't do this if there's a chance that the index is
5466 attacker-controlled. */
5467 && !ctxt->possibly_tainted_p (index_sval))
5469 if (out)
5470 *out = make_unique <rejected_default_case> (*this);
5471 return false;
5474 bounded_ranges_manager *ranges_mgr = get_range_manager ();
5475 const bounded_ranges *all_cases_ranges
5476 = ranges_mgr->get_or_create_ranges_for_switch (&edge, switch_stmt);
5477 bool sat = m_constraints->add_bounded_ranges (index_sval, all_cases_ranges);
5478 if (!sat && out)
5479 *out = make_unique <rejected_ranges_constraint> (*this, index, all_cases_ranges);
5480 if (sat && ctxt && !all_cases_ranges->empty_p ())
5481 ctxt->on_bounded_ranges (*index_sval, *all_cases_ranges);
5482 return sat;
5485 /* Given an edge reached by GOTO_STMT, determine appropriate constraints
5486 for the edge to be taken.
5488 If they are feasible, add the constraints and return true.
5490 Return false if the constraints contradict existing knowledge
5491 (and so the edge should not be taken). */
5493 bool
5494 region_model::apply_constraints_for_ggoto (const cfg_superedge &edge,
5495 const ggoto *goto_stmt,
5496 region_model_context *ctxt)
5498 tree dest = gimple_goto_dest (goto_stmt);
5499 const svalue *dest_sval = get_rvalue (dest, ctxt);
5501 /* If we know we were jumping to a specific label. */
5502 if (tree dst_label = edge.m_dest->get_label ())
5504 const label_region *dst_label_reg
5505 = m_mgr->get_region_for_label (dst_label);
5506 const svalue *dst_label_ptr
5507 = m_mgr->get_ptr_svalue (ptr_type_node, dst_label_reg);
5509 if (!add_constraint (dest_sval, EQ_EXPR, dst_label_ptr, ctxt))
5510 return false;
5513 return true;
5516 /* Apply any constraints due to an exception being thrown at LAST_STMT.
5518 If they are feasible, add the constraints and return true.
5520 Return false if the constraints contradict existing knowledge
5521 (and so the edge should not be taken).
5522 When returning false, if OUT is non-NULL, write a new rejected_constraint
5523 to it. */
5525 bool
5526 region_model::
5527 apply_constraints_for_exception (const gimple *last_stmt,
5528 region_model_context *ctxt,
5529 std::unique_ptr<rejected_constraint> *out)
5531 gcc_assert (last_stmt);
5532 if (const gcall *call = dyn_cast <const gcall *> (last_stmt))
5533 if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
5534 if (is_named_call_p (callee_fndecl, "operator new", call, 1)
5535 || is_named_call_p (callee_fndecl, "operator new []", call, 1))
5537 /* We have an exception thrown from operator new.
5538 Add a constraint that the result was NULL, to avoid a false
5539 leak report due to the result being lost when following
5540 the EH edge. */
5541 if (tree lhs = gimple_call_lhs (call))
5542 return add_constraint (lhs, EQ_EXPR, null_pointer_node, ctxt, out);
5543 return true;
5545 return true;
5548 /* For use with push_frame when handling a top-level call within the analysis.
5549 PARAM has a defined but unknown initial value.
5550 Anything it points to has escaped, since the calling context "knows"
5551 the pointer, and thus calls to unknown functions could read/write into
5552 the region.
5553 If NONNULL is true, then assume that PARAM must be non-NULL. */
5555 void
5556 region_model::on_top_level_param (tree param,
5557 bool nonnull,
5558 region_model_context *ctxt)
5560 if (POINTER_TYPE_P (TREE_TYPE (param)))
5562 const region *param_reg = get_lvalue (param, ctxt);
5563 const svalue *init_ptr_sval
5564 = m_mgr->get_or_create_initial_value (param_reg);
5565 const region *pointee_reg = m_mgr->get_symbolic_region (init_ptr_sval);
5566 m_store.mark_as_escaped (pointee_reg);
5567 if (nonnull)
5569 const svalue *null_ptr_sval
5570 = m_mgr->get_or_create_null_ptr (TREE_TYPE (param));
5571 add_constraint (init_ptr_sval, NE_EXPR, null_ptr_sval, ctxt);
5576 /* Update this region_model to reflect pushing a frame onto the stack
5577 for a call to FUN.
5579 If ARG_SVALS is non-NULL, use it to populate the parameters
5580 in the new frame.
5581 Otherwise, the params have their initial_svalues.
5583 Return the frame_region for the new frame. */
5585 const region *
5586 region_model::push_frame (function *fun, const vec<const svalue *> *arg_svals,
5587 region_model_context *ctxt)
5589 m_current_frame = m_mgr->get_frame_region (m_current_frame, fun);
5590 if (arg_svals)
5592 /* Arguments supplied from a caller frame. */
5593 tree fndecl = fun->decl;
5594 unsigned idx = 0;
5595 for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
5596 iter_parm = DECL_CHAIN (iter_parm), ++idx)
5598 /* If there's a mismatching declaration, the call stmt might
5599 not have enough args. Handle this case by leaving the
5600 rest of the params as uninitialized. */
5601 if (idx >= arg_svals->length ())
5602 break;
5603 tree parm_lval = iter_parm;
5604 if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
5605 parm_lval = parm_default_ssa;
5606 const region *parm_reg = get_lvalue (parm_lval, ctxt);
5607 const svalue *arg_sval = (*arg_svals)[idx];
5608 set_value (parm_reg, arg_sval, ctxt);
5611 /* Handle any variadic args. */
5612 unsigned va_arg_idx = 0;
5613 for (; idx < arg_svals->length (); idx++, va_arg_idx++)
5615 const svalue *arg_sval = (*arg_svals)[idx];
5616 const region *var_arg_reg
5617 = m_mgr->get_var_arg_region (m_current_frame,
5618 va_arg_idx);
5619 set_value (var_arg_reg, arg_sval, ctxt);
5622 else
5624 /* Otherwise we have a top-level call within the analysis. The params
5625 have defined but unknown initial values.
5626 Anything they point to has escaped. */
5627 tree fndecl = fun->decl;
5629 /* Handle "__attribute__((nonnull))". */
5630 tree fntype = TREE_TYPE (fndecl);
5631 bitmap nonnull_args = get_nonnull_args (fntype);
5633 unsigned parm_idx = 0;
5634 for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
5635 iter_parm = DECL_CHAIN (iter_parm))
5637 bool non_null = (nonnull_args
5638 ? (bitmap_empty_p (nonnull_args)
5639 || bitmap_bit_p (nonnull_args, parm_idx))
5640 : false);
5641 if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
5642 on_top_level_param (parm_default_ssa, non_null, ctxt);
5643 else
5644 on_top_level_param (iter_parm, non_null, ctxt);
5645 parm_idx++;
5648 BITMAP_FREE (nonnull_args);
5651 return m_current_frame;
5654 /* Get the function of the top-most frame in this region_model's stack.
5655 There must be such a frame. */
5657 function *
5658 region_model::get_current_function () const
5660 const frame_region *frame = get_current_frame ();
5661 gcc_assert (frame);
5662 return frame->get_function ();
5665 /* Pop the topmost frame_region from this region_model's stack;
5667 If RESULT_LVALUE is non-null, copy any return value from the frame
5668 into the corresponding region (evaluated with respect to the *caller*
5669 frame, rather than the called frame).
5670 If OUT_RESULT is non-null, copy any return value from the frame
5671 into *OUT_RESULT.
5673 If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
5674 This is for use when unwinding frames e.g. due to longjmp, to suppress
5675 erroneously reporting uninitialized return values.
5677 Purge the frame region and all its descendent regions.
5678 Convert any pointers that point into such regions into
5679 POISON_KIND_POPPED_STACK svalues. */
5681 void
5682 region_model::pop_frame (tree result_lvalue,
5683 const svalue **out_result,
5684 region_model_context *ctxt,
5685 bool eval_return_svalue)
5687 gcc_assert (m_current_frame);
5689 const region_model pre_popped_model = *this;
5690 const frame_region *frame_reg = m_current_frame;
5692 /* Notify state machines. */
5693 if (ctxt)
5694 ctxt->on_pop_frame (frame_reg);
5696 /* Evaluate the result, within the callee frame. */
5697 tree fndecl = m_current_frame->get_function ()->decl;
5698 tree result = DECL_RESULT (fndecl);
5699 const svalue *retval = NULL;
5700 if (result
5701 && TREE_TYPE (result) != void_type_node
5702 && eval_return_svalue)
5704 retval = get_rvalue (result, ctxt);
5705 if (out_result)
5706 *out_result = retval;
5709 /* Pop the frame. */
5710 m_current_frame = m_current_frame->get_calling_frame ();
5712 if (result_lvalue && retval)
5714 gcc_assert (eval_return_svalue);
5716 /* Compute result_dst_reg using RESULT_LVALUE *after* popping
5717 the frame, but before poisoning pointers into the old frame. */
5718 const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);
5719 set_value (result_dst_reg, retval, ctxt);
5722 unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK);
5723 notify_on_pop_frame (this, &pre_popped_model, retval, ctxt);
5726 /* Get the number of frames in this region_model's stack. */
5729 region_model::get_stack_depth () const
5731 const frame_region *frame = get_current_frame ();
5732 if (frame)
5733 return frame->get_stack_depth ();
5734 else
5735 return 0;
5738 /* Get the frame_region with the given index within the stack.
5739 The frame_region must exist. */
5741 const frame_region *
5742 region_model::get_frame_at_index (int index) const
5744 const frame_region *frame = get_current_frame ();
5745 gcc_assert (frame);
5746 gcc_assert (index >= 0);
5747 gcc_assert (index <= frame->get_index ());
5748 while (index != frame->get_index ())
5750 frame = frame->get_calling_frame ();
5751 gcc_assert (frame);
5753 return frame;
5756 /* Unbind svalues for any regions in REG and below.
5757 Find any pointers to such regions; convert them to
5758 poisoned values of kind PKIND.
5759 Also purge any dynamic extents. */
5761 void
5762 region_model::unbind_region_and_descendents (const region *reg,
5763 enum poison_kind pkind)
5765 /* Gather a set of base regions to be unbound. */
5766 hash_set<const region *> base_regs;
5767 for (store::cluster_map_t::iterator iter = m_store.begin ();
5768 iter != m_store.end (); ++iter)
5770 const region *iter_base_reg = (*iter).first;
5771 if (iter_base_reg->descendent_of_p (reg))
5772 base_regs.add (iter_base_reg);
5774 for (hash_set<const region *>::iterator iter = base_regs.begin ();
5775 iter != base_regs.end (); ++iter)
5776 m_store.purge_cluster (*iter);
5778 /* Find any pointers to REG or its descendents; convert to poisoned. */
5779 poison_any_pointers_to_descendents (reg, pkind);
5781 /* Purge dynamic extents of any base regions in REG and below
5782 (e.g. VLAs and alloca stack regions). */
5783 for (auto iter : m_dynamic_extents)
5785 const region *iter_reg = iter.first;
5786 if (iter_reg->descendent_of_p (reg))
5787 unset_dynamic_extents (iter_reg);
5791 /* Implementation of BindingVisitor.
5792 Update the bound svalues for regions below REG to use poisoned
5793 values instead. */
5795 struct bad_pointer_finder
5797 bad_pointer_finder (const region *reg, enum poison_kind pkind,
5798 region_model_manager *mgr)
5799 : m_reg (reg), m_pkind (pkind), m_mgr (mgr), m_count (0)
5802 void on_binding (const binding_key *, const svalue *&sval)
5804 if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
5806 const region *ptr_dst = ptr_sval->get_pointee ();
5807 /* Poison ptrs to descendents of REG, but not to REG itself,
5808 otherwise double-free detection doesn't work (since sm-state
5809 for "free" is stored on the original ptr svalue). */
5810 if (ptr_dst->descendent_of_p (m_reg)
5811 && ptr_dst != m_reg)
5813 sval = m_mgr->get_or_create_poisoned_svalue (m_pkind,
5814 sval->get_type ());
5815 ++m_count;
5820 const region *m_reg;
5821 enum poison_kind m_pkind;
5822 region_model_manager *const m_mgr;
5823 int m_count;
5826 /* Find any pointers to REG or its descendents; convert them to
5827 poisoned values of kind PKIND.
5828 Return the number of pointers that were poisoned. */
5831 region_model::poison_any_pointers_to_descendents (const region *reg,
5832 enum poison_kind pkind)
5834 bad_pointer_finder bv (reg, pkind, m_mgr);
5835 m_store.for_each_binding (bv);
5836 return bv.m_count;
5839 /* Attempt to merge THIS with OTHER_MODEL, writing the result
5840 to OUT_MODEL. Use POINT to distinguish values created as a
5841 result of merging. */
5843 bool
5844 region_model::can_merge_with_p (const region_model &other_model,
5845 const program_point &point,
5846 region_model *out_model,
5847 const extrinsic_state *ext_state,
5848 const program_state *state_a,
5849 const program_state *state_b) const
5851 gcc_assert (out_model);
5852 gcc_assert (m_mgr == other_model.m_mgr);
5853 gcc_assert (m_mgr == out_model->m_mgr);
5855 if (m_current_frame != other_model.m_current_frame)
5856 return false;
5857 out_model->m_current_frame = m_current_frame;
5859 model_merger m (this, &other_model, point, out_model,
5860 ext_state, state_a, state_b);
5862 if (!store::can_merge_p (&m_store, &other_model.m_store,
5863 &out_model->m_store, m_mgr->get_store_manager (),
5864 &m))
5865 return false;
5867 if (!m_dynamic_extents.can_merge_with_p (other_model.m_dynamic_extents,
5868 &out_model->m_dynamic_extents))
5869 return false;
5871 /* Merge constraints. */
5872 constraint_manager::merge (*m_constraints,
5873 *other_model.m_constraints,
5874 out_model->m_constraints);
5876 for (auto iter : m.m_svals_changing_meaning)
5877 out_model->m_constraints->purge_state_involving (iter);
5879 return true;
5882 /* Attempt to get the fndecl used at CALL, if known, or NULL_TREE
5883 otherwise. */
5885 tree
5886 region_model::get_fndecl_for_call (const gcall *call,
5887 region_model_context *ctxt)
5889 tree fn_ptr = gimple_call_fn (call);
5890 if (fn_ptr == NULL_TREE)
5891 return NULL_TREE;
5892 const svalue *fn_ptr_sval = get_rvalue (fn_ptr, ctxt);
5893 if (const region_svalue *fn_ptr_ptr
5894 = fn_ptr_sval->dyn_cast_region_svalue ())
5896 const region *reg = fn_ptr_ptr->get_pointee ();
5897 if (const function_region *fn_reg = reg->dyn_cast_function_region ())
5899 tree fn_decl = fn_reg->get_fndecl ();
5900 cgraph_node *node = cgraph_node::get (fn_decl);
5901 if (!node)
5902 return NULL_TREE;
5903 const cgraph_node *ultimate_node = node->ultimate_alias_target ();
5904 if (ultimate_node)
5905 return ultimate_node->decl;
5909 return NULL_TREE;
5912 /* Would be much simpler to use a lambda here, if it were supported. */
5914 struct append_regions_cb_data
5916 const region_model *model;
5917 auto_vec<const decl_region *> *out;
5920 /* Populate *OUT with all decl_regions in the current
5921 frame that have clusters within the store. */
5923 void
5924 region_model::
5925 get_regions_for_current_frame (auto_vec<const decl_region *> *out) const
5927 append_regions_cb_data data;
5928 data.model = this;
5929 data.out = out;
5930 m_store.for_each_cluster (append_regions_cb, &data);
5933 /* Implementation detail of get_regions_for_current_frame. */
5935 void
5936 region_model::append_regions_cb (const region *base_reg,
5937 append_regions_cb_data *cb_data)
5939 if (base_reg->get_parent_region () != cb_data->model->m_current_frame)
5940 return;
5941 if (const decl_region *decl_reg = base_reg->dyn_cast_decl_region ())
5942 cb_data->out->safe_push (decl_reg);
5946 /* Abstract class for diagnostics related to the use of
5947 floating-point arithmetic where precision is needed. */
5949 class imprecise_floating_point_arithmetic : public pending_diagnostic
5951 public:
5952 int get_controlling_option () const final override
5954 return OPT_Wanalyzer_imprecise_fp_arithmetic;
5958 /* Concrete diagnostic to complain about uses of floating-point arithmetic
5959 in the size argument of malloc etc. */
5961 class float_as_size_arg : public imprecise_floating_point_arithmetic
5963 public:
5964 float_as_size_arg (tree arg) : m_arg (arg)
5967 const char *get_kind () const final override
5969 return "float_as_size_arg_diagnostic";
5972 bool subclass_equal_p (const pending_diagnostic &other) const final override
5974 return same_tree_p (m_arg, ((const float_as_size_arg &) other).m_arg);
5977 bool emit (diagnostic_emission_context &ctxt) final override
5979 bool warned = ctxt.warn ("use of floating-point arithmetic here might"
5980 " yield unexpected results");
5981 if (warned)
5982 inform (ctxt.get_location (),
5983 "only use operands of an integer type"
5984 " inside the size argument");
5985 return warned;
5988 label_text describe_final_event (const evdesc::final_event &ev) final
5989 override
5991 if (m_arg)
5992 return ev.formatted_print ("operand %qE is of type %qT",
5993 m_arg, TREE_TYPE (m_arg));
5994 return ev.formatted_print ("at least one operand of the size argument is"
5995 " of a floating-point type");
5998 private:
5999 tree m_arg;
6002 /* Visitor to find uses of floating-point variables/constants in an svalue. */
6004 class contains_floating_point_visitor : public visitor
6006 public:
6007 contains_floating_point_visitor (const svalue *root_sval) : m_result (NULL)
6009 root_sval->accept (this);
6012 const svalue *get_svalue_to_report ()
6014 return m_result;
6017 void visit_constant_svalue (const constant_svalue *sval) final override
6019 /* At the point the analyzer runs, constant integer operands in a floating
6020 point expression are already implictly converted to floating-points.
6021 Thus, we do prefer to report non-constants such that the diagnostic
6022 always reports a floating-point operand. */
6023 tree type = sval->get_type ();
6024 if (type && FLOAT_TYPE_P (type) && !m_result)
6025 m_result = sval;
6028 void visit_conjured_svalue (const conjured_svalue *sval) final override
6030 tree type = sval->get_type ();
6031 if (type && FLOAT_TYPE_P (type))
6032 m_result = sval;
6035 void visit_initial_svalue (const initial_svalue *sval) final override
6037 tree type = sval->get_type ();
6038 if (type && FLOAT_TYPE_P (type))
6039 m_result = sval;
6042 private:
6043 /* Non-null if at least one floating-point operand was found. */
6044 const svalue *m_result;
6047 /* May complain about uses of floating-point operands in SIZE_IN_BYTES. */
6049 void
6050 region_model::check_dynamic_size_for_floats (const svalue *size_in_bytes,
6051 region_model_context *ctxt) const
6053 gcc_assert (ctxt);
6055 contains_floating_point_visitor v (size_in_bytes);
6056 if (const svalue *float_sval = v.get_svalue_to_report ())
6058 tree diag_arg = get_representative_tree (float_sval);
6059 ctxt->warn (make_unique<float_as_size_arg> (diag_arg));
6063 /* Return a region describing a heap-allocated block of memory.
6064 Use CTXT to complain about tainted sizes.
6066 Reuse an existing heap_allocated_region if it's not being referenced by
6067 this region_model; otherwise create a new one.
6069 Optionally (update_state_machine) transitions the pointer pointing to the
6070 heap_allocated_region from start to assumed non-null. */
6072 const region *
6073 region_model::get_or_create_region_for_heap_alloc (const svalue *size_in_bytes,
6074 region_model_context *ctxt,
6075 bool update_state_machine,
6076 const call_details *cd)
6078 /* Determine which regions are referenced in this region_model, so that
6079 we can reuse an existing heap_allocated_region if it's not in use on
6080 this path. */
6081 auto_bitmap base_regs_in_use;
6082 get_referenced_base_regions (base_regs_in_use);
6084 /* Don't reuse regions that are marked as TOUCHED. */
6085 for (store::cluster_map_t::iterator iter = m_store.begin ();
6086 iter != m_store.end (); ++iter)
6087 if ((*iter).second->touched_p ())
6089 const region *base_reg = (*iter).first;
6090 bitmap_set_bit (base_regs_in_use, base_reg->get_id ());
6093 const region *reg
6094 = m_mgr->get_or_create_region_for_heap_alloc (base_regs_in_use);
6095 if (size_in_bytes)
6096 if (compat_types_p (size_in_bytes->get_type (), size_type_node))
6097 set_dynamic_extents (reg, size_in_bytes, ctxt);
6099 if (update_state_machine && cd)
6101 const svalue *ptr_sval
6102 = m_mgr->get_ptr_svalue (cd->get_lhs_type (), reg);
6103 transition_ptr_sval_non_null (ctxt, ptr_sval);
6106 return reg;
6109 /* Populate OUT_IDS with the set of IDs of those base regions which are
6110 reachable in this region_model. */
6112 void
6113 region_model::get_referenced_base_regions (auto_bitmap &out_ids) const
6115 reachable_regions reachable_regs (const_cast<region_model *> (this));
6116 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
6117 &reachable_regs);
6118 /* Get regions for locals that have explicitly bound values. */
6119 for (store::cluster_map_t::iterator iter = m_store.begin ();
6120 iter != m_store.end (); ++iter)
6122 const region *base_reg = (*iter).first;
6123 if (const region *parent = base_reg->get_parent_region ())
6124 if (parent->get_kind () == RK_FRAME)
6125 reachable_regs.add (base_reg, false);
6128 bitmap_clear (out_ids);
6129 for (auto iter_reg : reachable_regs)
6130 bitmap_set_bit (out_ids, iter_reg->get_id ());
6133 /* Return a new region describing a block of memory allocated within the
6134 current frame.
6135 Use CTXT to complain about tainted sizes. */
6137 const region *
6138 region_model::create_region_for_alloca (const svalue *size_in_bytes,
6139 region_model_context *ctxt)
6141 const region *reg = m_mgr->create_region_for_alloca (m_current_frame);
6142 if (compat_types_p (size_in_bytes->get_type (), size_type_node))
6143 set_dynamic_extents (reg, size_in_bytes, ctxt);
6144 return reg;
6147 /* Record that the size of REG is SIZE_IN_BYTES.
6148 Use CTXT to complain about tainted sizes. */
6150 void
6151 region_model::set_dynamic_extents (const region *reg,
6152 const svalue *size_in_bytes,
6153 region_model_context *ctxt)
6155 assert_compat_types (size_in_bytes->get_type (), size_type_node);
6156 if (ctxt)
6158 check_dynamic_size_for_taint (reg->get_memory_space (), size_in_bytes,
6159 ctxt);
6160 check_dynamic_size_for_floats (size_in_bytes, ctxt);
6162 m_dynamic_extents.put (reg, size_in_bytes);
6165 /* Get the recording of REG in bytes, or NULL if no dynamic size was
6166 recorded. */
6168 const svalue *
6169 region_model::get_dynamic_extents (const region *reg) const
6171 if (const svalue * const *slot = m_dynamic_extents.get (reg))
6172 return *slot;
6173 return NULL;
6176 /* Unset any recorded dynamic size of REG. */
6178 void
6179 region_model::unset_dynamic_extents (const region *reg)
6181 m_dynamic_extents.remove (reg);
6184 /* A subclass of pending_diagnostic for complaining about uninitialized data
6185 being copied across a trust boundary to an untrusted output
6186 (e.g. copy_to_user infoleaks in the Linux kernel). */
6188 class exposure_through_uninit_copy
6189 : public pending_diagnostic_subclass<exposure_through_uninit_copy>
6191 public:
6192 exposure_through_uninit_copy (const region *src_region,
6193 const region *dest_region,
6194 const svalue *copied_sval)
6195 : m_src_region (src_region),
6196 m_dest_region (dest_region),
6197 m_copied_sval (copied_sval)
6199 gcc_assert (m_copied_sval->get_kind () == SK_POISONED
6200 || m_copied_sval->get_kind () == SK_COMPOUND);
6203 const char *get_kind () const final override
6205 return "exposure_through_uninit_copy";
6208 bool operator== (const exposure_through_uninit_copy &other) const
6210 return (m_src_region == other.m_src_region
6211 && m_dest_region == other.m_dest_region
6212 && m_copied_sval == other.m_copied_sval);
6215 int get_controlling_option () const final override
6217 return OPT_Wanalyzer_exposure_through_uninit_copy;
6220 bool emit (diagnostic_emission_context &ctxt) final override
6222 /* CWE-200: Exposure of Sensitive Information to an Unauthorized Actor. */
6223 ctxt.add_cwe (200);
6224 enum memory_space mem_space = get_src_memory_space ();
6225 bool warned;
6226 switch (mem_space)
6228 default:
6229 warned = ctxt.warn ("potential exposure of sensitive information"
6230 " by copying uninitialized data"
6231 " across trust boundary");
6232 break;
6233 case MEMSPACE_STACK:
6234 warned = ctxt.warn ("potential exposure of sensitive information"
6235 " by copying uninitialized data from stack"
6236 " across trust boundary");
6237 break;
6238 case MEMSPACE_HEAP:
6239 warned = ctxt.warn ("potential exposure of sensitive information"
6240 " by copying uninitialized data from heap"
6241 " across trust boundary");
6242 break;
6244 if (warned)
6246 const location_t loc = ctxt.get_location ();
6247 inform_number_of_uninit_bits (loc);
6248 complain_about_uninit_ranges (loc);
6250 if (mem_space == MEMSPACE_STACK)
6251 maybe_emit_fixit_hint ();
6253 return warned;
6256 label_text describe_final_event (const evdesc::final_event &) final override
6258 enum memory_space mem_space = get_src_memory_space ();
6259 switch (mem_space)
6261 default:
6262 return label_text::borrow ("uninitialized data copied here");
6264 case MEMSPACE_STACK:
6265 return label_text::borrow ("uninitialized data copied from stack here");
6267 case MEMSPACE_HEAP:
6268 return label_text::borrow ("uninitialized data copied from heap here");
6272 void mark_interesting_stuff (interesting_t *interest) final override
6274 if (m_src_region)
6275 interest->add_region_creation (m_src_region);
6278 void
6279 maybe_add_sarif_properties (sarif_object &result_obj) const final override
6281 sarif_property_bag &props = result_obj.get_or_create_properties ();
6282 #define PROPERTY_PREFIX "gcc/-Wanalyzer-exposure-through-uninit-copy/"
6283 props.set (PROPERTY_PREFIX "src_region", m_src_region->to_json ());
6284 props.set (PROPERTY_PREFIX "dest_region", m_dest_region->to_json ());
6285 props.set (PROPERTY_PREFIX "copied_sval", m_copied_sval->to_json ());
6286 #undef PROPERTY_PREFIX
6289 private:
6290 enum memory_space get_src_memory_space () const
6292 return m_src_region ? m_src_region->get_memory_space () : MEMSPACE_UNKNOWN;
6295 bit_size_t calc_num_uninit_bits () const
6297 switch (m_copied_sval->get_kind ())
6299 default:
6300 gcc_unreachable ();
6301 break;
6302 case SK_POISONED:
6304 const poisoned_svalue *poisoned_sval
6305 = as_a <const poisoned_svalue *> (m_copied_sval);
6306 gcc_assert (poisoned_sval->get_poison_kind () == POISON_KIND_UNINIT);
6308 /* Give up if don't have type information. */
6309 if (m_copied_sval->get_type () == NULL_TREE)
6310 return 0;
6312 bit_size_t size_in_bits;
6313 if (int_size_in_bits (m_copied_sval->get_type (), &size_in_bits))
6314 return size_in_bits;
6316 /* Give up if we can't get the size of the type. */
6317 return 0;
6319 break;
6320 case SK_COMPOUND:
6322 const compound_svalue *compound_sval
6323 = as_a <const compound_svalue *> (m_copied_sval);
6324 bit_size_t result = 0;
6325 /* Find keys for uninit svals. */
6326 for (auto iter : *compound_sval)
6328 const svalue *sval = iter.second;
6329 if (const poisoned_svalue *psval
6330 = sval->dyn_cast_poisoned_svalue ())
6331 if (psval->get_poison_kind () == POISON_KIND_UNINIT)
6333 const binding_key *key = iter.first;
6334 const concrete_binding *ckey
6335 = key->dyn_cast_concrete_binding ();
6336 gcc_assert (ckey);
6337 result += ckey->get_size_in_bits ();
6340 return result;
6345 void inform_number_of_uninit_bits (location_t loc) const
6347 bit_size_t num_uninit_bits = calc_num_uninit_bits ();
6348 if (num_uninit_bits <= 0)
6349 return;
6350 if (num_uninit_bits % BITS_PER_UNIT == 0)
6352 /* Express in bytes. */
6353 byte_size_t num_uninit_bytes = num_uninit_bits / BITS_PER_UNIT;
6354 if (num_uninit_bytes == 1)
6355 inform (loc, "1 byte is uninitialized");
6356 else
6357 inform (loc,
6358 "%wu bytes are uninitialized", num_uninit_bytes.to_uhwi ());
6360 else
6362 /* Express in bits. */
6363 if (num_uninit_bits == 1)
6364 inform (loc, "1 bit is uninitialized");
6365 else
6366 inform (loc,
6367 "%wu bits are uninitialized", num_uninit_bits.to_uhwi ());
6371 void complain_about_uninit_ranges (location_t loc) const
6373 if (const compound_svalue *compound_sval
6374 = m_copied_sval->dyn_cast_compound_svalue ())
6376 /* Find keys for uninit svals. */
6377 auto_vec<const concrete_binding *> uninit_keys;
6378 for (auto iter : *compound_sval)
6380 const svalue *sval = iter.second;
6381 if (const poisoned_svalue *psval
6382 = sval->dyn_cast_poisoned_svalue ())
6383 if (psval->get_poison_kind () == POISON_KIND_UNINIT)
6385 const binding_key *key = iter.first;
6386 const concrete_binding *ckey
6387 = key->dyn_cast_concrete_binding ();
6388 gcc_assert (ckey);
6389 uninit_keys.safe_push (ckey);
6392 /* Complain about them in sorted order. */
6393 uninit_keys.qsort (concrete_binding::cmp_ptr_ptr);
6395 std::unique_ptr<record_layout> layout;
6397 tree type = m_copied_sval->get_type ();
6398 if (type && TREE_CODE (type) == RECORD_TYPE)
6400 // (std::make_unique is C++14)
6401 layout = std::unique_ptr<record_layout> (new record_layout (type));
6403 if (0)
6404 layout->dump ();
6407 unsigned i;
6408 const concrete_binding *ckey;
6409 FOR_EACH_VEC_ELT (uninit_keys, i, ckey)
6411 bit_offset_t start_bit = ckey->get_start_bit_offset ();
6412 bit_offset_t next_bit = ckey->get_next_bit_offset ();
6413 complain_about_uninit_range (loc, start_bit, next_bit,
6414 layout.get ());
6419 void complain_about_uninit_range (location_t loc,
6420 bit_offset_t start_bit,
6421 bit_offset_t next_bit,
6422 const record_layout *layout) const
6424 if (layout)
6426 while (start_bit < next_bit)
6428 if (const record_layout::item *item
6429 = layout->get_item_at (start_bit))
6431 gcc_assert (start_bit >= item->get_start_bit_offset ());
6432 gcc_assert (start_bit < item->get_next_bit_offset ());
6433 if (item->get_start_bit_offset () == start_bit
6434 && item->get_next_bit_offset () <= next_bit)
6435 complain_about_fully_uninit_item (*item);
6436 else
6437 complain_about_partially_uninit_item (*item);
6438 start_bit = item->get_next_bit_offset ();
6439 continue;
6441 else
6442 break;
6446 if (start_bit >= next_bit)
6447 return;
6449 if (start_bit % 8 == 0 && next_bit % 8 == 0)
6451 /* Express in bytes. */
6452 byte_offset_t start_byte = start_bit / 8;
6453 byte_offset_t last_byte = (next_bit / 8) - 1;
6454 if (last_byte == start_byte)
6455 inform (loc,
6456 "byte %wu is uninitialized",
6457 start_byte.to_uhwi ());
6458 else
6459 inform (loc,
6460 "bytes %wu - %wu are uninitialized",
6461 start_byte.to_uhwi (),
6462 last_byte.to_uhwi ());
6464 else
6466 /* Express in bits. */
6467 bit_offset_t last_bit = next_bit - 1;
6468 if (last_bit == start_bit)
6469 inform (loc,
6470 "bit %wu is uninitialized",
6471 start_bit.to_uhwi ());
6472 else
6473 inform (loc,
6474 "bits %wu - %wu are uninitialized",
6475 start_bit.to_uhwi (),
6476 last_bit.to_uhwi ());
6480 static void
6481 complain_about_fully_uninit_item (const record_layout::item &item)
6483 tree field = item.m_field;
6484 bit_size_t num_bits = item.m_bit_range.m_size_in_bits;
6485 if (item.m_is_padding)
6487 if (num_bits % 8 == 0)
6489 /* Express in bytes. */
6490 byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
6491 if (num_bytes == 1)
6492 inform (DECL_SOURCE_LOCATION (field),
6493 "padding after field %qD is uninitialized (1 byte)",
6494 field);
6495 else
6496 inform (DECL_SOURCE_LOCATION (field),
6497 "padding after field %qD is uninitialized (%wu bytes)",
6498 field, num_bytes.to_uhwi ());
6500 else
6502 /* Express in bits. */
6503 if (num_bits == 1)
6504 inform (DECL_SOURCE_LOCATION (field),
6505 "padding after field %qD is uninitialized (1 bit)",
6506 field);
6507 else
6508 inform (DECL_SOURCE_LOCATION (field),
6509 "padding after field %qD is uninitialized (%wu bits)",
6510 field, num_bits.to_uhwi ());
6513 else
6515 if (num_bits % 8 == 0)
6517 /* Express in bytes. */
6518 byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
6519 if (num_bytes == 1)
6520 inform (DECL_SOURCE_LOCATION (field),
6521 "field %qD is uninitialized (1 byte)", field);
6522 else
6523 inform (DECL_SOURCE_LOCATION (field),
6524 "field %qD is uninitialized (%wu bytes)",
6525 field, num_bytes.to_uhwi ());
6527 else
6529 /* Express in bits. */
6530 if (num_bits == 1)
6531 inform (DECL_SOURCE_LOCATION (field),
6532 "field %qD is uninitialized (1 bit)", field);
6533 else
6534 inform (DECL_SOURCE_LOCATION (field),
6535 "field %qD is uninitialized (%wu bits)",
6536 field, num_bits.to_uhwi ());
6541 static void
6542 complain_about_partially_uninit_item (const record_layout::item &item)
6544 tree field = item.m_field;
6545 if (item.m_is_padding)
6546 inform (DECL_SOURCE_LOCATION (field),
6547 "padding after field %qD is partially uninitialized",
6548 field);
6549 else
6550 inform (DECL_SOURCE_LOCATION (field),
6551 "field %qD is partially uninitialized",
6552 field);
6553 /* TODO: ideally we'd describe what parts are uninitialized. */
6556 void maybe_emit_fixit_hint () const
6558 if (tree decl = m_src_region->maybe_get_decl ())
6560 gcc_rich_location hint_richloc (DECL_SOURCE_LOCATION (decl));
6561 hint_richloc.add_fixit_insert_after (" = {0}");
6562 inform (&hint_richloc,
6563 "suggest forcing zero-initialization by"
6564 " providing a %<{0}%> initializer");
6568 private:
6569 const region *m_src_region;
6570 const region *m_dest_region;
6571 const svalue *m_copied_sval;
6574 /* Return true if any part of SVAL is uninitialized. */
6576 static bool
6577 contains_uninit_p (const svalue *sval)
6579 struct uninit_finder : public visitor
6581 public:
6582 uninit_finder () : m_found_uninit (false) {}
6583 void visit_poisoned_svalue (const poisoned_svalue *sval)
6585 if (sval->get_poison_kind () == POISON_KIND_UNINIT)
6586 m_found_uninit = true;
6588 bool m_found_uninit;
6591 uninit_finder v;
6592 sval->accept (&v);
6594 return v.m_found_uninit;
6597 /* Function for use by plugins when simulating writing data through a
6598 pointer to an "untrusted" region DST_REG (and thus crossing a security
6599 boundary), such as copying data to user space in an OS kernel.
6601 Check that COPIED_SVAL is fully initialized. If not, complain about
6602 an infoleak to CTXT.
6604 SRC_REG can be NULL; if non-NULL it is used as a hint in the diagnostic
6605 as to where COPIED_SVAL came from. */
6607 void
6608 region_model::maybe_complain_about_infoleak (const region *dst_reg,
6609 const svalue *copied_sval,
6610 const region *src_reg,
6611 region_model_context *ctxt)
6613 /* Check for exposure. */
6614 if (contains_uninit_p (copied_sval))
6615 ctxt->warn (make_unique<exposure_through_uninit_copy> (src_reg,
6616 dst_reg,
6617 copied_sval));
6620 /* Set errno to a positive symbolic int, as if some error has occurred. */
6622 void
6623 region_model::set_errno (const call_details &cd)
6625 const region *errno_reg = m_mgr->get_errno_region ();
6626 conjured_purge p (this, cd.get_ctxt ());
6627 const svalue *new_errno_sval
6628 = m_mgr->get_or_create_conjured_svalue (integer_type_node,
6629 cd.get_call_stmt (),
6630 errno_reg, p);
6631 const svalue *zero
6632 = m_mgr->get_or_create_int_cst (integer_type_node, 0);
6633 add_constraint (new_errno_sval, GT_EXPR, zero, cd.get_ctxt ());
6634 set_value (errno_reg, new_errno_sval, cd.get_ctxt ());
6637 /* class noop_region_model_context : public region_model_context. */
6639 void
6640 noop_region_model_context::add_note (std::unique_ptr<pending_note>)
6644 void
6645 noop_region_model_context::add_event (std::unique_ptr<checker_event>)
6649 void
6650 noop_region_model_context::bifurcate (std::unique_ptr<custom_edge_info>)
6654 void
6655 noop_region_model_context::terminate_path ()
6659 /* class region_model_context_decorator : public region_model_context. */
6661 void
6662 region_model_context_decorator::add_event (std::unique_ptr<checker_event> event)
6664 if (m_inner)
6665 m_inner->add_event (std::move (event));
6668 /* struct model_merger. */
6670 /* Dump a multiline representation of this merger to PP. */
6672 void
6673 model_merger::dump_to_pp (pretty_printer *pp, bool simple) const
6675 pp_string (pp, "model A:");
6676 pp_newline (pp);
6677 m_model_a->dump_to_pp (pp, simple, true);
6678 pp_newline (pp);
6680 pp_string (pp, "model B:");
6681 pp_newline (pp);
6682 m_model_b->dump_to_pp (pp, simple, true);
6683 pp_newline (pp);
6685 pp_string (pp, "merged model:");
6686 pp_newline (pp);
6687 m_merged_model->dump_to_pp (pp, simple, true);
6688 pp_newline (pp);
6691 /* Dump a multiline representation of this merger to FILE. */
6693 void
6694 model_merger::dump (FILE *fp, bool simple) const
6696 pretty_printer pp;
6697 pp_format_decoder (&pp) = default_tree_printer;
6698 pp_show_color (&pp) = pp_show_color (global_dc->printer);
6699 pp.buffer->stream = fp;
6700 dump_to_pp (&pp, simple);
6701 pp_flush (&pp);
6704 /* Dump a multiline representation of this merger to stderr. */
6706 DEBUG_FUNCTION void
6707 model_merger::dump (bool simple) const
6709 dump (stderr, simple);
6712 /* Return true if it's OK to merge SVAL with other svalues. */
6714 bool
6715 model_merger::mergeable_svalue_p (const svalue *sval) const
6717 if (m_ext_state)
6719 /* Reject merging svalues that have non-purgable sm-state,
6720 to avoid falsely reporting memory leaks by merging them
6721 with something else. For example, given a local var "p",
6722 reject the merger of a:
6723 store_a mapping "p" to a malloc-ed ptr
6724 with:
6725 store_b mapping "p" to a NULL ptr. */
6726 if (m_state_a)
6727 if (!m_state_a->can_purge_p (*m_ext_state, sval))
6728 return false;
6729 if (m_state_b)
6730 if (!m_state_b->can_purge_p (*m_ext_state, sval))
6731 return false;
6733 return true;
6736 /* Mark WIDENING_SVAL as changing meaning during the merge. */
6738 void
6739 model_merger::on_widening_reuse (const widening_svalue *widening_sval)
6741 m_svals_changing_meaning.add (widening_sval);
6744 } // namespace ana
6746 /* Dump RMODEL fully to stderr (i.e. without summarization). */
6748 DEBUG_FUNCTION void
6749 debug (const region_model &rmodel)
6751 rmodel.dump (false);
6754 /* class rejected_op_constraint : public rejected_constraint. */
6756 void
6757 rejected_op_constraint::dump_to_pp (pretty_printer *pp) const
6759 region_model m (m_model);
6760 const svalue *lhs_sval = m.get_rvalue (m_lhs, NULL);
6761 const svalue *rhs_sval = m.get_rvalue (m_rhs, NULL);
6762 lhs_sval->dump_to_pp (pp, true);
6763 pp_printf (pp, " %s ", op_symbol_code (m_op));
6764 rhs_sval->dump_to_pp (pp, true);
6767 /* class rejected_default_case : public rejected_constraint. */
6769 void
6770 rejected_default_case::dump_to_pp (pretty_printer *pp) const
6772 pp_string (pp, "implicit default for enum");
6775 /* class rejected_ranges_constraint : public rejected_constraint. */
6777 void
6778 rejected_ranges_constraint::dump_to_pp (pretty_printer *pp) const
6780 region_model m (m_model);
6781 const svalue *sval = m.get_rvalue (m_expr, NULL);
6782 sval->dump_to_pp (pp, true);
6783 pp_string (pp, " in ");
6784 m_ranges->dump_to_pp (pp, true);
6787 /* class engine. */
6789 /* engine's ctor. */
6791 engine::engine (const supergraph *sg, logger *logger)
6792 : m_sg (sg), m_mgr (logger)
6796 /* Dump the managed objects by class to LOGGER, and the per-class totals. */
6798 void
6799 engine::log_stats (logger *logger) const
6801 m_mgr.log_stats (logger, true);
6804 namespace ana {
6806 #if CHECKING_P
6808 namespace selftest {
6810 /* Build a constant tree of the given type from STR. */
6812 static tree
6813 build_real_cst_from_string (tree type, const char *str)
6815 REAL_VALUE_TYPE real;
6816 real_from_string (&real, str);
6817 return build_real (type, real);
6820 /* Append various "interesting" constants to OUT (e.g. NaN). */
6822 static void
6823 append_interesting_constants (auto_vec<tree> *out)
6825 out->safe_push (build_int_cst (integer_type_node, 0));
6826 out->safe_push (build_int_cst (integer_type_node, 42));
6827 out->safe_push (build_int_cst (unsigned_type_node, 0));
6828 out->safe_push (build_int_cst (unsigned_type_node, 42));
6829 out->safe_push (build_real_cst_from_string (float_type_node, "QNaN"));
6830 out->safe_push (build_real_cst_from_string (float_type_node, "-QNaN"));
6831 out->safe_push (build_real_cst_from_string (float_type_node, "SNaN"));
6832 out->safe_push (build_real_cst_from_string (float_type_node, "-SNaN"));
6833 out->safe_push (build_real_cst_from_string (float_type_node, "0.0"));
6834 out->safe_push (build_real_cst_from_string (float_type_node, "-0.0"));
6835 out->safe_push (build_real_cst_from_string (float_type_node, "Inf"));
6836 out->safe_push (build_real_cst_from_string (float_type_node, "-Inf"));
6839 /* Verify that tree_cmp is a well-behaved comparator for qsort, even
6840 if the underlying constants aren't comparable. */
6842 static void
6843 test_tree_cmp_on_constants ()
6845 auto_vec<tree> csts;
6846 append_interesting_constants (&csts);
6848 /* Try sorting every triple. */
6849 const unsigned num = csts.length ();
6850 for (unsigned i = 0; i < num; i++)
6851 for (unsigned j = 0; j < num; j++)
6852 for (unsigned k = 0; k < num; k++)
6854 auto_vec<tree> v (3);
6855 v.quick_push (csts[i]);
6856 v.quick_push (csts[j]);
6857 v.quick_push (csts[k]);
6858 v.qsort (tree_cmp);
6862 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6864 void
6865 assert_condition (const location &loc,
6866 region_model &model,
6867 const svalue *lhs, tree_code op, const svalue *rhs,
6868 tristate expected)
6870 tristate actual = model.eval_condition (lhs, op, rhs);
6871 ASSERT_EQ_AT (loc, actual, expected);
6874 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6876 void
6877 assert_condition (const location &loc,
6878 region_model &model,
6879 tree lhs, tree_code op, tree rhs,
6880 tristate expected)
6882 tristate actual = model.eval_condition (lhs, op, rhs, NULL);
6883 ASSERT_EQ_AT (loc, actual, expected);
6886 /* Implementation detail of ASSERT_DUMP_TREE_EQ. */
6888 static void
6889 assert_dump_tree_eq (const location &loc, tree t, const char *expected)
6891 auto_fix_quotes sentinel;
6892 pretty_printer pp;
6893 pp_format_decoder (&pp) = default_tree_printer;
6894 dump_tree (&pp, t);
6895 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
6898 /* Assert that dump_tree (T) is EXPECTED. */
6900 #define ASSERT_DUMP_TREE_EQ(T, EXPECTED) \
6901 SELFTEST_BEGIN_STMT \
6902 assert_dump_tree_eq ((SELFTEST_LOCATION), (T), (EXPECTED)); \
6903 SELFTEST_END_STMT
6905 /* Implementation detail of ASSERT_DUMP_EQ. */
6907 static void
6908 assert_dump_eq (const location &loc,
6909 const region_model &model,
6910 bool summarize,
6911 const char *expected)
6913 auto_fix_quotes sentinel;
6914 pretty_printer pp;
6915 pp_format_decoder (&pp) = default_tree_printer;
6917 model.dump_to_pp (&pp, summarize, true);
6918 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
6921 /* Assert that MODEL.dump_to_pp (SUMMARIZE) is EXPECTED. */
6923 #define ASSERT_DUMP_EQ(MODEL, SUMMARIZE, EXPECTED) \
6924 SELFTEST_BEGIN_STMT \
6925 assert_dump_eq ((SELFTEST_LOCATION), (MODEL), (SUMMARIZE), (EXPECTED)); \
6926 SELFTEST_END_STMT
6928 /* Smoketest for region_model::dump_to_pp. */
6930 static void
6931 test_dump ()
6933 region_model_manager mgr;
6934 region_model model (&mgr);
6936 ASSERT_DUMP_EQ (model, false,
6937 "stack depth: 0\n"
6938 "m_called_unknown_fn: FALSE\n"
6939 "constraint_manager:\n"
6940 " equiv classes:\n"
6941 " constraints:\n");
6942 ASSERT_DUMP_EQ (model, true,
6943 "stack depth: 0\n"
6944 "m_called_unknown_fn: FALSE\n"
6945 "constraint_manager:\n"
6946 " equiv classes:\n"
6947 " constraints:\n");
6950 /* Helper function for selftests. Create a struct or union type named NAME,
6951 with the fields given by the FIELD_DECLS in FIELDS.
6952 If IS_STRUCT is true create a RECORD_TYPE (aka a struct), otherwise
6953 create a UNION_TYPE. */
6955 static tree
6956 make_test_compound_type (const char *name, bool is_struct,
6957 const auto_vec<tree> *fields)
6959 tree t = make_node (is_struct ? RECORD_TYPE : UNION_TYPE);
6960 TYPE_NAME (t) = get_identifier (name);
6961 TYPE_SIZE (t) = 0;
6963 tree fieldlist = NULL;
6964 int i;
6965 tree field;
6966 FOR_EACH_VEC_ELT (*fields, i, field)
6968 gcc_assert (TREE_CODE (field) == FIELD_DECL);
6969 DECL_CONTEXT (field) = t;
6970 fieldlist = chainon (field, fieldlist);
6972 fieldlist = nreverse (fieldlist);
6973 TYPE_FIELDS (t) = fieldlist;
6975 layout_type (t);
6976 return t;
6979 /* Selftest fixture for creating the type "struct coord {int x; int y; };". */
6981 struct coord_test
6983 coord_test ()
6985 auto_vec<tree> fields;
6986 m_x_field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
6987 get_identifier ("x"), integer_type_node);
6988 fields.safe_push (m_x_field);
6989 m_y_field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
6990 get_identifier ("y"), integer_type_node);
6991 fields.safe_push (m_y_field);
6992 m_coord_type = make_test_compound_type ("coord", true, &fields);
6995 tree m_x_field;
6996 tree m_y_field;
6997 tree m_coord_type;
7000 /* Verify usage of a struct. */
7002 static void
7003 test_struct ()
7005 coord_test ct;
7007 tree c = build_global_decl ("c", ct.m_coord_type);
7008 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7009 c, ct.m_x_field, NULL_TREE);
7010 tree c_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7011 c, ct.m_y_field, NULL_TREE);
7013 tree int_17 = build_int_cst (integer_type_node, 17);
7014 tree int_m3 = build_int_cst (integer_type_node, -3);
7016 region_model_manager mgr;
7017 region_model model (&mgr);
7018 model.set_value (c_x, int_17, NULL);
7019 model.set_value (c_y, int_m3, NULL);
7021 /* Verify get_offset for "c.x". */
7023 const region *c_x_reg = model.get_lvalue (c_x, NULL);
7024 region_offset offset = c_x_reg->get_offset (&mgr);
7025 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, NULL));
7026 ASSERT_EQ (offset.get_bit_offset (), 0);
7029 /* Verify get_offset for "c.y". */
7031 const region *c_y_reg = model.get_lvalue (c_y, NULL);
7032 region_offset offset = c_y_reg->get_offset (&mgr);
7033 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, NULL));
7034 ASSERT_EQ (offset.get_bit_offset (), INT_TYPE_SIZE);
7038 /* Verify usage of an array element. */
7040 static void
7041 test_array_1 ()
7043 tree tlen = size_int (10);
7044 tree arr_type = build_array_type (char_type_node, build_index_type (tlen));
7046 tree a = build_global_decl ("a", arr_type);
7048 region_model_manager mgr;
7049 region_model model (&mgr);
7050 tree int_0 = build_int_cst (integer_type_node, 0);
7051 tree a_0 = build4 (ARRAY_REF, char_type_node,
7052 a, int_0, NULL_TREE, NULL_TREE);
7053 tree char_A = build_int_cst (char_type_node, 'A');
7054 model.set_value (a_0, char_A, NULL);
7057 /* Verify that region_model::get_representative_tree works as expected. */
7059 static void
7060 test_get_representative_tree ()
7062 region_model_manager mgr;
7064 /* STRING_CST. */
7066 tree string_cst = build_string (4, "foo");
7067 region_model m (&mgr);
7068 const svalue *str_sval = m.get_rvalue (string_cst, NULL);
7069 tree rep = m.get_representative_tree (str_sval);
7070 ASSERT_EQ (rep, string_cst);
7073 /* String literal. */
7075 tree string_cst_ptr = build_string_literal (4, "foo");
7076 region_model m (&mgr);
7077 const svalue *str_sval = m.get_rvalue (string_cst_ptr, NULL);
7078 tree rep = m.get_representative_tree (str_sval);
7079 ASSERT_DUMP_TREE_EQ (rep, "&\"foo\"[0]");
7082 /* Value of an element within an array. */
7084 tree tlen = size_int (10);
7085 tree arr_type = build_array_type (char_type_node, build_index_type (tlen));
7086 tree a = build_global_decl ("a", arr_type);
7087 placeholder_svalue test_sval (mgr.alloc_symbol_id (),
7088 char_type_node, "test value");
7090 /* Value of a[3]. */
7092 test_region_model_context ctxt;
7093 region_model model (&mgr);
7094 tree int_3 = build_int_cst (integer_type_node, 3);
7095 tree a_3 = build4 (ARRAY_REF, char_type_node,
7096 a, int_3, NULL_TREE, NULL_TREE);
7097 const region *a_3_reg = model.get_lvalue (a_3, &ctxt);
7098 model.set_value (a_3_reg, &test_sval, &ctxt);
7099 tree rep = model.get_representative_tree (&test_sval);
7100 ASSERT_DUMP_TREE_EQ (rep, "a[3]");
7103 /* Value of a[0]. */
7105 test_region_model_context ctxt;
7106 region_model model (&mgr);
7107 tree idx = build_int_cst (integer_type_node, 0);
7108 tree a_0 = build4 (ARRAY_REF, char_type_node,
7109 a, idx, NULL_TREE, NULL_TREE);
7110 const region *a_0_reg = model.get_lvalue (a_0, &ctxt);
7111 model.set_value (a_0_reg, &test_sval, &ctxt);
7112 tree rep = model.get_representative_tree (&test_sval);
7113 ASSERT_DUMP_TREE_EQ (rep, "a[0]");
7117 /* Value of a field within a struct. */
7119 coord_test ct;
7121 tree c = build_global_decl ("c", ct.m_coord_type);
7122 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7123 c, ct.m_x_field, NULL_TREE);
7124 tree c_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7125 c, ct.m_y_field, NULL_TREE);
7127 test_region_model_context ctxt;
7129 /* Value of initial field. */
7131 region_model m (&mgr);
7132 const region *c_x_reg = m.get_lvalue (c_x, &ctxt);
7133 placeholder_svalue test_sval_x (mgr.alloc_symbol_id (),
7134 integer_type_node, "test x val");
7135 m.set_value (c_x_reg, &test_sval_x, &ctxt);
7136 tree rep = m.get_representative_tree (&test_sval_x);
7137 ASSERT_DUMP_TREE_EQ (rep, "c.x");
7140 /* Value of non-initial field. */
7142 region_model m (&mgr);
7143 const region *c_y_reg = m.get_lvalue (c_y, &ctxt);
7144 placeholder_svalue test_sval_y (mgr.alloc_symbol_id (),
7145 integer_type_node, "test y val");
7146 m.set_value (c_y_reg, &test_sval_y, &ctxt);
7147 tree rep = m.get_representative_tree (&test_sval_y);
7148 ASSERT_DUMP_TREE_EQ (rep, "c.y");
7153 /* Verify that calling region_model::get_rvalue repeatedly on the same
7154 tree constant retrieves the same svalue *. */
7156 static void
7157 test_unique_constants ()
7159 tree int_0 = build_int_cst (integer_type_node, 0);
7160 tree int_42 = build_int_cst (integer_type_node, 42);
7162 test_region_model_context ctxt;
7163 region_model_manager mgr;
7164 region_model model (&mgr);
7165 ASSERT_EQ (model.get_rvalue (int_0, &ctxt), model.get_rvalue (int_0, &ctxt));
7166 ASSERT_EQ (model.get_rvalue (int_42, &ctxt),
7167 model.get_rvalue (int_42, &ctxt));
7168 ASSERT_NE (model.get_rvalue (int_0, &ctxt), model.get_rvalue (int_42, &ctxt));
7169 ASSERT_EQ (ctxt.get_num_diagnostics (), 0);
7171 /* A "(const int)42" will be a different tree from "(int)42)"... */
7172 tree const_int_type_node
7173 = build_qualified_type (integer_type_node, TYPE_QUAL_CONST);
7174 tree const_int_42 = build_int_cst (const_int_type_node, 42);
7175 ASSERT_NE (int_42, const_int_42);
7176 /* It should have a different const_svalue. */
7177 const svalue *int_42_sval = model.get_rvalue (int_42, &ctxt);
7178 const svalue *const_int_42_sval = model.get_rvalue (const_int_42, &ctxt);
7179 ASSERT_NE (int_42_sval, const_int_42_sval);
7180 /* But they should compare as equal. */
7181 ASSERT_CONDITION_TRUE (model, int_42_sval, EQ_EXPR, const_int_42_sval);
7182 ASSERT_CONDITION_FALSE (model, int_42_sval, NE_EXPR, const_int_42_sval);
7185 /* Verify that each type gets its own singleton unknown_svalue within a
7186 region_model_manager, and that NULL_TREE gets its own singleton. */
7188 static void
7189 test_unique_unknowns ()
7191 region_model_manager mgr;
7192 const svalue *unknown_int
7193 = mgr.get_or_create_unknown_svalue (integer_type_node);
7194 /* Repeated calls with the same type should get the same "unknown"
7195 svalue. */
7196 const svalue *unknown_int_2
7197 = mgr.get_or_create_unknown_svalue (integer_type_node);
7198 ASSERT_EQ (unknown_int, unknown_int_2);
7200 /* Different types (or the NULL type) should have different
7201 unknown_svalues. */
7202 const svalue *unknown_NULL_type = mgr.get_or_create_unknown_svalue (NULL);
7203 ASSERT_NE (unknown_NULL_type, unknown_int);
7205 /* Repeated calls with NULL for the type should get the same "unknown"
7206 svalue. */
7207 const svalue *unknown_NULL_type_2 = mgr.get_or_create_unknown_svalue (NULL);
7208 ASSERT_EQ (unknown_NULL_type, unknown_NULL_type_2);
7211 /* Verify that initial_svalue are handled as expected. */
7213 static void
7214 test_initial_svalue_folding ()
7216 region_model_manager mgr;
7217 tree x = build_global_decl ("x", integer_type_node);
7218 tree y = build_global_decl ("y", integer_type_node);
7220 test_region_model_context ctxt;
7221 region_model model (&mgr);
7222 const svalue *x_init = model.get_rvalue (x, &ctxt);
7223 const svalue *y_init = model.get_rvalue (y, &ctxt);
7224 ASSERT_NE (x_init, y_init);
7225 const region *x_reg = model.get_lvalue (x, &ctxt);
7226 ASSERT_EQ (x_init, mgr.get_or_create_initial_value (x_reg));
7230 /* Verify that unary ops are folded as expected. */
7232 static void
7233 test_unaryop_svalue_folding ()
7235 region_model_manager mgr;
7236 tree x = build_global_decl ("x", integer_type_node);
7237 tree y = build_global_decl ("y", integer_type_node);
7239 test_region_model_context ctxt;
7240 region_model model (&mgr);
7241 const svalue *x_init = model.get_rvalue (x, &ctxt);
7242 const svalue *y_init = model.get_rvalue (y, &ctxt);
7243 const region *x_reg = model.get_lvalue (x, &ctxt);
7244 ASSERT_EQ (x_init, mgr.get_or_create_initial_value (x_reg));
7246 /* "(int)x" -> "x". */
7247 ASSERT_EQ (x_init, mgr.get_or_create_cast (integer_type_node, x_init));
7249 /* "(void *)x" -> something other than "x". */
7250 ASSERT_NE (x_init, mgr.get_or_create_cast (ptr_type_node, x_init));
7252 /* "!(x == y)" -> "x != y". */
7253 ASSERT_EQ (mgr.get_or_create_unaryop
7254 (boolean_type_node, TRUTH_NOT_EXPR,
7255 mgr.get_or_create_binop (boolean_type_node, EQ_EXPR,
7256 x_init, y_init)),
7257 mgr.get_or_create_binop (boolean_type_node, NE_EXPR,
7258 x_init, y_init));
7259 /* "!(x > y)" -> "x <= y". */
7260 ASSERT_EQ (mgr.get_or_create_unaryop
7261 (boolean_type_node, TRUTH_NOT_EXPR,
7262 mgr.get_or_create_binop (boolean_type_node, GT_EXPR,
7263 x_init, y_init)),
7264 mgr.get_or_create_binop (boolean_type_node, LE_EXPR,
7265 x_init, y_init));
7268 /* Verify that binops on constant svalues are folded. */
7270 static void
7271 test_binop_svalue_folding ()
7273 #define NUM_CSTS 10
7274 tree cst_int[NUM_CSTS];
7275 region_model_manager mgr;
7276 const svalue *cst_sval[NUM_CSTS];
7277 for (int i = 0; i < NUM_CSTS; i++)
7279 cst_int[i] = build_int_cst (integer_type_node, i);
7280 cst_sval[i] = mgr.get_or_create_constant_svalue (cst_int[i]);
7281 ASSERT_EQ (cst_sval[i]->get_kind (), SK_CONSTANT);
7282 ASSERT_EQ (cst_sval[i]->maybe_get_constant (), cst_int[i]);
7285 for (int i = 0; i < NUM_CSTS; i++)
7286 for (int j = 0; j < NUM_CSTS; j++)
7288 if (i != j)
7289 ASSERT_NE (cst_sval[i], cst_sval[j]);
7290 if (i + j < NUM_CSTS)
7292 const svalue *sum
7293 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7294 cst_sval[i], cst_sval[j]);
7295 ASSERT_EQ (sum, cst_sval[i + j]);
7297 if (i - j >= 0)
7299 const svalue *difference
7300 = mgr.get_or_create_binop (integer_type_node, MINUS_EXPR,
7301 cst_sval[i], cst_sval[j]);
7302 ASSERT_EQ (difference, cst_sval[i - j]);
7304 if (i * j < NUM_CSTS)
7306 const svalue *product
7307 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7308 cst_sval[i], cst_sval[j]);
7309 ASSERT_EQ (product, cst_sval[i * j]);
7311 const svalue *eq = mgr.get_or_create_binop (integer_type_node, EQ_EXPR,
7312 cst_sval[i], cst_sval[j]);
7313 ASSERT_EQ (eq, i == j ? cst_sval[1] : cst_sval [0]);
7314 const svalue *neq = mgr.get_or_create_binop (integer_type_node, NE_EXPR,
7315 cst_sval[i], cst_sval[j]);
7316 ASSERT_EQ (neq, i != j ? cst_sval[1] : cst_sval [0]);
7317 // etc
7320 tree x = build_global_decl ("x", integer_type_node);
7322 test_region_model_context ctxt;
7323 region_model model (&mgr);
7324 const svalue *x_init = model.get_rvalue (x, &ctxt);
7326 /* PLUS_EXPR folding. */
7327 const svalue *x_init_plus_zero
7328 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7329 x_init, cst_sval[0]);
7330 ASSERT_EQ (x_init_plus_zero, x_init);
7331 const svalue *zero_plus_x_init
7332 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7333 cst_sval[0], x_init);
7334 ASSERT_EQ (zero_plus_x_init, x_init);
7336 /* MULT_EXPR folding. */
7337 const svalue *x_init_times_zero
7338 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7339 x_init, cst_sval[0]);
7340 ASSERT_EQ (x_init_times_zero, cst_sval[0]);
7341 const svalue *zero_times_x_init
7342 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7343 cst_sval[0], x_init);
7344 ASSERT_EQ (zero_times_x_init, cst_sval[0]);
7346 const svalue *x_init_times_one
7347 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7348 x_init, cst_sval[1]);
7349 ASSERT_EQ (x_init_times_one, x_init);
7350 const svalue *one_times_x_init
7351 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7352 cst_sval[1], x_init);
7353 ASSERT_EQ (one_times_x_init, x_init);
7355 // etc
7356 // TODO: do we want to use the match-and-simplify DSL for this?
7358 /* Verify that binops put any constants on the RHS. */
7359 const svalue *four_times_x_init
7360 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7361 cst_sval[4], x_init);
7362 const svalue *x_init_times_four
7363 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7364 x_init, cst_sval[4]);
7365 ASSERT_EQ (four_times_x_init, x_init_times_four);
7366 const binop_svalue *binop = four_times_x_init->dyn_cast_binop_svalue ();
7367 ASSERT_EQ (binop->get_op (), MULT_EXPR);
7368 ASSERT_EQ (binop->get_arg0 (), x_init);
7369 ASSERT_EQ (binop->get_arg1 (), cst_sval[4]);
7371 /* Verify that ((x + 1) + 1) == (x + 2). */
7372 const svalue *x_init_plus_one
7373 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7374 x_init, cst_sval[1]);
7375 const svalue *x_init_plus_two
7376 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7377 x_init, cst_sval[2]);
7378 const svalue *x_init_plus_one_plus_one
7379 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7380 x_init_plus_one, cst_sval[1]);
7381 ASSERT_EQ (x_init_plus_one_plus_one, x_init_plus_two);
7383 /* Verify various binops on booleans. */
7385 const svalue *sval_true = mgr.get_or_create_int_cst (boolean_type_node, 1);
7386 const svalue *sval_false = mgr.get_or_create_int_cst (boolean_type_node, 0);
7387 const svalue *sval_unknown
7388 = mgr.get_or_create_unknown_svalue (boolean_type_node);
7389 const placeholder_svalue sval_placeholder (mgr.alloc_symbol_id (),
7390 boolean_type_node, "v");
7391 for (auto op : {BIT_IOR_EXPR, TRUTH_OR_EXPR})
7393 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7394 sval_true, sval_unknown),
7395 sval_true);
7396 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7397 sval_false, sval_unknown),
7398 sval_unknown);
7399 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7400 sval_false, &sval_placeholder),
7401 &sval_placeholder);
7403 for (auto op : {BIT_AND_EXPR, TRUTH_AND_EXPR})
7405 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7406 sval_false, sval_unknown),
7407 sval_false);
7408 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7409 sval_true, sval_unknown),
7410 sval_unknown);
7411 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7412 sval_true, &sval_placeholder),
7413 &sval_placeholder);
7418 /* Verify that sub_svalues are folded as expected. */
7420 static void
7421 test_sub_svalue_folding ()
7423 coord_test ct;
7424 tree c = build_global_decl ("c", ct.m_coord_type);
7425 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7426 c, ct.m_x_field, NULL_TREE);
7428 region_model_manager mgr;
7429 region_model model (&mgr);
7430 test_region_model_context ctxt;
7431 const region *c_x_reg = model.get_lvalue (c_x, &ctxt);
7433 /* Verify that sub_svalue of "unknown" simply
7434 yields an unknown. */
7436 const svalue *unknown = mgr.get_or_create_unknown_svalue (ct.m_coord_type);
7437 const svalue *sub = mgr.get_or_create_sub_svalue (TREE_TYPE (ct.m_x_field),
7438 unknown, c_x_reg);
7439 ASSERT_EQ (sub->get_kind (), SK_UNKNOWN);
7440 ASSERT_EQ (sub->get_type (), TREE_TYPE (ct.m_x_field));
7443 /* Get BIT within VAL as a symbolic value within MGR. */
7445 static const svalue *
7446 get_bit (region_model_manager *mgr,
7447 bit_offset_t bit,
7448 unsigned HOST_WIDE_INT val)
7450 const svalue *inner_svalue
7451 = mgr->get_or_create_int_cst (unsigned_type_node, val);
7452 return mgr->get_or_create_bits_within (boolean_type_node,
7453 bit_range (bit, 1),
7454 inner_svalue);
7457 /* Verify that bits_within_svalues are folded as expected. */
7459 static void
7460 test_bits_within_svalue_folding ()
7462 region_model_manager mgr;
7464 const svalue *zero = mgr.get_or_create_int_cst (boolean_type_node, 0);
7465 const svalue *one = mgr.get_or_create_int_cst (boolean_type_node, 1);
7468 const unsigned val = 0x0000;
7469 for (unsigned bit = 0; bit < 16; bit++)
7470 ASSERT_EQ (get_bit (&mgr, bit, val), zero);
7474 const unsigned val = 0x0001;
7475 ASSERT_EQ (get_bit (&mgr, 0, val), one);
7476 for (unsigned bit = 1; bit < 16; bit++)
7477 ASSERT_EQ (get_bit (&mgr, bit, val), zero);
7481 const unsigned val = 0x8000;
7482 for (unsigned bit = 0; bit < 15; bit++)
7483 ASSERT_EQ (get_bit (&mgr, bit, val), zero);
7484 ASSERT_EQ (get_bit (&mgr, 15, val), one);
7488 const unsigned val = 0xFFFF;
7489 for (unsigned bit = 0; bit < 16; bit++)
7490 ASSERT_EQ (get_bit (&mgr, bit, val), one);
7494 /* Test that region::descendent_of_p works as expected. */
7496 static void
7497 test_descendent_of_p ()
7499 region_model_manager mgr;
7500 const region *stack = mgr.get_stack_region ();
7501 const region *heap = mgr.get_heap_region ();
7502 const region *code = mgr.get_code_region ();
7503 const region *globals = mgr.get_globals_region ();
7505 /* descendent_of_p should return true when used on the region itself. */
7506 ASSERT_TRUE (stack->descendent_of_p (stack));
7507 ASSERT_FALSE (stack->descendent_of_p (heap));
7508 ASSERT_FALSE (stack->descendent_of_p (code));
7509 ASSERT_FALSE (stack->descendent_of_p (globals));
7511 tree x = build_global_decl ("x", integer_type_node);
7512 const region *x_reg = mgr.get_region_for_global (x);
7513 ASSERT_TRUE (x_reg->descendent_of_p (globals));
7515 /* A cast_region should be a descendent of the original region. */
7516 const region *cast_reg = mgr.get_cast_region (x_reg, ptr_type_node);
7517 ASSERT_TRUE (cast_reg->descendent_of_p (x_reg));
7520 /* Verify that bit_range_region works as expected. */
7522 static void
7523 test_bit_range_regions ()
7525 tree x = build_global_decl ("x", integer_type_node);
7526 region_model_manager mgr;
7527 const region *x_reg = mgr.get_region_for_global (x);
7528 const region *byte0
7529 = mgr.get_bit_range (x_reg, char_type_node, bit_range (0, 8));
7530 const region *byte1
7531 = mgr.get_bit_range (x_reg, char_type_node, bit_range (8, 8));
7532 ASSERT_TRUE (byte0->descendent_of_p (x_reg));
7533 ASSERT_TRUE (byte1->descendent_of_p (x_reg));
7534 ASSERT_NE (byte0, byte1);
7537 /* Verify that simple assignments work as expected. */
7539 static void
7540 test_assignment ()
7542 tree int_0 = build_int_cst (integer_type_node, 0);
7543 tree x = build_global_decl ("x", integer_type_node);
7544 tree y = build_global_decl ("y", integer_type_node);
7546 /* "x == 0", then use of y, then "y = 0;". */
7547 region_model_manager mgr;
7548 region_model model (&mgr);
7549 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
7550 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, int_0);
7551 model.set_value (model.get_lvalue (y, NULL),
7552 model.get_rvalue (int_0, NULL),
7553 NULL);
7554 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, int_0);
7555 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
7558 /* Verify that compound assignments work as expected. */
7560 static void
7561 test_compound_assignment ()
7563 coord_test ct;
7565 tree c = build_global_decl ("c", ct.m_coord_type);
7566 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7567 c, ct.m_x_field, NULL_TREE);
7568 tree c_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7569 c, ct.m_y_field, NULL_TREE);
7570 tree d = build_global_decl ("d", ct.m_coord_type);
7571 tree d_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7572 d, ct.m_x_field, NULL_TREE);
7573 tree d_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7574 d, ct.m_y_field, NULL_TREE);
7576 tree int_17 = build_int_cst (integer_type_node, 17);
7577 tree int_m3 = build_int_cst (integer_type_node, -3);
7579 region_model_manager mgr;
7580 region_model model (&mgr);
7581 model.set_value (c_x, int_17, NULL);
7582 model.set_value (c_y, int_m3, NULL);
7584 /* Copy c to d. */
7585 const svalue *sval = model.get_rvalue (c, NULL);
7586 model.set_value (model.get_lvalue (d, NULL), sval, NULL);
7588 /* Check that the fields have the same svalues. */
7589 ASSERT_EQ (model.get_rvalue (c_x, NULL), model.get_rvalue (d_x, NULL));
7590 ASSERT_EQ (model.get_rvalue (c_y, NULL), model.get_rvalue (d_y, NULL));
7593 /* Verify the details of pushing and popping stack frames. */
7595 static void
7596 test_stack_frames ()
7598 tree int_42 = build_int_cst (integer_type_node, 42);
7599 tree int_10 = build_int_cst (integer_type_node, 10);
7600 tree int_5 = build_int_cst (integer_type_node, 5);
7601 tree int_0 = build_int_cst (integer_type_node, 0);
7603 auto_vec <tree> param_types;
7604 tree parent_fndecl = make_fndecl (integer_type_node,
7605 "parent_fn",
7606 param_types);
7607 allocate_struct_function (parent_fndecl, true);
7609 tree child_fndecl = make_fndecl (integer_type_node,
7610 "child_fn",
7611 param_types);
7612 allocate_struct_function (child_fndecl, true);
7614 /* "a" and "b" in the parent frame. */
7615 tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7616 get_identifier ("a"),
7617 integer_type_node);
7618 DECL_CONTEXT (a) = parent_fndecl;
7619 tree b = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7620 get_identifier ("b"),
7621 integer_type_node);
7622 DECL_CONTEXT (b) = parent_fndecl;
7623 /* "x" and "y" in a child frame. */
7624 tree x = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7625 get_identifier ("x"),
7626 integer_type_node);
7627 DECL_CONTEXT (x) = child_fndecl;
7628 tree y = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7629 get_identifier ("y"),
7630 integer_type_node);
7631 DECL_CONTEXT (y) = child_fndecl;
7633 /* "p" global. */
7634 tree p = build_global_decl ("p", ptr_type_node);
7636 /* "q" global. */
7637 tree q = build_global_decl ("q", ptr_type_node);
7639 region_model_manager mgr;
7640 test_region_model_context ctxt;
7641 region_model model (&mgr);
7643 /* Push stack frame for "parent_fn". */
7644 const region *parent_frame_reg
7645 = model.push_frame (DECL_STRUCT_FUNCTION (parent_fndecl),
7646 NULL, &ctxt);
7647 ASSERT_EQ (model.get_current_frame (), parent_frame_reg);
7648 ASSERT_TRUE (model.region_exists_p (parent_frame_reg));
7649 const region *a_in_parent_reg = model.get_lvalue (a, &ctxt);
7650 model.set_value (a_in_parent_reg,
7651 model.get_rvalue (int_42, &ctxt),
7652 &ctxt);
7653 ASSERT_EQ (a_in_parent_reg->maybe_get_frame_region (), parent_frame_reg);
7655 model.add_constraint (b, LT_EXPR, int_10, &ctxt);
7656 ASSERT_EQ (model.eval_condition (b, LT_EXPR, int_10, &ctxt),
7657 tristate (tristate::TS_TRUE));
7659 /* Push stack frame for "child_fn". */
7660 const region *child_frame_reg
7661 = model.push_frame (DECL_STRUCT_FUNCTION (child_fndecl), NULL, &ctxt);
7662 ASSERT_EQ (model.get_current_frame (), child_frame_reg);
7663 ASSERT_TRUE (model.region_exists_p (child_frame_reg));
7664 const region *x_in_child_reg = model.get_lvalue (x, &ctxt);
7665 model.set_value (x_in_child_reg,
7666 model.get_rvalue (int_0, &ctxt),
7667 &ctxt);
7668 ASSERT_EQ (x_in_child_reg->maybe_get_frame_region (), child_frame_reg);
7670 model.add_constraint (y, NE_EXPR, int_5, &ctxt);
7671 ASSERT_EQ (model.eval_condition (y, NE_EXPR, int_5, &ctxt),
7672 tristate (tristate::TS_TRUE));
7674 /* Point a global pointer at a local in the child frame: p = &x. */
7675 const region *p_in_globals_reg = model.get_lvalue (p, &ctxt);
7676 model.set_value (p_in_globals_reg,
7677 mgr.get_ptr_svalue (ptr_type_node, x_in_child_reg),
7678 &ctxt);
7679 ASSERT_EQ (p_in_globals_reg->maybe_get_frame_region (), NULL);
7681 /* Point another global pointer at p: q = &p. */
7682 const region *q_in_globals_reg = model.get_lvalue (q, &ctxt);
7683 model.set_value (q_in_globals_reg,
7684 mgr.get_ptr_svalue (ptr_type_node, p_in_globals_reg),
7685 &ctxt);
7687 /* Test region::descendent_of_p. */
7688 ASSERT_TRUE (child_frame_reg->descendent_of_p (child_frame_reg));
7689 ASSERT_TRUE (x_in_child_reg->descendent_of_p (child_frame_reg));
7690 ASSERT_FALSE (a_in_parent_reg->descendent_of_p (child_frame_reg));
7692 /* Pop the "child_fn" frame from the stack. */
7693 model.pop_frame (NULL, NULL, &ctxt);
7694 ASSERT_FALSE (model.region_exists_p (child_frame_reg));
7695 ASSERT_TRUE (model.region_exists_p (parent_frame_reg));
7697 /* Verify that p (which was pointing at the local "x" in the popped
7698 frame) has been poisoned. */
7699 const svalue *new_p_sval = model.get_rvalue (p, NULL);
7700 ASSERT_EQ (new_p_sval->get_kind (), SK_POISONED);
7701 ASSERT_EQ (new_p_sval->dyn_cast_poisoned_svalue ()->get_poison_kind (),
7702 POISON_KIND_POPPED_STACK);
7704 /* Verify that q still points to p, in spite of the region
7705 renumbering. */
7706 const svalue *new_q_sval = model.get_rvalue (q, &ctxt);
7707 ASSERT_EQ (new_q_sval->get_kind (), SK_REGION);
7708 ASSERT_EQ (new_q_sval->maybe_get_region (),
7709 model.get_lvalue (p, &ctxt));
7711 /* Verify that top of stack has been updated. */
7712 ASSERT_EQ (model.get_current_frame (), parent_frame_reg);
7714 /* Verify locals in parent frame. */
7715 /* Verify "a" still has its value. */
7716 const svalue *new_a_sval = model.get_rvalue (a, &ctxt);
7717 ASSERT_EQ (new_a_sval->get_kind (), SK_CONSTANT);
7718 ASSERT_EQ (new_a_sval->dyn_cast_constant_svalue ()->get_constant (),
7719 int_42);
7720 /* Verify "b" still has its constraint. */
7721 ASSERT_EQ (model.eval_condition (b, LT_EXPR, int_10, &ctxt),
7722 tristate (tristate::TS_TRUE));
7725 /* Verify that get_representative_path_var works as expected, that
7726 we can map from regions to parms and back within a recursive call
7727 stack. */
7729 static void
7730 test_get_representative_path_var ()
7732 auto_vec <tree> param_types;
7733 tree fndecl = make_fndecl (integer_type_node,
7734 "factorial",
7735 param_types);
7736 allocate_struct_function (fndecl, true);
7738 /* Parm "n". */
7739 tree n = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7740 get_identifier ("n"),
7741 integer_type_node);
7742 DECL_CONTEXT (n) = fndecl;
7744 region_model_manager mgr;
7745 test_region_model_context ctxt;
7746 region_model model (&mgr);
7748 /* Push 5 stack frames for "factorial", each with a param */
7749 auto_vec<const region *> parm_regs;
7750 auto_vec<const svalue *> parm_svals;
7751 for (int depth = 0; depth < 5; depth++)
7753 const region *frame_n_reg
7754 = model.push_frame (DECL_STRUCT_FUNCTION (fndecl), NULL, &ctxt);
7755 const region *parm_n_reg = model.get_lvalue (path_var (n, depth), &ctxt);
7756 parm_regs.safe_push (parm_n_reg);
7758 ASSERT_EQ (parm_n_reg->get_parent_region (), frame_n_reg);
7759 const svalue *sval_n = mgr.get_or_create_initial_value (parm_n_reg);
7760 parm_svals.safe_push (sval_n);
7763 /* Verify that we can recognize that the regions are the parms,
7764 at every depth. */
7765 for (int depth = 0; depth < 5; depth++)
7768 svalue_set visited;
7769 ASSERT_EQ (model.get_representative_path_var (parm_regs[depth],
7770 &visited),
7771 path_var (n, depth + 1));
7773 /* ...and that we can lookup lvalues for locals for all frames,
7774 not just the top. */
7775 ASSERT_EQ (model.get_lvalue (path_var (n, depth), NULL),
7776 parm_regs[depth]);
7777 /* ...and that we can locate the svalues. */
7779 svalue_set visited;
7780 ASSERT_EQ (model.get_representative_path_var (parm_svals[depth],
7781 &visited),
7782 path_var (n, depth + 1));
7787 /* Ensure that region_model::operator== works as expected. */
7789 static void
7790 test_equality_1 ()
7792 tree int_42 = build_int_cst (integer_type_node, 42);
7793 tree int_17 = build_int_cst (integer_type_node, 17);
7795 /* Verify that "empty" region_model instances are equal to each other. */
7796 region_model_manager mgr;
7797 region_model model0 (&mgr);
7798 region_model model1 (&mgr);
7799 ASSERT_EQ (model0, model1);
7801 /* Verify that setting state in model1 makes the models non-equal. */
7802 tree x = build_global_decl ("x", integer_type_node);
7803 model0.set_value (x, int_42, NULL);
7804 ASSERT_EQ (model0.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
7805 ASSERT_NE (model0, model1);
7807 /* Verify the copy-ctor. */
7808 region_model model2 (model0);
7809 ASSERT_EQ (model0, model2);
7810 ASSERT_EQ (model2.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
7811 ASSERT_NE (model1, model2);
7813 /* Verify that models obtained from copy-ctor are independently editable
7814 w/o affecting the original model. */
7815 model2.set_value (x, int_17, NULL);
7816 ASSERT_NE (model0, model2);
7817 ASSERT_EQ (model2.get_rvalue (x, NULL)->maybe_get_constant (), int_17);
7818 ASSERT_EQ (model0.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
7821 /* Verify that region models for
7822 x = 42; y = 113;
7824 y = 113; x = 42;
7825 are equal. */
7827 static void
7828 test_canonicalization_2 ()
7830 tree int_42 = build_int_cst (integer_type_node, 42);
7831 tree int_113 = build_int_cst (integer_type_node, 113);
7832 tree x = build_global_decl ("x", integer_type_node);
7833 tree y = build_global_decl ("y", integer_type_node);
7835 region_model_manager mgr;
7836 region_model model0 (&mgr);
7837 model0.set_value (model0.get_lvalue (x, NULL),
7838 model0.get_rvalue (int_42, NULL),
7839 NULL);
7840 model0.set_value (model0.get_lvalue (y, NULL),
7841 model0.get_rvalue (int_113, NULL),
7842 NULL);
7844 region_model model1 (&mgr);
7845 model1.set_value (model1.get_lvalue (y, NULL),
7846 model1.get_rvalue (int_113, NULL),
7847 NULL);
7848 model1.set_value (model1.get_lvalue (x, NULL),
7849 model1.get_rvalue (int_42, NULL),
7850 NULL);
7852 ASSERT_EQ (model0, model1);
7855 /* Verify that constraints for
7856 x > 3 && y > 42
7858 y > 42 && x > 3
7859 are equal after canonicalization. */
7861 static void
7862 test_canonicalization_3 ()
7864 tree int_3 = build_int_cst (integer_type_node, 3);
7865 tree int_42 = build_int_cst (integer_type_node, 42);
7866 tree x = build_global_decl ("x", integer_type_node);
7867 tree y = build_global_decl ("y", integer_type_node);
7869 region_model_manager mgr;
7870 region_model model0 (&mgr);
7871 model0.add_constraint (x, GT_EXPR, int_3, NULL);
7872 model0.add_constraint (y, GT_EXPR, int_42, NULL);
7874 region_model model1 (&mgr);
7875 model1.add_constraint (y, GT_EXPR, int_42, NULL);
7876 model1.add_constraint (x, GT_EXPR, int_3, NULL);
7878 model0.canonicalize ();
7879 model1.canonicalize ();
7880 ASSERT_EQ (model0, model1);
7883 /* Verify that we can canonicalize a model containing NaN and other real
7884 constants. */
7886 static void
7887 test_canonicalization_4 ()
7889 auto_vec<tree> csts;
7890 append_interesting_constants (&csts);
7892 region_model_manager mgr;
7893 region_model model (&mgr);
7895 for (tree cst : csts)
7896 model.get_rvalue (cst, NULL);
7898 model.canonicalize ();
7901 /* Assert that if we have two region_model instances
7902 with values VAL_A and VAL_B for EXPR that they are
7903 mergable. Write the merged model to *OUT_MERGED_MODEL,
7904 and the merged svalue ptr to *OUT_MERGED_SVALUE.
7905 If VAL_A or VAL_B are NULL_TREE, don't populate EXPR
7906 for that region_model. */
7908 static void
7909 assert_region_models_merge (tree expr, tree val_a, tree val_b,
7910 region_model *out_merged_model,
7911 const svalue **out_merged_svalue)
7913 region_model_manager *mgr = out_merged_model->get_manager ();
7914 program_point point (program_point::origin (*mgr));
7915 test_region_model_context ctxt;
7916 region_model model0 (mgr);
7917 region_model model1 (mgr);
7918 if (val_a)
7919 model0.set_value (model0.get_lvalue (expr, &ctxt),
7920 model0.get_rvalue (val_a, &ctxt),
7921 &ctxt);
7922 if (val_b)
7923 model1.set_value (model1.get_lvalue (expr, &ctxt),
7924 model1.get_rvalue (val_b, &ctxt),
7925 &ctxt);
7927 /* They should be mergeable. */
7928 ASSERT_TRUE (model0.can_merge_with_p (model1, point, out_merged_model));
7929 *out_merged_svalue = out_merged_model->get_rvalue (expr, &ctxt);
7932 /* Verify that we can merge region_model instances. */
7934 static void
7935 test_state_merging ()
7937 tree int_42 = build_int_cst (integer_type_node, 42);
7938 tree int_113 = build_int_cst (integer_type_node, 113);
7939 tree x = build_global_decl ("x", integer_type_node);
7940 tree y = build_global_decl ("y", integer_type_node);
7941 tree z = build_global_decl ("z", integer_type_node);
7942 tree p = build_global_decl ("p", ptr_type_node);
7944 tree addr_of_y = build1 (ADDR_EXPR, ptr_type_node, y);
7945 tree addr_of_z = build1 (ADDR_EXPR, ptr_type_node, z);
7947 auto_vec <tree> param_types;
7948 tree test_fndecl = make_fndecl (integer_type_node, "test_fn", param_types);
7949 allocate_struct_function (test_fndecl, true);
7951 /* Param "a". */
7952 tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7953 get_identifier ("a"),
7954 integer_type_node);
7955 DECL_CONTEXT (a) = test_fndecl;
7956 tree addr_of_a = build1 (ADDR_EXPR, ptr_type_node, a);
7958 /* Param "q", a pointer. */
7959 tree q = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7960 get_identifier ("q"),
7961 ptr_type_node);
7962 DECL_CONTEXT (q) = test_fndecl;
7964 region_model_manager mgr;
7965 program_point point (program_point::origin (mgr));
7968 region_model model0 (&mgr);
7969 region_model model1 (&mgr);
7970 region_model merged (&mgr);
7971 /* Verify empty models can be merged. */
7972 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
7973 ASSERT_EQ (model0, merged);
7976 /* Verify that we can merge two contradictory constraints on the
7977 value for a global. */
7978 /* TODO: verify that the merged model doesn't have a value for
7979 the global */
7981 region_model model0 (&mgr);
7982 region_model model1 (&mgr);
7983 region_model merged (&mgr);
7984 test_region_model_context ctxt;
7985 model0.add_constraint (x, EQ_EXPR, int_42, &ctxt);
7986 model1.add_constraint (x, EQ_EXPR, int_113, &ctxt);
7987 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
7988 ASSERT_NE (model0, merged);
7989 ASSERT_NE (model1, merged);
7992 /* Verify handling of a PARM_DECL. */
7994 test_region_model_context ctxt;
7995 region_model model0 (&mgr);
7996 region_model model1 (&mgr);
7997 ASSERT_EQ (model0.get_stack_depth (), 0);
7998 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt);
7999 ASSERT_EQ (model0.get_stack_depth (), 1);
8000 model1.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt);
8002 placeholder_svalue test_sval (mgr.alloc_symbol_id (),
8003 integer_type_node, "test sval");
8004 model0.set_value (model0.get_lvalue (a, &ctxt), &test_sval, &ctxt);
8005 model1.set_value (model1.get_lvalue (a, &ctxt), &test_sval, &ctxt);
8006 ASSERT_EQ (model0, model1);
8008 /* They should be mergeable, and the result should be the same. */
8009 region_model merged (&mgr);
8010 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8011 ASSERT_EQ (model0, merged);
8012 /* In particular, "a" should have the placeholder value. */
8013 ASSERT_EQ (merged.get_rvalue (a, &ctxt), &test_sval);
8016 /* Verify handling of a global. */
8018 test_region_model_context ctxt;
8019 region_model model0 (&mgr);
8020 region_model model1 (&mgr);
8022 placeholder_svalue test_sval (mgr.alloc_symbol_id (),
8023 integer_type_node, "test sval");
8024 model0.set_value (model0.get_lvalue (x, &ctxt), &test_sval, &ctxt);
8025 model1.set_value (model1.get_lvalue (x, &ctxt), &test_sval, &ctxt);
8026 ASSERT_EQ (model0, model1);
8028 /* They should be mergeable, and the result should be the same. */
8029 region_model merged (&mgr);
8030 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8031 ASSERT_EQ (model0, merged);
8032 /* In particular, "x" should have the placeholder value. */
8033 ASSERT_EQ (merged.get_rvalue (x, &ctxt), &test_sval);
8036 /* Use global-handling to verify various combinations of values. */
8038 /* Two equal constant values. */
8040 region_model merged (&mgr);
8041 const svalue *merged_x_sval;
8042 assert_region_models_merge (x, int_42, int_42, &merged, &merged_x_sval);
8044 /* In particular, there should be a constant value for "x". */
8045 ASSERT_EQ (merged_x_sval->get_kind (), SK_CONSTANT);
8046 ASSERT_EQ (merged_x_sval->dyn_cast_constant_svalue ()->get_constant (),
8047 int_42);
8050 /* Two non-equal constant values. */
8052 region_model merged (&mgr);
8053 const svalue *merged_x_sval;
8054 assert_region_models_merge (x, int_42, int_113, &merged, &merged_x_sval);
8056 /* In particular, there should be a "widening" value for "x". */
8057 ASSERT_EQ (merged_x_sval->get_kind (), SK_WIDENING);
8060 /* Initial and constant. */
8062 region_model merged (&mgr);
8063 const svalue *merged_x_sval;
8064 assert_region_models_merge (x, NULL_TREE, int_113, &merged, &merged_x_sval);
8066 /* In particular, there should be an unknown value for "x". */
8067 ASSERT_EQ (merged_x_sval->get_kind (), SK_UNKNOWN);
8070 /* Constant and initial. */
8072 region_model merged (&mgr);
8073 const svalue *merged_x_sval;
8074 assert_region_models_merge (x, int_42, NULL_TREE, &merged, &merged_x_sval);
8076 /* In particular, there should be an unknown value for "x". */
8077 ASSERT_EQ (merged_x_sval->get_kind (), SK_UNKNOWN);
8080 /* Unknown and constant. */
8081 // TODO
8083 /* Pointers: NULL and NULL. */
8084 // TODO
8086 /* Pointers: NULL and non-NULL. */
8087 // TODO
8089 /* Pointers: non-NULL and non-NULL: ptr to a local. */
8091 region_model model0 (&mgr);
8092 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8093 model0.set_value (model0.get_lvalue (p, NULL),
8094 model0.get_rvalue (addr_of_a, NULL), NULL);
8096 region_model model1 (model0);
8097 ASSERT_EQ (model0, model1);
8099 /* They should be mergeable, and the result should be the same. */
8100 region_model merged (&mgr);
8101 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8102 ASSERT_EQ (model0, merged);
8105 /* Pointers: non-NULL and non-NULL: ptr to a global. */
8107 region_model merged (&mgr);
8108 /* p == &y in both input models. */
8109 const svalue *merged_p_sval;
8110 assert_region_models_merge (p, addr_of_y, addr_of_y, &merged,
8111 &merged_p_sval);
8113 /* We should get p == &y in the merged model. */
8114 ASSERT_EQ (merged_p_sval->get_kind (), SK_REGION);
8115 const region_svalue *merged_p_ptr
8116 = merged_p_sval->dyn_cast_region_svalue ();
8117 const region *merged_p_star_reg = merged_p_ptr->get_pointee ();
8118 ASSERT_EQ (merged_p_star_reg, merged.get_lvalue (y, NULL));
8121 /* Pointers: non-NULL ptrs to different globals: should be unknown. */
8123 region_model merged (&mgr);
8124 /* x == &y vs x == &z in the input models; these are actually casts
8125 of the ptrs to "int". */
8126 const svalue *merged_x_sval;
8127 // TODO:
8128 assert_region_models_merge (x, addr_of_y, addr_of_z, &merged,
8129 &merged_x_sval);
8131 /* We should get x == unknown in the merged model. */
8132 ASSERT_EQ (merged_x_sval->get_kind (), SK_UNKNOWN);
8135 /* Pointers: non-NULL and non-NULL: ptr to a heap region. */
8137 test_region_model_context ctxt;
8138 region_model model0 (&mgr);
8139 tree size = build_int_cst (size_type_node, 1024);
8140 const svalue *size_sval = mgr.get_or_create_constant_svalue (size);
8141 const region *new_reg
8142 = model0.get_or_create_region_for_heap_alloc (size_sval, &ctxt);
8143 const svalue *ptr_sval = mgr.get_ptr_svalue (ptr_type_node, new_reg);
8144 model0.set_value (model0.get_lvalue (p, &ctxt),
8145 ptr_sval, &ctxt);
8147 region_model model1 (model0);
8149 ASSERT_EQ (model0, model1);
8151 region_model merged (&mgr);
8152 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8154 /* The merged model ought to be identical. */
8155 ASSERT_EQ (model0, merged);
8158 /* Two regions sharing the same placeholder svalue should continue sharing
8159 it after self-merger. */
8161 test_region_model_context ctxt;
8162 region_model model0 (&mgr);
8163 placeholder_svalue placeholder_sval (mgr.alloc_symbol_id (),
8164 integer_type_node, "test");
8165 model0.set_value (model0.get_lvalue (x, &ctxt),
8166 &placeholder_sval, &ctxt);
8167 model0.set_value (model0.get_lvalue (y, &ctxt), &placeholder_sval, &ctxt);
8168 region_model model1 (model0);
8170 /* They should be mergeable, and the result should be the same. */
8171 region_model merged (&mgr);
8172 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8173 ASSERT_EQ (model0, merged);
8175 /* In particular, we should have x == y. */
8176 ASSERT_EQ (merged.eval_condition (x, EQ_EXPR, y, &ctxt),
8177 tristate (tristate::TS_TRUE));
8181 region_model model0 (&mgr);
8182 region_model model1 (&mgr);
8183 test_region_model_context ctxt;
8184 model0.add_constraint (x, EQ_EXPR, int_42, &ctxt);
8185 model1.add_constraint (x, NE_EXPR, int_42, &ctxt);
8186 region_model merged (&mgr);
8187 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8191 region_model model0 (&mgr);
8192 region_model model1 (&mgr);
8193 test_region_model_context ctxt;
8194 model0.add_constraint (x, EQ_EXPR, int_42, &ctxt);
8195 model1.add_constraint (x, NE_EXPR, int_42, &ctxt);
8196 model1.add_constraint (x, EQ_EXPR, int_113, &ctxt);
8197 region_model merged (&mgr);
8198 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8201 // TODO: what can't we merge? need at least one such test
8203 /* TODO: various things
8204 - heap regions
8205 - value merging:
8206 - every combination, but in particular
8207 - pairs of regions
8210 /* Views. */
8212 test_region_model_context ctxt;
8213 region_model model0 (&mgr);
8215 const region *x_reg = model0.get_lvalue (x, &ctxt);
8216 const region *x_as_ptr = mgr.get_cast_region (x_reg, ptr_type_node);
8217 model0.set_value (x_as_ptr, model0.get_rvalue (addr_of_y, &ctxt), &ctxt);
8219 region_model model1 (model0);
8220 ASSERT_EQ (model1, model0);
8222 /* They should be mergeable, and the result should be the same. */
8223 region_model merged (&mgr);
8224 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8227 /* Verify that we can merge a model in which a local in an older stack
8228 frame points to a local in a more recent stack frame. */
8230 region_model model0 (&mgr);
8231 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8232 const region *q_in_first_frame = model0.get_lvalue (q, NULL);
8234 /* Push a second frame. */
8235 const region *reg_2nd_frame
8236 = model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8238 /* Have a pointer in the older frame point to a local in the
8239 more recent frame. */
8240 const svalue *sval_ptr = model0.get_rvalue (addr_of_a, NULL);
8241 model0.set_value (q_in_first_frame, sval_ptr, NULL);
8243 /* Verify that it's pointing at the newer frame. */
8244 const region *reg_pointee = sval_ptr->maybe_get_region ();
8245 ASSERT_EQ (reg_pointee->get_parent_region (), reg_2nd_frame);
8247 model0.canonicalize ();
8249 region_model model1 (model0);
8250 ASSERT_EQ (model0, model1);
8252 /* They should be mergeable, and the result should be the same
8253 (after canonicalization, at least). */
8254 region_model merged (&mgr);
8255 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8256 merged.canonicalize ();
8257 ASSERT_EQ (model0, merged);
8260 /* Verify that we can merge a model in which a local points to a global. */
8262 region_model model0 (&mgr);
8263 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8264 model0.set_value (model0.get_lvalue (q, NULL),
8265 model0.get_rvalue (addr_of_y, NULL), NULL);
8267 region_model model1 (model0);
8268 ASSERT_EQ (model0, model1);
8270 /* They should be mergeable, and the result should be the same
8271 (after canonicalization, at least). */
8272 region_model merged (&mgr);
8273 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8274 ASSERT_EQ (model0, merged);
8278 /* Verify that constraints are correctly merged when merging region_model
8279 instances. */
8281 static void
8282 test_constraint_merging ()
8284 tree int_0 = build_int_cst (integer_type_node, 0);
8285 tree int_5 = build_int_cst (integer_type_node, 5);
8286 tree x = build_global_decl ("x", integer_type_node);
8287 tree y = build_global_decl ("y", integer_type_node);
8288 tree z = build_global_decl ("z", integer_type_node);
8289 tree n = build_global_decl ("n", integer_type_node);
8291 region_model_manager mgr;
8292 test_region_model_context ctxt;
8294 /* model0: 0 <= (x == y) < n. */
8295 region_model model0 (&mgr);
8296 model0.add_constraint (x, EQ_EXPR, y, &ctxt);
8297 model0.add_constraint (x, GE_EXPR, int_0, NULL);
8298 model0.add_constraint (x, LT_EXPR, n, NULL);
8300 /* model1: z != 5 && (0 <= x < n). */
8301 region_model model1 (&mgr);
8302 model1.add_constraint (z, NE_EXPR, int_5, NULL);
8303 model1.add_constraint (x, GE_EXPR, int_0, NULL);
8304 model1.add_constraint (x, LT_EXPR, n, NULL);
8306 /* They should be mergeable; the merged constraints should
8307 be: (0 <= x < n). */
8308 program_point point (program_point::origin (mgr));
8309 region_model merged (&mgr);
8310 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8312 ASSERT_EQ (merged.eval_condition (x, GE_EXPR, int_0, &ctxt),
8313 tristate (tristate::TS_TRUE));
8314 ASSERT_EQ (merged.eval_condition (x, LT_EXPR, n, &ctxt),
8315 tristate (tristate::TS_TRUE));
8317 ASSERT_EQ (merged.eval_condition (z, NE_EXPR, int_5, &ctxt),
8318 tristate (tristate::TS_UNKNOWN));
8319 ASSERT_EQ (merged.eval_condition (x, LT_EXPR, y, &ctxt),
8320 tristate (tristate::TS_UNKNOWN));
8323 /* Verify that widening_svalue::eval_condition_without_cm works as
8324 expected. */
8326 static void
8327 test_widening_constraints ()
8329 region_model_manager mgr;
8330 function_point point (program_point::origin (mgr).get_function_point ());
8331 tree int_0 = build_int_cst (integer_type_node, 0);
8332 tree int_m1 = build_int_cst (integer_type_node, -1);
8333 tree int_1 = build_int_cst (integer_type_node, 1);
8334 tree int_256 = build_int_cst (integer_type_node, 256);
8335 test_region_model_context ctxt;
8336 const svalue *int_0_sval = mgr.get_or_create_constant_svalue (int_0);
8337 const svalue *int_1_sval = mgr.get_or_create_constant_svalue (int_1);
8338 const svalue *w_zero_then_one_sval
8339 = mgr.get_or_create_widening_svalue (integer_type_node, point,
8340 int_0_sval, int_1_sval);
8341 const widening_svalue *w_zero_then_one
8342 = w_zero_then_one_sval->dyn_cast_widening_svalue ();
8343 ASSERT_EQ (w_zero_then_one->get_direction (),
8344 widening_svalue::DIR_ASCENDING);
8345 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_m1),
8346 tristate::TS_FALSE);
8347 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_0),
8348 tristate::TS_FALSE);
8349 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_1),
8350 tristate::TS_UNKNOWN);
8351 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_256),
8352 tristate::TS_UNKNOWN);
8354 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_m1),
8355 tristate::TS_FALSE);
8356 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_0),
8357 tristate::TS_UNKNOWN);
8358 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_1),
8359 tristate::TS_UNKNOWN);
8360 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_256),
8361 tristate::TS_UNKNOWN);
8363 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_m1),
8364 tristate::TS_TRUE);
8365 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_0),
8366 tristate::TS_UNKNOWN);
8367 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_1),
8368 tristate::TS_UNKNOWN);
8369 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_256),
8370 tristate::TS_UNKNOWN);
8372 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_m1),
8373 tristate::TS_TRUE);
8374 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_0),
8375 tristate::TS_TRUE);
8376 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_1),
8377 tristate::TS_UNKNOWN);
8378 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_256),
8379 tristate::TS_UNKNOWN);
8381 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_m1),
8382 tristate::TS_FALSE);
8383 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_0),
8384 tristate::TS_UNKNOWN);
8385 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_1),
8386 tristate::TS_UNKNOWN);
8387 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_256),
8388 tristate::TS_UNKNOWN);
8390 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_m1),
8391 tristate::TS_TRUE);
8392 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_0),
8393 tristate::TS_UNKNOWN);
8394 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_1),
8395 tristate::TS_UNKNOWN);
8396 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_256),
8397 tristate::TS_UNKNOWN);
8400 /* Verify merging constraints for states simulating successive iterations
8401 of a loop.
8402 Simulate:
8403 for (i = 0; i < 256; i++)
8404 [...body...]
8405 i.e. this gimple:.
8406 i_15 = 0;
8407 goto <bb 4>;
8409 <bb 4> :
8410 i_11 = PHI <i_15(2), i_23(3)>
8411 if (i_11 <= 255)
8412 goto <bb 3>;
8413 else
8414 goto [AFTER LOOP]
8416 <bb 3> :
8417 [LOOP BODY]
8418 i_23 = i_11 + 1;
8420 and thus these ops (and resultant states):
8421 i_11 = PHI()
8422 {i_11: 0}
8423 add_constraint (i_11 <= 255) [for the true edge]
8424 {i_11: 0} [constraint was a no-op]
8425 i_23 = i_11 + 1;
8426 {i_22: 1}
8427 i_11 = PHI()
8428 {i_11: WIDENED (at phi, 0, 1)}
8429 add_constraint (i_11 <= 255) [for the true edge]
8430 {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}
8431 i_23 = i_11 + 1;
8432 {i_23: (WIDENED (at phi, 0, 1) + 1); WIDENED <= 255}
8433 i_11 = PHI(); merge with state at phi above
8434 {i_11: WIDENED (at phi, 0, 1); WIDENED <= 256}
8435 [changing meaning of "WIDENED" here]
8436 if (i_11 <= 255)
8437 T: {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}; cache hit
8438 F: {i_11: 256}
8441 static void
8442 test_iteration_1 ()
8444 region_model_manager mgr;
8445 program_point point (program_point::origin (mgr));
8447 tree int_0 = build_int_cst (integer_type_node, 0);
8448 tree int_1 = build_int_cst (integer_type_node, 1);
8449 tree int_256 = build_int_cst (integer_type_node, 256);
8450 tree i = build_global_decl ("i", integer_type_node);
8452 test_region_model_context ctxt;
8454 /* model0: i: 0. */
8455 region_model model0 (&mgr);
8456 model0.set_value (i, int_0, &ctxt);
8458 /* model1: i: 1. */
8459 region_model model1 (&mgr);
8460 model1.set_value (i, int_1, &ctxt);
8462 /* Should merge "i" to a widened value. */
8463 region_model model2 (&mgr);
8464 ASSERT_TRUE (model1.can_merge_with_p (model0, point, &model2));
8465 const svalue *merged_i = model2.get_rvalue (i, &ctxt);
8466 ASSERT_EQ (merged_i->get_kind (), SK_WIDENING);
8467 const widening_svalue *w = merged_i->dyn_cast_widening_svalue ();
8468 ASSERT_EQ (w->get_direction (), widening_svalue::DIR_ASCENDING);
8470 /* Add constraint: i < 256 */
8471 model2.add_constraint (i, LT_EXPR, int_256, &ctxt);
8472 ASSERT_EQ (model2.eval_condition (i, LT_EXPR, int_256, &ctxt),
8473 tristate (tristate::TS_TRUE));
8474 ASSERT_EQ (model2.eval_condition (i, GE_EXPR, int_0, &ctxt),
8475 tristate (tristate::TS_TRUE));
8477 /* Try merging with the initial state. */
8478 region_model model3 (&mgr);
8479 ASSERT_TRUE (model2.can_merge_with_p (model0, point, &model3));
8480 /* Merging the merged value with the initial value should be idempotent,
8481 so that the analysis converges. */
8482 ASSERT_EQ (model3.get_rvalue (i, &ctxt), merged_i);
8483 /* Merger of 0 and a widening value with constraint < CST
8484 should retain the constraint, even though it was implicit
8485 for the 0 case. */
8486 ASSERT_EQ (model3.eval_condition (i, LT_EXPR, int_256, &ctxt),
8487 tristate (tristate::TS_TRUE));
8488 /* ...and we should have equality: the analysis should have converged. */
8489 ASSERT_EQ (model3, model2);
8491 /* "i_23 = i_11 + 1;" */
8492 region_model model4 (model3);
8493 ASSERT_EQ (model4, model2);
8494 model4.set_value (i, build2 (PLUS_EXPR, integer_type_node, i, int_1), &ctxt);
8495 const svalue *plus_one = model4.get_rvalue (i, &ctxt);
8496 ASSERT_EQ (plus_one->get_kind (), SK_BINOP);
8498 /* Try merging with the "i: 1" state. */
8499 region_model model5 (&mgr);
8500 ASSERT_TRUE (model4.can_merge_with_p (model1, point, &model5));
8501 ASSERT_EQ (model5.get_rvalue (i, &ctxt), plus_one);
8502 ASSERT_EQ (model5, model4);
8504 /* "i_11 = PHI();" merge with state at phi above.
8505 For i, we should have a merger of WIDENING with WIDENING + 1,
8506 and this should be WIDENING again. */
8507 region_model model6 (&mgr);
8508 ASSERT_TRUE (model5.can_merge_with_p (model2, point, &model6));
8509 const svalue *merged_widening = model6.get_rvalue (i, &ctxt);
8510 ASSERT_EQ (merged_widening->get_kind (), SK_WIDENING);
8513 /* Verify that if we mark a pointer to a malloc-ed region as non-NULL,
8514 all cast pointers to that region are also known to be non-NULL. */
8516 static void
8517 test_malloc_constraints ()
8519 region_model_manager mgr;
8520 region_model model (&mgr);
8521 tree p = build_global_decl ("p", ptr_type_node);
8522 tree char_star = build_pointer_type (char_type_node);
8523 tree q = build_global_decl ("q", char_star);
8524 tree null_ptr = build_int_cst (ptr_type_node, 0);
8526 const svalue *size_in_bytes
8527 = mgr.get_or_create_unknown_svalue (size_type_node);
8528 const region *reg
8529 = model.get_or_create_region_for_heap_alloc (size_in_bytes, NULL);
8530 const svalue *sval = mgr.get_ptr_svalue (ptr_type_node, reg);
8531 model.set_value (model.get_lvalue (p, NULL), sval, NULL);
8532 model.set_value (q, p, NULL);
8534 ASSERT_CONDITION_UNKNOWN (model, p, NE_EXPR, null_ptr);
8535 ASSERT_CONDITION_UNKNOWN (model, p, EQ_EXPR, null_ptr);
8536 ASSERT_CONDITION_UNKNOWN (model, q, NE_EXPR, null_ptr);
8537 ASSERT_CONDITION_UNKNOWN (model, q, EQ_EXPR, null_ptr);
8539 model.add_constraint (p, NE_EXPR, null_ptr, NULL);
8541 ASSERT_CONDITION_TRUE (model, p, NE_EXPR, null_ptr);
8542 ASSERT_CONDITION_FALSE (model, p, EQ_EXPR, null_ptr);
8543 ASSERT_CONDITION_TRUE (model, q, NE_EXPR, null_ptr);
8544 ASSERT_CONDITION_FALSE (model, q, EQ_EXPR, null_ptr);
8547 /* Smoketest of getting and setting the value of a variable. */
8549 static void
8550 test_var ()
8552 /* "int i;" */
8553 tree i = build_global_decl ("i", integer_type_node);
8555 tree int_17 = build_int_cst (integer_type_node, 17);
8556 tree int_m3 = build_int_cst (integer_type_node, -3);
8558 region_model_manager mgr;
8559 region_model model (&mgr);
8561 const region *i_reg = model.get_lvalue (i, NULL);
8562 ASSERT_EQ (i_reg->get_kind (), RK_DECL);
8564 /* Reading "i" should give a symbolic "initial value". */
8565 const svalue *sval_init = model.get_rvalue (i, NULL);
8566 ASSERT_EQ (sval_init->get_kind (), SK_INITIAL);
8567 ASSERT_EQ (sval_init->dyn_cast_initial_svalue ()->get_region (), i_reg);
8568 /* ..and doing it again should give the same "initial value". */
8569 ASSERT_EQ (model.get_rvalue (i, NULL), sval_init);
8571 /* "i = 17;". */
8572 model.set_value (i, int_17, NULL);
8573 ASSERT_EQ (model.get_rvalue (i, NULL),
8574 model.get_rvalue (int_17, NULL));
8576 /* "i = -3;". */
8577 model.set_value (i, int_m3, NULL);
8578 ASSERT_EQ (model.get_rvalue (i, NULL),
8579 model.get_rvalue (int_m3, NULL));
8581 /* Verify get_offset for "i". */
8583 region_offset offset = i_reg->get_offset (&mgr);
8584 ASSERT_EQ (offset.get_base_region (), i_reg);
8585 ASSERT_EQ (offset.get_bit_offset (), 0);
8589 static void
8590 test_array_2 ()
8592 /* "int arr[10];" */
8593 tree tlen = size_int (10);
8594 tree arr_type
8595 = build_array_type (integer_type_node, build_index_type (tlen));
8596 tree arr = build_global_decl ("arr", arr_type);
8598 /* "int i;" */
8599 tree i = build_global_decl ("i", integer_type_node);
8601 tree int_0 = build_int_cst (integer_type_node, 0);
8602 tree int_1 = build_int_cst (integer_type_node, 1);
8604 tree arr_0 = build4 (ARRAY_REF, integer_type_node,
8605 arr, int_0, NULL_TREE, NULL_TREE);
8606 tree arr_1 = build4 (ARRAY_REF, integer_type_node,
8607 arr, int_1, NULL_TREE, NULL_TREE);
8608 tree arr_i = build4 (ARRAY_REF, integer_type_node,
8609 arr, i, NULL_TREE, NULL_TREE);
8611 tree int_17 = build_int_cst (integer_type_node, 17);
8612 tree int_42 = build_int_cst (integer_type_node, 42);
8613 tree int_m3 = build_int_cst (integer_type_node, -3);
8615 region_model_manager mgr;
8616 region_model model (&mgr);
8617 /* "arr[0] = 17;". */
8618 model.set_value (arr_0, int_17, NULL);
8619 /* "arr[1] = -3;". */
8620 model.set_value (arr_1, int_m3, NULL);
8622 ASSERT_EQ (model.get_rvalue (arr_0, NULL), model.get_rvalue (int_17, NULL));
8623 ASSERT_EQ (model.get_rvalue (arr_1, NULL), model.get_rvalue (int_m3, NULL));
8625 /* Overwrite a pre-existing binding: "arr[1] = 42;". */
8626 model.set_value (arr_1, int_42, NULL);
8627 ASSERT_EQ (model.get_rvalue (arr_1, NULL), model.get_rvalue (int_42, NULL));
8629 /* Verify get_offset for "arr[0]". */
8631 const region *arr_0_reg = model.get_lvalue (arr_0, NULL);
8632 region_offset offset = arr_0_reg->get_offset (&mgr);
8633 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
8634 ASSERT_EQ (offset.get_bit_offset (), 0);
8637 /* Verify get_offset for "arr[1]". */
8639 const region *arr_1_reg = model.get_lvalue (arr_1, NULL);
8640 region_offset offset = arr_1_reg->get_offset (&mgr);
8641 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
8642 ASSERT_EQ (offset.get_bit_offset (), INT_TYPE_SIZE);
8645 /* Verify get_offset for "arr[i]". */
8647 const region *arr_i_reg = model.get_lvalue (arr_i, NULL);
8648 region_offset offset = arr_i_reg->get_offset (&mgr);
8649 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
8650 ASSERT_EQ (offset.get_symbolic_byte_offset ()->get_kind (), SK_BINOP);
8653 /* "arr[i] = i;" - this should remove the earlier bindings. */
8654 model.set_value (arr_i, i, NULL);
8655 ASSERT_EQ (model.get_rvalue (arr_i, NULL), model.get_rvalue (i, NULL));
8656 ASSERT_EQ (model.get_rvalue (arr_0, NULL)->get_kind (), SK_UNKNOWN);
8658 /* "arr[0] = 17;" - this should remove the arr[i] binding. */
8659 model.set_value (arr_0, int_17, NULL);
8660 ASSERT_EQ (model.get_rvalue (arr_0, NULL), model.get_rvalue (int_17, NULL));
8661 ASSERT_EQ (model.get_rvalue (arr_i, NULL)->get_kind (), SK_UNKNOWN);
8664 /* Smoketest of dereferencing a pointer via MEM_REF. */
8666 static void
8667 test_mem_ref ()
8670 x = 17;
8671 p = &x;
8674 tree x = build_global_decl ("x", integer_type_node);
8675 tree int_star = build_pointer_type (integer_type_node);
8676 tree p = build_global_decl ("p", int_star);
8678 tree int_17 = build_int_cst (integer_type_node, 17);
8679 tree addr_of_x = build1 (ADDR_EXPR, int_star, x);
8680 tree offset_0 = build_int_cst (integer_type_node, 0);
8681 tree star_p = build2 (MEM_REF, integer_type_node, p, offset_0);
8683 region_model_manager mgr;
8684 region_model model (&mgr);
8686 /* "x = 17;". */
8687 model.set_value (x, int_17, NULL);
8689 /* "p = &x;". */
8690 model.set_value (p, addr_of_x, NULL);
8692 const svalue *sval = model.get_rvalue (star_p, NULL);
8693 ASSERT_EQ (sval->maybe_get_constant (), int_17);
8696 /* Test for a POINTER_PLUS_EXPR followed by a MEM_REF.
8697 Analogous to this code:
8698 void test_6 (int a[10])
8700 __analyzer_eval (a[3] == 42); [should be UNKNOWN]
8701 a[3] = 42;
8702 __analyzer_eval (a[3] == 42); [should be TRUE]
8704 from data-model-1.c, which looks like this at the gimple level:
8705 # __analyzer_eval (a[3] == 42); [should be UNKNOWN]
8706 int *_1 = a_10(D) + 12; # POINTER_PLUS_EXPR
8707 int _2 = *_1; # MEM_REF
8708 _Bool _3 = _2 == 42;
8709 int _4 = (int) _3;
8710 __analyzer_eval (_4);
8712 # a[3] = 42;
8713 int *_5 = a_10(D) + 12; # POINTER_PLUS_EXPR
8714 *_5 = 42; # MEM_REF
8716 # __analyzer_eval (a[3] == 42); [should be TRUE]
8717 int *_6 = a_10(D) + 12; # POINTER_PLUS_EXPR
8718 int _7 = *_6; # MEM_REF
8719 _Bool _8 = _7 == 42;
8720 int _9 = (int) _8;
8721 __analyzer_eval (_9); */
8723 static void
8724 test_POINTER_PLUS_EXPR_then_MEM_REF ()
8726 tree int_star = build_pointer_type (integer_type_node);
8727 tree a = build_global_decl ("a", int_star);
8728 tree offset_12 = build_int_cst (size_type_node, 12);
8729 tree pointer_plus_expr = build2 (POINTER_PLUS_EXPR, int_star, a, offset_12);
8730 tree offset_0 = build_int_cst (integer_type_node, 0);
8731 tree mem_ref = build2 (MEM_REF, integer_type_node,
8732 pointer_plus_expr, offset_0);
8733 region_model_manager mgr;
8734 region_model m (&mgr);
8736 tree int_42 = build_int_cst (integer_type_node, 42);
8737 m.set_value (mem_ref, int_42, NULL);
8738 ASSERT_EQ (m.get_rvalue (mem_ref, NULL)->maybe_get_constant (), int_42);
8741 /* Verify that malloc works. */
8743 static void
8744 test_malloc ()
8746 tree int_star = build_pointer_type (integer_type_node);
8747 tree p = build_global_decl ("p", int_star);
8748 tree n = build_global_decl ("n", integer_type_node);
8749 tree n_times_4 = build2 (MULT_EXPR, size_type_node,
8750 n, build_int_cst (size_type_node, 4));
8752 region_model_manager mgr;
8753 test_region_model_context ctxt;
8754 region_model model (&mgr);
8756 /* "p = malloc (n * 4);". */
8757 const svalue *size_sval = model.get_rvalue (n_times_4, &ctxt);
8758 const region *reg
8759 = model.get_or_create_region_for_heap_alloc (size_sval, &ctxt);
8760 const svalue *ptr = mgr.get_ptr_svalue (int_star, reg);
8761 model.set_value (model.get_lvalue (p, &ctxt), ptr, &ctxt);
8762 ASSERT_EQ (model.get_capacity (reg), size_sval);
8765 /* Verify that alloca works. */
8767 static void
8768 test_alloca ()
8770 auto_vec <tree> param_types;
8771 tree fndecl = make_fndecl (integer_type_node,
8772 "test_fn",
8773 param_types);
8774 allocate_struct_function (fndecl, true);
8777 tree int_star = build_pointer_type (integer_type_node);
8778 tree p = build_global_decl ("p", int_star);
8779 tree n = build_global_decl ("n", integer_type_node);
8780 tree n_times_4 = build2 (MULT_EXPR, size_type_node,
8781 n, build_int_cst (size_type_node, 4));
8783 region_model_manager mgr;
8784 test_region_model_context ctxt;
8785 region_model model (&mgr);
8787 /* Push stack frame. */
8788 const region *frame_reg
8789 = model.push_frame (DECL_STRUCT_FUNCTION (fndecl),
8790 NULL, &ctxt);
8791 /* "p = alloca (n * 4);". */
8792 const svalue *size_sval = model.get_rvalue (n_times_4, &ctxt);
8793 const region *reg = model.create_region_for_alloca (size_sval, &ctxt);
8794 ASSERT_EQ (reg->get_parent_region (), frame_reg);
8795 const svalue *ptr = mgr.get_ptr_svalue (int_star, reg);
8796 model.set_value (model.get_lvalue (p, &ctxt), ptr, &ctxt);
8797 ASSERT_EQ (model.get_capacity (reg), size_sval);
8799 /* Verify that the pointers to the alloca region are replaced by
8800 poisoned values when the frame is popped. */
8801 model.pop_frame (NULL, NULL, &ctxt);
8802 ASSERT_EQ (model.get_rvalue (p, NULL)->get_kind (), SK_POISONED);
8805 /* Verify that svalue::involves_p works. */
8807 static void
8808 test_involves_p ()
8810 region_model_manager mgr;
8811 tree int_star = build_pointer_type (integer_type_node);
8812 tree p = build_global_decl ("p", int_star);
8813 tree q = build_global_decl ("q", int_star);
8815 test_region_model_context ctxt;
8816 region_model model (&mgr);
8817 const svalue *p_init = model.get_rvalue (p, &ctxt);
8818 const svalue *q_init = model.get_rvalue (q, &ctxt);
8820 ASSERT_TRUE (p_init->involves_p (p_init));
8821 ASSERT_FALSE (p_init->involves_p (q_init));
8823 const region *star_p_reg = mgr.get_symbolic_region (p_init);
8824 const region *star_q_reg = mgr.get_symbolic_region (q_init);
8826 const svalue *init_star_p = mgr.get_or_create_initial_value (star_p_reg);
8827 const svalue *init_star_q = mgr.get_or_create_initial_value (star_q_reg);
8829 ASSERT_TRUE (init_star_p->involves_p (p_init));
8830 ASSERT_FALSE (p_init->involves_p (init_star_p));
8831 ASSERT_FALSE (init_star_p->involves_p (q_init));
8832 ASSERT_TRUE (init_star_q->involves_p (q_init));
8833 ASSERT_FALSE (init_star_q->involves_p (p_init));
8836 /* Run all of the selftests within this file. */
8838 void
8839 analyzer_region_model_cc_tests ()
8841 test_tree_cmp_on_constants ();
8842 test_dump ();
8843 test_struct ();
8844 test_array_1 ();
8845 test_get_representative_tree ();
8846 test_unique_constants ();
8847 test_unique_unknowns ();
8848 test_initial_svalue_folding ();
8849 test_unaryop_svalue_folding ();
8850 test_binop_svalue_folding ();
8851 test_sub_svalue_folding ();
8852 test_bits_within_svalue_folding ();
8853 test_descendent_of_p ();
8854 test_bit_range_regions ();
8855 test_assignment ();
8856 test_compound_assignment ();
8857 test_stack_frames ();
8858 test_get_representative_path_var ();
8859 test_equality_1 ();
8860 test_canonicalization_2 ();
8861 test_canonicalization_3 ();
8862 test_canonicalization_4 ();
8863 test_state_merging ();
8864 test_constraint_merging ();
8865 test_widening_constraints ();
8866 test_iteration_1 ();
8867 test_malloc_constraints ();
8868 test_var ();
8869 test_array_2 ();
8870 test_mem_ref ();
8871 test_POINTER_PLUS_EXPR_then_MEM_REF ();
8872 test_malloc ();
8873 test_alloca ();
8874 test_involves_p ();
8877 } // namespace selftest
8879 #endif /* CHECKING_P */
8881 } // namespace ana
8883 #endif /* #if ENABLE_ANALYZER */