hppa: Export main in pr104869.C on hpux
[official-gcc.git] / gcc / analyzer / region-model.cc
blob420c10380a4e7c666af10cf1c098a2903e28c6cb
1 /* Classes for modeling the state of memory.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #define INCLUDE_MEMORY
23 #define INCLUDE_ALGORITHM
24 #include "system.h"
25 #include "coretypes.h"
26 #include "make-unique.h"
27 #include "tree.h"
28 #include "function.h"
29 #include "basic-block.h"
30 #include "gimple.h"
31 #include "gimple-iterator.h"
32 #include "diagnostic-core.h"
33 #include "graphviz.h"
34 #include "options.h"
35 #include "cgraph.h"
36 #include "tree-dfa.h"
37 #include "stringpool.h"
38 #include "convert.h"
39 #include "target.h"
40 #include "fold-const.h"
41 #include "tree-pretty-print.h"
42 #include "diagnostic-color.h"
43 #include "diagnostic-metadata.h"
44 #include "bitmap.h"
45 #include "selftest.h"
46 #include "analyzer/analyzer.h"
47 #include "analyzer/analyzer-logging.h"
48 #include "ordered-hash-map.h"
49 #include "options.h"
50 #include "cgraph.h"
51 #include "cfg.h"
52 #include "analyzer/supergraph.h"
53 #include "sbitmap.h"
54 #include "analyzer/call-string.h"
55 #include "analyzer/program-point.h"
56 #include "analyzer/store.h"
57 #include "analyzer/region-model.h"
58 #include "analyzer/constraint-manager.h"
59 #include "diagnostic-event-id.h"
60 #include "analyzer/sm.h"
61 #include "diagnostic-event-id.h"
62 #include "analyzer/sm.h"
63 #include "analyzer/pending-diagnostic.h"
64 #include "analyzer/region-model-reachability.h"
65 #include "analyzer/analyzer-selftests.h"
66 #include "analyzer/program-state.h"
67 #include "analyzer/call-summary.h"
68 #include "stor-layout.h"
69 #include "attribs.h"
70 #include "tree-object-size.h"
71 #include "gimple-ssa.h"
72 #include "tree-phinodes.h"
73 #include "tree-ssa-operands.h"
74 #include "ssa-iterators.h"
75 #include "calls.h"
76 #include "is-a.h"
77 #include "gcc-rich-location.h"
78 #include "analyzer/checker-event.h"
79 #include "analyzer/checker-path.h"
80 #include "analyzer/feasible-graph.h"
81 #include "analyzer/record-layout.h"
83 #if ENABLE_ANALYZER
85 namespace ana {
87 auto_vec<pop_frame_callback> region_model::pop_frame_callbacks;
89 /* Dump T to PP in language-independent form, for debugging/logging/dumping
90 purposes. */
92 void
93 dump_tree (pretty_printer *pp, tree t)
95 dump_generic_node (pp, t, 0, TDF_SLIM, 0);
98 /* Dump T to PP in language-independent form in quotes, for
99 debugging/logging/dumping purposes. */
101 void
102 dump_quoted_tree (pretty_printer *pp, tree t)
104 pp_begin_quote (pp, pp_show_color (pp));
105 dump_tree (pp, t);
106 pp_end_quote (pp, pp_show_color (pp));
109 /* Equivalent to pp_printf (pp, "%qT", t), to avoid nesting pp_printf
110 calls within other pp_printf calls.
112 default_tree_printer handles 'T' and some other codes by calling
113 dump_generic_node (pp, t, 0, TDF_SLIM, 0);
114 dump_generic_node calls pp_printf in various places, leading to
115 garbled output.
117 Ideally pp_printf could be made to be reentrant, but in the meantime
118 this function provides a workaround. */
120 void
121 print_quoted_type (pretty_printer *pp, tree t)
123 pp_begin_quote (pp, pp_show_color (pp));
124 dump_generic_node (pp, t, 0, TDF_SLIM, 0);
125 pp_end_quote (pp, pp_show_color (pp));
128 /* class region_to_value_map. */
130 /* Assignment operator for region_to_value_map. */
132 region_to_value_map &
133 region_to_value_map::operator= (const region_to_value_map &other)
135 m_hash_map.empty ();
136 for (auto iter : other.m_hash_map)
138 const region *reg = iter.first;
139 const svalue *sval = iter.second;
140 m_hash_map.put (reg, sval);
142 return *this;
145 /* Equality operator for region_to_value_map. */
147 bool
148 region_to_value_map::operator== (const region_to_value_map &other) const
150 if (m_hash_map.elements () != other.m_hash_map.elements ())
151 return false;
153 for (auto iter : *this)
155 const region *reg = iter.first;
156 const svalue *sval = iter.second;
157 const svalue * const *other_slot = other.get (reg);
158 if (other_slot == NULL)
159 return false;
160 if (sval != *other_slot)
161 return false;
164 return true;
167 /* Dump this object to PP. */
169 void
170 region_to_value_map::dump_to_pp (pretty_printer *pp, bool simple,
171 bool multiline) const
173 auto_vec<const region *> regs;
174 for (iterator iter = begin (); iter != end (); ++iter)
175 regs.safe_push ((*iter).first);
176 regs.qsort (region::cmp_ptr_ptr);
177 if (multiline)
178 pp_newline (pp);
179 else
180 pp_string (pp, " {");
181 unsigned i;
182 const region *reg;
183 FOR_EACH_VEC_ELT (regs, i, reg)
185 if (multiline)
186 pp_string (pp, " ");
187 else if (i > 0)
188 pp_string (pp, ", ");
189 reg->dump_to_pp (pp, simple);
190 pp_string (pp, ": ");
191 const svalue *sval = *get (reg);
192 sval->dump_to_pp (pp, true);
193 if (multiline)
194 pp_newline (pp);
196 if (!multiline)
197 pp_string (pp, "}");
200 /* Dump this object to stderr. */
202 DEBUG_FUNCTION void
203 region_to_value_map::dump (bool simple) const
205 pretty_printer pp;
206 pp_format_decoder (&pp) = default_tree_printer;
207 pp_show_color (&pp) = pp_show_color (global_dc->printer);
208 pp.buffer->stream = stderr;
209 dump_to_pp (&pp, simple, true);
210 pp_newline (&pp);
211 pp_flush (&pp);
215 /* Attempt to merge THIS with OTHER, writing the result
216 to OUT.
218 For now, write (region, value) mappings that are in common between THIS
219 and OTHER to OUT, effectively taking the intersection.
221 Reject merger of different values. */
223 bool
224 region_to_value_map::can_merge_with_p (const region_to_value_map &other,
225 region_to_value_map *out) const
227 for (auto iter : *this)
229 const region *iter_reg = iter.first;
230 const svalue *iter_sval = iter.second;
231 const svalue * const * other_slot = other.get (iter_reg);
232 if (other_slot)
234 if (iter_sval == *other_slot)
235 out->put (iter_reg, iter_sval);
236 else
237 return false;
240 return true;
243 /* Purge any state involving SVAL. */
245 void
246 region_to_value_map::purge_state_involving (const svalue *sval)
248 auto_vec<const region *> to_purge;
249 for (auto iter : *this)
251 const region *iter_reg = iter.first;
252 const svalue *iter_sval = iter.second;
253 if (iter_reg->involves_p (sval) || iter_sval->involves_p (sval))
254 to_purge.safe_push (iter_reg);
256 for (auto iter : to_purge)
257 m_hash_map.remove (iter);
260 /* class region_model. */
262 /* Ctor for region_model: construct an "empty" model. */
264 region_model::region_model (region_model_manager *mgr)
265 : m_mgr (mgr), m_store (), m_current_frame (NULL),
266 m_dynamic_extents ()
268 m_constraints = new constraint_manager (mgr);
271 /* region_model's copy ctor. */
273 region_model::region_model (const region_model &other)
274 : m_mgr (other.m_mgr), m_store (other.m_store),
275 m_constraints (new constraint_manager (*other.m_constraints)),
276 m_current_frame (other.m_current_frame),
277 m_dynamic_extents (other.m_dynamic_extents)
281 /* region_model's dtor. */
283 region_model::~region_model ()
285 delete m_constraints;
288 /* region_model's assignment operator. */
290 region_model &
291 region_model::operator= (const region_model &other)
293 /* m_mgr is const. */
294 gcc_assert (m_mgr == other.m_mgr);
296 m_store = other.m_store;
298 delete m_constraints;
299 m_constraints = new constraint_manager (*other.m_constraints);
301 m_current_frame = other.m_current_frame;
303 m_dynamic_extents = other.m_dynamic_extents;
305 return *this;
308 /* Equality operator for region_model.
310 Amongst other things this directly compares the stores and the constraint
311 managers, so for this to be meaningful both this and OTHER should
312 have been canonicalized. */
314 bool
315 region_model::operator== (const region_model &other) const
317 /* We can only compare instances that use the same manager. */
318 gcc_assert (m_mgr == other.m_mgr);
320 if (m_store != other.m_store)
321 return false;
323 if (*m_constraints != *other.m_constraints)
324 return false;
326 if (m_current_frame != other.m_current_frame)
327 return false;
329 if (m_dynamic_extents != other.m_dynamic_extents)
330 return false;
332 gcc_checking_assert (hash () == other.hash ());
334 return true;
337 /* Generate a hash value for this region_model. */
339 hashval_t
340 region_model::hash () const
342 hashval_t result = m_store.hash ();
343 result ^= m_constraints->hash ();
344 return result;
347 /* Dump a representation of this model to PP, showing the
348 stack, the store, and any constraints.
349 Use SIMPLE to control how svalues and regions are printed. */
351 void
352 region_model::dump_to_pp (pretty_printer *pp, bool simple,
353 bool multiline) const
355 /* Dump stack. */
356 pp_printf (pp, "stack depth: %i", get_stack_depth ());
357 if (multiline)
358 pp_newline (pp);
359 else
360 pp_string (pp, " {");
361 for (const frame_region *iter_frame = m_current_frame; iter_frame;
362 iter_frame = iter_frame->get_calling_frame ())
364 if (multiline)
365 pp_string (pp, " ");
366 else if (iter_frame != m_current_frame)
367 pp_string (pp, ", ");
368 pp_printf (pp, "frame (index %i): ", iter_frame->get_index ());
369 iter_frame->dump_to_pp (pp, simple);
370 if (multiline)
371 pp_newline (pp);
373 if (!multiline)
374 pp_string (pp, "}");
376 /* Dump store. */
377 if (!multiline)
378 pp_string (pp, ", {");
379 m_store.dump_to_pp (pp, simple, multiline,
380 m_mgr->get_store_manager ());
381 if (!multiline)
382 pp_string (pp, "}");
384 /* Dump constraints. */
385 pp_string (pp, "constraint_manager:");
386 if (multiline)
387 pp_newline (pp);
388 else
389 pp_string (pp, " {");
390 m_constraints->dump_to_pp (pp, multiline);
391 if (!multiline)
392 pp_string (pp, "}");
394 /* Dump sizes of dynamic regions, if any are known. */
395 if (!m_dynamic_extents.is_empty ())
397 pp_string (pp, "dynamic_extents:");
398 m_dynamic_extents.dump_to_pp (pp, simple, multiline);
402 /* Dump a representation of this model to FILE. */
404 void
405 region_model::dump (FILE *fp, bool simple, bool multiline) const
407 pretty_printer pp;
408 pp_format_decoder (&pp) = default_tree_printer;
409 pp_show_color (&pp) = pp_show_color (global_dc->printer);
410 pp.buffer->stream = fp;
411 dump_to_pp (&pp, simple, multiline);
412 pp_newline (&pp);
413 pp_flush (&pp);
416 /* Dump a multiline representation of this model to stderr. */
418 DEBUG_FUNCTION void
419 region_model::dump (bool simple) const
421 dump (stderr, simple, true);
424 /* Dump a multiline representation of this model to stderr. */
426 DEBUG_FUNCTION void
427 region_model::debug () const
429 dump (true);
432 /* Assert that this object is valid. */
434 void
435 region_model::validate () const
437 m_store.validate ();
440 /* Canonicalize the store and constraints, to maximize the chance of
441 equality between region_model instances. */
443 void
444 region_model::canonicalize ()
446 m_store.canonicalize (m_mgr->get_store_manager ());
447 m_constraints->canonicalize ();
450 /* Return true if this region_model is in canonical form. */
452 bool
453 region_model::canonicalized_p () const
455 region_model copy (*this);
456 copy.canonicalize ();
457 return *this == copy;
460 /* See the comment for store::loop_replay_fixup. */
462 void
463 region_model::loop_replay_fixup (const region_model *dst_state)
465 m_store.loop_replay_fixup (dst_state->get_store (), m_mgr);
468 /* A subclass of pending_diagnostic for complaining about uses of
469 poisoned values. */
471 class poisoned_value_diagnostic
472 : public pending_diagnostic_subclass<poisoned_value_diagnostic>
474 public:
475 poisoned_value_diagnostic (tree expr, enum poison_kind pkind,
476 const region *src_region,
477 tree check_expr)
478 : m_expr (expr), m_pkind (pkind),
479 m_src_region (src_region),
480 m_check_expr (check_expr)
483 const char *get_kind () const final override { return "poisoned_value_diagnostic"; }
485 bool use_of_uninit_p () const final override
487 return m_pkind == POISON_KIND_UNINIT;
490 bool operator== (const poisoned_value_diagnostic &other) const
492 return (m_expr == other.m_expr
493 && m_pkind == other.m_pkind
494 && m_src_region == other.m_src_region);
497 int get_controlling_option () const final override
499 switch (m_pkind)
501 default:
502 gcc_unreachable ();
503 case POISON_KIND_UNINIT:
504 return OPT_Wanalyzer_use_of_uninitialized_value;
505 case POISON_KIND_FREED:
506 case POISON_KIND_DELETED:
507 return OPT_Wanalyzer_use_after_free;
508 case POISON_KIND_POPPED_STACK:
509 return OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame;
513 bool terminate_path_p () const final override { return true; }
515 bool emit (rich_location *rich_loc, logger *) final override
517 switch (m_pkind)
519 default:
520 gcc_unreachable ();
521 case POISON_KIND_UNINIT:
523 diagnostic_metadata m;
524 m.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
525 return warning_meta (rich_loc, m, get_controlling_option (),
526 "use of uninitialized value %qE",
527 m_expr);
529 break;
530 case POISON_KIND_FREED:
532 diagnostic_metadata m;
533 m.add_cwe (416); /* "CWE-416: Use After Free". */
534 return warning_meta (rich_loc, m, get_controlling_option (),
535 "use after %<free%> of %qE",
536 m_expr);
538 break;
539 case POISON_KIND_DELETED:
541 diagnostic_metadata m;
542 m.add_cwe (416); /* "CWE-416: Use After Free". */
543 return warning_meta (rich_loc, m, get_controlling_option (),
544 "use after %<delete%> of %qE",
545 m_expr);
547 break;
548 case POISON_KIND_POPPED_STACK:
550 /* TODO: which CWE? */
551 return warning_at
552 (rich_loc, get_controlling_option (),
553 "dereferencing pointer %qE to within stale stack frame",
554 m_expr);
556 break;
560 label_text describe_final_event (const evdesc::final_event &ev) final override
562 switch (m_pkind)
564 default:
565 gcc_unreachable ();
566 case POISON_KIND_UNINIT:
567 return ev.formatted_print ("use of uninitialized value %qE here",
568 m_expr);
569 case POISON_KIND_FREED:
570 return ev.formatted_print ("use after %<free%> of %qE here",
571 m_expr);
572 case POISON_KIND_DELETED:
573 return ev.formatted_print ("use after %<delete%> of %qE here",
574 m_expr);
575 case POISON_KIND_POPPED_STACK:
576 return ev.formatted_print
577 ("dereferencing pointer %qE to within stale stack frame",
578 m_expr);
582 void mark_interesting_stuff (interesting_t *interest) final override
584 if (m_src_region)
585 interest->add_region_creation (m_src_region);
588 /* Attempt to suppress false positives.
589 Reject paths where the value of the underlying region isn't poisoned.
590 This can happen due to state merging when exploring the exploded graph,
591 where the more precise analysis during feasibility analysis finds that
592 the region is in fact valid.
593 To do this we need to get the value from the fgraph. Unfortunately
594 we can't simply query the state of m_src_region (from the enode),
595 since it might be a different region in the fnode state (e.g. with
596 heap-allocated regions, the numbering could be different).
597 Hence we access m_check_expr, if available. */
599 bool check_valid_fpath_p (const feasible_node &fnode,
600 const gimple *emission_stmt)
601 const final override
603 if (!m_check_expr)
604 return true;
606 /* We've reached the enode, but not necessarily the right function_point.
607 Try to get the state at the correct stmt. */
608 region_model emission_model (fnode.get_model ().get_manager());
609 if (!fnode.get_state_at_stmt (emission_stmt, &emission_model))
610 /* Couldn't get state; accept this diagnostic. */
611 return true;
613 const svalue *fsval = emission_model.get_rvalue (m_check_expr, NULL);
614 /* Check to see if the expr is also poisoned in FNODE (and in the
615 same way). */
616 const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();
617 if (!fspval)
618 return false;
619 if (fspval->get_poison_kind () != m_pkind)
620 return false;
621 return true;
624 private:
625 tree m_expr;
626 enum poison_kind m_pkind;
627 const region *m_src_region;
628 tree m_check_expr;
631 /* A subclass of pending_diagnostic for complaining about shifts
632 by negative counts. */
634 class shift_count_negative_diagnostic
635 : public pending_diagnostic_subclass<shift_count_negative_diagnostic>
637 public:
638 shift_count_negative_diagnostic (const gassign *assign, tree count_cst)
639 : m_assign (assign), m_count_cst (count_cst)
642 const char *get_kind () const final override
644 return "shift_count_negative_diagnostic";
647 bool operator== (const shift_count_negative_diagnostic &other) const
649 return (m_assign == other.m_assign
650 && same_tree_p (m_count_cst, other.m_count_cst));
653 int get_controlling_option () const final override
655 return OPT_Wanalyzer_shift_count_negative;
658 bool emit (rich_location *rich_loc, logger *) final override
660 return warning_at (rich_loc, get_controlling_option (),
661 "shift by negative count (%qE)", m_count_cst);
664 label_text describe_final_event (const evdesc::final_event &ev) final override
666 return ev.formatted_print ("shift by negative amount here (%qE)", m_count_cst);
669 private:
670 const gassign *m_assign;
671 tree m_count_cst;
674 /* A subclass of pending_diagnostic for complaining about shifts
675 by counts >= the width of the operand type. */
677 class shift_count_overflow_diagnostic
678 : public pending_diagnostic_subclass<shift_count_overflow_diagnostic>
680 public:
681 shift_count_overflow_diagnostic (const gassign *assign,
682 int operand_precision,
683 tree count_cst)
684 : m_assign (assign), m_operand_precision (operand_precision),
685 m_count_cst (count_cst)
688 const char *get_kind () const final override
690 return "shift_count_overflow_diagnostic";
693 bool operator== (const shift_count_overflow_diagnostic &other) const
695 return (m_assign == other.m_assign
696 && m_operand_precision == other.m_operand_precision
697 && same_tree_p (m_count_cst, other.m_count_cst));
700 int get_controlling_option () const final override
702 return OPT_Wanalyzer_shift_count_overflow;
705 bool emit (rich_location *rich_loc, logger *) final override
707 return warning_at (rich_loc, get_controlling_option (),
708 "shift by count (%qE) >= precision of type (%qi)",
709 m_count_cst, m_operand_precision);
712 label_text describe_final_event (const evdesc::final_event &ev) final override
714 return ev.formatted_print ("shift by count %qE here", m_count_cst);
717 private:
718 const gassign *m_assign;
719 int m_operand_precision;
720 tree m_count_cst;
723 /* If ASSIGN is a stmt that can be modelled via
724 set_value (lhs_reg, SVALUE, CTXT)
725 for some SVALUE, get the SVALUE.
726 Otherwise return NULL. */
728 const svalue *
729 region_model::get_gassign_result (const gassign *assign,
730 region_model_context *ctxt)
732 tree lhs = gimple_assign_lhs (assign);
734 if (gimple_has_volatile_ops (assign)
735 && !gimple_clobber_p (assign))
737 conjured_purge p (this, ctxt);
738 return m_mgr->get_or_create_conjured_svalue (TREE_TYPE (lhs),
739 assign,
740 get_lvalue (lhs, ctxt),
744 tree rhs1 = gimple_assign_rhs1 (assign);
745 enum tree_code op = gimple_assign_rhs_code (assign);
746 switch (op)
748 default:
749 return NULL;
751 case POINTER_PLUS_EXPR:
753 /* e.g. "_1 = a_10(D) + 12;" */
754 tree ptr = rhs1;
755 tree offset = gimple_assign_rhs2 (assign);
757 const svalue *ptr_sval = get_rvalue (ptr, ctxt);
758 const svalue *offset_sval = get_rvalue (offset, ctxt);
759 /* Quoting tree.def, "the second operand [of a POINTER_PLUS_EXPR]
760 is an integer of type sizetype". */
761 offset_sval = m_mgr->get_or_create_cast (size_type_node, offset_sval);
763 const svalue *sval_binop
764 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
765 ptr_sval, offset_sval);
766 return sval_binop;
768 break;
770 case POINTER_DIFF_EXPR:
772 /* e.g. "_1 = p_2(D) - q_3(D);". */
773 tree rhs2 = gimple_assign_rhs2 (assign);
774 const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
775 const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
777 // TODO: perhaps fold to zero if they're known to be equal?
779 const svalue *sval_binop
780 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
781 rhs1_sval, rhs2_sval);
782 return sval_binop;
784 break;
786 /* Assignments of the form
787 set_value (lvalue (LHS), rvalue (EXPR))
788 for various EXPR.
789 We already have the lvalue for the LHS above, as "lhs_reg". */
790 case ADDR_EXPR: /* LHS = &RHS; */
791 case BIT_FIELD_REF:
792 case COMPONENT_REF: /* LHS = op0.op1; */
793 case MEM_REF:
794 case REAL_CST:
795 case COMPLEX_CST:
796 case VECTOR_CST:
797 case INTEGER_CST:
798 case ARRAY_REF:
799 case SSA_NAME: /* LHS = VAR; */
800 case VAR_DECL: /* LHS = VAR; */
801 case PARM_DECL:/* LHS = VAR; */
802 case REALPART_EXPR:
803 case IMAGPART_EXPR:
804 return get_rvalue (rhs1, ctxt);
806 case ABS_EXPR:
807 case ABSU_EXPR:
808 case CONJ_EXPR:
809 case BIT_NOT_EXPR:
810 case FIX_TRUNC_EXPR:
811 case FLOAT_EXPR:
812 case NEGATE_EXPR:
813 case NOP_EXPR:
814 case VIEW_CONVERT_EXPR:
816 /* Unary ops. */
817 const svalue *rhs_sval = get_rvalue (rhs1, ctxt);
818 const svalue *sval_unaryop
819 = m_mgr->get_or_create_unaryop (TREE_TYPE (lhs), op, rhs_sval);
820 return sval_unaryop;
823 case EQ_EXPR:
824 case GE_EXPR:
825 case LE_EXPR:
826 case NE_EXPR:
827 case GT_EXPR:
828 case LT_EXPR:
829 case UNORDERED_EXPR:
830 case ORDERED_EXPR:
832 tree rhs2 = gimple_assign_rhs2 (assign);
834 const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
835 const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
837 if (TREE_TYPE (lhs) == boolean_type_node)
839 /* Consider constraints between svalues. */
840 tristate t = eval_condition (rhs1_sval, op, rhs2_sval);
841 if (t.is_known ())
842 return m_mgr->get_or_create_constant_svalue
843 (t.is_true () ? boolean_true_node : boolean_false_node);
846 /* Otherwise, generate a symbolic binary op. */
847 const svalue *sval_binop
848 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
849 rhs1_sval, rhs2_sval);
850 return sval_binop;
852 break;
854 case PLUS_EXPR:
855 case MINUS_EXPR:
856 case MULT_EXPR:
857 case MULT_HIGHPART_EXPR:
858 case TRUNC_DIV_EXPR:
859 case CEIL_DIV_EXPR:
860 case FLOOR_DIV_EXPR:
861 case ROUND_DIV_EXPR:
862 case TRUNC_MOD_EXPR:
863 case CEIL_MOD_EXPR:
864 case FLOOR_MOD_EXPR:
865 case ROUND_MOD_EXPR:
866 case RDIV_EXPR:
867 case EXACT_DIV_EXPR:
868 case LSHIFT_EXPR:
869 case RSHIFT_EXPR:
870 case LROTATE_EXPR:
871 case RROTATE_EXPR:
872 case BIT_IOR_EXPR:
873 case BIT_XOR_EXPR:
874 case BIT_AND_EXPR:
875 case MIN_EXPR:
876 case MAX_EXPR:
877 case COMPLEX_EXPR:
879 /* Binary ops. */
880 tree rhs2 = gimple_assign_rhs2 (assign);
882 const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
883 const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
885 if (ctxt && (op == LSHIFT_EXPR || op == RSHIFT_EXPR))
887 /* "INT34-C. Do not shift an expression by a negative number of bits
888 or by greater than or equal to the number of bits that exist in
889 the operand." */
890 if (const tree rhs2_cst = rhs2_sval->maybe_get_constant ())
891 if (TREE_CODE (rhs2_cst) == INTEGER_CST
892 && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
894 if (tree_int_cst_sgn (rhs2_cst) < 0)
895 ctxt->warn
896 (make_unique<shift_count_negative_diagnostic>
897 (assign, rhs2_cst));
898 else if (compare_tree_int (rhs2_cst,
899 TYPE_PRECISION (TREE_TYPE (rhs1)))
900 >= 0)
901 ctxt->warn
902 (make_unique<shift_count_overflow_diagnostic>
903 (assign,
904 int (TYPE_PRECISION (TREE_TYPE (rhs1))),
905 rhs2_cst));
909 const svalue *sval_binop
910 = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
911 rhs1_sval, rhs2_sval);
912 return sval_binop;
915 /* Vector expressions. In theory we could implement these elementwise,
916 but for now, simply return unknown values. */
917 case VEC_DUPLICATE_EXPR:
918 case VEC_SERIES_EXPR:
919 case VEC_COND_EXPR:
920 case VEC_PERM_EXPR:
921 case VEC_WIDEN_MULT_HI_EXPR:
922 case VEC_WIDEN_MULT_LO_EXPR:
923 case VEC_WIDEN_MULT_EVEN_EXPR:
924 case VEC_WIDEN_MULT_ODD_EXPR:
925 case VEC_UNPACK_HI_EXPR:
926 case VEC_UNPACK_LO_EXPR:
927 case VEC_UNPACK_FLOAT_HI_EXPR:
928 case VEC_UNPACK_FLOAT_LO_EXPR:
929 case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
930 case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
931 case VEC_PACK_TRUNC_EXPR:
932 case VEC_PACK_SAT_EXPR:
933 case VEC_PACK_FIX_TRUNC_EXPR:
934 case VEC_PACK_FLOAT_EXPR:
935 case VEC_WIDEN_LSHIFT_HI_EXPR:
936 case VEC_WIDEN_LSHIFT_LO_EXPR:
937 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (lhs));
941 /* Workaround for discarding certain false positives from
942 -Wanalyzer-use-of-uninitialized-value
943 of the form:
944 ((A OR-IF B) OR-IF C)
945 and:
946 ((A AND-IF B) AND-IF C)
947 where evaluating B is redundant, but could involve simple accesses of
948 uninitialized locals.
950 When optimization is turned on the FE can immediately fold compound
951 conditionals. Specifically, c_parser_condition parses this condition:
952 ((A OR-IF B) OR-IF C)
953 and calls c_fully_fold on the condition.
954 Within c_fully_fold, fold_truth_andor is called, which bails when
955 optimization is off, but if any optimization is turned on can convert the
956 ((A OR-IF B) OR-IF C)
957 into:
958 ((A OR B) OR_IF C)
959 for sufficiently simple B
960 i.e. the inner OR-IF becomes an OR.
961 At gimplification time the inner OR becomes BIT_IOR_EXPR (in gimplify_expr),
962 giving this for the inner condition:
963 tmp = A | B;
964 if (tmp)
965 thus effectively synthesizing a redundant access of B when optimization
966 is turned on, when compared to:
967 if (A) goto L1; else goto L4;
968 L1: if (B) goto L2; else goto L4;
969 L2: if (C) goto L3; else goto L4;
970 for the unoptimized case.
972 Return true if CTXT appears to be handling such a short-circuitable stmt,
973 such as the def-stmt for B for the:
974 tmp = A | B;
975 case above, for the case where A is true and thus B would have been
976 short-circuited without optimization, using MODEL for the value of A. */
978 static bool
979 within_short_circuited_stmt_p (const region_model *model,
980 const gassign *assign_stmt)
982 /* We must have an assignment to a temporary of _Bool type. */
983 tree lhs = gimple_assign_lhs (assign_stmt);
984 if (TREE_TYPE (lhs) != boolean_type_node)
985 return false;
986 if (TREE_CODE (lhs) != SSA_NAME)
987 return false;
988 if (SSA_NAME_VAR (lhs) != NULL_TREE)
989 return false;
991 /* The temporary bool must be used exactly once: as the second arg of
992 a BIT_IOR_EXPR or BIT_AND_EXPR. */
993 use_operand_p use_op;
994 gimple *use_stmt;
995 if (!single_imm_use (lhs, &use_op, &use_stmt))
996 return false;
997 const gassign *use_assign = dyn_cast <const gassign *> (use_stmt);
998 if (!use_assign)
999 return false;
1000 enum tree_code op = gimple_assign_rhs_code (use_assign);
1001 if (!(op == BIT_IOR_EXPR ||op == BIT_AND_EXPR))
1002 return false;
1003 if (!(gimple_assign_rhs1 (use_assign) != lhs
1004 && gimple_assign_rhs2 (use_assign) == lhs))
1005 return false;
1007 /* The first arg of the bitwise stmt must have a known value in MODEL
1008 that implies that the value of the second arg doesn't matter, i.e.
1009 1 for bitwise or, 0 for bitwise and. */
1010 tree other_arg = gimple_assign_rhs1 (use_assign);
1011 /* Use a NULL ctxt here to avoid generating warnings. */
1012 const svalue *other_arg_sval = model->get_rvalue (other_arg, NULL);
1013 tree other_arg_cst = other_arg_sval->maybe_get_constant ();
1014 if (!other_arg_cst)
1015 return false;
1016 switch (op)
1018 default:
1019 gcc_unreachable ();
1020 case BIT_IOR_EXPR:
1021 if (zerop (other_arg_cst))
1022 return false;
1023 break;
1024 case BIT_AND_EXPR:
1025 if (!zerop (other_arg_cst))
1026 return false;
1027 break;
1030 /* All tests passed. We appear to be in a stmt that generates a boolean
1031 temporary with a value that won't matter. */
1032 return true;
1035 /* Workaround for discarding certain false positives from
1036 -Wanalyzer-use-of-uninitialized-value
1037 seen with -ftrivial-auto-var-init=.
1039 -ftrivial-auto-var-init= will generate calls to IFN_DEFERRED_INIT.
1041 If the address of the var is taken, gimplification will give us
1042 something like:
1044 _1 = .DEFERRED_INIT (4, 2, &"len"[0]);
1045 len = _1;
1047 The result of DEFERRED_INIT will be an uninit value; we don't
1048 want to emit a false positive for "len = _1;"
1050 Return true if ASSIGN_STMT is such a stmt. */
1052 static bool
1053 due_to_ifn_deferred_init_p (const gassign *assign_stmt)
1056 /* We must have an assignment to a decl from an SSA name that's the
1057 result of a IFN_DEFERRED_INIT call. */
1058 if (gimple_assign_rhs_code (assign_stmt) != SSA_NAME)
1059 return false;
1060 tree lhs = gimple_assign_lhs (assign_stmt);
1061 if (TREE_CODE (lhs) != VAR_DECL)
1062 return false;
1063 tree rhs = gimple_assign_rhs1 (assign_stmt);
1064 if (TREE_CODE (rhs) != SSA_NAME)
1065 return false;
1066 const gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
1067 const gcall *call = dyn_cast <const gcall *> (def_stmt);
1068 if (!call)
1069 return false;
1070 if (gimple_call_internal_p (call)
1071 && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1072 return true;
1073 return false;
1076 /* Check for SVAL being poisoned, adding a warning to CTXT.
1077 Return SVAL, or, if a warning is added, another value, to avoid
1078 repeatedly complaining about the same poisoned value in followup code.
1079 SRC_REGION is a hint about where SVAL came from, and can be NULL. */
1081 const svalue *
1082 region_model::check_for_poison (const svalue *sval,
1083 tree expr,
1084 const region *src_region,
1085 region_model_context *ctxt) const
1087 if (!ctxt)
1088 return sval;
1090 if (const poisoned_svalue *poisoned_sval = sval->dyn_cast_poisoned_svalue ())
1092 enum poison_kind pkind = poisoned_sval->get_poison_kind ();
1094 /* Ignore uninitialized uses of empty types; there's nothing
1095 to initialize. */
1096 if (pkind == POISON_KIND_UNINIT
1097 && sval->get_type ()
1098 && is_empty_type (sval->get_type ()))
1099 return sval;
1101 if (pkind == POISON_KIND_UNINIT)
1102 if (const gimple *curr_stmt = ctxt->get_stmt ())
1103 if (const gassign *assign_stmt
1104 = dyn_cast <const gassign *> (curr_stmt))
1106 /* Special case to avoid certain false positives. */
1107 if (within_short_circuited_stmt_p (this, assign_stmt))
1108 return sval;
1110 /* Special case to avoid false positive on
1111 -ftrivial-auto-var-init=. */
1112 if (due_to_ifn_deferred_init_p (assign_stmt))
1113 return sval;
1116 /* If we have an SSA name for a temporary, we don't want to print
1117 '<unknown>'.
1118 Poisoned values are shared by type, and so we can't reconstruct
1119 the tree other than via the def stmts, using
1120 fixup_tree_for_diagnostic. */
1121 tree diag_arg = fixup_tree_for_diagnostic (expr);
1122 if (src_region == NULL && pkind == POISON_KIND_UNINIT)
1123 src_region = get_region_for_poisoned_expr (expr);
1125 /* Can we reliably get the poisoned value from "expr"?
1126 This is for use by poisoned_value_diagnostic::check_valid_fpath_p.
1127 Unfortunately, we might not have a reliable value for EXPR.
1128 Hence we only query its value now, and only use it if we get the
1129 poisoned value back again. */
1130 tree check_expr = expr;
1131 const svalue *foo_sval = get_rvalue (expr, NULL);
1132 if (foo_sval == sval)
1133 check_expr = expr;
1134 else
1135 check_expr = NULL;
1136 if (ctxt->warn (make_unique<poisoned_value_diagnostic> (diag_arg,
1137 pkind,
1138 src_region,
1139 check_expr)))
1141 /* We only want to report use of a poisoned value at the first
1142 place it gets used; return an unknown value to avoid generating
1143 a chain of followup warnings. */
1144 sval = m_mgr->get_or_create_unknown_svalue (sval->get_type ());
1147 return sval;
1150 return sval;
1153 /* Attempt to get a region for describing EXPR, the source of region of
1154 a poisoned_svalue for use in a poisoned_value_diagnostic.
1155 Return NULL if there is no good region to use. */
1157 const region *
1158 region_model::get_region_for_poisoned_expr (tree expr) const
1160 if (TREE_CODE (expr) == SSA_NAME)
1162 tree decl = SSA_NAME_VAR (expr);
1163 if (decl && DECL_P (decl))
1164 expr = decl;
1165 else
1166 return NULL;
1168 return get_lvalue (expr, NULL);
1171 /* Update this model for the ASSIGN stmt, using CTXT to report any
1172 diagnostics. */
1174 void
1175 region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
1177 tree lhs = gimple_assign_lhs (assign);
1178 tree rhs1 = gimple_assign_rhs1 (assign);
1180 const region *lhs_reg = get_lvalue (lhs, ctxt);
1182 /* Any writes other than to the stack are treated
1183 as externally visible. */
1184 if (ctxt)
1186 enum memory_space memspace = lhs_reg->get_memory_space ();
1187 if (memspace != MEMSPACE_STACK)
1188 ctxt->maybe_did_work ();
1191 /* Most assignments are handled by:
1192 set_value (lhs_reg, SVALUE, CTXT)
1193 for some SVALUE. */
1194 if (const svalue *sval = get_gassign_result (assign, ctxt))
1196 tree expr = get_diagnostic_tree_for_gassign (assign);
1197 check_for_poison (sval, expr, NULL, ctxt);
1198 set_value (lhs_reg, sval, ctxt);
1199 return;
1202 enum tree_code op = gimple_assign_rhs_code (assign);
1203 switch (op)
1205 default:
1207 if (0)
1208 sorry_at (assign->location, "unhandled assignment op: %qs",
1209 get_tree_code_name (op));
1210 const svalue *unknown_sval
1211 = m_mgr->get_or_create_unknown_svalue (TREE_TYPE (lhs));
1212 set_value (lhs_reg, unknown_sval, ctxt);
1214 break;
1216 case CONSTRUCTOR:
1218 if (TREE_CLOBBER_P (rhs1))
1220 /* e.g. "x ={v} {CLOBBER};" */
1221 clobber_region (lhs_reg);
1223 else
1225 /* Any CONSTRUCTOR that survives to this point is either
1226 just a zero-init of everything, or a vector. */
1227 if (!CONSTRUCTOR_NO_CLEARING (rhs1))
1228 zero_fill_region (lhs_reg, ctxt);
1229 unsigned ix;
1230 tree index;
1231 tree val;
1232 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs1), ix, index, val)
1234 gcc_assert (TREE_CODE (TREE_TYPE (rhs1)) == VECTOR_TYPE);
1235 if (!index)
1236 index = build_int_cst (integer_type_node, ix);
1237 gcc_assert (TREE_CODE (index) == INTEGER_CST);
1238 const svalue *index_sval
1239 = m_mgr->get_or_create_constant_svalue (index);
1240 gcc_assert (index_sval);
1241 const region *sub_reg
1242 = m_mgr->get_element_region (lhs_reg,
1243 TREE_TYPE (val),
1244 index_sval);
1245 const svalue *val_sval = get_rvalue (val, ctxt);
1246 set_value (sub_reg, val_sval, ctxt);
1250 break;
1252 case STRING_CST:
1254 /* e.g. "struct s2 x = {{'A', 'B', 'C', 'D'}};". */
1255 const svalue *rhs_sval = get_rvalue (rhs1, ctxt);
1256 m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
1257 ctxt ? ctxt->get_uncertainty () : NULL);
1259 break;
1263 /* Handle the pre-sm-state part of STMT, modifying this object in-place.
1264 Write true to *OUT_UNKNOWN_SIDE_EFFECTS if the stmt has unknown
1265 side effects. */
1267 void
1268 region_model::on_stmt_pre (const gimple *stmt,
1269 bool *out_unknown_side_effects,
1270 region_model_context *ctxt)
1272 switch (gimple_code (stmt))
1274 default:
1275 /* No-op for now. */
1276 break;
1278 case GIMPLE_ASSIGN:
1280 const gassign *assign = as_a <const gassign *> (stmt);
1281 on_assignment (assign, ctxt);
1283 break;
1285 case GIMPLE_ASM:
1287 const gasm *asm_stmt = as_a <const gasm *> (stmt);
1288 on_asm_stmt (asm_stmt, ctxt);
1289 if (ctxt)
1290 ctxt->maybe_did_work ();
1292 break;
1294 case GIMPLE_CALL:
1296 /* Track whether we have a gcall to a function that's not recognized by
1297 anything, for which we don't have a function body, or for which we
1298 don't know the fndecl. */
1299 const gcall *call = as_a <const gcall *> (stmt);
1300 *out_unknown_side_effects = on_call_pre (call, ctxt);
1302 break;
1304 case GIMPLE_RETURN:
1306 const greturn *return_ = as_a <const greturn *> (stmt);
1307 on_return (return_, ctxt);
1309 break;
1313 /* Given a call CD with function attribute FORMAT_ATTR, check that the
1314 format arg to the call is a valid null-terminated string. */
1316 void
1317 region_model::check_call_format_attr (const call_details &cd,
1318 tree format_attr) const
1320 /* We assume that FORMAT_ATTR has already been validated. */
1322 /* arg0 of the attribute should be kind of format strings
1323 that this function expects (e.g. "printf"). */
1324 const tree arg0_tree_list = TREE_VALUE (format_attr);
1325 if (!arg0_tree_list)
1326 return;
1328 /* arg1 of the attribute should be the 1-based parameter index
1329 to treat as the format string. */
1330 const tree arg1_tree_list = TREE_CHAIN (arg0_tree_list);
1331 if (!arg1_tree_list)
1332 return;
1333 const tree arg1_value = TREE_VALUE (arg1_tree_list);
1334 if (!arg1_value)
1335 return;
1337 unsigned format_arg_idx = TREE_INT_CST_LOW (arg1_value) - 1;
1338 if (cd.num_args () <= format_arg_idx)
1339 return;
1341 /* Subclass of annotating_context that
1342 adds a note about the format attr to any saved diagnostics. */
1343 class annotating_ctxt : public annotating_context
1345 public:
1346 annotating_ctxt (const call_details &cd,
1347 unsigned fmt_param_idx)
1348 : annotating_context (cd.get_ctxt ()),
1349 m_cd (cd),
1350 m_fmt_param_idx (fmt_param_idx)
1353 void add_annotations () final override
1355 class reason_format_attr
1356 : public pending_note_subclass<reason_format_attr>
1358 public:
1359 reason_format_attr (const call_arg_details &arg_details)
1360 : m_arg_details (arg_details)
1364 const char *get_kind () const final override
1366 return "reason_format_attr";
1369 void emit () const final override
1371 inform (DECL_SOURCE_LOCATION (m_arg_details.m_called_fndecl),
1372 "parameter %i of %qD marked as a format string"
1373 " via %qs attribute",
1374 m_arg_details.m_arg_idx + 1, m_arg_details.m_called_fndecl,
1375 "format");
1378 bool operator== (const reason_format_attr &other) const
1380 return m_arg_details == other.m_arg_details;
1383 private:
1384 call_arg_details m_arg_details;
1387 call_arg_details arg_details (m_cd, m_fmt_param_idx);
1388 add_note (make_unique<reason_format_attr> (arg_details));
1390 private:
1391 const call_details &m_cd;
1392 unsigned m_fmt_param_idx;
1395 annotating_ctxt my_ctxt (cd, format_arg_idx);
1396 call_details my_cd (cd, &my_ctxt);
1397 my_cd.check_for_null_terminated_string_arg (format_arg_idx);
1400 /* Ensure that all arguments at the call described by CD are checked
1401 for poisoned values, by calling get_rvalue on each argument.
1403 Check that calls to functions with "format" attribute have valid
1404 null-terminated strings for their format argument. */
1406 void
1407 region_model::check_call_args (const call_details &cd) const
1409 for (unsigned arg_idx = 0; arg_idx < cd.num_args (); arg_idx++)
1410 cd.get_arg_svalue (arg_idx);
1412 /* Handle attribute "format". */
1413 if (tree format_attr = cd.lookup_function_attribute ("format"))
1414 check_call_format_attr (cd, format_attr);
1417 /* Update this model for an outcome of a call that returns a specific
1418 integer constant.
1419 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1420 the state-merger code from merging success and failure outcomes. */
1422 void
1423 region_model::update_for_int_cst_return (const call_details &cd,
1424 int retval,
1425 bool unmergeable)
1427 if (!cd.get_lhs_type ())
1428 return;
1429 if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1430 return;
1431 const svalue *result
1432 = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), retval);
1433 if (unmergeable)
1434 result = m_mgr->get_or_create_unmergeable (result);
1435 set_value (cd.get_lhs_region (), result, cd.get_ctxt ());
1438 /* Update this model for an outcome of a call that returns zero.
1439 If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1440 the state-merger code from merging success and failure outcomes. */
1442 void
1443 region_model::update_for_zero_return (const call_details &cd,
1444 bool unmergeable)
1446 update_for_int_cst_return (cd, 0, unmergeable);
1449 /* Update this model for an outcome of a call that returns non-zero.
1450 Specifically, assign an svalue to the LHS, and add a constraint that
1451 that svalue is non-zero. */
1453 void
1454 region_model::update_for_nonzero_return (const call_details &cd)
1456 if (!cd.get_lhs_type ())
1457 return;
1458 if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1459 return;
1460 cd.set_any_lhs_with_defaults ();
1461 const svalue *zero
1462 = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
1463 const svalue *result
1464 = get_store_value (cd.get_lhs_region (), cd.get_ctxt ());
1465 add_constraint (result, NE_EXPR, zero, cd.get_ctxt ());
1468 /* Subroutine of region_model::maybe_get_copy_bounds.
1469 The Linux kernel commonly uses
1470 min_t([unsigned] long, VAR, sizeof(T));
1471 to set an upper bound on the size of a copy_to_user.
1472 Attempt to simplify such sizes by trying to get the upper bound as a
1473 constant.
1474 Return the simplified svalue if possible, or NULL otherwise. */
1476 static const svalue *
1477 maybe_simplify_upper_bound (const svalue *num_bytes_sval,
1478 region_model_manager *mgr)
1480 tree type = num_bytes_sval->get_type ();
1481 while (const svalue *raw = num_bytes_sval->maybe_undo_cast ())
1482 num_bytes_sval = raw;
1483 if (const binop_svalue *binop_sval = num_bytes_sval->dyn_cast_binop_svalue ())
1484 if (binop_sval->get_op () == MIN_EXPR)
1485 if (binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT)
1487 return mgr->get_or_create_cast (type, binop_sval->get_arg1 ());
1488 /* TODO: we might want to also capture the constraint
1489 when recording the diagnostic, or note that we're using
1490 the upper bound. */
1492 return NULL;
1495 /* Attempt to get an upper bound for the size of a copy when simulating a
1496 copy function.
1498 NUM_BYTES_SVAL is the symbolic value for the size of the copy.
1499 Use it if it's constant, otherwise try to simplify it. Failing
1500 that, use the size of SRC_REG if constant.
1502 Return a symbolic value for an upper limit on the number of bytes
1503 copied, or NULL if no such value could be determined. */
1505 const svalue *
1506 region_model::maybe_get_copy_bounds (const region *src_reg,
1507 const svalue *num_bytes_sval)
1509 if (num_bytes_sval->maybe_get_constant ())
1510 return num_bytes_sval;
1512 if (const svalue *simplified
1513 = maybe_simplify_upper_bound (num_bytes_sval, m_mgr))
1514 num_bytes_sval = simplified;
1516 if (num_bytes_sval->maybe_get_constant ())
1517 return num_bytes_sval;
1519 /* For now, try just guessing the size as the capacity of the
1520 base region of the src.
1521 This is a hack; we might get too large a value. */
1522 const region *src_base_reg = src_reg->get_base_region ();
1523 num_bytes_sval = get_capacity (src_base_reg);
1525 if (num_bytes_sval->maybe_get_constant ())
1526 return num_bytes_sval;
1528 /* Non-constant: give up. */
1529 return NULL;
1532 /* Get any known_function for FNDECL for call CD.
1534 The call must match all assumptions made by the known_function (such as
1535 e.g. "argument 1's type must be a pointer type").
1537 Return NULL if no known_function is found, or it does not match the
1538 assumption(s). */
1540 const known_function *
1541 region_model::get_known_function (tree fndecl, const call_details &cd) const
1543 known_function_manager *known_fn_mgr = m_mgr->get_known_function_manager ();
1544 return known_fn_mgr->get_match (fndecl, cd);
1547 /* Get any known_function for IFN, or NULL. */
1549 const known_function *
1550 region_model::get_known_function (enum internal_fn ifn) const
1552 known_function_manager *known_fn_mgr = m_mgr->get_known_function_manager ();
1553 return known_fn_mgr->get_internal_fn (ifn);
1556 /* Get any builtin_known_function for CALL and emit any warning to CTXT
1557 if not NULL.
1559 The call must match all assumptions made by the known_function (such as
1560 e.g. "argument 1's type must be a pointer type").
1562 Return NULL if no builtin_known_function is found, or it does
1563 not match the assumption(s).
1565 Internally calls get_known_function to find a known_function and cast it
1566 to a builtin_known_function.
1568 For instance, calloc is a C builtin, defined in gcc/builtins.def
1569 by the DEF_LIB_BUILTIN macro. Such builtins are recognized by the
1570 analyzer by their name, so that even in C++ or if the user redeclares
1571 them but mismatch their signature, they are still recognized as builtins.
1573 Cases when a supposed builtin is not flagged as one by the FE:
1575 The C++ FE does not recognize calloc as a builtin if it has not been
1576 included from a standard header, but the C FE does. Hence in C++ if
1577 CALL comes from a calloc and stdlib is not included,
1578 gcc/tree.h:fndecl_built_in_p (CALL) would be false.
1580 In C code, a __SIZE_TYPE__ calloc (__SIZE_TYPE__, __SIZE_TYPE__) user
1581 declaration has obviously a mismatching signature from the standard, and
1582 its function_decl tree won't be unified by
1583 gcc/c-decl.cc:match_builtin_function_types.
1585 Yet in both cases the analyzer should treat the calls as a builtin calloc
1586 so that extra attributes unspecified by the standard but added by GCC
1587 (e.g. sprintf attributes in gcc/builtins.def), useful for the detection of
1588 dangerous behavior, are indeed processed.
1590 Therefore for those cases when a "builtin flag" is not added by the FE,
1591 builtins' kf are derived from builtin_known_function, whose method
1592 builtin_known_function::builtin_decl returns the builtin's
1593 function_decl tree as defined in gcc/builtins.def, with all the extra
1594 attributes. */
1596 const builtin_known_function *
1597 region_model::get_builtin_kf (const gcall *call,
1598 region_model_context *ctxt /* = NULL */) const
1600 region_model *mut_this = const_cast <region_model *> (this);
1601 tree callee_fndecl = mut_this->get_fndecl_for_call (call, ctxt);
1602 if (! callee_fndecl)
1603 return NULL;
1605 call_details cd (call, mut_this, ctxt);
1606 if (const known_function *kf = get_known_function (callee_fndecl, cd))
1607 return kf->dyn_cast_builtin_kf ();
1609 return NULL;
1612 /* Update this model for the CALL stmt, using CTXT to report any
1613 diagnostics - the first half.
1615 Updates to the region_model that should be made *before* sm-states
1616 are updated are done here; other updates to the region_model are done
1617 in region_model::on_call_post.
1619 Return true if the function call has unknown side effects (it wasn't
1620 recognized and we don't have a body for it, or are unable to tell which
1621 fndecl it is). */
1623 bool
1624 region_model::on_call_pre (const gcall *call, region_model_context *ctxt)
1626 call_details cd (call, this, ctxt);
1628 /* Special-case for IFN_DEFERRED_INIT.
1629 We want to report uninitialized variables with -fanalyzer (treating
1630 -ftrivial-auto-var-init= as purely a mitigation feature).
1631 Handle IFN_DEFERRED_INIT by treating it as no-op: don't touch the
1632 lhs of the call, so that it is still uninitialized from the point of
1633 view of the analyzer. */
1634 if (gimple_call_internal_p (call)
1635 && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1636 return false; /* No side effects. */
1638 /* Get svalues for all of the arguments at the callsite, to ensure that we
1639 complain about any uninitialized arguments. This might lead to
1640 duplicates if any of the handling below also looks up the svalues,
1641 but the deduplication code should deal with that. */
1642 if (ctxt)
1643 check_call_args (cd);
1645 tree callee_fndecl = get_fndecl_for_call (call, ctxt);
1647 if (gimple_call_internal_p (call))
1648 if (const known_function *kf
1649 = get_known_function (gimple_call_internal_fn (call)))
1651 kf->impl_call_pre (cd);
1652 return false; /* No further side effects. */
1655 if (!callee_fndecl)
1657 cd.set_any_lhs_with_defaults ();
1658 return true; /* Unknown side effects. */
1661 if (const known_function *kf = get_known_function (callee_fndecl, cd))
1663 kf->impl_call_pre (cd);
1664 return false; /* No further side effects. */
1667 cd.set_any_lhs_with_defaults ();
1669 const int callee_fndecl_flags = flags_from_decl_or_type (callee_fndecl);
1670 if (callee_fndecl_flags & (ECF_CONST | ECF_PURE))
1671 return false; /* No side effects. */
1673 if (fndecl_built_in_p (callee_fndecl))
1674 return true; /* Unknown side effects. */
1676 if (!fndecl_has_gimple_body_p (callee_fndecl))
1677 return true; /* Unknown side effects. */
1679 return false; /* No side effects. */
1682 /* Update this model for the CALL stmt, using CTXT to report any
1683 diagnostics - the second half.
1685 Updates to the region_model that should be made *after* sm-states
1686 are updated are done here; other updates to the region_model are done
1687 in region_model::on_call_pre.
1689 If UNKNOWN_SIDE_EFFECTS is true, also call handle_unrecognized_call
1690 to purge state. */
1692 void
1693 region_model::on_call_post (const gcall *call,
1694 bool unknown_side_effects,
1695 region_model_context *ctxt)
1697 if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
1699 call_details cd (call, this, ctxt);
1700 if (const known_function *kf = get_known_function (callee_fndecl, cd))
1702 kf->impl_call_post (cd);
1703 return;
1705 /* Was this fndecl referenced by
1706 __attribute__((malloc(FOO)))? */
1707 if (lookup_attribute ("*dealloc", DECL_ATTRIBUTES (callee_fndecl)))
1709 impl_deallocation_call (cd);
1710 return;
1714 if (unknown_side_effects)
1716 handle_unrecognized_call (call, ctxt);
1717 if (ctxt)
1718 ctxt->maybe_did_work ();
1722 /* Purge state involving SVAL from this region_model, using CTXT
1723 (if non-NULL) to purge other state in a program_state.
1725 For example, if we're at the def-stmt of an SSA name, then we need to
1726 purge any state for svalues that involve that SSA name. This avoids
1727 false positives in loops, since a symbolic value referring to the
1728 SSA name will be referring to the previous value of that SSA name.
1730 For example, in:
1731 while ((e = hashmap_iter_next(&iter))) {
1732 struct oid2strbuf *e_strbuf = (struct oid2strbuf *)e;
1733 free (e_strbuf->value);
1735 at the def-stmt of e_8:
1736 e_8 = hashmap_iter_next (&iter);
1737 we should purge the "freed" state of:
1738 INIT_VAL(CAST_REG(‘struct oid2strbuf’, (*INIT_VAL(e_8))).value)
1739 which is the "e_strbuf->value" value from the previous iteration,
1740 or we will erroneously report a double-free - the "e_8" within it
1741 refers to the previous value. */
1743 void
1744 region_model::purge_state_involving (const svalue *sval,
1745 region_model_context *ctxt)
1747 if (!sval->can_have_associated_state_p ())
1748 return;
1749 m_store.purge_state_involving (sval, m_mgr);
1750 m_constraints->purge_state_involving (sval);
1751 m_dynamic_extents.purge_state_involving (sval);
1752 if (ctxt)
1753 ctxt->purge_state_involving (sval);
1756 /* A pending_note subclass for adding a note about an
1757 __attribute__((access, ...)) to a diagnostic. */
1759 class reason_attr_access : public pending_note_subclass<reason_attr_access>
1761 public:
1762 reason_attr_access (tree callee_fndecl, const attr_access &access)
1763 : m_callee_fndecl (callee_fndecl),
1764 m_ptr_argno (access.ptrarg),
1765 m_access_str (TREE_STRING_POINTER (access.to_external_string ()))
1769 const char *get_kind () const final override { return "reason_attr_access"; }
1771 void emit () const final override
1773 inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
1774 "parameter %i of %qD marked with attribute %qs",
1775 m_ptr_argno + 1, m_callee_fndecl, m_access_str);
1778 bool operator== (const reason_attr_access &other) const
1780 return (m_callee_fndecl == other.m_callee_fndecl
1781 && m_ptr_argno == other.m_ptr_argno
1782 && !strcmp (m_access_str, other.m_access_str));
1785 private:
1786 tree m_callee_fndecl;
1787 unsigned m_ptr_argno;
1788 const char *m_access_str;
1791 /* Check CALL a call to external function CALLEE_FNDECL based on
1792 any __attribute__ ((access, ....) on the latter, complaining to
1793 CTXT about any issues.
1795 Currently we merely call check_region_for_write on any regions
1796 pointed to by arguments marked with a "write_only" or "read_write"
1797 attribute. */
1799 void
1800 region_model::check_function_attr_access (const gcall *call,
1801 tree callee_fndecl,
1802 region_model_context *ctxt,
1803 rdwr_map &rdwr_idx) const
1805 gcc_assert (call);
1806 gcc_assert (callee_fndecl);
1807 gcc_assert (ctxt);
1809 tree fntype = TREE_TYPE (callee_fndecl);
1810 gcc_assert (fntype);
1812 unsigned argno = 0;
1814 for (tree iter = TYPE_ARG_TYPES (fntype); iter;
1815 iter = TREE_CHAIN (iter), ++argno)
1817 const attr_access* access = rdwr_idx.get (argno);
1818 if (!access)
1819 continue;
1821 /* Ignore any duplicate entry in the map for the size argument. */
1822 if (access->ptrarg != argno)
1823 continue;
1825 if (access->mode == access_write_only
1826 || access->mode == access_read_write)
1828 /* Subclass of annotating_context that
1829 adds a note about the attr access to any saved diagnostics. */
1830 class annotating_ctxt : public annotating_context
1832 public:
1833 annotating_ctxt (tree callee_fndecl,
1834 const attr_access &access,
1835 region_model_context *ctxt)
1836 : annotating_context (ctxt),
1837 m_callee_fndecl (callee_fndecl),
1838 m_access (access)
1841 void add_annotations () final override
1843 add_note (make_unique<reason_attr_access>
1844 (m_callee_fndecl, m_access));
1846 private:
1847 tree m_callee_fndecl;
1848 const attr_access &m_access;
1851 /* Use this ctxt below so that any diagnostics get the
1852 note added to them. */
1853 annotating_ctxt my_ctxt (callee_fndecl, *access, ctxt);
1855 tree ptr_tree = gimple_call_arg (call, access->ptrarg);
1856 const svalue *ptr_sval = get_rvalue (ptr_tree, &my_ctxt);
1857 const region *reg = deref_rvalue (ptr_sval, ptr_tree, &my_ctxt);
1858 check_region_for_write (reg, nullptr, &my_ctxt);
1859 /* We don't use the size arg for now. */
1864 /* Subroutine of region_model::check_function_attr_null_terminated_string_arg,
1865 checking one instance of __attribute__((null_terminated_string_arg)). */
1867 void
1868 region_model::
1869 check_one_function_attr_null_terminated_string_arg (const gcall *call,
1870 tree callee_fndecl,
1871 region_model_context *ctxt,
1872 rdwr_map &rdwr_idx,
1873 tree attr)
1875 gcc_assert (call);
1876 gcc_assert (callee_fndecl);
1877 gcc_assert (ctxt);
1878 gcc_assert (attr);
1880 tree arg = TREE_VALUE (attr);
1881 if (!arg)
1882 return;
1884 /* Convert from 1-based to 0-based index. */
1885 unsigned int arg_idx = TREE_INT_CST_LOW (TREE_VALUE (arg)) - 1;
1887 /* If there's also an "access" attribute on the ptr param
1888 for reading with a size param specified, then that size
1889 limits the size of the possible read from the pointer. */
1890 if (const attr_access* access = rdwr_idx.get (arg_idx))
1891 if ((access->mode == access_read_only
1892 || access->mode == access_read_write)
1893 && access->sizarg != UINT_MAX)
1895 call_details cd_checked (call, this, ctxt);
1896 const svalue *limit_sval
1897 = cd_checked.get_arg_svalue (access->sizarg);
1898 const svalue *ptr_sval
1899 = cd_checked.get_arg_svalue (arg_idx);
1900 /* Try reading all of the bytes expressed by the size param,
1901 but without emitting warnings (via a null context). */
1902 const svalue *limited_sval
1903 = read_bytes (deref_rvalue (ptr_sval, NULL_TREE, nullptr),
1904 NULL_TREE,
1905 limit_sval,
1906 nullptr);
1907 if (limited_sval->get_kind () == SK_POISONED)
1909 /* Reading up to the truncation limit caused issues.
1910 Assume that the string is meant to be terminated
1911 before then, so perform a *checked* check for the
1912 terminator. */
1913 check_for_null_terminated_string_arg (cd_checked,
1914 arg_idx);
1916 else
1918 /* Reading up to the truncation limit seems OK; repeat
1919 the read, but with checking enabled. */
1920 read_bytes (deref_rvalue (ptr_sval, NULL_TREE, ctxt),
1921 NULL_TREE,
1922 limit_sval,
1923 ctxt);
1925 return;
1928 /* Otherwise, we don't have an access-attribute limiting the read.
1929 Simulate a read up to the null terminator (if any). */
1931 call_details cd (call, this, ctxt);
1932 check_for_null_terminated_string_arg (cd, arg_idx);
1935 /* Check CALL a call to external function CALLEE_FNDECL for any uses
1936 of __attribute__ ((null_terminated_string_arg)), compaining
1937 to CTXT about any issues.
1939 Use RDWR_IDX for tracking uses of __attribute__ ((access, ....). */
1941 void
1942 region_model::
1943 check_function_attr_null_terminated_string_arg (const gcall *call,
1944 tree callee_fndecl,
1945 region_model_context *ctxt,
1946 rdwr_map &rdwr_idx)
1948 gcc_assert (call);
1949 gcc_assert (callee_fndecl);
1950 gcc_assert (ctxt);
1952 tree fntype = TREE_TYPE (callee_fndecl);
1953 gcc_assert (fntype);
1955 /* A function declaration can specify multiple attribute
1956 null_terminated_string_arg, each with one argument. */
1957 for (tree attr = TYPE_ATTRIBUTES (fntype); attr; attr = TREE_CHAIN (attr))
1959 attr = lookup_attribute ("null_terminated_string_arg", attr);
1960 if (!attr)
1961 return;
1963 check_one_function_attr_null_terminated_string_arg (call, callee_fndecl,
1964 ctxt, rdwr_idx,
1965 attr);
1969 /* Check CALL a call to external function CALLEE_FNDECL for any
1970 function attributes, complaining to CTXT about any issues. */
1972 void
1973 region_model::check_function_attrs (const gcall *call,
1974 tree callee_fndecl,
1975 region_model_context *ctxt)
1977 gcc_assert (call);
1978 gcc_assert (callee_fndecl);
1979 gcc_assert (ctxt);
1981 tree fntype = TREE_TYPE (callee_fndecl);
1982 if (!fntype)
1983 return;
1985 if (!TYPE_ATTRIBUTES (fntype))
1986 return;
1988 /* Initialize a map of attribute access specifications for arguments
1989 to the function call. */
1990 rdwr_map rdwr_idx;
1991 init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype));
1993 check_function_attr_access (call, callee_fndecl, ctxt, rdwr_idx);
1994 check_function_attr_null_terminated_string_arg (call, callee_fndecl,
1995 ctxt, rdwr_idx);
1998 /* Handle a call CALL to a function with unknown behavior.
2000 Traverse the regions in this model, determining what regions are
2001 reachable from pointer arguments to CALL and from global variables,
2002 recursively.
2004 Set all reachable regions to new unknown values and purge sm-state
2005 from their values, and from values that point to them. */
2007 void
2008 region_model::handle_unrecognized_call (const gcall *call,
2009 region_model_context *ctxt)
2011 tree fndecl = get_fndecl_for_call (call, ctxt);
2013 if (fndecl && ctxt)
2014 check_function_attrs (call, fndecl, ctxt);
2016 reachable_regions reachable_regs (this);
2018 /* Determine the reachable regions and their mutability. */
2020 /* Add globals and regions that already escaped in previous
2021 unknown calls. */
2022 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2023 &reachable_regs);
2025 /* Params that are pointers. */
2026 tree iter_param_types = NULL_TREE;
2027 if (fndecl)
2028 iter_param_types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
2029 for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
2031 /* Track expected param type, where available. */
2032 tree param_type = NULL_TREE;
2033 if (iter_param_types)
2035 param_type = TREE_VALUE (iter_param_types);
2036 gcc_assert (param_type);
2037 iter_param_types = TREE_CHAIN (iter_param_types);
2040 tree parm = gimple_call_arg (call, arg_idx);
2041 const svalue *parm_sval = get_rvalue (parm, ctxt);
2042 reachable_regs.handle_parm (parm_sval, param_type);
2046 uncertainty_t *uncertainty = ctxt ? ctxt->get_uncertainty () : NULL;
2048 /* Purge sm-state for the svalues that were reachable,
2049 both in non-mutable and mutable form. */
2050 for (svalue_set::iterator iter
2051 = reachable_regs.begin_reachable_svals ();
2052 iter != reachable_regs.end_reachable_svals (); ++iter)
2054 const svalue *sval = (*iter);
2055 if (ctxt)
2056 ctxt->on_unknown_change (sval, false);
2058 for (svalue_set::iterator iter
2059 = reachable_regs.begin_mutable_svals ();
2060 iter != reachable_regs.end_mutable_svals (); ++iter)
2062 const svalue *sval = (*iter);
2063 if (ctxt)
2064 ctxt->on_unknown_change (sval, true);
2065 if (uncertainty)
2066 uncertainty->on_mutable_sval_at_unknown_call (sval);
2069 /* Mark any clusters that have escaped. */
2070 reachable_regs.mark_escaped_clusters (ctxt);
2072 /* Update bindings for all clusters that have escaped, whether above,
2073 or previously. */
2074 m_store.on_unknown_fncall (call, m_mgr->get_store_manager (),
2075 conjured_purge (this, ctxt));
2077 /* Purge dynamic extents from any regions that have escaped mutably:
2078 realloc could have been called on them. */
2079 for (hash_set<const region *>::iterator
2080 iter = reachable_regs.begin_mutable_base_regs ();
2081 iter != reachable_regs.end_mutable_base_regs ();
2082 ++iter)
2084 const region *base_reg = (*iter);
2085 unset_dynamic_extents (base_reg);
2089 /* Traverse the regions in this model, determining what regions are
2090 reachable from the store and populating *OUT.
2092 If EXTRA_SVAL is non-NULL, treat it as an additional "root"
2093 for reachability (for handling return values from functions when
2094 analyzing return of the only function on the stack).
2096 If UNCERTAINTY is non-NULL, treat any svalues that were recorded
2097 within it as being maybe-bound as additional "roots" for reachability.
2099 Find svalues that haven't leaked. */
2101 void
2102 region_model::get_reachable_svalues (svalue_set *out,
2103 const svalue *extra_sval,
2104 const uncertainty_t *uncertainty)
2106 reachable_regions reachable_regs (this);
2108 /* Add globals and regions that already escaped in previous
2109 unknown calls. */
2110 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2111 &reachable_regs);
2113 if (extra_sval)
2114 reachable_regs.handle_sval (extra_sval);
2116 if (uncertainty)
2117 for (uncertainty_t::iterator iter
2118 = uncertainty->begin_maybe_bound_svals ();
2119 iter != uncertainty->end_maybe_bound_svals (); ++iter)
2120 reachable_regs.handle_sval (*iter);
2122 /* Get regions for locals that have explicitly bound values. */
2123 for (store::cluster_map_t::iterator iter = m_store.begin ();
2124 iter != m_store.end (); ++iter)
2126 const region *base_reg = (*iter).first;
2127 if (const region *parent = base_reg->get_parent_region ())
2128 if (parent->get_kind () == RK_FRAME)
2129 reachable_regs.add (base_reg, false);
2132 /* Populate *OUT based on the values that were reachable. */
2133 for (svalue_set::iterator iter
2134 = reachable_regs.begin_reachable_svals ();
2135 iter != reachable_regs.end_reachable_svals (); ++iter)
2136 out->add (*iter);
2139 /* Update this model for the RETURN_STMT, using CTXT to report any
2140 diagnostics. */
2142 void
2143 region_model::on_return (const greturn *return_stmt, region_model_context *ctxt)
2145 tree callee = get_current_function ()->decl;
2146 tree lhs = DECL_RESULT (callee);
2147 tree rhs = gimple_return_retval (return_stmt);
2149 if (lhs && rhs)
2151 const svalue *sval = get_rvalue (rhs, ctxt);
2152 const region *ret_reg = get_lvalue (lhs, ctxt);
2153 set_value (ret_reg, sval, ctxt);
2157 /* Update this model for a call and return of setjmp/sigsetjmp at CALL within
2158 ENODE, using CTXT to report any diagnostics.
2160 This is for the initial direct invocation of setjmp/sigsetjmp (which returns
2161 0), as opposed to any second return due to longjmp/sigsetjmp. */
2163 void
2164 region_model::on_setjmp (const gcall *call, const exploded_node *enode,
2165 region_model_context *ctxt)
2167 const svalue *buf_ptr = get_rvalue (gimple_call_arg (call, 0), ctxt);
2168 const region *buf_reg = deref_rvalue (buf_ptr, gimple_call_arg (call, 0),
2169 ctxt);
2171 /* Create a setjmp_svalue for this call and store it in BUF_REG's
2172 region. */
2173 if (buf_reg)
2175 setjmp_record r (enode, call);
2176 const svalue *sval
2177 = m_mgr->get_or_create_setjmp_svalue (r, buf_reg->get_type ());
2178 set_value (buf_reg, sval, ctxt);
2181 /* Direct calls to setjmp return 0. */
2182 if (tree lhs = gimple_call_lhs (call))
2184 const svalue *new_sval
2185 = m_mgr->get_or_create_int_cst (TREE_TYPE (lhs), 0);
2186 const region *lhs_reg = get_lvalue (lhs, ctxt);
2187 set_value (lhs_reg, new_sval, ctxt);
2191 /* Update this region_model for rewinding from a "longjmp" at LONGJMP_CALL
2192 to a "setjmp" at SETJMP_CALL where the final stack depth should be
2193 SETJMP_STACK_DEPTH. Pop any stack frames. Leak detection is *not*
2194 done, and should be done by the caller. */
2196 void
2197 region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
2198 int setjmp_stack_depth, region_model_context *ctxt)
2200 /* Evaluate the val, using the frame of the "longjmp". */
2201 tree fake_retval = gimple_call_arg (longjmp_call, 1);
2202 const svalue *fake_retval_sval = get_rvalue (fake_retval, ctxt);
2204 /* Pop any frames until we reach the stack depth of the function where
2205 setjmp was called. */
2206 gcc_assert (get_stack_depth () >= setjmp_stack_depth);
2207 while (get_stack_depth () > setjmp_stack_depth)
2208 pop_frame (NULL, NULL, ctxt, false);
2210 gcc_assert (get_stack_depth () == setjmp_stack_depth);
2212 /* Assign to LHS of "setjmp" in new_state. */
2213 if (tree lhs = gimple_call_lhs (setjmp_call))
2215 /* Passing 0 as the val to longjmp leads to setjmp returning 1. */
2216 const svalue *zero_sval
2217 = m_mgr->get_or_create_int_cst (TREE_TYPE (fake_retval), 0);
2218 tristate eq_zero = eval_condition (fake_retval_sval, EQ_EXPR, zero_sval);
2219 /* If we have 0, use 1. */
2220 if (eq_zero.is_true ())
2222 const svalue *one_sval
2223 = m_mgr->get_or_create_int_cst (TREE_TYPE (fake_retval), 1);
2224 fake_retval_sval = one_sval;
2226 else
2228 /* Otherwise note that the value is nonzero. */
2229 m_constraints->add_constraint (fake_retval_sval, NE_EXPR, zero_sval);
2232 /* Decorate the return value from setjmp as being unmergeable,
2233 so that we don't attempt to merge states with it as zero
2234 with states in which it's nonzero, leading to a clean distinction
2235 in the exploded_graph betweeen the first return and the second
2236 return. */
2237 fake_retval_sval = m_mgr->get_or_create_unmergeable (fake_retval_sval);
2239 const region *lhs_reg = get_lvalue (lhs, ctxt);
2240 set_value (lhs_reg, fake_retval_sval, ctxt);
2244 /* Update this region_model for a phi stmt of the form
2245 LHS = PHI <...RHS...>.
2246 where RHS is for the appropriate edge.
2247 Get state from OLD_STATE so that all of the phi stmts for a basic block
2248 are effectively handled simultaneously. */
2250 void
2251 region_model::handle_phi (const gphi *phi,
2252 tree lhs, tree rhs,
2253 const region_model &old_state,
2254 hash_set<const svalue *> &svals_changing_meaning,
2255 region_model_context *ctxt)
2257 /* For now, don't bother tracking the .MEM SSA names. */
2258 if (tree var = SSA_NAME_VAR (lhs))
2259 if (TREE_CODE (var) == VAR_DECL)
2260 if (VAR_DECL_IS_VIRTUAL_OPERAND (var))
2261 return;
2263 const svalue *src_sval = old_state.get_rvalue (rhs, ctxt);
2264 const region *dst_reg = old_state.get_lvalue (lhs, ctxt);
2266 const svalue *sval = old_state.get_rvalue (lhs, nullptr);
2267 if (sval->get_kind () == SK_WIDENING)
2268 svals_changing_meaning.add (sval);
2270 set_value (dst_reg, src_sval, ctxt);
2272 if (ctxt)
2273 ctxt->on_phi (phi, rhs);
2276 /* Implementation of region_model::get_lvalue; the latter adds type-checking.
2278 Get the id of the region for PV within this region_model,
2279 emitting any diagnostics to CTXT. */
2281 const region *
2282 region_model::get_lvalue_1 (path_var pv, region_model_context *ctxt) const
2284 tree expr = pv.m_tree;
2286 gcc_assert (expr);
2288 switch (TREE_CODE (expr))
2290 default:
2291 return m_mgr->get_region_for_unexpected_tree_code (ctxt, expr,
2292 dump_location_t ());
2294 case ARRAY_REF:
2296 tree array = TREE_OPERAND (expr, 0);
2297 tree index = TREE_OPERAND (expr, 1);
2299 const region *array_reg = get_lvalue (array, ctxt);
2300 const svalue *index_sval = get_rvalue (index, ctxt);
2301 return m_mgr->get_element_region (array_reg,
2302 TREE_TYPE (TREE_TYPE (array)),
2303 index_sval);
2305 break;
2307 case BIT_FIELD_REF:
2309 tree inner_expr = TREE_OPERAND (expr, 0);
2310 const region *inner_reg = get_lvalue (inner_expr, ctxt);
2311 tree num_bits = TREE_OPERAND (expr, 1);
2312 tree first_bit_offset = TREE_OPERAND (expr, 2);
2313 gcc_assert (TREE_CODE (num_bits) == INTEGER_CST);
2314 gcc_assert (TREE_CODE (first_bit_offset) == INTEGER_CST);
2315 bit_range bits (TREE_INT_CST_LOW (first_bit_offset),
2316 TREE_INT_CST_LOW (num_bits));
2317 return m_mgr->get_bit_range (inner_reg, TREE_TYPE (expr), bits);
2319 break;
2321 case MEM_REF:
2323 tree ptr = TREE_OPERAND (expr, 0);
2324 tree offset = TREE_OPERAND (expr, 1);
2325 const svalue *ptr_sval = get_rvalue (ptr, ctxt);
2326 const svalue *offset_sval = get_rvalue (offset, ctxt);
2327 const region *star_ptr = deref_rvalue (ptr_sval, ptr, ctxt);
2328 return m_mgr->get_offset_region (star_ptr,
2329 TREE_TYPE (expr),
2330 offset_sval);
2332 break;
2334 case FUNCTION_DECL:
2335 return m_mgr->get_region_for_fndecl (expr);
2337 case LABEL_DECL:
2338 return m_mgr->get_region_for_label (expr);
2340 case VAR_DECL:
2341 /* Handle globals. */
2342 if (is_global_var (expr))
2343 return m_mgr->get_region_for_global (expr);
2345 /* Fall through. */
2347 case SSA_NAME:
2348 case PARM_DECL:
2349 case RESULT_DECL:
2351 gcc_assert (TREE_CODE (expr) == SSA_NAME
2352 || TREE_CODE (expr) == PARM_DECL
2353 || VAR_P (expr)
2354 || TREE_CODE (expr) == RESULT_DECL);
2356 int stack_index = pv.m_stack_depth;
2357 const frame_region *frame = get_frame_at_index (stack_index);
2358 gcc_assert (frame);
2359 return frame->get_region_for_local (m_mgr, expr, ctxt);
2362 case COMPONENT_REF:
2364 /* obj.field */
2365 tree obj = TREE_OPERAND (expr, 0);
2366 tree field = TREE_OPERAND (expr, 1);
2367 const region *obj_reg = get_lvalue (obj, ctxt);
2368 return m_mgr->get_field_region (obj_reg, field);
2370 break;
2372 case STRING_CST:
2373 return m_mgr->get_region_for_string (expr);
2377 /* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op. */
2379 static void
2380 assert_compat_types (tree src_type, tree dst_type)
2382 if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2384 #if CHECKING_P
2385 if (!(useless_type_conversion_p (src_type, dst_type)))
2386 internal_error ("incompatible types: %qT and %qT", src_type, dst_type);
2387 #endif
2391 /* Return true if SRC_TYPE can be converted to DST_TYPE as a no-op. */
2393 bool
2394 compat_types_p (tree src_type, tree dst_type)
2396 if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2397 if (!(useless_type_conversion_p (src_type, dst_type)))
2398 return false;
2399 return true;
2402 /* Get the region for PV within this region_model,
2403 emitting any diagnostics to CTXT. */
2405 const region *
2406 region_model::get_lvalue (path_var pv, region_model_context *ctxt) const
2408 if (pv.m_tree == NULL_TREE)
2409 return NULL;
2411 const region *result_reg = get_lvalue_1 (pv, ctxt);
2412 assert_compat_types (result_reg->get_type (), TREE_TYPE (pv.m_tree));
2413 return result_reg;
2416 /* Get the region for EXPR within this region_model (assuming the most
2417 recent stack frame if it's a local). */
2419 const region *
2420 region_model::get_lvalue (tree expr, region_model_context *ctxt) const
2422 return get_lvalue (path_var (expr, get_stack_depth () - 1), ctxt);
2425 /* Implementation of region_model::get_rvalue; the latter adds type-checking.
2427 Get the value of PV within this region_model,
2428 emitting any diagnostics to CTXT. */
2430 const svalue *
2431 region_model::get_rvalue_1 (path_var pv, region_model_context *ctxt) const
2433 gcc_assert (pv.m_tree);
2435 switch (TREE_CODE (pv.m_tree))
2437 default:
2438 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2440 case ADDR_EXPR:
2442 /* "&EXPR". */
2443 tree expr = pv.m_tree;
2444 tree op0 = TREE_OPERAND (expr, 0);
2445 const region *expr_reg = get_lvalue (op0, ctxt);
2446 return m_mgr->get_ptr_svalue (TREE_TYPE (expr), expr_reg);
2448 break;
2450 case BIT_FIELD_REF:
2452 tree expr = pv.m_tree;
2453 tree op0 = TREE_OPERAND (expr, 0);
2454 const region *reg = get_lvalue (op0, ctxt);
2455 tree num_bits = TREE_OPERAND (expr, 1);
2456 tree first_bit_offset = TREE_OPERAND (expr, 2);
2457 gcc_assert (TREE_CODE (num_bits) == INTEGER_CST);
2458 gcc_assert (TREE_CODE (first_bit_offset) == INTEGER_CST);
2459 bit_range bits (TREE_INT_CST_LOW (first_bit_offset),
2460 TREE_INT_CST_LOW (num_bits));
2461 return get_rvalue_for_bits (TREE_TYPE (expr), reg, bits, ctxt);
2464 case VAR_DECL:
2465 if (DECL_HARD_REGISTER (pv.m_tree))
2467 /* If it has a hard register, it doesn't have a memory region
2468 and can't be referred to as an lvalue. */
2469 return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2471 /* Fall through. */
2472 case PARM_DECL:
2473 case SSA_NAME:
2474 case RESULT_DECL:
2475 case ARRAY_REF:
2477 const region *reg = get_lvalue (pv, ctxt);
2478 return get_store_value (reg, ctxt);
2481 case REALPART_EXPR:
2482 case IMAGPART_EXPR:
2483 case VIEW_CONVERT_EXPR:
2485 tree expr = pv.m_tree;
2486 tree arg = TREE_OPERAND (expr, 0);
2487 const svalue *arg_sval = get_rvalue (arg, ctxt);
2488 const svalue *sval_unaryop
2489 = m_mgr->get_or_create_unaryop (TREE_TYPE (expr), TREE_CODE (expr),
2490 arg_sval);
2491 return sval_unaryop;
2494 case INTEGER_CST:
2495 case REAL_CST:
2496 case COMPLEX_CST:
2497 case VECTOR_CST:
2498 case STRING_CST:
2499 return m_mgr->get_or_create_constant_svalue (pv.m_tree);
2501 case POINTER_PLUS_EXPR:
2503 tree expr = pv.m_tree;
2504 tree ptr = TREE_OPERAND (expr, 0);
2505 tree offset = TREE_OPERAND (expr, 1);
2506 const svalue *ptr_sval = get_rvalue (ptr, ctxt);
2507 const svalue *offset_sval = get_rvalue (offset, ctxt);
2508 const svalue *sval_binop
2509 = m_mgr->get_or_create_binop (TREE_TYPE (expr), POINTER_PLUS_EXPR,
2510 ptr_sval, offset_sval);
2511 return sval_binop;
2514 /* Binary ops. */
2515 case PLUS_EXPR:
2516 case MULT_EXPR:
2517 case BIT_AND_EXPR:
2518 case BIT_IOR_EXPR:
2519 case BIT_XOR_EXPR:
2521 tree expr = pv.m_tree;
2522 tree arg0 = TREE_OPERAND (expr, 0);
2523 tree arg1 = TREE_OPERAND (expr, 1);
2524 const svalue *arg0_sval = get_rvalue (arg0, ctxt);
2525 const svalue *arg1_sval = get_rvalue (arg1, ctxt);
2526 const svalue *sval_binop
2527 = m_mgr->get_or_create_binop (TREE_TYPE (expr), TREE_CODE (expr),
2528 arg0_sval, arg1_sval);
2529 return sval_binop;
2532 case COMPONENT_REF:
2533 case MEM_REF:
2535 const region *ref_reg = get_lvalue (pv, ctxt);
2536 return get_store_value (ref_reg, ctxt);
2538 case OBJ_TYPE_REF:
2540 tree expr = OBJ_TYPE_REF_EXPR (pv.m_tree);
2541 return get_rvalue (expr, ctxt);
2546 /* Get the value of PV within this region_model,
2547 emitting any diagnostics to CTXT. */
2549 const svalue *
2550 region_model::get_rvalue (path_var pv, region_model_context *ctxt) const
2552 if (pv.m_tree == NULL_TREE)
2553 return NULL;
2555 const svalue *result_sval = get_rvalue_1 (pv, ctxt);
2557 assert_compat_types (result_sval->get_type (), TREE_TYPE (pv.m_tree));
2559 result_sval = check_for_poison (result_sval, pv.m_tree, NULL, ctxt);
2561 return result_sval;
2564 /* Get the value of EXPR within this region_model (assuming the most
2565 recent stack frame if it's a local). */
2567 const svalue *
2568 region_model::get_rvalue (tree expr, region_model_context *ctxt) const
2570 return get_rvalue (path_var (expr, get_stack_depth () - 1), ctxt);
2573 /* Return true if this model is on a path with "main" as the entrypoint
2574 (as opposed to one in which we're merely analyzing a subset of the
2575 path through the code). */
2577 bool
2578 region_model::called_from_main_p () const
2580 if (!m_current_frame)
2581 return false;
2582 /* Determine if the oldest stack frame in this model is for "main". */
2583 const frame_region *frame0 = get_frame_at_index (0);
2584 gcc_assert (frame0);
2585 return id_equal (DECL_NAME (frame0->get_function ()->decl), "main");
2588 /* Subroutine of region_model::get_store_value for when REG is (or is within)
2589 a global variable that hasn't been touched since the start of this path
2590 (or was implicitly touched due to a call to an unknown function). */
2592 const svalue *
2593 region_model::get_initial_value_for_global (const region *reg) const
2595 /* Get the decl that REG is for (or is within). */
2596 const decl_region *base_reg
2597 = reg->get_base_region ()->dyn_cast_decl_region ();
2598 gcc_assert (base_reg);
2599 tree decl = base_reg->get_decl ();
2601 /* Special-case: to avoid having to explicitly update all previously
2602 untracked globals when calling an unknown fn, they implicitly have
2603 an unknown value if an unknown call has occurred, unless this is
2604 static to-this-TU and hasn't escaped. Globals that have escaped
2605 are explicitly tracked, so we shouldn't hit this case for them. */
2606 if (m_store.called_unknown_fn_p ()
2607 && TREE_PUBLIC (decl)
2608 && !TREE_READONLY (decl))
2609 return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
2611 /* If we are on a path from the entrypoint from "main" and we have a
2612 global decl defined in this TU that hasn't been touched yet, then
2613 the initial value of REG can be taken from the initialization value
2614 of the decl. */
2615 if (called_from_main_p () || TREE_READONLY (decl))
2616 return reg->get_initial_value_at_main (m_mgr);
2618 /* Otherwise, return INIT_VAL(REG). */
2619 return m_mgr->get_or_create_initial_value (reg);
2622 /* Get a value for REG, looking it up in the store, or otherwise falling
2623 back to "initial" or "unknown" values.
2624 Use CTXT to report any warnings associated with reading from REG. */
2626 const svalue *
2627 region_model::get_store_value (const region *reg,
2628 region_model_context *ctxt) const
2630 /* Getting the value of an empty region gives an unknown_svalue. */
2631 if (reg->empty_p ())
2632 return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
2634 bool check_poisoned = true;
2635 if (check_region_for_read (reg, ctxt))
2636 check_poisoned = false;
2638 /* Special-case: handle var_decls in the constant pool. */
2639 if (const decl_region *decl_reg = reg->dyn_cast_decl_region ())
2640 if (const svalue *sval = decl_reg->maybe_get_constant_value (m_mgr))
2641 return sval;
2643 const svalue *sval
2644 = m_store.get_any_binding (m_mgr->get_store_manager (), reg);
2645 if (sval)
2647 if (reg->get_type ())
2648 sval = m_mgr->get_or_create_cast (reg->get_type (), sval);
2649 return sval;
2652 /* Special-case: read at a constant index within a STRING_CST. */
2653 if (const offset_region *offset_reg = reg->dyn_cast_offset_region ())
2654 if (tree byte_offset_cst
2655 = offset_reg->get_byte_offset ()->maybe_get_constant ())
2656 if (const string_region *str_reg
2657 = reg->get_parent_region ()->dyn_cast_string_region ())
2659 tree string_cst = str_reg->get_string_cst ();
2660 if (const svalue *char_sval
2661 = m_mgr->maybe_get_char_from_string_cst (string_cst,
2662 byte_offset_cst))
2663 return m_mgr->get_or_create_cast (reg->get_type (), char_sval);
2666 /* Special-case: read the initial char of a STRING_CST. */
2667 if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
2668 if (const string_region *str_reg
2669 = cast_reg->get_original_region ()->dyn_cast_string_region ())
2671 tree string_cst = str_reg->get_string_cst ();
2672 tree byte_offset_cst = build_int_cst (integer_type_node, 0);
2673 if (const svalue *char_sval
2674 = m_mgr->maybe_get_char_from_string_cst (string_cst,
2675 byte_offset_cst))
2676 return m_mgr->get_or_create_cast (reg->get_type (), char_sval);
2679 /* Otherwise we implicitly have the initial value of the region
2680 (if the cluster had been touched, binding_cluster::get_any_binding,
2681 would have returned UNKNOWN, and we would already have returned
2682 that above). */
2684 /* Handle globals. */
2685 if (reg->get_base_region ()->get_parent_region ()->get_kind ()
2686 == RK_GLOBALS)
2687 return get_initial_value_for_global (reg);
2689 return m_mgr->get_or_create_initial_value (reg, check_poisoned);
2692 /* Return false if REG does not exist, true if it may do.
2693 This is for detecting regions within the stack that don't exist anymore
2694 after frames are popped. */
2696 bool
2697 region_model::region_exists_p (const region *reg) const
2699 /* If within a stack frame, check that the stack frame is live. */
2700 if (const frame_region *enclosing_frame = reg->maybe_get_frame_region ())
2702 /* Check that the current frame is the enclosing frame, or is called
2703 by it. */
2704 for (const frame_region *iter_frame = get_current_frame (); iter_frame;
2705 iter_frame = iter_frame->get_calling_frame ())
2706 if (iter_frame == enclosing_frame)
2707 return true;
2708 return false;
2711 return true;
2714 /* Get a region for referencing PTR_SVAL, creating a region if need be, and
2715 potentially generating warnings via CTXT.
2716 PTR_SVAL must be of pointer type.
2717 PTR_TREE if non-NULL can be used when emitting diagnostics. */
2719 const region *
2720 region_model::deref_rvalue (const svalue *ptr_sval, tree ptr_tree,
2721 region_model_context *ctxt,
2722 bool add_nonnull_constraint) const
2724 gcc_assert (ptr_sval);
2725 gcc_assert (POINTER_TYPE_P (ptr_sval->get_type ()));
2727 /* If we're dereferencing PTR_SVAL, assume that it is non-NULL; add this
2728 as a constraint. This suppresses false positives from
2729 -Wanalyzer-null-dereference for the case where we later have an
2730 if (PTR_SVAL) that would occur if we considered the false branch
2731 and transitioned the malloc state machine from start->null. */
2732 if (add_nonnull_constraint)
2734 tree null_ptr_cst = build_int_cst (ptr_sval->get_type (), 0);
2735 const svalue *null_ptr
2736 = m_mgr->get_or_create_constant_svalue (null_ptr_cst);
2737 m_constraints->add_constraint (ptr_sval, NE_EXPR, null_ptr);
2740 switch (ptr_sval->get_kind ())
2742 default:
2743 break;
2745 case SK_REGION:
2747 const region_svalue *region_sval
2748 = as_a <const region_svalue *> (ptr_sval);
2749 return region_sval->get_pointee ();
2752 case SK_BINOP:
2754 const binop_svalue *binop_sval
2755 = as_a <const binop_svalue *> (ptr_sval);
2756 switch (binop_sval->get_op ())
2758 case POINTER_PLUS_EXPR:
2760 /* If we have a symbolic value expressing pointer arithmentic,
2761 try to convert it to a suitable region. */
2762 const region *parent_region
2763 = deref_rvalue (binop_sval->get_arg0 (), NULL_TREE, ctxt);
2764 const svalue *offset = binop_sval->get_arg1 ();
2765 tree type= TREE_TYPE (ptr_sval->get_type ());
2766 return m_mgr->get_offset_region (parent_region, type, offset);
2768 default:
2769 break;
2772 break;
2774 case SK_POISONED:
2776 if (ctxt)
2778 tree ptr = get_representative_tree (ptr_sval);
2779 /* If we can't get a representative tree for PTR_SVAL
2780 (e.g. if it hasn't been bound into the store), then
2781 fall back on PTR_TREE, if non-NULL. */
2782 if (!ptr)
2783 ptr = ptr_tree;
2784 if (ptr)
2786 const poisoned_svalue *poisoned_sval
2787 = as_a <const poisoned_svalue *> (ptr_sval);
2788 enum poison_kind pkind = poisoned_sval->get_poison_kind ();
2789 ctxt->warn (::make_unique<poisoned_value_diagnostic>
2790 (ptr, pkind, nullptr, nullptr));
2794 break;
2797 return m_mgr->get_symbolic_region (ptr_sval);
2800 /* Attempt to get BITS within any value of REG, as TYPE.
2801 In particular, extract values from compound_svalues for the case
2802 where there's a concrete binding at BITS.
2803 Return an unknown svalue if we can't handle the given case.
2804 Use CTXT to report any warnings associated with reading from REG. */
2806 const svalue *
2807 region_model::get_rvalue_for_bits (tree type,
2808 const region *reg,
2809 const bit_range &bits,
2810 region_model_context *ctxt) const
2812 const svalue *sval = get_store_value (reg, ctxt);
2813 return m_mgr->get_or_create_bits_within (type, bits, sval);
2816 /* A subclass of pending_diagnostic for complaining about writes to
2817 constant regions of memory. */
2819 class write_to_const_diagnostic
2820 : public pending_diagnostic_subclass<write_to_const_diagnostic>
2822 public:
2823 write_to_const_diagnostic (const region *reg, tree decl)
2824 : m_reg (reg), m_decl (decl)
2827 const char *get_kind () const final override
2829 return "write_to_const_diagnostic";
2832 bool operator== (const write_to_const_diagnostic &other) const
2834 return (m_reg == other.m_reg
2835 && m_decl == other.m_decl);
2838 int get_controlling_option () const final override
2840 return OPT_Wanalyzer_write_to_const;
2843 bool emit (rich_location *rich_loc, logger *) final override
2845 auto_diagnostic_group d;
2846 bool warned;
2847 switch (m_reg->get_kind ())
2849 default:
2850 warned = warning_at (rich_loc, get_controlling_option (),
2851 "write to %<const%> object %qE", m_decl);
2852 break;
2853 case RK_FUNCTION:
2854 warned = warning_at (rich_loc, get_controlling_option (),
2855 "write to function %qE", m_decl);
2856 break;
2857 case RK_LABEL:
2858 warned = warning_at (rich_loc, get_controlling_option (),
2859 "write to label %qE", m_decl);
2860 break;
2862 if (warned)
2863 inform (DECL_SOURCE_LOCATION (m_decl), "declared here");
2864 return warned;
2867 label_text describe_final_event (const evdesc::final_event &ev) final override
2869 switch (m_reg->get_kind ())
2871 default:
2872 return ev.formatted_print ("write to %<const%> object %qE here", m_decl);
2873 case RK_FUNCTION:
2874 return ev.formatted_print ("write to function %qE here", m_decl);
2875 case RK_LABEL:
2876 return ev.formatted_print ("write to label %qE here", m_decl);
2880 private:
2881 const region *m_reg;
2882 tree m_decl;
2885 /* A subclass of pending_diagnostic for complaining about writes to
2886 string literals. */
2888 class write_to_string_literal_diagnostic
2889 : public pending_diagnostic_subclass<write_to_string_literal_diagnostic>
2891 public:
2892 write_to_string_literal_diagnostic (const region *reg)
2893 : m_reg (reg)
2896 const char *get_kind () const final override
2898 return "write_to_string_literal_diagnostic";
2901 bool operator== (const write_to_string_literal_diagnostic &other) const
2903 return m_reg == other.m_reg;
2906 int get_controlling_option () const final override
2908 return OPT_Wanalyzer_write_to_string_literal;
2911 bool emit (rich_location *rich_loc, logger *) final override
2913 return warning_at (rich_loc, get_controlling_option (),
2914 "write to string literal");
2915 /* Ideally we would show the location of the STRING_CST as well,
2916 but it is not available at this point. */
2919 label_text describe_final_event (const evdesc::final_event &ev) final override
2921 return ev.formatted_print ("write to string literal here");
2924 private:
2925 const region *m_reg;
2928 /* Use CTXT to warn If DEST_REG is a region that shouldn't be written to. */
2930 void
2931 region_model::check_for_writable_region (const region* dest_reg,
2932 region_model_context *ctxt) const
2934 /* Fail gracefully if CTXT is NULL. */
2935 if (!ctxt)
2936 return;
2938 const region *base_reg = dest_reg->get_base_region ();
2939 switch (base_reg->get_kind ())
2941 default:
2942 break;
2943 case RK_FUNCTION:
2945 const function_region *func_reg = as_a <const function_region *> (base_reg);
2946 tree fndecl = func_reg->get_fndecl ();
2947 ctxt->warn (make_unique<write_to_const_diagnostic>
2948 (func_reg, fndecl));
2950 break;
2951 case RK_LABEL:
2953 const label_region *label_reg = as_a <const label_region *> (base_reg);
2954 tree label = label_reg->get_label ();
2955 ctxt->warn (make_unique<write_to_const_diagnostic>
2956 (label_reg, label));
2958 break;
2959 case RK_DECL:
2961 const decl_region *decl_reg = as_a <const decl_region *> (base_reg);
2962 tree decl = decl_reg->get_decl ();
2963 /* Warn about writes to const globals.
2964 Don't warn for writes to const locals, and params in particular,
2965 since we would warn in push_frame when setting them up (e.g the
2966 "this" param is "T* const"). */
2967 if (TREE_READONLY (decl)
2968 && is_global_var (decl))
2969 ctxt->warn (make_unique<write_to_const_diagnostic> (dest_reg, decl));
2971 break;
2972 case RK_STRING:
2973 ctxt->warn (make_unique<write_to_string_literal_diagnostic> (dest_reg));
2974 break;
2978 /* Get the capacity of REG in bytes. */
2980 const svalue *
2981 region_model::get_capacity (const region *reg) const
2983 switch (reg->get_kind ())
2985 default:
2986 break;
2987 case RK_DECL:
2989 const decl_region *decl_reg = as_a <const decl_region *> (reg);
2990 tree decl = decl_reg->get_decl ();
2991 if (TREE_CODE (decl) == SSA_NAME)
2993 tree type = TREE_TYPE (decl);
2994 tree size = TYPE_SIZE (type);
2995 return get_rvalue (size, NULL);
2997 else
2999 tree size = decl_init_size (decl, false);
3000 if (size)
3001 return get_rvalue (size, NULL);
3004 break;
3005 case RK_SIZED:
3006 /* Look through sized regions to get at the capacity
3007 of the underlying regions. */
3008 return get_capacity (reg->get_parent_region ());
3009 case RK_STRING:
3011 /* "Capacity" here means "size". */
3012 const string_region *string_reg = as_a <const string_region *> (reg);
3013 tree string_cst = string_reg->get_string_cst ();
3014 return m_mgr->get_or_create_int_cst (size_type_node,
3015 TREE_STRING_LENGTH (string_cst));
3017 break;
3020 if (const svalue *recorded = get_dynamic_extents (reg))
3021 return recorded;
3023 return m_mgr->get_or_create_unknown_svalue (sizetype);
3026 /* If CTXT is non-NULL, use it to warn about any problems accessing REG,
3027 using DIR to determine if this access is a read or write.
3028 Return TRUE if an OOB access was detected.
3029 If SVAL_HINT is non-NULL, use it as a hint in diagnostics
3030 about the value that would be written to REG. */
3032 bool
3033 region_model::check_region_access (const region *reg,
3034 enum access_direction dir,
3035 const svalue *sval_hint,
3036 region_model_context *ctxt) const
3038 /* Fail gracefully if CTXT is NULL. */
3039 if (!ctxt)
3040 return false;
3042 bool oob_access_detected = false;
3043 check_region_for_taint (reg, dir, ctxt);
3044 if (!check_region_bounds (reg, dir, sval_hint, ctxt))
3045 oob_access_detected = true;
3047 switch (dir)
3049 default:
3050 gcc_unreachable ();
3051 case DIR_READ:
3052 /* Currently a no-op. */
3053 break;
3054 case DIR_WRITE:
3055 check_for_writable_region (reg, ctxt);
3056 break;
3058 return oob_access_detected;
3061 /* If CTXT is non-NULL, use it to warn about any problems writing to REG. */
3063 void
3064 region_model::check_region_for_write (const region *dest_reg,
3065 const svalue *sval_hint,
3066 region_model_context *ctxt) const
3068 check_region_access (dest_reg, DIR_WRITE, sval_hint, ctxt);
3071 /* If CTXT is non-NULL, use it to warn about any problems reading from REG.
3072 Returns TRUE if an OOB read was detected. */
3074 bool
3075 region_model::check_region_for_read (const region *src_reg,
3076 region_model_context *ctxt) const
3078 return check_region_access (src_reg, DIR_READ, NULL, ctxt);
3081 /* Concrete subclass for casts of pointers that lead to trailing bytes. */
3083 class dubious_allocation_size
3084 : public pending_diagnostic_subclass<dubious_allocation_size>
3086 public:
3087 dubious_allocation_size (const region *lhs, const region *rhs,
3088 const gimple *stmt)
3089 : m_lhs (lhs), m_rhs (rhs), m_expr (NULL_TREE), m_stmt (stmt),
3090 m_has_allocation_event (false)
3093 dubious_allocation_size (const region *lhs, const region *rhs,
3094 tree expr, const gimple *stmt)
3095 : m_lhs (lhs), m_rhs (rhs), m_expr (expr), m_stmt (stmt),
3096 m_has_allocation_event (false)
3099 const char *get_kind () const final override
3101 return "dubious_allocation_size";
3104 bool operator== (const dubious_allocation_size &other) const
3106 return (m_stmt == other.m_stmt
3107 && pending_diagnostic::same_tree_p (m_expr, other.m_expr));
3110 int get_controlling_option () const final override
3112 return OPT_Wanalyzer_allocation_size;
3115 bool emit (rich_location *rich_loc, logger *) final override
3117 diagnostic_metadata m;
3118 m.add_cwe (131);
3120 return warning_meta (rich_loc, m, get_controlling_option (),
3121 "allocated buffer size is not a multiple"
3122 " of the pointee's size");
3125 label_text describe_final_event (const evdesc::final_event &ev) final
3126 override
3128 tree pointee_type = TREE_TYPE (m_lhs->get_type ());
3129 if (m_has_allocation_event)
3130 return ev.formatted_print ("assigned to %qT here;"
3131 " %<sizeof (%T)%> is %qE",
3132 m_lhs->get_type (), pointee_type,
3133 size_in_bytes (pointee_type));
3134 /* Fallback: Typically, we should always see an allocation_event
3135 before. */
3136 if (m_expr)
3138 if (TREE_CODE (m_expr) == INTEGER_CST)
3139 return ev.formatted_print ("allocated %E bytes and assigned to"
3140 " %qT here; %<sizeof (%T)%> is %qE",
3141 m_expr, m_lhs->get_type (), pointee_type,
3142 size_in_bytes (pointee_type));
3143 else
3144 return ev.formatted_print ("allocated %qE bytes and assigned to"
3145 " %qT here; %<sizeof (%T)%> is %qE",
3146 m_expr, m_lhs->get_type (), pointee_type,
3147 size_in_bytes (pointee_type));
3150 return ev.formatted_print ("allocated and assigned to %qT here;"
3151 " %<sizeof (%T)%> is %qE",
3152 m_lhs->get_type (), pointee_type,
3153 size_in_bytes (pointee_type));
3156 void
3157 add_region_creation_events (const region *,
3158 tree capacity,
3159 const event_loc_info &loc_info,
3160 checker_path &emission_path) final override
3162 emission_path.add_event
3163 (make_unique<region_creation_event_allocation_size> (capacity, loc_info));
3165 m_has_allocation_event = true;
3168 void mark_interesting_stuff (interesting_t *interest) final override
3170 interest->add_region_creation (m_rhs);
3173 private:
3174 const region *m_lhs;
3175 const region *m_rhs;
3176 const tree m_expr;
3177 const gimple *m_stmt;
3178 bool m_has_allocation_event;
3181 /* Return true on dubious allocation sizes for constant sizes. */
3183 static bool
3184 capacity_compatible_with_type (tree cst, tree pointee_size_tree,
3185 bool is_struct)
3187 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
3188 gcc_assert (TREE_CODE (pointee_size_tree) == INTEGER_CST);
3190 unsigned HOST_WIDE_INT pointee_size = TREE_INT_CST_LOW (pointee_size_tree);
3191 unsigned HOST_WIDE_INT alloc_size = TREE_INT_CST_LOW (cst);
3193 if (is_struct)
3194 return alloc_size == 0 || alloc_size >= pointee_size;
3195 return alloc_size % pointee_size == 0;
3198 static bool
3199 capacity_compatible_with_type (tree cst, tree pointee_size_tree)
3201 return capacity_compatible_with_type (cst, pointee_size_tree, false);
3204 /* Checks whether SVAL could be a multiple of SIZE_CST.
3206 It works by visiting all svalues inside SVAL until it reaches
3207 atomic nodes. From those, it goes back up again and adds each
3208 node that is not a multiple of SIZE_CST to the RESULT_SET. */
3210 class size_visitor : public visitor
3212 public:
3213 size_visitor (tree size_cst, const svalue *root_sval, constraint_manager *cm)
3214 : m_size_cst (size_cst), m_root_sval (root_sval), m_cm (cm)
3216 m_root_sval->accept (this);
3219 bool is_dubious_capacity ()
3221 return result_set.contains (m_root_sval);
3224 void visit_constant_svalue (const constant_svalue *sval) final override
3226 check_constant (sval->get_constant (), sval);
3229 void visit_unaryop_svalue (const unaryop_svalue *sval) final override
3231 if (CONVERT_EXPR_CODE_P (sval->get_op ())
3232 && result_set.contains (sval->get_arg ()))
3233 result_set.add (sval);
3236 void visit_binop_svalue (const binop_svalue *sval) final override
3238 const svalue *arg0 = sval->get_arg0 ();
3239 const svalue *arg1 = sval->get_arg1 ();
3241 switch (sval->get_op ())
3243 case MULT_EXPR:
3244 if (result_set.contains (arg0) && result_set.contains (arg1))
3245 result_set.add (sval);
3246 break;
3247 case PLUS_EXPR:
3248 case MINUS_EXPR:
3249 if (result_set.contains (arg0) || result_set.contains (arg1))
3250 result_set.add (sval);
3251 break;
3252 default:
3253 break;
3257 void visit_unmergeable_svalue (const unmergeable_svalue *sval) final override
3259 if (result_set.contains (sval->get_arg ()))
3260 result_set.add (sval);
3263 void visit_widening_svalue (const widening_svalue *sval) final override
3265 const svalue *base = sval->get_base_svalue ();
3266 const svalue *iter = sval->get_iter_svalue ();
3268 if (result_set.contains (base) || result_set.contains (iter))
3269 result_set.add (sval);
3272 void visit_initial_svalue (const initial_svalue *sval) final override
3274 equiv_class_id id = equiv_class_id::null ();
3275 if (m_cm->get_equiv_class_by_svalue (sval, &id))
3277 if (tree cst = id.get_obj (*m_cm).get_any_constant ())
3278 check_constant (cst, sval);
3280 else if (!m_cm->sval_constrained_p (sval))
3282 result_set.add (sval);
3286 void visit_conjured_svalue (const conjured_svalue *sval) final override
3288 equiv_class_id id = equiv_class_id::null ();
3289 if (m_cm->get_equiv_class_by_svalue (sval, &id))
3290 if (tree cst = id.get_obj (*m_cm).get_any_constant ())
3291 check_constant (cst, sval);
3294 private:
3295 void check_constant (tree cst, const svalue *sval)
3297 switch (TREE_CODE (cst))
3299 default:
3300 /* Assume all unhandled operands are compatible. */
3301 break;
3302 case INTEGER_CST:
3303 if (!capacity_compatible_with_type (cst, m_size_cst))
3304 result_set.add (sval);
3305 break;
3309 tree m_size_cst;
3310 const svalue *m_root_sval;
3311 constraint_manager *m_cm;
3312 svalue_set result_set; /* Used as a mapping of svalue*->bool. */
3315 /* Return true if a struct or union either uses the inheritance pattern,
3316 where the first field is a base struct, or the flexible array member
3317 pattern, where the last field is an array without a specified size. */
3319 static bool
3320 struct_or_union_with_inheritance_p (tree struc)
3322 tree iter = TYPE_FIELDS (struc);
3323 if (iter == NULL_TREE)
3324 return false;
3325 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (iter)))
3326 return true;
3328 tree last_field;
3329 while (iter != NULL_TREE)
3331 last_field = iter;
3332 iter = DECL_CHAIN (iter);
3335 if (last_field != NULL_TREE
3336 && TREE_CODE (TREE_TYPE (last_field)) == ARRAY_TYPE)
3337 return true;
3339 return false;
3342 /* Return true if the lhs and rhs of an assignment have different types. */
3344 static bool
3345 is_any_cast_p (const gimple *stmt)
3347 if (const gassign *assign = dyn_cast <const gassign *> (stmt))
3348 return gimple_assign_cast_p (assign)
3349 || !pending_diagnostic::same_tree_p (
3350 TREE_TYPE (gimple_assign_lhs (assign)),
3351 TREE_TYPE (gimple_assign_rhs1 (assign)));
3352 else if (const gcall *call = dyn_cast <const gcall *> (stmt))
3354 tree lhs = gimple_call_lhs (call);
3355 return lhs != NULL_TREE && !pending_diagnostic::same_tree_p (
3356 TREE_TYPE (gimple_call_lhs (call)),
3357 gimple_call_return_type (call));
3360 return false;
3363 /* On pointer assignments, check whether the buffer size of
3364 RHS_SVAL is compatible with the type of the LHS_REG.
3365 Use a non-null CTXT to report allocation size warnings. */
3367 void
3368 region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval,
3369 region_model_context *ctxt) const
3371 if (!ctxt || ctxt->get_stmt () == NULL)
3372 return;
3373 /* Only report warnings on assignments that actually change the type. */
3374 if (!is_any_cast_p (ctxt->get_stmt ()))
3375 return;
3377 tree pointer_type = lhs_reg->get_type ();
3378 if (pointer_type == NULL_TREE || !POINTER_TYPE_P (pointer_type))
3379 return;
3381 tree pointee_type = TREE_TYPE (pointer_type);
3382 /* Make sure that the type on the left-hand size actually has a size. */
3383 if (pointee_type == NULL_TREE || VOID_TYPE_P (pointee_type)
3384 || TYPE_SIZE_UNIT (pointee_type) == NULL_TREE)
3385 return;
3387 /* Bail out early on pointers to structs where we can
3388 not deduce whether the buffer size is compatible. */
3389 bool is_struct = RECORD_OR_UNION_TYPE_P (pointee_type);
3390 if (is_struct && struct_or_union_with_inheritance_p (pointee_type))
3391 return;
3393 tree pointee_size_tree = size_in_bytes (pointee_type);
3394 /* We give up if the type size is not known at compile-time or the
3395 type size is always compatible regardless of the buffer size. */
3396 if (TREE_CODE (pointee_size_tree) != INTEGER_CST
3397 || integer_zerop (pointee_size_tree)
3398 || integer_onep (pointee_size_tree))
3399 return;
3401 const region *rhs_reg = deref_rvalue (rhs_sval, NULL_TREE, ctxt, false);
3402 const svalue *capacity = get_capacity (rhs_reg);
3403 switch (capacity->get_kind ())
3405 case svalue_kind::SK_CONSTANT:
3407 const constant_svalue *cst_cap_sval
3408 = as_a <const constant_svalue *> (capacity);
3409 tree cst_cap = cst_cap_sval->get_constant ();
3410 if (TREE_CODE (cst_cap) == INTEGER_CST
3411 && !capacity_compatible_with_type (cst_cap, pointee_size_tree,
3412 is_struct))
3413 ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg, rhs_reg,
3414 cst_cap,
3415 ctxt->get_stmt ()));
3417 break;
3418 default:
3420 if (!is_struct)
3422 size_visitor v (pointee_size_tree, capacity, m_constraints);
3423 if (v.is_dubious_capacity ())
3425 tree expr = get_representative_tree (capacity);
3426 ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg,
3427 rhs_reg,
3428 expr,
3429 ctxt->get_stmt ()));
3432 break;
3437 /* Set the value of the region given by LHS_REG to the value given
3438 by RHS_SVAL.
3439 Use CTXT to report any warnings associated with writing to LHS_REG. */
3441 void
3442 region_model::set_value (const region *lhs_reg, const svalue *rhs_sval,
3443 region_model_context *ctxt)
3445 gcc_assert (lhs_reg);
3446 gcc_assert (rhs_sval);
3448 /* Setting the value of an empty region is a no-op. */
3449 if (lhs_reg->empty_p ())
3450 return;
3452 check_region_size (lhs_reg, rhs_sval, ctxt);
3454 check_region_for_write (lhs_reg, rhs_sval, ctxt);
3456 m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
3457 ctxt ? ctxt->get_uncertainty () : NULL);
3460 /* Set the value of the region given by LHS to the value given by RHS. */
3462 void
3463 region_model::set_value (tree lhs, tree rhs, region_model_context *ctxt)
3465 const region *lhs_reg = get_lvalue (lhs, ctxt);
3466 const svalue *rhs_sval = get_rvalue (rhs, ctxt);
3467 gcc_assert (lhs_reg);
3468 gcc_assert (rhs_sval);
3469 set_value (lhs_reg, rhs_sval, ctxt);
3472 /* Issue a note specifying that a particular function parameter is expected
3473 to be a valid null-terminated string. */
3475 static void
3476 inform_about_expected_null_terminated_string_arg (const call_arg_details &ad)
3478 // TODO: ideally we'd underline the param here
3479 inform (DECL_SOURCE_LOCATION (ad.m_called_fndecl),
3480 "argument %d of %qD must be a pointer to a null-terminated string",
3481 ad.m_arg_idx + 1, ad.m_called_fndecl);
3484 /* A binding of a specific svalue at a concrete byte range. */
3486 struct fragment
3488 fragment ()
3489 : m_byte_range (0, 0), m_sval (nullptr)
3493 fragment (const byte_range &bytes, const svalue *sval)
3494 : m_byte_range (bytes), m_sval (sval)
3498 static int cmp_ptrs (const void *p1, const void *p2)
3500 const fragment *f1 = (const fragment *)p1;
3501 const fragment *f2 = (const fragment *)p2;
3502 return byte_range::cmp (f1->m_byte_range, f2->m_byte_range);
3505 /* Determine if there is a zero terminator somewhere in the
3506 bytes of this fragment, starting at START_READ_OFFSET (which
3507 is absolute to the start of the cluster as a whole), and stopping
3508 at the end of this fragment.
3510 Return a tristate:
3511 - true if there definitely is a zero byte, writing to *OUT_BYTES_READ
3512 the number of bytes from that would be read, including the zero byte.
3513 - false if there definitely isn't a zero byte
3514 - unknown if we don't know. */
3515 tristate has_null_terminator (byte_offset_t start_read_offset,
3516 byte_offset_t *out_bytes_read) const
3518 byte_offset_t rel_start_read_offset
3519 = start_read_offset - m_byte_range.get_start_byte_offset ();
3520 gcc_assert (rel_start_read_offset >= 0);
3521 byte_offset_t available_bytes
3522 = (m_byte_range.get_next_byte_offset () - start_read_offset);
3523 gcc_assert (available_bytes >= 0);
3525 if (rel_start_read_offset > INT_MAX)
3526 return tristate::TS_UNKNOWN;
3527 HOST_WIDE_INT rel_start_read_offset_hwi = rel_start_read_offset.slow ();
3529 if (available_bytes > INT_MAX)
3530 return tristate::TS_UNKNOWN;
3531 HOST_WIDE_INT available_bytes_hwi = available_bytes.slow ();
3533 switch (m_sval->get_kind ())
3535 case SK_CONSTANT:
3537 tree cst
3538 = as_a <const constant_svalue *> (m_sval)->get_constant ();
3539 switch (TREE_CODE (cst))
3541 case STRING_CST:
3542 return string_cst_has_null_terminator (cst,
3543 rel_start_read_offset_hwi,
3544 available_bytes_hwi,
3545 out_bytes_read);
3546 case INTEGER_CST:
3547 if (rel_start_read_offset_hwi == 0
3548 && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (cst))))
3550 /* Model accesses to the initial byte of a 1-byte
3551 INTEGER_CST. */
3552 if (zerop (cst))
3554 *out_bytes_read = 1;
3555 return tristate (true);
3557 else
3559 *out_bytes_read = available_bytes;
3560 return tristate (false);
3563 /* Treat any other access to an INTEGER_CST as unknown. */
3564 return tristate::TS_UNKNOWN;
3566 default:
3567 gcc_unreachable ();
3568 break;
3571 break;
3573 case SK_INITIAL:
3575 const initial_svalue *initial_sval = (const initial_svalue *)m_sval;
3576 const region *reg = initial_sval->get_region ();
3577 if (const string_region *string_reg = reg->dyn_cast_string_region ())
3579 tree string_cst = string_reg->get_string_cst ();
3580 return string_cst_has_null_terminator (string_cst,
3581 rel_start_read_offset_hwi,
3582 available_bytes_hwi,
3583 out_bytes_read);
3585 return tristate::TS_UNKNOWN;
3587 break;
3589 case SK_BITS_WITHIN:
3591 const bits_within_svalue *bits_within_sval
3592 = (const bits_within_svalue *)m_sval;
3593 byte_range bytes (0, 0);
3594 if (bits_within_sval->get_bits ().as_byte_range (&bytes))
3596 const svalue *inner_sval = bits_within_sval->get_inner_svalue ();
3597 fragment f (byte_range
3598 (start_read_offset - bytes.get_start_bit_offset (),
3599 std::max<byte_size_t> (bytes.m_size_in_bytes,
3600 available_bytes)),
3601 inner_sval);
3602 return f.has_null_terminator (start_read_offset, out_bytes_read);
3605 break;
3607 default:
3608 // TODO: it may be possible to handle other cases here.
3609 break;
3611 return tristate::TS_UNKNOWN;
3614 static tristate
3615 string_cst_has_null_terminator (tree string_cst,
3616 HOST_WIDE_INT rel_start_read_offset_hwi,
3617 HOST_WIDE_INT available_bytes_hwi,
3618 byte_offset_t *out_bytes_read)
3620 /* Look for the first 0 byte within STRING_CST
3621 from START_READ_OFFSET onwards. */
3622 const HOST_WIDE_INT num_bytes_to_search
3623 = std::min<HOST_WIDE_INT> ((TREE_STRING_LENGTH (string_cst)
3624 - rel_start_read_offset_hwi),
3625 available_bytes_hwi);
3626 const char *start = (TREE_STRING_POINTER (string_cst)
3627 + rel_start_read_offset_hwi);
3628 if (num_bytes_to_search >= 0)
3629 if (const void *p = memchr (start, 0,
3630 num_bytes_to_search))
3632 *out_bytes_read = (const char *)p - start + 1;
3633 return tristate (true);
3636 *out_bytes_read = available_bytes_hwi;
3637 return tristate (false);
3640 byte_range m_byte_range;
3641 const svalue *m_sval;
3644 /* A frozen copy of a single base region's binding_cluster within a store,
3645 optimized for traversal of the concrete parts in byte order.
3646 This only captures concrete bindings, and is an implementation detail
3647 of region_model::scan_for_null_terminator. */
3649 class iterable_cluster
3651 public:
3652 iterable_cluster (const binding_cluster *cluster)
3654 if (!cluster)
3655 return;
3656 for (auto iter : *cluster)
3658 const binding_key *key = iter.first;
3659 const svalue *sval = iter.second;
3661 if (const concrete_binding *concrete_key
3662 = key->dyn_cast_concrete_binding ())
3664 byte_range fragment_bytes (0, 0);
3665 if (concrete_key->get_byte_range (&fragment_bytes))
3666 m_fragments.safe_push (fragment (fragment_bytes, sval));
3668 else
3669 m_symbolic_bindings.safe_push (key);
3671 m_fragments.qsort (fragment::cmp_ptrs);
3674 bool
3675 get_fragment_for_byte (byte_offset_t byte, fragment *out_frag) const
3677 /* TODO: binary search rather than linear. */
3678 unsigned iter_idx;
3679 for (iter_idx = 0; iter_idx < m_fragments.length (); iter_idx++)
3681 if (m_fragments[iter_idx].m_byte_range.contains_p (byte))
3683 *out_frag = m_fragments[iter_idx];
3684 return true;
3687 return false;
3690 bool has_symbolic_bindings_p () const
3692 return !m_symbolic_bindings.is_empty ();
3695 private:
3696 auto_vec<fragment> m_fragments;
3697 auto_vec<const binding_key *> m_symbolic_bindings;
3700 /* Simulate reading the bytes at BYTES from BASE_REG.
3701 Complain to CTXT about any issues with the read e.g. out-of-bounds. */
3703 const svalue *
3704 region_model::get_store_bytes (const region *base_reg,
3705 const byte_range &bytes,
3706 region_model_context *ctxt) const
3708 /* Shortcut reading all of a string_region. */
3709 if (bytes.get_start_byte_offset () == 0)
3710 if (const string_region *string_reg = base_reg->dyn_cast_string_region ())
3711 if (bytes.m_size_in_bytes
3712 == TREE_STRING_LENGTH (string_reg->get_string_cst ()))
3713 return m_mgr->get_or_create_initial_value (base_reg);
3715 const svalue *index_sval
3716 = m_mgr->get_or_create_int_cst (size_type_node,
3717 bytes.get_start_byte_offset ());
3718 const region *offset_reg = m_mgr->get_offset_region (base_reg,
3719 NULL_TREE,
3720 index_sval);
3721 const svalue *byte_size_sval
3722 = m_mgr->get_or_create_int_cst (size_type_node, bytes.m_size_in_bytes);
3723 const region *read_reg = m_mgr->get_sized_region (offset_reg,
3724 NULL_TREE,
3725 byte_size_sval);
3727 /* Simulate reading those bytes from the store. */
3728 const svalue *sval = get_store_value (read_reg, ctxt);
3729 return sval;
3732 static tree
3733 get_tree_for_byte_offset (tree ptr_expr, byte_offset_t byte_offset)
3735 gcc_assert (ptr_expr);
3736 return fold_build2 (MEM_REF,
3737 char_type_node,
3738 ptr_expr, wide_int_to_tree (size_type_node, byte_offset));
3741 /* Simulate a series of reads of REG until we find a 0 byte
3742 (equivalent to calling strlen).
3744 Complain to CTXT and return NULL if:
3745 - the buffer pointed to isn't null-terminated
3746 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3747 - any of the reads aren't within the bounds of the underlying base region
3749 Otherwise, return a svalue for the number of bytes read (strlen + 1),
3750 and, if OUT_SVAL is non-NULL, write to *OUT_SVAL with an svalue
3751 representing the content of REG up to and including the terminator.
3753 Algorithm
3754 =========
3756 Get offset for first byte to read.
3757 Find the binding (if any) that contains it.
3758 Find the size in bits of that binding.
3759 Round to the nearest byte (which way???)
3760 Or maybe give up if we have a partial binding there.
3761 Get the svalue from the binding.
3762 Determine the strlen (if any) of that svalue.
3763 Does it have a 0-terminator within it?
3764 If so, we have a partial read up to and including that terminator
3765 Read those bytes from the store; add to the result in the correct place.
3766 Finish
3767 If not, we have a full read of that svalue
3768 Read those bytes from the store; add to the result in the correct place.
3769 Update read/write offsets
3770 Continue
3771 If unknown:
3772 Result is unknown
3773 Finish
3776 const svalue *
3777 region_model::scan_for_null_terminator (const region *reg,
3778 tree expr,
3779 const svalue **out_sval,
3780 region_model_context *ctxt) const
3782 store_manager *store_mgr = m_mgr->get_store_manager ();
3784 region_offset offset = reg->get_offset (m_mgr);
3785 if (offset.symbolic_p ())
3787 if (out_sval)
3788 *out_sval = get_store_value (reg, nullptr);
3789 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3791 byte_offset_t src_byte_offset;
3792 if (!offset.get_concrete_byte_offset (&src_byte_offset))
3794 if (out_sval)
3795 *out_sval = get_store_value (reg, nullptr);
3796 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3798 const byte_offset_t initial_src_byte_offset = src_byte_offset;
3799 byte_offset_t dst_byte_offset = 0;
3801 const region *base_reg = reg->get_base_region ();
3803 if (const string_region *str_reg = base_reg->dyn_cast_string_region ())
3805 tree string_cst = str_reg->get_string_cst ();
3806 if (const void *p = memchr (TREE_STRING_POINTER (string_cst),
3808 TREE_STRING_LENGTH (string_cst)))
3810 size_t num_bytes_read
3811 = (const char *)p - TREE_STRING_POINTER (string_cst) + 1;
3812 /* Simulate the read. */
3813 byte_range bytes_to_read (0, num_bytes_read);
3814 const svalue *sval = get_store_bytes (reg, bytes_to_read, ctxt);
3815 if (out_sval)
3816 *out_sval = sval;
3817 return m_mgr->get_or_create_int_cst (size_type_node,
3818 num_bytes_read);
3822 const binding_cluster *cluster = m_store.get_cluster (base_reg);
3823 iterable_cluster c (cluster);
3824 binding_map result;
3826 while (1)
3828 fragment f;
3829 if (c.get_fragment_for_byte (src_byte_offset, &f))
3831 byte_offset_t fragment_bytes_read;
3832 tristate is_terminated
3833 = f.has_null_terminator (src_byte_offset, &fragment_bytes_read);
3834 if (is_terminated.is_unknown ())
3836 if (out_sval)
3837 *out_sval = get_store_value (reg, nullptr);
3838 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3841 /* Simulate reading those bytes from the store. */
3842 byte_range bytes_to_read (src_byte_offset, fragment_bytes_read);
3843 const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
3844 check_for_poison (sval, expr, nullptr, ctxt);
3846 if (out_sval)
3848 byte_range bytes_to_write (dst_byte_offset, fragment_bytes_read);
3849 const binding_key *key
3850 = store_mgr->get_concrete_binding (bytes_to_write);
3851 result.put (key, sval);
3854 src_byte_offset += fragment_bytes_read;
3855 dst_byte_offset += fragment_bytes_read;
3857 if (is_terminated.is_true ())
3859 if (out_sval)
3860 *out_sval = m_mgr->get_or_create_compound_svalue (NULL_TREE,
3861 result);
3862 return m_mgr->get_or_create_int_cst (size_type_node,
3863 dst_byte_offset);
3866 else
3867 break;
3870 /* No binding for this base_region, or no binding at src_byte_offset
3871 (or a symbolic binding). */
3873 if (c.has_symbolic_bindings_p ())
3875 if (out_sval)
3876 *out_sval = get_store_value (reg, nullptr);
3877 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3880 /* TODO: the various special-cases seen in
3881 region_model::get_store_value. */
3883 /* Simulate reading from this byte, then give up. */
3884 byte_range bytes_to_read (src_byte_offset, 1);
3885 const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
3886 tree byte_expr
3887 = (expr
3888 ? get_tree_for_byte_offset (expr,
3889 src_byte_offset - initial_src_byte_offset)
3890 : NULL_TREE);
3891 check_for_poison (sval, byte_expr, nullptr, ctxt);
3892 if (base_reg->can_have_initial_svalue_p ())
3894 if (out_sval)
3895 *out_sval = get_store_value (reg, nullptr);
3896 return m_mgr->get_or_create_unknown_svalue (size_type_node);
3898 else
3899 return nullptr;
3902 /* Check that argument ARG_IDX (0-based) to the call described by CD
3903 is a pointer to a valid null-terminated string.
3905 Simulate scanning through the buffer, reading until we find a 0 byte
3906 (equivalent to calling strlen).
3908 Complain and return NULL if:
3909 - the buffer pointed to isn't null-terminated
3910 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3911 - any of the reads aren't within the bounds of the underlying base region
3913 Otherwise, return a svalue for strlen of the buffer (*not* including
3914 the null terminator).
3916 TODO: we should also complain if:
3917 - the pointer is NULL (or could be). */
3919 const svalue *
3920 region_model::check_for_null_terminated_string_arg (const call_details &cd,
3921 unsigned arg_idx) const
3923 return check_for_null_terminated_string_arg (cd,
3924 arg_idx,
3925 false, /* include_terminator */
3926 nullptr); // out_sval
3930 /* Check that argument ARG_IDX (0-based) to the call described by CD
3931 is a pointer to a valid null-terminated string.
3933 Simulate scanning through the buffer, reading until we find a 0 byte
3934 (equivalent to calling strlen).
3936 Complain and return NULL if:
3937 - the buffer pointed to isn't null-terminated
3938 - the buffer pointed to has any uninitalized bytes before any 0-terminator
3939 - any of the reads aren't within the bounds of the underlying base region
3941 Otherwise, return a svalue. This will be the number of bytes read
3942 (including the null terminator) if INCLUDE_TERMINATOR is true, or strlen
3943 of the buffer (not including the null terminator) if it is false.
3945 Also, when returning an svalue, if OUT_SVAL is non-NULL, write to
3946 *OUT_SVAL with an svalue representing the content of the buffer up to
3947 and including the terminator.
3949 TODO: we should also complain if:
3950 - the pointer is NULL (or could be). */
3952 const svalue *
3953 region_model::check_for_null_terminated_string_arg (const call_details &cd,
3954 unsigned arg_idx,
3955 bool include_terminator,
3956 const svalue **out_sval) const
3958 class null_terminator_check_event : public custom_event
3960 public:
3961 null_terminator_check_event (const event_loc_info &loc_info,
3962 const call_arg_details &arg_details)
3963 : custom_event (loc_info),
3964 m_arg_details (arg_details)
3968 label_text get_desc (bool can_colorize) const final override
3970 if (m_arg_details.m_arg_expr)
3971 return make_label_text (can_colorize,
3972 "while looking for null terminator"
3973 " for argument %i (%qE) of %qD...",
3974 m_arg_details.m_arg_idx + 1,
3975 m_arg_details.m_arg_expr,
3976 m_arg_details.m_called_fndecl);
3977 else
3978 return make_label_text (can_colorize,
3979 "while looking for null terminator"
3980 " for argument %i of %qD...",
3981 m_arg_details.m_arg_idx + 1,
3982 m_arg_details.m_called_fndecl);
3985 private:
3986 const call_arg_details m_arg_details;
3989 class null_terminator_check_decl_note
3990 : public pending_note_subclass<null_terminator_check_decl_note>
3992 public:
3993 null_terminator_check_decl_note (const call_arg_details &arg_details)
3994 : m_arg_details (arg_details)
3998 const char *get_kind () const final override
4000 return "null_terminator_check_decl_note";
4003 void emit () const final override
4005 inform_about_expected_null_terminated_string_arg (m_arg_details);
4008 bool operator== (const null_terminator_check_decl_note &other) const
4010 return m_arg_details == other.m_arg_details;
4013 private:
4014 const call_arg_details m_arg_details;
4017 /* Subclass of decorated_region_model_context that
4018 adds the above event and note to any saved diagnostics. */
4019 class annotating_ctxt : public annotating_context
4021 public:
4022 annotating_ctxt (const call_details &cd,
4023 unsigned arg_idx)
4024 : annotating_context (cd.get_ctxt ()),
4025 m_cd (cd),
4026 m_arg_idx (arg_idx)
4029 void add_annotations () final override
4031 call_arg_details arg_details (m_cd, m_arg_idx);
4032 event_loc_info loc_info (m_cd.get_location (),
4033 m_cd.get_model ()->get_current_function ()->decl,
4034 m_cd.get_model ()->get_stack_depth ());
4036 add_event (make_unique<null_terminator_check_event> (loc_info,
4037 arg_details));
4038 add_note (make_unique <null_terminator_check_decl_note> (arg_details));
4040 private:
4041 const call_details &m_cd;
4042 unsigned m_arg_idx;
4045 /* Use this ctxt below so that any diagnostics that get added
4046 get annotated. */
4047 annotating_ctxt my_ctxt (cd, arg_idx);
4049 const svalue *arg_sval = cd.get_arg_svalue (arg_idx);
4050 const region *buf_reg
4051 = deref_rvalue (arg_sval, cd.get_arg_tree (arg_idx), &my_ctxt);
4053 if (const svalue *num_bytes_read_sval
4054 = scan_for_null_terminator (buf_reg,
4055 cd.get_arg_tree (arg_idx),
4056 out_sval,
4057 &my_ctxt))
4059 if (include_terminator)
4060 return num_bytes_read_sval;
4061 else
4063 /* strlen is (bytes_read - 1). */
4064 const svalue *one = m_mgr->get_or_create_int_cst (size_type_node, 1);
4065 return m_mgr->get_or_create_binop (size_type_node,
4066 MINUS_EXPR,
4067 num_bytes_read_sval,
4068 one);
4071 else
4072 return nullptr;
4075 /* Remove all bindings overlapping REG within the store. */
4077 void
4078 region_model::clobber_region (const region *reg)
4080 m_store.clobber_region (m_mgr->get_store_manager(), reg);
4083 /* Remove any bindings for REG within the store. */
4085 void
4086 region_model::purge_region (const region *reg)
4088 m_store.purge_region (m_mgr->get_store_manager(), reg);
4091 /* Fill REG with SVAL.
4092 Use CTXT to report any warnings associated with the write
4093 (e.g. out-of-bounds). */
4095 void
4096 region_model::fill_region (const region *reg,
4097 const svalue *sval,
4098 region_model_context *ctxt)
4100 check_region_for_write (reg, nullptr, ctxt);
4101 m_store.fill_region (m_mgr->get_store_manager(), reg, sval);
4104 /* Zero-fill REG.
4105 Use CTXT to report any warnings associated with the write
4106 (e.g. out-of-bounds). */
4108 void
4109 region_model::zero_fill_region (const region *reg,
4110 region_model_context *ctxt)
4112 check_region_for_write (reg, nullptr, ctxt);
4113 m_store.zero_fill_region (m_mgr->get_store_manager(), reg);
4116 /* Copy NUM_BYTES_SVAL of SVAL to DEST_REG.
4117 Use CTXT to report any warnings associated with the copy
4118 (e.g. out-of-bounds writes). */
4120 void
4121 region_model::write_bytes (const region *dest_reg,
4122 const svalue *num_bytes_sval,
4123 const svalue *sval,
4124 region_model_context *ctxt)
4126 const region *sized_dest_reg
4127 = m_mgr->get_sized_region (dest_reg, NULL_TREE, num_bytes_sval);
4128 set_value (sized_dest_reg, sval, ctxt);
4131 /* Read NUM_BYTES_SVAL from SRC_REG.
4132 Use CTXT to report any warnings associated with the copy
4133 (e.g. out-of-bounds reads, copying of uninitialized values, etc). */
4135 const svalue *
4136 region_model::read_bytes (const region *src_reg,
4137 tree src_ptr_expr,
4138 const svalue *num_bytes_sval,
4139 region_model_context *ctxt) const
4141 if (num_bytes_sval->get_kind () == SK_UNKNOWN)
4142 return m_mgr->get_or_create_unknown_svalue (NULL_TREE);
4143 const region *sized_src_reg
4144 = m_mgr->get_sized_region (src_reg, NULL_TREE, num_bytes_sval);
4145 const svalue *src_contents_sval = get_store_value (sized_src_reg, ctxt);
4146 check_for_poison (src_contents_sval, src_ptr_expr,
4147 sized_src_reg, ctxt);
4148 return src_contents_sval;
4151 /* Copy NUM_BYTES_SVAL bytes from SRC_REG to DEST_REG.
4152 Use CTXT to report any warnings associated with the copy
4153 (e.g. out-of-bounds reads/writes, copying of uninitialized values,
4154 etc). */
4156 void
4157 region_model::copy_bytes (const region *dest_reg,
4158 const region *src_reg,
4159 tree src_ptr_expr,
4160 const svalue *num_bytes_sval,
4161 region_model_context *ctxt)
4163 const svalue *data_sval
4164 = read_bytes (src_reg, src_ptr_expr, num_bytes_sval, ctxt);
4165 write_bytes (dest_reg, num_bytes_sval, data_sval, ctxt);
4168 /* Mark REG as having unknown content. */
4170 void
4171 region_model::mark_region_as_unknown (const region *reg,
4172 uncertainty_t *uncertainty)
4174 svalue_set maybe_live_values;
4175 m_store.mark_region_as_unknown (m_mgr->get_store_manager(), reg,
4176 uncertainty, &maybe_live_values);
4177 m_store.on_maybe_live_values (maybe_live_values);
4180 /* Determine what is known about the condition "LHS_SVAL OP RHS_SVAL" within
4181 this model. */
4183 tristate
4184 region_model::eval_condition (const svalue *lhs,
4185 enum tree_code op,
4186 const svalue *rhs) const
4188 gcc_assert (lhs);
4189 gcc_assert (rhs);
4191 /* For now, make no attempt to capture constraints on floating-point
4192 values. */
4193 if ((lhs->get_type () && FLOAT_TYPE_P (lhs->get_type ()))
4194 || (rhs->get_type () && FLOAT_TYPE_P (rhs->get_type ())))
4195 return tristate::unknown ();
4197 /* See what we know based on the values. */
4199 /* Unwrap any unmergeable values. */
4200 lhs = lhs->unwrap_any_unmergeable ();
4201 rhs = rhs->unwrap_any_unmergeable ();
4203 if (lhs == rhs)
4205 /* If we have the same svalue, then we have equality
4206 (apart from NaN-handling).
4207 TODO: should this definitely be the case for poisoned values? */
4208 /* Poisoned and unknown values are "unknowable". */
4209 if (lhs->get_kind () == SK_POISONED
4210 || lhs->get_kind () == SK_UNKNOWN)
4211 return tristate::TS_UNKNOWN;
4213 switch (op)
4215 case EQ_EXPR:
4216 case GE_EXPR:
4217 case LE_EXPR:
4218 return tristate::TS_TRUE;
4220 case NE_EXPR:
4221 case GT_EXPR:
4222 case LT_EXPR:
4223 return tristate::TS_FALSE;
4225 default:
4226 /* For other ops, use the logic below. */
4227 break;
4231 /* If we have a pair of region_svalues, compare them. */
4232 if (const region_svalue *lhs_ptr = lhs->dyn_cast_region_svalue ())
4233 if (const region_svalue *rhs_ptr = rhs->dyn_cast_region_svalue ())
4235 tristate res = region_svalue::eval_condition (lhs_ptr, op, rhs_ptr);
4236 if (res.is_known ())
4237 return res;
4238 /* Otherwise, only known through constraints. */
4241 if (const constant_svalue *cst_lhs = lhs->dyn_cast_constant_svalue ())
4243 /* If we have a pair of constants, compare them. */
4244 if (const constant_svalue *cst_rhs = rhs->dyn_cast_constant_svalue ())
4245 return constant_svalue::eval_condition (cst_lhs, op, cst_rhs);
4246 else
4248 /* When we have one constant, put it on the RHS. */
4249 std::swap (lhs, rhs);
4250 op = swap_tree_comparison (op);
4253 gcc_assert (lhs->get_kind () != SK_CONSTANT);
4255 /* Handle comparison against zero. */
4256 if (const constant_svalue *cst_rhs = rhs->dyn_cast_constant_svalue ())
4257 if (zerop (cst_rhs->get_constant ()))
4259 if (const region_svalue *ptr = lhs->dyn_cast_region_svalue ())
4261 /* A region_svalue is a non-NULL pointer, except in certain
4262 special cases (see the comment for region::non_null_p). */
4263 const region *pointee = ptr->get_pointee ();
4264 if (pointee->non_null_p ())
4266 switch (op)
4268 default:
4269 gcc_unreachable ();
4271 case EQ_EXPR:
4272 case GE_EXPR:
4273 case LE_EXPR:
4274 return tristate::TS_FALSE;
4276 case NE_EXPR:
4277 case GT_EXPR:
4278 case LT_EXPR:
4279 return tristate::TS_TRUE;
4283 else if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4285 /* Treat offsets from a non-NULL pointer as being non-NULL. This
4286 isn't strictly true, in that eventually ptr++ will wrap
4287 around and be NULL, but it won't occur in practise and thus
4288 can be used to suppress effectively false positives that we
4289 shouldn't warn for. */
4290 if (binop->get_op () == POINTER_PLUS_EXPR)
4292 tristate lhs_ts = eval_condition (binop->get_arg0 (), op, rhs);
4293 if (lhs_ts.is_known ())
4294 return lhs_ts;
4297 else if (const unaryop_svalue *unaryop
4298 = lhs->dyn_cast_unaryop_svalue ())
4300 if (unaryop->get_op () == NEGATE_EXPR)
4302 /* e.g. "-X <= 0" is equivalent to X >= 0". */
4303 tristate lhs_ts = eval_condition (unaryop->get_arg (),
4304 swap_tree_comparison (op),
4305 rhs);
4306 if (lhs_ts.is_known ())
4307 return lhs_ts;
4312 /* Handle rejection of equality for comparisons of the initial values of
4313 "external" values (such as params) with the address of locals. */
4314 if (const initial_svalue *init_lhs = lhs->dyn_cast_initial_svalue ())
4315 if (const region_svalue *rhs_ptr = rhs->dyn_cast_region_svalue ())
4317 tristate res = compare_initial_and_pointer (init_lhs, rhs_ptr);
4318 if (res.is_known ())
4319 return res;
4321 if (const initial_svalue *init_rhs = rhs->dyn_cast_initial_svalue ())
4322 if (const region_svalue *lhs_ptr = lhs->dyn_cast_region_svalue ())
4324 tristate res = compare_initial_and_pointer (init_rhs, lhs_ptr);
4325 if (res.is_known ())
4326 return res;
4329 if (const widening_svalue *widen_lhs = lhs->dyn_cast_widening_svalue ())
4330 if (tree rhs_cst = rhs->maybe_get_constant ())
4332 tristate res = widen_lhs->eval_condition_without_cm (op, rhs_cst);
4333 if (res.is_known ())
4334 return res;
4337 /* Handle comparisons between two svalues with more than one operand. */
4338 if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4340 switch (op)
4342 default:
4343 break;
4344 case EQ_EXPR:
4346 /* TODO: binops can be equal even if they are not structurally
4347 equal in case of commutative operators. */
4348 tristate res = structural_equality (lhs, rhs);
4349 if (res.is_true ())
4350 return res;
4352 break;
4353 case LE_EXPR:
4355 tristate res = structural_equality (lhs, rhs);
4356 if (res.is_true ())
4357 return res;
4359 break;
4360 case GE_EXPR:
4362 tristate res = structural_equality (lhs, rhs);
4363 if (res.is_true ())
4364 return res;
4365 res = symbolic_greater_than (binop, rhs);
4366 if (res.is_true ())
4367 return res;
4369 break;
4370 case GT_EXPR:
4372 tristate res = symbolic_greater_than (binop, rhs);
4373 if (res.is_true ())
4374 return res;
4376 break;
4380 /* Attempt to unwrap cast if there is one, and the types match. */
4381 tree lhs_type = lhs->get_type ();
4382 tree rhs_type = rhs->get_type ();
4383 if (lhs_type && rhs_type)
4385 const unaryop_svalue *lhs_un_op = dyn_cast <const unaryop_svalue *> (lhs);
4386 const unaryop_svalue *rhs_un_op = dyn_cast <const unaryop_svalue *> (rhs);
4387 if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
4388 && rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
4389 && lhs_type == rhs_type)
4390 return eval_condition (lhs_un_op->get_arg (),
4392 rhs_un_op->get_arg ());
4394 else if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
4395 && lhs_type == rhs_type)
4396 return eval_condition (lhs_un_op->get_arg (), op, rhs);
4398 else if (rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
4399 && lhs_type == rhs_type)
4400 return eval_condition (lhs, op, rhs_un_op->get_arg ());
4403 /* Otherwise, try constraints.
4404 Cast to const to ensure we don't change the constraint_manager as we
4405 do this (e.g. by creating equivalence classes). */
4406 const constraint_manager *constraints = m_constraints;
4407 return constraints->eval_condition (lhs, op, rhs);
4410 /* Subroutine of region_model::eval_condition, for rejecting
4411 equality of INIT_VAL(PARM) with &LOCAL. */
4413 tristate
4414 region_model::compare_initial_and_pointer (const initial_svalue *init,
4415 const region_svalue *ptr) const
4417 const region *pointee = ptr->get_pointee ();
4419 /* If we have a pointer to something within a stack frame, it can't be the
4420 initial value of a param. */
4421 if (pointee->maybe_get_frame_region ())
4422 if (init->initial_value_of_param_p ())
4423 return tristate::TS_FALSE;
4425 return tristate::TS_UNKNOWN;
4428 /* Return true if SVAL is definitely positive. */
4430 static bool
4431 is_positive_svalue (const svalue *sval)
4433 if (tree cst = sval->maybe_get_constant ())
4434 return !zerop (cst) && get_range_pos_neg (cst) == 1;
4435 tree type = sval->get_type ();
4436 if (!type)
4437 return false;
4438 /* Consider a binary operation size_t + int. The analyzer wraps the int in
4439 an unaryop_svalue, converting it to a size_t, but in the dynamic execution
4440 the result is smaller than the first operand. Thus, we have to look if
4441 the argument of the unaryop_svalue is also positive. */
4442 if (const unaryop_svalue *un_op = dyn_cast <const unaryop_svalue *> (sval))
4443 return CONVERT_EXPR_CODE_P (un_op->get_op ()) && TYPE_UNSIGNED (type)
4444 && is_positive_svalue (un_op->get_arg ());
4445 return TYPE_UNSIGNED (type);
4448 /* Return true if A is definitely larger than B.
4450 Limitation: does not account for integer overflows and does not try to
4451 return false, so it can not be used negated. */
4453 tristate
4454 region_model::symbolic_greater_than (const binop_svalue *bin_a,
4455 const svalue *b) const
4457 if (bin_a->get_op () == PLUS_EXPR || bin_a->get_op () == MULT_EXPR)
4459 /* Eliminate the right-hand side of both svalues. */
4460 if (const binop_svalue *bin_b = dyn_cast <const binop_svalue *> (b))
4461 if (bin_a->get_op () == bin_b->get_op ()
4462 && eval_condition (bin_a->get_arg1 (),
4463 GT_EXPR,
4464 bin_b->get_arg1 ()).is_true ()
4465 && eval_condition (bin_a->get_arg0 (),
4466 GE_EXPR,
4467 bin_b->get_arg0 ()).is_true ())
4468 return tristate (tristate::TS_TRUE);
4470 /* Otherwise, try to remove a positive offset or factor from BIN_A. */
4471 if (is_positive_svalue (bin_a->get_arg1 ())
4472 && eval_condition (bin_a->get_arg0 (),
4473 GE_EXPR, b).is_true ())
4474 return tristate (tristate::TS_TRUE);
4476 return tristate::unknown ();
4479 /* Return true if A and B are equal structurally.
4481 Structural equality means that A and B are equal if the svalues A and B have
4482 the same nodes at the same positions in the tree and the leafs are equal.
4483 Equality for conjured_svalues and initial_svalues is determined by comparing
4484 the pointers while constants are compared by value. That behavior is useful
4485 to check for binaryop_svlaues that evaluate to the same concrete value but
4486 might use one operand with a different type but the same constant value.
4488 For example,
4489 binop_svalue (mult_expr,
4490 initial_svalue (‘size_t’, decl_region (..., 'some_var')),
4491 constant_svalue (‘size_t’, 4))
4493 binop_svalue (mult_expr,
4494 initial_svalue (‘size_t’, decl_region (..., 'some_var'),
4495 constant_svalue (‘sizetype’, 4))
4496 are structurally equal. A concrete C code example, where this occurs, can
4497 be found in test7 of out-of-bounds-5.c. */
4499 tristate
4500 region_model::structural_equality (const svalue *a, const svalue *b) const
4502 /* If A and B are referentially equal, they are also structurally equal. */
4503 if (a == b)
4504 return tristate (tristate::TS_TRUE);
4506 switch (a->get_kind ())
4508 default:
4509 return tristate::unknown ();
4510 /* SK_CONJURED and SK_INITIAL are already handled
4511 by the referential equality above. */
4512 case SK_CONSTANT:
4514 tree a_cst = a->maybe_get_constant ();
4515 tree b_cst = b->maybe_get_constant ();
4516 if (a_cst && b_cst)
4517 return tristate (tree_int_cst_equal (a_cst, b_cst));
4519 return tristate (tristate::TS_FALSE);
4520 case SK_UNARYOP:
4522 const unaryop_svalue *un_a = as_a <const unaryop_svalue *> (a);
4523 if (const unaryop_svalue *un_b = dyn_cast <const unaryop_svalue *> (b))
4524 return tristate (pending_diagnostic::same_tree_p (un_a->get_type (),
4525 un_b->get_type ())
4526 && un_a->get_op () == un_b->get_op ()
4527 && structural_equality (un_a->get_arg (),
4528 un_b->get_arg ()));
4530 return tristate (tristate::TS_FALSE);
4531 case SK_BINOP:
4533 const binop_svalue *bin_a = as_a <const binop_svalue *> (a);
4534 if (const binop_svalue *bin_b = dyn_cast <const binop_svalue *> (b))
4535 return tristate (bin_a->get_op () == bin_b->get_op ()
4536 && structural_equality (bin_a->get_arg0 (),
4537 bin_b->get_arg0 ())
4538 && structural_equality (bin_a->get_arg1 (),
4539 bin_b->get_arg1 ()));
4541 return tristate (tristate::TS_FALSE);
4545 /* Handle various constraints of the form:
4546 LHS: ((bool)INNER_LHS INNER_OP INNER_RHS))
4547 OP : == or !=
4548 RHS: zero
4549 and (with a cast):
4550 LHS: CAST([long]int, ((bool)INNER_LHS INNER_OP INNER_RHS))
4551 OP : == or !=
4552 RHS: zero
4553 by adding constraints for INNER_LHS INNEROP INNER_RHS.
4555 Return true if this function can fully handle the constraint; if
4556 so, add the implied constraint(s) and write true to *OUT if they
4557 are consistent with existing constraints, or write false to *OUT
4558 if they contradicts existing constraints.
4560 Return false for cases that this function doeesn't know how to handle.
4562 For example, if we're checking a stored conditional, we'll have
4563 something like:
4564 LHS: CAST(long int, (&HEAP_ALLOCATED_REGION(8)!=(int *)0B))
4565 OP : NE_EXPR
4566 RHS: zero
4567 which this function can turn into an add_constraint of:
4568 (&HEAP_ALLOCATED_REGION(8) != (int *)0B)
4570 Similarly, optimized && and || conditionals lead to e.g.
4571 if (p && q)
4572 becoming gimple like this:
4573 _1 = p_6 == 0B;
4574 _2 = q_8 == 0B
4575 _3 = _1 | _2
4576 On the "_3 is false" branch we can have constraints of the form:
4577 ((&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
4578 | (&HEAP_ALLOCATED_REGION(10)!=(int *)0B))
4579 == 0
4580 which implies that both _1 and _2 are false,
4581 which this function can turn into a pair of add_constraints of
4582 (&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
4583 and:
4584 (&HEAP_ALLOCATED_REGION(10)!=(int *)0B). */
4586 bool
4587 region_model::add_constraints_from_binop (const svalue *outer_lhs,
4588 enum tree_code outer_op,
4589 const svalue *outer_rhs,
4590 bool *out,
4591 region_model_context *ctxt)
4593 while (const svalue *cast = outer_lhs->maybe_undo_cast ())
4594 outer_lhs = cast;
4595 const binop_svalue *binop_sval = outer_lhs->dyn_cast_binop_svalue ();
4596 if (!binop_sval)
4597 return false;
4598 if (!outer_rhs->all_zeroes_p ())
4599 return false;
4601 const svalue *inner_lhs = binop_sval->get_arg0 ();
4602 enum tree_code inner_op = binop_sval->get_op ();
4603 const svalue *inner_rhs = binop_sval->get_arg1 ();
4605 if (outer_op != NE_EXPR && outer_op != EQ_EXPR)
4606 return false;
4608 /* We have either
4609 - "OUTER_LHS != false" (i.e. OUTER is true), or
4610 - "OUTER_LHS == false" (i.e. OUTER is false). */
4611 bool is_true = outer_op == NE_EXPR;
4613 switch (inner_op)
4615 default:
4616 return false;
4618 case EQ_EXPR:
4619 case NE_EXPR:
4620 case GE_EXPR:
4621 case GT_EXPR:
4622 case LE_EXPR:
4623 case LT_EXPR:
4625 /* ...and "(inner_lhs OP inner_rhs) == 0"
4626 then (inner_lhs OP inner_rhs) must have the same
4627 logical value as LHS. */
4628 if (!is_true)
4629 inner_op = invert_tree_comparison (inner_op, false /* honor_nans */);
4630 *out = add_constraint (inner_lhs, inner_op, inner_rhs, ctxt);
4631 return true;
4633 break;
4635 case BIT_AND_EXPR:
4636 if (is_true)
4638 /* ...and "(inner_lhs & inner_rhs) != 0"
4639 then both inner_lhs and inner_rhs must be true. */
4640 const svalue *false_sval
4641 = m_mgr->get_or_create_constant_svalue (boolean_false_node);
4642 bool sat1 = add_constraint (inner_lhs, NE_EXPR, false_sval, ctxt);
4643 bool sat2 = add_constraint (inner_rhs, NE_EXPR, false_sval, ctxt);
4644 *out = sat1 && sat2;
4645 return true;
4647 return false;
4649 case BIT_IOR_EXPR:
4650 if (!is_true)
4652 /* ...and "(inner_lhs | inner_rhs) == 0"
4653 i.e. "(inner_lhs | inner_rhs)" is false
4654 then both inner_lhs and inner_rhs must be false. */
4655 const svalue *false_sval
4656 = m_mgr->get_or_create_constant_svalue (boolean_false_node);
4657 bool sat1 = add_constraint (inner_lhs, EQ_EXPR, false_sval, ctxt);
4658 bool sat2 = add_constraint (inner_rhs, EQ_EXPR, false_sval, ctxt);
4659 *out = sat1 && sat2;
4660 return true;
4662 return false;
4666 /* Attempt to add the constraint "LHS OP RHS" to this region_model.
4667 If it is consistent with existing constraints, add it, and return true.
4668 Return false if it contradicts existing constraints.
4669 Use CTXT for reporting any diagnostics associated with the accesses. */
4671 bool
4672 region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
4673 region_model_context *ctxt)
4675 /* For now, make no attempt to capture constraints on floating-point
4676 values. */
4677 if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
4678 return true;
4680 const svalue *lhs_sval = get_rvalue (lhs, ctxt);
4681 const svalue *rhs_sval = get_rvalue (rhs, ctxt);
4683 return add_constraint (lhs_sval, op, rhs_sval, ctxt);
4686 static bool
4687 unusable_in_infinite_loop_constraint_p (const svalue *sval)
4689 if (sval->get_kind () == SK_WIDENING)
4690 return true;
4691 return false;
4694 /* Attempt to add the constraint "LHS OP RHS" to this region_model.
4695 If it is consistent with existing constraints, add it, and return true.
4696 Return false if it contradicts existing constraints.
4697 Use CTXT for reporting any diagnostics associated with the accesses. */
4699 bool
4700 region_model::add_constraint (const svalue *lhs,
4701 enum tree_code op,
4702 const svalue *rhs,
4703 region_model_context *ctxt)
4705 const bool checking_for_infinite_loop
4706 = ctxt ? ctxt->checking_for_infinite_loop_p () : false;
4708 if (checking_for_infinite_loop)
4710 if (unusable_in_infinite_loop_constraint_p (lhs)
4711 || unusable_in_infinite_loop_constraint_p (rhs))
4713 gcc_assert (ctxt);
4714 ctxt->on_unusable_in_infinite_loop ();
4715 return false;
4719 tristate t_cond = eval_condition (lhs, op, rhs);
4721 /* If we already have the condition, do nothing. */
4722 if (t_cond.is_true ())
4723 return true;
4725 /* Reject a constraint that would contradict existing knowledge, as
4726 unsatisfiable. */
4727 if (t_cond.is_false ())
4728 return false;
4730 if (checking_for_infinite_loop)
4732 /* Here, we don't have a definite true/false value, so bail out
4733 when checking for infinite loops. */
4734 gcc_assert (ctxt);
4735 ctxt->on_unusable_in_infinite_loop ();
4736 return false;
4739 bool out;
4740 if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt))
4741 return out;
4743 /* Attempt to store the constraint. */
4744 if (!m_constraints->add_constraint (lhs, op, rhs))
4745 return false;
4747 /* Notify the context, if any. This exists so that the state machines
4748 in a program_state can be notified about the condition, and so can
4749 set sm-state for e.g. unchecked->checked, both for cfg-edges, and
4750 when synthesizing constraints as above. */
4751 if (ctxt)
4752 ctxt->on_condition (lhs, op, rhs);
4754 /* If we have &REGION == NULL, then drop dynamic extents for REGION (for
4755 the case where REGION is heap-allocated and thus could be NULL). */
4756 if (tree rhs_cst = rhs->maybe_get_constant ())
4757 if (op == EQ_EXPR && zerop (rhs_cst))
4758 if (const region_svalue *region_sval = lhs->dyn_cast_region_svalue ())
4759 unset_dynamic_extents (region_sval->get_pointee ());
4761 return true;
4764 /* As above, but when returning false, if OUT is non-NULL, write a
4765 new rejected_constraint to *OUT. */
4767 bool
4768 region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
4769 region_model_context *ctxt,
4770 std::unique_ptr<rejected_constraint> *out)
4772 bool sat = add_constraint (lhs, op, rhs, ctxt);
4773 if (!sat && out)
4774 *out = make_unique <rejected_op_constraint> (*this, lhs, op, rhs);
4775 return sat;
4778 /* Determine what is known about the condition "LHS OP RHS" within
4779 this model.
4780 Use CTXT for reporting any diagnostics associated with the accesses. */
4782 tristate
4783 region_model::eval_condition (tree lhs,
4784 enum tree_code op,
4785 tree rhs,
4786 region_model_context *ctxt) const
4788 /* For now, make no attempt to model constraints on floating-point
4789 values. */
4790 if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
4791 return tristate::unknown ();
4793 return eval_condition (get_rvalue (lhs, ctxt), op, get_rvalue (rhs, ctxt));
4796 /* Implementation of region_model::get_representative_path_var.
4797 Attempt to return a path_var that represents SVAL, or return NULL_TREE.
4798 Use VISITED to prevent infinite mutual recursion with the overload for
4799 regions. */
4801 path_var
4802 region_model::get_representative_path_var_1 (const svalue *sval,
4803 svalue_set *visited) const
4805 gcc_assert (sval);
4807 /* Prevent infinite recursion. */
4808 if (visited->contains (sval))
4810 if (sval->get_kind () == SK_CONSTANT)
4811 return path_var (sval->maybe_get_constant (), 0);
4812 else
4813 return path_var (NULL_TREE, 0);
4815 visited->add (sval);
4817 /* Handle casts by recursion into get_representative_path_var. */
4818 if (const svalue *cast_sval = sval->maybe_undo_cast ())
4820 path_var result = get_representative_path_var (cast_sval, visited);
4821 tree orig_type = sval->get_type ();
4822 /* If necessary, wrap the result in a cast. */
4823 if (result.m_tree && orig_type)
4824 result.m_tree = build1 (NOP_EXPR, orig_type, result.m_tree);
4825 return result;
4828 auto_vec<path_var> pvs;
4829 m_store.get_representative_path_vars (this, visited, sval, &pvs);
4831 if (tree cst = sval->maybe_get_constant ())
4832 pvs.safe_push (path_var (cst, 0));
4834 /* Handle string literals and various other pointers. */
4835 if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
4837 const region *reg = ptr_sval->get_pointee ();
4838 if (path_var pv = get_representative_path_var (reg, visited))
4839 return path_var (build1 (ADDR_EXPR,
4840 sval->get_type (),
4841 pv.m_tree),
4842 pv.m_stack_depth);
4845 /* If we have a sub_svalue, look for ways to represent the parent. */
4846 if (const sub_svalue *sub_sval = sval->dyn_cast_sub_svalue ())
4848 const svalue *parent_sval = sub_sval->get_parent ();
4849 const region *subreg = sub_sval->get_subregion ();
4850 if (path_var parent_pv
4851 = get_representative_path_var (parent_sval, visited))
4852 if (const field_region *field_reg = subreg->dyn_cast_field_region ())
4853 return path_var (build3 (COMPONENT_REF,
4854 sval->get_type (),
4855 parent_pv.m_tree,
4856 field_reg->get_field (),
4857 NULL_TREE),
4858 parent_pv.m_stack_depth);
4861 /* Handle binops. */
4862 if (const binop_svalue *binop_sval = sval->dyn_cast_binop_svalue ())
4863 if (path_var lhs_pv
4864 = get_representative_path_var (binop_sval->get_arg0 (), visited))
4865 if (path_var rhs_pv
4866 = get_representative_path_var (binop_sval->get_arg1 (), visited))
4867 return path_var (build2 (binop_sval->get_op (),
4868 sval->get_type (),
4869 lhs_pv.m_tree, rhs_pv.m_tree),
4870 lhs_pv.m_stack_depth);
4872 if (pvs.length () < 1)
4873 return path_var (NULL_TREE, 0);
4875 pvs.qsort (readability_comparator);
4876 return pvs[0];
4879 /* Attempt to return a path_var that represents SVAL, or return NULL_TREE.
4880 Use VISITED to prevent infinite mutual recursion with the overload for
4881 regions
4883 This function defers to get_representative_path_var_1 to do the work;
4884 it adds verification that get_representative_path_var_1 returned a tree
4885 of the correct type. */
4887 path_var
4888 region_model::get_representative_path_var (const svalue *sval,
4889 svalue_set *visited) const
4891 if (sval == NULL)
4892 return path_var (NULL_TREE, 0);
4894 tree orig_type = sval->get_type ();
4896 path_var result = get_representative_path_var_1 (sval, visited);
4898 /* Verify that the result has the same type as SVAL, if any. */
4899 if (result.m_tree && orig_type)
4900 gcc_assert (TREE_TYPE (result.m_tree) == orig_type);
4902 return result;
4905 /* Attempt to return a tree that represents SVAL, or return NULL_TREE.
4907 Strip off any top-level cast, to avoid messages like
4908 double-free of '(void *)ptr'
4909 from analyzer diagnostics. */
4911 tree
4912 region_model::get_representative_tree (const svalue *sval) const
4914 svalue_set visited;
4915 tree expr = get_representative_path_var (sval, &visited).m_tree;
4917 /* Strip off any top-level cast. */
4918 if (expr && TREE_CODE (expr) == NOP_EXPR)
4919 expr = TREE_OPERAND (expr, 0);
4921 return fixup_tree_for_diagnostic (expr);
4924 tree
4925 region_model::get_representative_tree (const region *reg) const
4927 svalue_set visited;
4928 tree expr = get_representative_path_var (reg, &visited).m_tree;
4930 /* Strip off any top-level cast. */
4931 if (expr && TREE_CODE (expr) == NOP_EXPR)
4932 expr = TREE_OPERAND (expr, 0);
4934 return fixup_tree_for_diagnostic (expr);
4937 /* Implementation of region_model::get_representative_path_var.
4939 Attempt to return a path_var that represents REG, or return
4940 the NULL path_var.
4941 For example, a region for a field of a local would be a path_var
4942 wrapping a COMPONENT_REF.
4943 Use VISITED to prevent infinite mutual recursion with the overload for
4944 svalues. */
4946 path_var
4947 region_model::get_representative_path_var_1 (const region *reg,
4948 svalue_set *visited) const
4950 switch (reg->get_kind ())
4952 default:
4953 gcc_unreachable ();
4955 case RK_FRAME:
4956 case RK_GLOBALS:
4957 case RK_CODE:
4958 case RK_HEAP:
4959 case RK_STACK:
4960 case RK_THREAD_LOCAL:
4961 case RK_ROOT:
4962 /* Regions that represent memory spaces are not expressible as trees. */
4963 return path_var (NULL_TREE, 0);
4965 case RK_FUNCTION:
4967 const function_region *function_reg
4968 = as_a <const function_region *> (reg);
4969 return path_var (function_reg->get_fndecl (), 0);
4971 case RK_LABEL:
4973 const label_region *label_reg = as_a <const label_region *> (reg);
4974 return path_var (label_reg->get_label (), 0);
4977 case RK_SYMBOLIC:
4979 const symbolic_region *symbolic_reg
4980 = as_a <const symbolic_region *> (reg);
4981 const svalue *pointer = symbolic_reg->get_pointer ();
4982 path_var pointer_pv = get_representative_path_var (pointer, visited);
4983 if (!pointer_pv)
4984 return path_var (NULL_TREE, 0);
4985 tree offset = build_int_cst (pointer->get_type (), 0);
4986 return path_var (build2 (MEM_REF,
4987 reg->get_type (),
4988 pointer_pv.m_tree,
4989 offset),
4990 pointer_pv.m_stack_depth);
4992 case RK_DECL:
4994 const decl_region *decl_reg = as_a <const decl_region *> (reg);
4995 return path_var (decl_reg->get_decl (), decl_reg->get_stack_depth ());
4997 case RK_FIELD:
4999 const field_region *field_reg = as_a <const field_region *> (reg);
5000 path_var parent_pv
5001 = get_representative_path_var (reg->get_parent_region (), visited);
5002 if (!parent_pv)
5003 return path_var (NULL_TREE, 0);
5004 return path_var (build3 (COMPONENT_REF,
5005 reg->get_type (),
5006 parent_pv.m_tree,
5007 field_reg->get_field (),
5008 NULL_TREE),
5009 parent_pv.m_stack_depth);
5012 case RK_ELEMENT:
5014 const element_region *element_reg
5015 = as_a <const element_region *> (reg);
5016 path_var parent_pv
5017 = get_representative_path_var (reg->get_parent_region (), visited);
5018 if (!parent_pv)
5019 return path_var (NULL_TREE, 0);
5020 path_var index_pv
5021 = get_representative_path_var (element_reg->get_index (), visited);
5022 if (!index_pv)
5023 return path_var (NULL_TREE, 0);
5024 return path_var (build4 (ARRAY_REF,
5025 reg->get_type (),
5026 parent_pv.m_tree, index_pv.m_tree,
5027 NULL_TREE, NULL_TREE),
5028 parent_pv.m_stack_depth);
5031 case RK_OFFSET:
5033 const offset_region *offset_reg
5034 = as_a <const offset_region *> (reg);
5035 path_var parent_pv
5036 = get_representative_path_var (reg->get_parent_region (), visited);
5037 if (!parent_pv)
5038 return path_var (NULL_TREE, 0);
5039 path_var offset_pv
5040 = get_representative_path_var (offset_reg->get_byte_offset (),
5041 visited);
5042 if (!offset_pv || TREE_CODE (offset_pv.m_tree) != INTEGER_CST)
5043 return path_var (NULL_TREE, 0);
5044 tree addr_parent = build1 (ADDR_EXPR,
5045 build_pointer_type (reg->get_type ()),
5046 parent_pv.m_tree);
5047 return path_var (build2 (MEM_REF,
5048 reg->get_type (),
5049 addr_parent, offset_pv.m_tree),
5050 parent_pv.m_stack_depth);
5053 case RK_SIZED:
5054 return path_var (NULL_TREE, 0);
5056 case RK_CAST:
5058 path_var parent_pv
5059 = get_representative_path_var (reg->get_parent_region (), visited);
5060 if (!parent_pv)
5061 return path_var (NULL_TREE, 0);
5062 return path_var (build1 (NOP_EXPR,
5063 reg->get_type (),
5064 parent_pv.m_tree),
5065 parent_pv.m_stack_depth);
5068 case RK_HEAP_ALLOCATED:
5069 case RK_ALLOCA:
5070 /* No good way to express heap-allocated/alloca regions as trees. */
5071 return path_var (NULL_TREE, 0);
5073 case RK_STRING:
5075 const string_region *string_reg = as_a <const string_region *> (reg);
5076 return path_var (string_reg->get_string_cst (), 0);
5079 case RK_VAR_ARG:
5080 case RK_ERRNO:
5081 case RK_UNKNOWN:
5082 case RK_PRIVATE:
5083 return path_var (NULL_TREE, 0);
5087 /* Attempt to return a path_var that represents REG, or return
5088 the NULL path_var.
5089 For example, a region for a field of a local would be a path_var
5090 wrapping a COMPONENT_REF.
5091 Use VISITED to prevent infinite mutual recursion with the overload for
5092 svalues.
5094 This function defers to get_representative_path_var_1 to do the work;
5095 it adds verification that get_representative_path_var_1 returned a tree
5096 of the correct type. */
5098 path_var
5099 region_model::get_representative_path_var (const region *reg,
5100 svalue_set *visited) const
5102 path_var result = get_representative_path_var_1 (reg, visited);
5104 /* Verify that the result has the same type as REG, if any. */
5105 if (result.m_tree && reg->get_type ())
5106 gcc_assert (TREE_TYPE (result.m_tree) == reg->get_type ());
5108 return result;
5111 /* Update this model for any phis in SNODE, assuming we came from
5112 LAST_CFG_SUPEREDGE. */
5114 void
5115 region_model::update_for_phis (const supernode *snode,
5116 const cfg_superedge *last_cfg_superedge,
5117 region_model_context *ctxt)
5119 gcc_assert (last_cfg_superedge);
5121 /* Copy this state and pass it to handle_phi so that all of the phi stmts
5122 are effectively handled simultaneously. */
5123 const region_model old_state (*this);
5125 hash_set<const svalue *> svals_changing_meaning;
5127 for (gphi_iterator gpi = const_cast<supernode *>(snode)->start_phis ();
5128 !gsi_end_p (gpi); gsi_next (&gpi))
5130 gphi *phi = gpi.phi ();
5132 tree src = last_cfg_superedge->get_phi_arg (phi);
5133 tree lhs = gimple_phi_result (phi);
5135 /* Update next_state based on phi and old_state. */
5136 handle_phi (phi, lhs, src, old_state, svals_changing_meaning, ctxt);
5139 for (auto iter : svals_changing_meaning)
5140 m_constraints->purge_state_involving (iter);
5143 /* Attempt to update this model for taking EDGE (where the last statement
5144 was LAST_STMT), returning true if the edge can be taken, false
5145 otherwise.
5146 When returning false, if OUT is non-NULL, write a new rejected_constraint
5147 to it.
5149 For CFG superedges where LAST_STMT is a conditional or a switch
5150 statement, attempt to add the relevant conditions for EDGE to this
5151 model, returning true if they are feasible, or false if they are
5152 impossible.
5154 For call superedges, push frame information and store arguments
5155 into parameters.
5157 For return superedges, pop frame information and store return
5158 values into any lhs.
5160 Rejection of call/return superedges happens elsewhere, in
5161 program_point::on_edge (i.e. based on program point, rather
5162 than program state). */
5164 bool
5165 region_model::maybe_update_for_edge (const superedge &edge,
5166 const gimple *last_stmt,
5167 region_model_context *ctxt,
5168 std::unique_ptr<rejected_constraint> *out)
5170 /* Handle frame updates for interprocedural edges. */
5171 switch (edge.m_kind)
5173 default:
5174 break;
5176 case SUPEREDGE_CALL:
5178 const call_superedge *call_edge = as_a <const call_superedge *> (&edge);
5179 update_for_call_superedge (*call_edge, ctxt);
5181 break;
5183 case SUPEREDGE_RETURN:
5185 const return_superedge *return_edge
5186 = as_a <const return_superedge *> (&edge);
5187 update_for_return_superedge (*return_edge, ctxt);
5189 break;
5191 case SUPEREDGE_INTRAPROCEDURAL_CALL:
5192 /* This is a no-op for call summaries; we should already
5193 have handled the effect of the call summary at the call stmt. */
5194 break;
5197 if (last_stmt == NULL)
5198 return true;
5200 /* Apply any constraints for conditionals/switch/computed-goto statements. */
5202 if (const gcond *cond_stmt = dyn_cast <const gcond *> (last_stmt))
5204 const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (&edge);
5205 return apply_constraints_for_gcond (*cfg_sedge, cond_stmt, ctxt, out);
5208 if (const gswitch *switch_stmt = dyn_cast <const gswitch *> (last_stmt))
5210 const switch_cfg_superedge *switch_sedge
5211 = as_a <const switch_cfg_superedge *> (&edge);
5212 return apply_constraints_for_gswitch (*switch_sedge, switch_stmt,
5213 ctxt, out);
5216 if (const ggoto *goto_stmt = dyn_cast <const ggoto *> (last_stmt))
5218 const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (&edge);
5219 return apply_constraints_for_ggoto (*cfg_sedge, goto_stmt, ctxt);
5222 /* Apply any constraints due to an exception being thrown. */
5223 if (const cfg_superedge *cfg_sedge = dyn_cast <const cfg_superedge *> (&edge))
5224 if (cfg_sedge->get_flags () & EDGE_EH)
5225 return apply_constraints_for_exception (last_stmt, ctxt, out);
5227 return true;
5230 /* Push a new frame_region on to the stack region.
5231 Populate the frame_region with child regions for the function call's
5232 parameters, using values from the arguments at the callsite in the
5233 caller's frame. */
5235 void
5236 region_model::update_for_gcall (const gcall *call_stmt,
5237 region_model_context *ctxt,
5238 function *callee)
5240 /* Build a vec of argument svalues, using the current top
5241 frame for resolving tree expressions. */
5242 auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt));
5244 for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
5246 tree arg = gimple_call_arg (call_stmt, i);
5247 arg_svals.quick_push (get_rvalue (arg, ctxt));
5250 if(!callee)
5252 /* Get the function * from the gcall. */
5253 tree fn_decl = get_fndecl_for_call (call_stmt,ctxt);
5254 callee = DECL_STRUCT_FUNCTION (fn_decl);
5257 push_frame (callee, &arg_svals, ctxt);
5260 /* Pop the top-most frame_region from the stack, and copy the return
5261 region's values (if any) into the region for the lvalue of the LHS of
5262 the call (if any). */
5264 void
5265 region_model::update_for_return_gcall (const gcall *call_stmt,
5266 region_model_context *ctxt)
5268 /* Get the lvalue for the result of the call, passing it to pop_frame,
5269 so that pop_frame can determine the region with respect to the
5270 *caller* frame. */
5271 tree lhs = gimple_call_lhs (call_stmt);
5272 pop_frame (lhs, NULL, ctxt);
5275 /* Extract calling information from the superedge and update the model for the
5276 call */
5278 void
5279 region_model::update_for_call_superedge (const call_superedge &call_edge,
5280 region_model_context *ctxt)
5282 const gcall *call_stmt = call_edge.get_call_stmt ();
5283 update_for_gcall (call_stmt, ctxt, call_edge.get_callee_function ());
5286 /* Extract calling information from the return superedge and update the model
5287 for the returning call */
5289 void
5290 region_model::update_for_return_superedge (const return_superedge &return_edge,
5291 region_model_context *ctxt)
5293 const gcall *call_stmt = return_edge.get_call_stmt ();
5294 update_for_return_gcall (call_stmt, ctxt);
5297 /* Attempt to to use R to replay SUMMARY into this object.
5298 Return true if it is possible. */
5300 bool
5301 region_model::replay_call_summary (call_summary_replay &r,
5302 const region_model &summary)
5304 gcc_assert (summary.get_stack_depth () == 1);
5306 m_store.replay_call_summary (r, summary.m_store);
5308 if (r.get_ctxt ())
5309 r.get_ctxt ()->maybe_did_work ();
5311 if (!m_constraints->replay_call_summary (r, *summary.m_constraints))
5312 return false;
5314 for (auto kv : summary.m_dynamic_extents)
5316 const region *summary_reg = kv.first;
5317 const region *caller_reg = r.convert_region_from_summary (summary_reg);
5318 if (!caller_reg)
5319 continue;
5320 const svalue *summary_sval = kv.second;
5321 const svalue *caller_sval = r.convert_svalue_from_summary (summary_sval);
5322 if (!caller_sval)
5323 continue;
5324 m_dynamic_extents.put (caller_reg, caller_sval);
5327 return true;
5330 /* Given a true or false edge guarded by conditional statement COND_STMT,
5331 determine appropriate constraints for the edge to be taken.
5333 If they are feasible, add the constraints and return true.
5335 Return false if the constraints contradict existing knowledge
5336 (and so the edge should not be taken).
5337 When returning false, if OUT is non-NULL, write a new rejected_constraint
5338 to it. */
5340 bool
5341 region_model::
5342 apply_constraints_for_gcond (const cfg_superedge &sedge,
5343 const gcond *cond_stmt,
5344 region_model_context *ctxt,
5345 std::unique_ptr<rejected_constraint> *out)
5347 ::edge cfg_edge = sedge.get_cfg_edge ();
5348 gcc_assert (cfg_edge != NULL);
5349 gcc_assert (cfg_edge->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE));
5351 enum tree_code op = gimple_cond_code (cond_stmt);
5352 tree lhs = gimple_cond_lhs (cond_stmt);
5353 tree rhs = gimple_cond_rhs (cond_stmt);
5354 if (cfg_edge->flags & EDGE_FALSE_VALUE)
5355 op = invert_tree_comparison (op, false /* honor_nans */);
5356 return add_constraint (lhs, op, rhs, ctxt, out);
5359 /* Return true iff SWITCH_STMT has a non-default label that contains
5360 INT_CST. */
5362 static bool
5363 has_nondefault_case_for_value_p (const gswitch *switch_stmt, tree int_cst)
5365 /* We expect the initial label to be the default; skip it. */
5366 gcc_assert (CASE_LOW (gimple_switch_label (switch_stmt, 0)) == NULL);
5367 unsigned min_idx = 1;
5368 unsigned max_idx = gimple_switch_num_labels (switch_stmt) - 1;
5370 /* Binary search: try to find the label containing INT_CST.
5371 This requires the cases to be sorted by CASE_LOW (done by the
5372 gimplifier). */
5373 while (max_idx >= min_idx)
5375 unsigned case_idx = (min_idx + max_idx) / 2;
5376 tree label = gimple_switch_label (switch_stmt, case_idx);
5377 tree low = CASE_LOW (label);
5378 gcc_assert (low);
5379 tree high = CASE_HIGH (label);
5380 if (!high)
5381 high = low;
5382 if (tree_int_cst_compare (int_cst, low) < 0)
5384 /* INT_CST is below the range of this label. */
5385 gcc_assert (case_idx > 0);
5386 max_idx = case_idx - 1;
5388 else if (tree_int_cst_compare (int_cst, high) > 0)
5390 /* INT_CST is above the range of this case. */
5391 min_idx = case_idx + 1;
5393 else
5394 /* This case contains INT_CST. */
5395 return true;
5397 /* Not found. */
5398 return false;
5401 /* Return true iff SWITCH_STMT (which must be on an enum value)
5402 has nondefault cases handling all values in the enum. */
5404 static bool
5405 has_nondefault_cases_for_all_enum_values_p (const gswitch *switch_stmt)
5407 gcc_assert (switch_stmt);
5408 tree type = TREE_TYPE (gimple_switch_index (switch_stmt));
5409 gcc_assert (TREE_CODE (type) == ENUMERAL_TYPE);
5411 for (tree enum_val_iter = TYPE_VALUES (type);
5412 enum_val_iter;
5413 enum_val_iter = TREE_CHAIN (enum_val_iter))
5415 tree enum_val = TREE_VALUE (enum_val_iter);
5416 gcc_assert (TREE_CODE (enum_val) == CONST_DECL);
5417 gcc_assert (TREE_CODE (DECL_INITIAL (enum_val)) == INTEGER_CST);
5418 if (!has_nondefault_case_for_value_p (switch_stmt,
5419 DECL_INITIAL (enum_val)))
5420 return false;
5422 return true;
5425 /* Given an EDGE guarded by SWITCH_STMT, determine appropriate constraints
5426 for the edge to be taken.
5428 If they are feasible, add the constraints and return true.
5430 Return false if the constraints contradict existing knowledge
5431 (and so the edge should not be taken).
5432 When returning false, if OUT is non-NULL, write a new rejected_constraint
5433 to it. */
5435 bool
5436 region_model::
5437 apply_constraints_for_gswitch (const switch_cfg_superedge &edge,
5438 const gswitch *switch_stmt,
5439 region_model_context *ctxt,
5440 std::unique_ptr<rejected_constraint> *out)
5442 tree index = gimple_switch_index (switch_stmt);
5443 const svalue *index_sval = get_rvalue (index, ctxt);
5445 /* If we're switching based on an enum type, assume that the user is only
5446 working with values from the enum. Hence if this is an
5447 implicitly-created "default", assume it doesn't get followed.
5448 This fixes numerous "uninitialized" false positives where we otherwise
5449 consider jumping past the initialization cases. */
5451 if (/* Don't check during feasibility-checking (when ctxt is NULL). */
5452 ctxt
5453 /* Must be an enum value. */
5454 && index_sval->get_type ()
5455 && TREE_CODE (TREE_TYPE (index)) == ENUMERAL_TYPE
5456 && TREE_CODE (index_sval->get_type ()) == ENUMERAL_TYPE
5457 /* If we have a constant, then we can check it directly. */
5458 && index_sval->get_kind () != SK_CONSTANT
5459 && edge.implicitly_created_default_p ()
5460 && has_nondefault_cases_for_all_enum_values_p (switch_stmt)
5461 /* Don't do this if there's a chance that the index is
5462 attacker-controlled. */
5463 && !ctxt->possibly_tainted_p (index_sval))
5465 if (out)
5466 *out = make_unique <rejected_default_case> (*this);
5467 return false;
5470 bounded_ranges_manager *ranges_mgr = get_range_manager ();
5471 const bounded_ranges *all_cases_ranges
5472 = ranges_mgr->get_or_create_ranges_for_switch (&edge, switch_stmt);
5473 bool sat = m_constraints->add_bounded_ranges (index_sval, all_cases_ranges);
5474 if (!sat && out)
5475 *out = make_unique <rejected_ranges_constraint> (*this, index, all_cases_ranges);
5476 if (sat && ctxt && !all_cases_ranges->empty_p ())
5477 ctxt->on_bounded_ranges (*index_sval, *all_cases_ranges);
5478 return sat;
5481 /* Given an edge reached by GOTO_STMT, determine appropriate constraints
5482 for the edge to be taken.
5484 If they are feasible, add the constraints and return true.
5486 Return false if the constraints contradict existing knowledge
5487 (and so the edge should not be taken). */
5489 bool
5490 region_model::apply_constraints_for_ggoto (const cfg_superedge &edge,
5491 const ggoto *goto_stmt,
5492 region_model_context *ctxt)
5494 tree dest = gimple_goto_dest (goto_stmt);
5495 const svalue *dest_sval = get_rvalue (dest, ctxt);
5497 /* If we know we were jumping to a specific label. */
5498 if (tree dst_label = edge.m_dest->get_label ())
5500 const label_region *dst_label_reg
5501 = m_mgr->get_region_for_label (dst_label);
5502 const svalue *dst_label_ptr
5503 = m_mgr->get_ptr_svalue (ptr_type_node, dst_label_reg);
5505 if (!add_constraint (dest_sval, EQ_EXPR, dst_label_ptr, ctxt))
5506 return false;
5509 return true;
5512 /* Apply any constraints due to an exception being thrown at LAST_STMT.
5514 If they are feasible, add the constraints and return true.
5516 Return false if the constraints contradict existing knowledge
5517 (and so the edge should not be taken).
5518 When returning false, if OUT is non-NULL, write a new rejected_constraint
5519 to it. */
5521 bool
5522 region_model::
5523 apply_constraints_for_exception (const gimple *last_stmt,
5524 region_model_context *ctxt,
5525 std::unique_ptr<rejected_constraint> *out)
5527 gcc_assert (last_stmt);
5528 if (const gcall *call = dyn_cast <const gcall *> (last_stmt))
5529 if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
5530 if (is_named_call_p (callee_fndecl, "operator new", call, 1)
5531 || is_named_call_p (callee_fndecl, "operator new []", call, 1))
5533 /* We have an exception thrown from operator new.
5534 Add a constraint that the result was NULL, to avoid a false
5535 leak report due to the result being lost when following
5536 the EH edge. */
5537 if (tree lhs = gimple_call_lhs (call))
5538 return add_constraint (lhs, EQ_EXPR, null_pointer_node, ctxt, out);
5539 return true;
5541 return true;
5544 /* For use with push_frame when handling a top-level call within the analysis.
5545 PARAM has a defined but unknown initial value.
5546 Anything it points to has escaped, since the calling context "knows"
5547 the pointer, and thus calls to unknown functions could read/write into
5548 the region.
5549 If NONNULL is true, then assume that PARAM must be non-NULL. */
5551 void
5552 region_model::on_top_level_param (tree param,
5553 bool nonnull,
5554 region_model_context *ctxt)
5556 if (POINTER_TYPE_P (TREE_TYPE (param)))
5558 const region *param_reg = get_lvalue (param, ctxt);
5559 const svalue *init_ptr_sval
5560 = m_mgr->get_or_create_initial_value (param_reg);
5561 const region *pointee_reg = m_mgr->get_symbolic_region (init_ptr_sval);
5562 m_store.mark_as_escaped (pointee_reg);
5563 if (nonnull)
5565 const svalue *null_ptr_sval
5566 = m_mgr->get_or_create_null_ptr (TREE_TYPE (param));
5567 add_constraint (init_ptr_sval, NE_EXPR, null_ptr_sval, ctxt);
5572 /* Update this region_model to reflect pushing a frame onto the stack
5573 for a call to FUN.
5575 If ARG_SVALS is non-NULL, use it to populate the parameters
5576 in the new frame.
5577 Otherwise, the params have their initial_svalues.
5579 Return the frame_region for the new frame. */
5581 const region *
5582 region_model::push_frame (function *fun, const vec<const svalue *> *arg_svals,
5583 region_model_context *ctxt)
5585 m_current_frame = m_mgr->get_frame_region (m_current_frame, fun);
5586 if (arg_svals)
5588 /* Arguments supplied from a caller frame. */
5589 tree fndecl = fun->decl;
5590 unsigned idx = 0;
5591 for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
5592 iter_parm = DECL_CHAIN (iter_parm), ++idx)
5594 /* If there's a mismatching declaration, the call stmt might
5595 not have enough args. Handle this case by leaving the
5596 rest of the params as uninitialized. */
5597 if (idx >= arg_svals->length ())
5598 break;
5599 tree parm_lval = iter_parm;
5600 if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
5601 parm_lval = parm_default_ssa;
5602 const region *parm_reg = get_lvalue (parm_lval, ctxt);
5603 const svalue *arg_sval = (*arg_svals)[idx];
5604 set_value (parm_reg, arg_sval, ctxt);
5607 /* Handle any variadic args. */
5608 unsigned va_arg_idx = 0;
5609 for (; idx < arg_svals->length (); idx++, va_arg_idx++)
5611 const svalue *arg_sval = (*arg_svals)[idx];
5612 const region *var_arg_reg
5613 = m_mgr->get_var_arg_region (m_current_frame,
5614 va_arg_idx);
5615 set_value (var_arg_reg, arg_sval, ctxt);
5618 else
5620 /* Otherwise we have a top-level call within the analysis. The params
5621 have defined but unknown initial values.
5622 Anything they point to has escaped. */
5623 tree fndecl = fun->decl;
5625 /* Handle "__attribute__((nonnull))". */
5626 tree fntype = TREE_TYPE (fndecl);
5627 bitmap nonnull_args = get_nonnull_args (fntype);
5629 unsigned parm_idx = 0;
5630 for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
5631 iter_parm = DECL_CHAIN (iter_parm))
5633 bool non_null = (nonnull_args
5634 ? (bitmap_empty_p (nonnull_args)
5635 || bitmap_bit_p (nonnull_args, parm_idx))
5636 : false);
5637 if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
5638 on_top_level_param (parm_default_ssa, non_null, ctxt);
5639 else
5640 on_top_level_param (iter_parm, non_null, ctxt);
5641 parm_idx++;
5644 BITMAP_FREE (nonnull_args);
5647 return m_current_frame;
5650 /* Get the function of the top-most frame in this region_model's stack.
5651 There must be such a frame. */
5653 function *
5654 region_model::get_current_function () const
5656 const frame_region *frame = get_current_frame ();
5657 gcc_assert (frame);
5658 return frame->get_function ();
5661 /* Pop the topmost frame_region from this region_model's stack;
5663 If RESULT_LVALUE is non-null, copy any return value from the frame
5664 into the corresponding region (evaluated with respect to the *caller*
5665 frame, rather than the called frame).
5666 If OUT_RESULT is non-null, copy any return value from the frame
5667 into *OUT_RESULT.
5669 If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
5670 This is for use when unwinding frames e.g. due to longjmp, to suppress
5671 erroneously reporting uninitialized return values.
5673 Purge the frame region and all its descendent regions.
5674 Convert any pointers that point into such regions into
5675 POISON_KIND_POPPED_STACK svalues. */
5677 void
5678 region_model::pop_frame (tree result_lvalue,
5679 const svalue **out_result,
5680 region_model_context *ctxt,
5681 bool eval_return_svalue)
5683 gcc_assert (m_current_frame);
5685 const region_model pre_popped_model = *this;
5686 const frame_region *frame_reg = m_current_frame;
5688 /* Notify state machines. */
5689 if (ctxt)
5690 ctxt->on_pop_frame (frame_reg);
5692 /* Evaluate the result, within the callee frame. */
5693 tree fndecl = m_current_frame->get_function ()->decl;
5694 tree result = DECL_RESULT (fndecl);
5695 const svalue *retval = NULL;
5696 if (result
5697 && TREE_TYPE (result) != void_type_node
5698 && eval_return_svalue)
5700 retval = get_rvalue (result, ctxt);
5701 if (out_result)
5702 *out_result = retval;
5705 /* Pop the frame. */
5706 m_current_frame = m_current_frame->get_calling_frame ();
5708 if (result_lvalue && retval)
5710 gcc_assert (eval_return_svalue);
5712 /* Compute result_dst_reg using RESULT_LVALUE *after* popping
5713 the frame, but before poisoning pointers into the old frame. */
5714 const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);
5715 set_value (result_dst_reg, retval, ctxt);
5718 unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK);
5719 notify_on_pop_frame (this, &pre_popped_model, retval, ctxt);
5722 /* Get the number of frames in this region_model's stack. */
5725 region_model::get_stack_depth () const
5727 const frame_region *frame = get_current_frame ();
5728 if (frame)
5729 return frame->get_stack_depth ();
5730 else
5731 return 0;
5734 /* Get the frame_region with the given index within the stack.
5735 The frame_region must exist. */
5737 const frame_region *
5738 region_model::get_frame_at_index (int index) const
5740 const frame_region *frame = get_current_frame ();
5741 gcc_assert (frame);
5742 gcc_assert (index >= 0);
5743 gcc_assert (index <= frame->get_index ());
5744 while (index != frame->get_index ())
5746 frame = frame->get_calling_frame ();
5747 gcc_assert (frame);
5749 return frame;
5752 /* Unbind svalues for any regions in REG and below.
5753 Find any pointers to such regions; convert them to
5754 poisoned values of kind PKIND.
5755 Also purge any dynamic extents. */
5757 void
5758 region_model::unbind_region_and_descendents (const region *reg,
5759 enum poison_kind pkind)
5761 /* Gather a set of base regions to be unbound. */
5762 hash_set<const region *> base_regs;
5763 for (store::cluster_map_t::iterator iter = m_store.begin ();
5764 iter != m_store.end (); ++iter)
5766 const region *iter_base_reg = (*iter).first;
5767 if (iter_base_reg->descendent_of_p (reg))
5768 base_regs.add (iter_base_reg);
5770 for (hash_set<const region *>::iterator iter = base_regs.begin ();
5771 iter != base_regs.end (); ++iter)
5772 m_store.purge_cluster (*iter);
5774 /* Find any pointers to REG or its descendents; convert to poisoned. */
5775 poison_any_pointers_to_descendents (reg, pkind);
5777 /* Purge dynamic extents of any base regions in REG and below
5778 (e.g. VLAs and alloca stack regions). */
5779 for (auto iter : m_dynamic_extents)
5781 const region *iter_reg = iter.first;
5782 if (iter_reg->descendent_of_p (reg))
5783 unset_dynamic_extents (iter_reg);
5787 /* Implementation of BindingVisitor.
5788 Update the bound svalues for regions below REG to use poisoned
5789 values instead. */
5791 struct bad_pointer_finder
5793 bad_pointer_finder (const region *reg, enum poison_kind pkind,
5794 region_model_manager *mgr)
5795 : m_reg (reg), m_pkind (pkind), m_mgr (mgr), m_count (0)
5798 void on_binding (const binding_key *, const svalue *&sval)
5800 if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
5802 const region *ptr_dst = ptr_sval->get_pointee ();
5803 /* Poison ptrs to descendents of REG, but not to REG itself,
5804 otherwise double-free detection doesn't work (since sm-state
5805 for "free" is stored on the original ptr svalue). */
5806 if (ptr_dst->descendent_of_p (m_reg)
5807 && ptr_dst != m_reg)
5809 sval = m_mgr->get_or_create_poisoned_svalue (m_pkind,
5810 sval->get_type ());
5811 ++m_count;
5816 const region *m_reg;
5817 enum poison_kind m_pkind;
5818 region_model_manager *const m_mgr;
5819 int m_count;
5822 /* Find any pointers to REG or its descendents; convert them to
5823 poisoned values of kind PKIND.
5824 Return the number of pointers that were poisoned. */
5827 region_model::poison_any_pointers_to_descendents (const region *reg,
5828 enum poison_kind pkind)
5830 bad_pointer_finder bv (reg, pkind, m_mgr);
5831 m_store.for_each_binding (bv);
5832 return bv.m_count;
5835 /* Attempt to merge THIS with OTHER_MODEL, writing the result
5836 to OUT_MODEL. Use POINT to distinguish values created as a
5837 result of merging. */
5839 bool
5840 region_model::can_merge_with_p (const region_model &other_model,
5841 const program_point &point,
5842 region_model *out_model,
5843 const extrinsic_state *ext_state,
5844 const program_state *state_a,
5845 const program_state *state_b) const
5847 gcc_assert (out_model);
5848 gcc_assert (m_mgr == other_model.m_mgr);
5849 gcc_assert (m_mgr == out_model->m_mgr);
5851 if (m_current_frame != other_model.m_current_frame)
5852 return false;
5853 out_model->m_current_frame = m_current_frame;
5855 model_merger m (this, &other_model, point, out_model,
5856 ext_state, state_a, state_b);
5858 if (!store::can_merge_p (&m_store, &other_model.m_store,
5859 &out_model->m_store, m_mgr->get_store_manager (),
5860 &m))
5861 return false;
5863 if (!m_dynamic_extents.can_merge_with_p (other_model.m_dynamic_extents,
5864 &out_model->m_dynamic_extents))
5865 return false;
5867 /* Merge constraints. */
5868 constraint_manager::merge (*m_constraints,
5869 *other_model.m_constraints,
5870 out_model->m_constraints);
5872 for (auto iter : m.m_svals_changing_meaning)
5873 out_model->m_constraints->purge_state_involving (iter);
5875 return true;
5878 /* Attempt to get the fndecl used at CALL, if known, or NULL_TREE
5879 otherwise. */
5881 tree
5882 region_model::get_fndecl_for_call (const gcall *call,
5883 region_model_context *ctxt)
5885 tree fn_ptr = gimple_call_fn (call);
5886 if (fn_ptr == NULL_TREE)
5887 return NULL_TREE;
5888 const svalue *fn_ptr_sval = get_rvalue (fn_ptr, ctxt);
5889 if (const region_svalue *fn_ptr_ptr
5890 = fn_ptr_sval->dyn_cast_region_svalue ())
5892 const region *reg = fn_ptr_ptr->get_pointee ();
5893 if (const function_region *fn_reg = reg->dyn_cast_function_region ())
5895 tree fn_decl = fn_reg->get_fndecl ();
5896 cgraph_node *node = cgraph_node::get (fn_decl);
5897 if (!node)
5898 return NULL_TREE;
5899 const cgraph_node *ultimate_node = node->ultimate_alias_target ();
5900 if (ultimate_node)
5901 return ultimate_node->decl;
5905 return NULL_TREE;
5908 /* Would be much simpler to use a lambda here, if it were supported. */
5910 struct append_regions_cb_data
5912 const region_model *model;
5913 auto_vec<const decl_region *> *out;
5916 /* Populate *OUT with all decl_regions in the current
5917 frame that have clusters within the store. */
5919 void
5920 region_model::
5921 get_regions_for_current_frame (auto_vec<const decl_region *> *out) const
5923 append_regions_cb_data data;
5924 data.model = this;
5925 data.out = out;
5926 m_store.for_each_cluster (append_regions_cb, &data);
5929 /* Implementation detail of get_regions_for_current_frame. */
5931 void
5932 region_model::append_regions_cb (const region *base_reg,
5933 append_regions_cb_data *cb_data)
5935 if (base_reg->get_parent_region () != cb_data->model->m_current_frame)
5936 return;
5937 if (const decl_region *decl_reg = base_reg->dyn_cast_decl_region ())
5938 cb_data->out->safe_push (decl_reg);
5942 /* Abstract class for diagnostics related to the use of
5943 floating-point arithmetic where precision is needed. */
5945 class imprecise_floating_point_arithmetic : public pending_diagnostic
5947 public:
5948 int get_controlling_option () const final override
5950 return OPT_Wanalyzer_imprecise_fp_arithmetic;
5954 /* Concrete diagnostic to complain about uses of floating-point arithmetic
5955 in the size argument of malloc etc. */
5957 class float_as_size_arg : public imprecise_floating_point_arithmetic
5959 public:
5960 float_as_size_arg (tree arg) : m_arg (arg)
5963 const char *get_kind () const final override
5965 return "float_as_size_arg_diagnostic";
5968 bool subclass_equal_p (const pending_diagnostic &other) const final override
5970 return same_tree_p (m_arg, ((const float_as_size_arg &) other).m_arg);
5973 bool emit (rich_location *rich_loc, logger *) final override
5975 diagnostic_metadata m;
5976 bool warned = warning_meta (rich_loc, m, get_controlling_option (),
5977 "use of floating-point arithmetic here might"
5978 " yield unexpected results");
5979 if (warned)
5980 inform (rich_loc->get_loc (), "only use operands of an integer type"
5981 " inside the size argument");
5982 return warned;
5985 label_text describe_final_event (const evdesc::final_event &ev) final
5986 override
5988 if (m_arg)
5989 return ev.formatted_print ("operand %qE is of type %qT",
5990 m_arg, TREE_TYPE (m_arg));
5991 return ev.formatted_print ("at least one operand of the size argument is"
5992 " of a floating-point type");
5995 private:
5996 tree m_arg;
5999 /* Visitor to find uses of floating-point variables/constants in an svalue. */
6001 class contains_floating_point_visitor : public visitor
6003 public:
6004 contains_floating_point_visitor (const svalue *root_sval) : m_result (NULL)
6006 root_sval->accept (this);
6009 const svalue *get_svalue_to_report ()
6011 return m_result;
6014 void visit_constant_svalue (const constant_svalue *sval) final override
6016 /* At the point the analyzer runs, constant integer operands in a floating
6017 point expression are already implictly converted to floating-points.
6018 Thus, we do prefer to report non-constants such that the diagnostic
6019 always reports a floating-point operand. */
6020 tree type = sval->get_type ();
6021 if (type && FLOAT_TYPE_P (type) && !m_result)
6022 m_result = sval;
6025 void visit_conjured_svalue (const conjured_svalue *sval) final override
6027 tree type = sval->get_type ();
6028 if (type && FLOAT_TYPE_P (type))
6029 m_result = sval;
6032 void visit_initial_svalue (const initial_svalue *sval) final override
6034 tree type = sval->get_type ();
6035 if (type && FLOAT_TYPE_P (type))
6036 m_result = sval;
6039 private:
6040 /* Non-null if at least one floating-point operand was found. */
6041 const svalue *m_result;
6044 /* May complain about uses of floating-point operands in SIZE_IN_BYTES. */
6046 void
6047 region_model::check_dynamic_size_for_floats (const svalue *size_in_bytes,
6048 region_model_context *ctxt) const
6050 gcc_assert (ctxt);
6052 contains_floating_point_visitor v (size_in_bytes);
6053 if (const svalue *float_sval = v.get_svalue_to_report ())
6055 tree diag_arg = get_representative_tree (float_sval);
6056 ctxt->warn (make_unique<float_as_size_arg> (diag_arg));
6060 /* Return a region describing a heap-allocated block of memory.
6061 Use CTXT to complain about tainted sizes.
6063 Reuse an existing heap_allocated_region if it's not being referenced by
6064 this region_model; otherwise create a new one.
6066 Optionally (update_state_machine) transitions the pointer pointing to the
6067 heap_allocated_region from start to assumed non-null. */
6069 const region *
6070 region_model::get_or_create_region_for_heap_alloc (const svalue *size_in_bytes,
6071 region_model_context *ctxt,
6072 bool update_state_machine,
6073 const call_details *cd)
6075 /* Determine which regions are referenced in this region_model, so that
6076 we can reuse an existing heap_allocated_region if it's not in use on
6077 this path. */
6078 auto_bitmap base_regs_in_use;
6079 get_referenced_base_regions (base_regs_in_use);
6081 /* Don't reuse regions that are marked as TOUCHED. */
6082 for (store::cluster_map_t::iterator iter = m_store.begin ();
6083 iter != m_store.end (); ++iter)
6084 if ((*iter).second->touched_p ())
6086 const region *base_reg = (*iter).first;
6087 bitmap_set_bit (base_regs_in_use, base_reg->get_id ());
6090 const region *reg
6091 = m_mgr->get_or_create_region_for_heap_alloc (base_regs_in_use);
6092 if (size_in_bytes)
6093 if (compat_types_p (size_in_bytes->get_type (), size_type_node))
6094 set_dynamic_extents (reg, size_in_bytes, ctxt);
6096 if (update_state_machine && cd)
6098 const svalue *ptr_sval
6099 = m_mgr->get_ptr_svalue (cd->get_lhs_type (), reg);
6100 transition_ptr_sval_non_null (ctxt, ptr_sval);
6103 return reg;
6106 /* Populate OUT_IDS with the set of IDs of those base regions which are
6107 reachable in this region_model. */
6109 void
6110 region_model::get_referenced_base_regions (auto_bitmap &out_ids) const
6112 reachable_regions reachable_regs (const_cast<region_model *> (this));
6113 m_store.for_each_cluster (reachable_regions::init_cluster_cb,
6114 &reachable_regs);
6115 /* Get regions for locals that have explicitly bound values. */
6116 for (store::cluster_map_t::iterator iter = m_store.begin ();
6117 iter != m_store.end (); ++iter)
6119 const region *base_reg = (*iter).first;
6120 if (const region *parent = base_reg->get_parent_region ())
6121 if (parent->get_kind () == RK_FRAME)
6122 reachable_regs.add (base_reg, false);
6125 bitmap_clear (out_ids);
6126 for (auto iter_reg : reachable_regs)
6127 bitmap_set_bit (out_ids, iter_reg->get_id ());
6130 /* Return a new region describing a block of memory allocated within the
6131 current frame.
6132 Use CTXT to complain about tainted sizes. */
6134 const region *
6135 region_model::create_region_for_alloca (const svalue *size_in_bytes,
6136 region_model_context *ctxt)
6138 const region *reg = m_mgr->create_region_for_alloca (m_current_frame);
6139 if (compat_types_p (size_in_bytes->get_type (), size_type_node))
6140 set_dynamic_extents (reg, size_in_bytes, ctxt);
6141 return reg;
6144 /* Record that the size of REG is SIZE_IN_BYTES.
6145 Use CTXT to complain about tainted sizes. */
6147 void
6148 region_model::set_dynamic_extents (const region *reg,
6149 const svalue *size_in_bytes,
6150 region_model_context *ctxt)
6152 assert_compat_types (size_in_bytes->get_type (), size_type_node);
6153 if (ctxt)
6155 check_dynamic_size_for_taint (reg->get_memory_space (), size_in_bytes,
6156 ctxt);
6157 check_dynamic_size_for_floats (size_in_bytes, ctxt);
6159 m_dynamic_extents.put (reg, size_in_bytes);
6162 /* Get the recording of REG in bytes, or NULL if no dynamic size was
6163 recorded. */
6165 const svalue *
6166 region_model::get_dynamic_extents (const region *reg) const
6168 if (const svalue * const *slot = m_dynamic_extents.get (reg))
6169 return *slot;
6170 return NULL;
6173 /* Unset any recorded dynamic size of REG. */
6175 void
6176 region_model::unset_dynamic_extents (const region *reg)
6178 m_dynamic_extents.remove (reg);
6181 /* A subclass of pending_diagnostic for complaining about uninitialized data
6182 being copied across a trust boundary to an untrusted output
6183 (e.g. copy_to_user infoleaks in the Linux kernel). */
6185 class exposure_through_uninit_copy
6186 : public pending_diagnostic_subclass<exposure_through_uninit_copy>
6188 public:
6189 exposure_through_uninit_copy (const region *src_region,
6190 const region *dest_region,
6191 const svalue *copied_sval)
6192 : m_src_region (src_region),
6193 m_dest_region (dest_region),
6194 m_copied_sval (copied_sval)
6196 gcc_assert (m_copied_sval->get_kind () == SK_POISONED
6197 || m_copied_sval->get_kind () == SK_COMPOUND);
6200 const char *get_kind () const final override
6202 return "exposure_through_uninit_copy";
6205 bool operator== (const exposure_through_uninit_copy &other) const
6207 return (m_src_region == other.m_src_region
6208 && m_dest_region == other.m_dest_region
6209 && m_copied_sval == other.m_copied_sval);
6212 int get_controlling_option () const final override
6214 return OPT_Wanalyzer_exposure_through_uninit_copy;
6217 bool emit (rich_location *rich_loc, logger *) final override
6219 diagnostic_metadata m;
6220 /* CWE-200: Exposure of Sensitive Information to an Unauthorized Actor. */
6221 m.add_cwe (200);
6222 enum memory_space mem_space = get_src_memory_space ();
6223 bool warned;
6224 switch (mem_space)
6226 default:
6227 warned = warning_meta
6228 (rich_loc, m, get_controlling_option (),
6229 "potential exposure of sensitive information"
6230 " by copying uninitialized data across trust boundary");
6231 break;
6232 case MEMSPACE_STACK:
6233 warned = warning_meta
6234 (rich_loc, m, get_controlling_option (),
6235 "potential exposure of sensitive information"
6236 " by copying uninitialized data from stack across trust boundary");
6237 break;
6238 case MEMSPACE_HEAP:
6239 warned = warning_meta
6240 (rich_loc, m, get_controlling_option (),
6241 "potential exposure of sensitive information"
6242 " by copying uninitialized data from heap across trust boundary");
6243 break;
6245 if (warned)
6247 location_t loc = rich_loc->get_loc ();
6248 inform_number_of_uninit_bits (loc);
6249 complain_about_uninit_ranges (loc);
6251 if (mem_space == MEMSPACE_STACK)
6252 maybe_emit_fixit_hint ();
6254 return warned;
6257 label_text describe_final_event (const evdesc::final_event &) final override
6259 enum memory_space mem_space = get_src_memory_space ();
6260 switch (mem_space)
6262 default:
6263 return label_text::borrow ("uninitialized data copied here");
6265 case MEMSPACE_STACK:
6266 return label_text::borrow ("uninitialized data copied from stack here");
6268 case MEMSPACE_HEAP:
6269 return label_text::borrow ("uninitialized data copied from heap here");
6273 void mark_interesting_stuff (interesting_t *interest) final override
6275 if (m_src_region)
6276 interest->add_region_creation (m_src_region);
6279 private:
6280 enum memory_space get_src_memory_space () const
6282 return m_src_region ? m_src_region->get_memory_space () : MEMSPACE_UNKNOWN;
6285 bit_size_t calc_num_uninit_bits () const
6287 switch (m_copied_sval->get_kind ())
6289 default:
6290 gcc_unreachable ();
6291 break;
6292 case SK_POISONED:
6294 const poisoned_svalue *poisoned_sval
6295 = as_a <const poisoned_svalue *> (m_copied_sval);
6296 gcc_assert (poisoned_sval->get_poison_kind () == POISON_KIND_UNINIT);
6298 /* Give up if don't have type information. */
6299 if (m_copied_sval->get_type () == NULL_TREE)
6300 return 0;
6302 bit_size_t size_in_bits;
6303 if (int_size_in_bits (m_copied_sval->get_type (), &size_in_bits))
6304 return size_in_bits;
6306 /* Give up if we can't get the size of the type. */
6307 return 0;
6309 break;
6310 case SK_COMPOUND:
6312 const compound_svalue *compound_sval
6313 = as_a <const compound_svalue *> (m_copied_sval);
6314 bit_size_t result = 0;
6315 /* Find keys for uninit svals. */
6316 for (auto iter : *compound_sval)
6318 const svalue *sval = iter.second;
6319 if (const poisoned_svalue *psval
6320 = sval->dyn_cast_poisoned_svalue ())
6321 if (psval->get_poison_kind () == POISON_KIND_UNINIT)
6323 const binding_key *key = iter.first;
6324 const concrete_binding *ckey
6325 = key->dyn_cast_concrete_binding ();
6326 gcc_assert (ckey);
6327 result += ckey->get_size_in_bits ();
6330 return result;
6335 void inform_number_of_uninit_bits (location_t loc) const
6337 bit_size_t num_uninit_bits = calc_num_uninit_bits ();
6338 if (num_uninit_bits <= 0)
6339 return;
6340 if (num_uninit_bits % BITS_PER_UNIT == 0)
6342 /* Express in bytes. */
6343 byte_size_t num_uninit_bytes = num_uninit_bits / BITS_PER_UNIT;
6344 if (num_uninit_bytes == 1)
6345 inform (loc, "1 byte is uninitialized");
6346 else
6347 inform (loc,
6348 "%wu bytes are uninitialized", num_uninit_bytes.to_uhwi ());
6350 else
6352 /* Express in bits. */
6353 if (num_uninit_bits == 1)
6354 inform (loc, "1 bit is uninitialized");
6355 else
6356 inform (loc,
6357 "%wu bits are uninitialized", num_uninit_bits.to_uhwi ());
6361 void complain_about_uninit_ranges (location_t loc) const
6363 if (const compound_svalue *compound_sval
6364 = m_copied_sval->dyn_cast_compound_svalue ())
6366 /* Find keys for uninit svals. */
6367 auto_vec<const concrete_binding *> uninit_keys;
6368 for (auto iter : *compound_sval)
6370 const svalue *sval = iter.second;
6371 if (const poisoned_svalue *psval
6372 = sval->dyn_cast_poisoned_svalue ())
6373 if (psval->get_poison_kind () == POISON_KIND_UNINIT)
6375 const binding_key *key = iter.first;
6376 const concrete_binding *ckey
6377 = key->dyn_cast_concrete_binding ();
6378 gcc_assert (ckey);
6379 uninit_keys.safe_push (ckey);
6382 /* Complain about them in sorted order. */
6383 uninit_keys.qsort (concrete_binding::cmp_ptr_ptr);
6385 std::unique_ptr<record_layout> layout;
6387 tree type = m_copied_sval->get_type ();
6388 if (type && TREE_CODE (type) == RECORD_TYPE)
6390 // (std::make_unique is C++14)
6391 layout = std::unique_ptr<record_layout> (new record_layout (type));
6393 if (0)
6394 layout->dump ();
6397 unsigned i;
6398 const concrete_binding *ckey;
6399 FOR_EACH_VEC_ELT (uninit_keys, i, ckey)
6401 bit_offset_t start_bit = ckey->get_start_bit_offset ();
6402 bit_offset_t next_bit = ckey->get_next_bit_offset ();
6403 complain_about_uninit_range (loc, start_bit, next_bit,
6404 layout.get ());
6409 void complain_about_uninit_range (location_t loc,
6410 bit_offset_t start_bit,
6411 bit_offset_t next_bit,
6412 const record_layout *layout) const
6414 if (layout)
6416 while (start_bit < next_bit)
6418 if (const record_layout::item *item
6419 = layout->get_item_at (start_bit))
6421 gcc_assert (start_bit >= item->get_start_bit_offset ());
6422 gcc_assert (start_bit < item->get_next_bit_offset ());
6423 if (item->get_start_bit_offset () == start_bit
6424 && item->get_next_bit_offset () <= next_bit)
6425 complain_about_fully_uninit_item (*item);
6426 else
6427 complain_about_partially_uninit_item (*item);
6428 start_bit = item->get_next_bit_offset ();
6429 continue;
6431 else
6432 break;
6436 if (start_bit >= next_bit)
6437 return;
6439 if (start_bit % 8 == 0 && next_bit % 8 == 0)
6441 /* Express in bytes. */
6442 byte_offset_t start_byte = start_bit / 8;
6443 byte_offset_t last_byte = (next_bit / 8) - 1;
6444 if (last_byte == start_byte)
6445 inform (loc,
6446 "byte %wu is uninitialized",
6447 start_byte.to_uhwi ());
6448 else
6449 inform (loc,
6450 "bytes %wu - %wu are uninitialized",
6451 start_byte.to_uhwi (),
6452 last_byte.to_uhwi ());
6454 else
6456 /* Express in bits. */
6457 bit_offset_t last_bit = next_bit - 1;
6458 if (last_bit == start_bit)
6459 inform (loc,
6460 "bit %wu is uninitialized",
6461 start_bit.to_uhwi ());
6462 else
6463 inform (loc,
6464 "bits %wu - %wu are uninitialized",
6465 start_bit.to_uhwi (),
6466 last_bit.to_uhwi ());
6470 static void
6471 complain_about_fully_uninit_item (const record_layout::item &item)
6473 tree field = item.m_field;
6474 bit_size_t num_bits = item.m_bit_range.m_size_in_bits;
6475 if (item.m_is_padding)
6477 if (num_bits % 8 == 0)
6479 /* Express in bytes. */
6480 byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
6481 if (num_bytes == 1)
6482 inform (DECL_SOURCE_LOCATION (field),
6483 "padding after field %qD is uninitialized (1 byte)",
6484 field);
6485 else
6486 inform (DECL_SOURCE_LOCATION (field),
6487 "padding after field %qD is uninitialized (%wu bytes)",
6488 field, num_bytes.to_uhwi ());
6490 else
6492 /* Express in bits. */
6493 if (num_bits == 1)
6494 inform (DECL_SOURCE_LOCATION (field),
6495 "padding after field %qD is uninitialized (1 bit)",
6496 field);
6497 else
6498 inform (DECL_SOURCE_LOCATION (field),
6499 "padding after field %qD is uninitialized (%wu bits)",
6500 field, num_bits.to_uhwi ());
6503 else
6505 if (num_bits % 8 == 0)
6507 /* Express in bytes. */
6508 byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
6509 if (num_bytes == 1)
6510 inform (DECL_SOURCE_LOCATION (field),
6511 "field %qD is uninitialized (1 byte)", field);
6512 else
6513 inform (DECL_SOURCE_LOCATION (field),
6514 "field %qD is uninitialized (%wu bytes)",
6515 field, num_bytes.to_uhwi ());
6517 else
6519 /* Express in bits. */
6520 if (num_bits == 1)
6521 inform (DECL_SOURCE_LOCATION (field),
6522 "field %qD is uninitialized (1 bit)", field);
6523 else
6524 inform (DECL_SOURCE_LOCATION (field),
6525 "field %qD is uninitialized (%wu bits)",
6526 field, num_bits.to_uhwi ());
6531 static void
6532 complain_about_partially_uninit_item (const record_layout::item &item)
6534 tree field = item.m_field;
6535 if (item.m_is_padding)
6536 inform (DECL_SOURCE_LOCATION (field),
6537 "padding after field %qD is partially uninitialized",
6538 field);
6539 else
6540 inform (DECL_SOURCE_LOCATION (field),
6541 "field %qD is partially uninitialized",
6542 field);
6543 /* TODO: ideally we'd describe what parts are uninitialized. */
6546 void maybe_emit_fixit_hint () const
6548 if (tree decl = m_src_region->maybe_get_decl ())
6550 gcc_rich_location hint_richloc (DECL_SOURCE_LOCATION (decl));
6551 hint_richloc.add_fixit_insert_after (" = {0}");
6552 inform (&hint_richloc,
6553 "suggest forcing zero-initialization by"
6554 " providing a %<{0}%> initializer");
6558 private:
6559 const region *m_src_region;
6560 const region *m_dest_region;
6561 const svalue *m_copied_sval;
6564 /* Return true if any part of SVAL is uninitialized. */
6566 static bool
6567 contains_uninit_p (const svalue *sval)
6569 struct uninit_finder : public visitor
6571 public:
6572 uninit_finder () : m_found_uninit (false) {}
6573 void visit_poisoned_svalue (const poisoned_svalue *sval)
6575 if (sval->get_poison_kind () == POISON_KIND_UNINIT)
6576 m_found_uninit = true;
6578 bool m_found_uninit;
6581 uninit_finder v;
6582 sval->accept (&v);
6584 return v.m_found_uninit;
6587 /* Function for use by plugins when simulating writing data through a
6588 pointer to an "untrusted" region DST_REG (and thus crossing a security
6589 boundary), such as copying data to user space in an OS kernel.
6591 Check that COPIED_SVAL is fully initialized. If not, complain about
6592 an infoleak to CTXT.
6594 SRC_REG can be NULL; if non-NULL it is used as a hint in the diagnostic
6595 as to where COPIED_SVAL came from. */
6597 void
6598 region_model::maybe_complain_about_infoleak (const region *dst_reg,
6599 const svalue *copied_sval,
6600 const region *src_reg,
6601 region_model_context *ctxt)
6603 /* Check for exposure. */
6604 if (contains_uninit_p (copied_sval))
6605 ctxt->warn (make_unique<exposure_through_uninit_copy> (src_reg,
6606 dst_reg,
6607 copied_sval));
6610 /* Set errno to a positive symbolic int, as if some error has occurred. */
6612 void
6613 region_model::set_errno (const call_details &cd)
6615 const region *errno_reg = m_mgr->get_errno_region ();
6616 conjured_purge p (this, cd.get_ctxt ());
6617 const svalue *new_errno_sval
6618 = m_mgr->get_or_create_conjured_svalue (integer_type_node,
6619 cd.get_call_stmt (),
6620 errno_reg, p);
6621 const svalue *zero
6622 = m_mgr->get_or_create_int_cst (integer_type_node, 0);
6623 add_constraint (new_errno_sval, GT_EXPR, zero, cd.get_ctxt ());
6624 set_value (errno_reg, new_errno_sval, cd.get_ctxt ());
6627 /* class noop_region_model_context : public region_model_context. */
6629 void
6630 noop_region_model_context::add_note (std::unique_ptr<pending_note>)
6634 void
6635 noop_region_model_context::add_event (std::unique_ptr<checker_event>)
6639 void
6640 noop_region_model_context::bifurcate (std::unique_ptr<custom_edge_info>)
6644 void
6645 noop_region_model_context::terminate_path ()
6649 /* class region_model_context_decorator : public region_model_context. */
6651 void
6652 region_model_context_decorator::add_event (std::unique_ptr<checker_event> event)
6654 if (m_inner)
6655 m_inner->add_event (std::move (event));
6658 /* struct model_merger. */
6660 /* Dump a multiline representation of this merger to PP. */
6662 void
6663 model_merger::dump_to_pp (pretty_printer *pp, bool simple) const
6665 pp_string (pp, "model A:");
6666 pp_newline (pp);
6667 m_model_a->dump_to_pp (pp, simple, true);
6668 pp_newline (pp);
6670 pp_string (pp, "model B:");
6671 pp_newline (pp);
6672 m_model_b->dump_to_pp (pp, simple, true);
6673 pp_newline (pp);
6675 pp_string (pp, "merged model:");
6676 pp_newline (pp);
6677 m_merged_model->dump_to_pp (pp, simple, true);
6678 pp_newline (pp);
6681 /* Dump a multiline representation of this merger to FILE. */
6683 void
6684 model_merger::dump (FILE *fp, bool simple) const
6686 pretty_printer pp;
6687 pp_format_decoder (&pp) = default_tree_printer;
6688 pp_show_color (&pp) = pp_show_color (global_dc->printer);
6689 pp.buffer->stream = fp;
6690 dump_to_pp (&pp, simple);
6691 pp_flush (&pp);
6694 /* Dump a multiline representation of this merger to stderr. */
6696 DEBUG_FUNCTION void
6697 model_merger::dump (bool simple) const
6699 dump (stderr, simple);
6702 /* Return true if it's OK to merge SVAL with other svalues. */
6704 bool
6705 model_merger::mergeable_svalue_p (const svalue *sval) const
6707 if (m_ext_state)
6709 /* Reject merging svalues that have non-purgable sm-state,
6710 to avoid falsely reporting memory leaks by merging them
6711 with something else. For example, given a local var "p",
6712 reject the merger of a:
6713 store_a mapping "p" to a malloc-ed ptr
6714 with:
6715 store_b mapping "p" to a NULL ptr. */
6716 if (m_state_a)
6717 if (!m_state_a->can_purge_p (*m_ext_state, sval))
6718 return false;
6719 if (m_state_b)
6720 if (!m_state_b->can_purge_p (*m_ext_state, sval))
6721 return false;
6723 return true;
6726 /* Mark WIDENING_SVAL as changing meaning during the merge. */
6728 void
6729 model_merger::on_widening_reuse (const widening_svalue *widening_sval)
6731 m_svals_changing_meaning.add (widening_sval);
6734 } // namespace ana
6736 /* Dump RMODEL fully to stderr (i.e. without summarization). */
6738 DEBUG_FUNCTION void
6739 debug (const region_model &rmodel)
6741 rmodel.dump (false);
6744 /* class rejected_op_constraint : public rejected_constraint. */
6746 void
6747 rejected_op_constraint::dump_to_pp (pretty_printer *pp) const
6749 region_model m (m_model);
6750 const svalue *lhs_sval = m.get_rvalue (m_lhs, NULL);
6751 const svalue *rhs_sval = m.get_rvalue (m_rhs, NULL);
6752 lhs_sval->dump_to_pp (pp, true);
6753 pp_printf (pp, " %s ", op_symbol_code (m_op));
6754 rhs_sval->dump_to_pp (pp, true);
6757 /* class rejected_default_case : public rejected_constraint. */
6759 void
6760 rejected_default_case::dump_to_pp (pretty_printer *pp) const
6762 pp_string (pp, "implicit default for enum");
6765 /* class rejected_ranges_constraint : public rejected_constraint. */
6767 void
6768 rejected_ranges_constraint::dump_to_pp (pretty_printer *pp) const
6770 region_model m (m_model);
6771 const svalue *sval = m.get_rvalue (m_expr, NULL);
6772 sval->dump_to_pp (pp, true);
6773 pp_string (pp, " in ");
6774 m_ranges->dump_to_pp (pp, true);
6777 /* class engine. */
6779 /* engine's ctor. */
6781 engine::engine (const supergraph *sg, logger *logger)
6782 : m_sg (sg), m_mgr (logger)
6786 /* Dump the managed objects by class to LOGGER, and the per-class totals. */
6788 void
6789 engine::log_stats (logger *logger) const
6791 m_mgr.log_stats (logger, true);
6794 namespace ana {
6796 #if CHECKING_P
6798 namespace selftest {
6800 /* Build a constant tree of the given type from STR. */
6802 static tree
6803 build_real_cst_from_string (tree type, const char *str)
6805 REAL_VALUE_TYPE real;
6806 real_from_string (&real, str);
6807 return build_real (type, real);
6810 /* Append various "interesting" constants to OUT (e.g. NaN). */
6812 static void
6813 append_interesting_constants (auto_vec<tree> *out)
6815 out->safe_push (build_int_cst (integer_type_node, 0));
6816 out->safe_push (build_int_cst (integer_type_node, 42));
6817 out->safe_push (build_int_cst (unsigned_type_node, 0));
6818 out->safe_push (build_int_cst (unsigned_type_node, 42));
6819 out->safe_push (build_real_cst_from_string (float_type_node, "QNaN"));
6820 out->safe_push (build_real_cst_from_string (float_type_node, "-QNaN"));
6821 out->safe_push (build_real_cst_from_string (float_type_node, "SNaN"));
6822 out->safe_push (build_real_cst_from_string (float_type_node, "-SNaN"));
6823 out->safe_push (build_real_cst_from_string (float_type_node, "0.0"));
6824 out->safe_push (build_real_cst_from_string (float_type_node, "-0.0"));
6825 out->safe_push (build_real_cst_from_string (float_type_node, "Inf"));
6826 out->safe_push (build_real_cst_from_string (float_type_node, "-Inf"));
6829 /* Verify that tree_cmp is a well-behaved comparator for qsort, even
6830 if the underlying constants aren't comparable. */
6832 static void
6833 test_tree_cmp_on_constants ()
6835 auto_vec<tree> csts;
6836 append_interesting_constants (&csts);
6838 /* Try sorting every triple. */
6839 const unsigned num = csts.length ();
6840 for (unsigned i = 0; i < num; i++)
6841 for (unsigned j = 0; j < num; j++)
6842 for (unsigned k = 0; k < num; k++)
6844 auto_vec<tree> v (3);
6845 v.quick_push (csts[i]);
6846 v.quick_push (csts[j]);
6847 v.quick_push (csts[k]);
6848 v.qsort (tree_cmp);
6852 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6854 void
6855 assert_condition (const location &loc,
6856 region_model &model,
6857 const svalue *lhs, tree_code op, const svalue *rhs,
6858 tristate expected)
6860 tristate actual = model.eval_condition (lhs, op, rhs);
6861 ASSERT_EQ_AT (loc, actual, expected);
6864 /* Implementation detail of the ASSERT_CONDITION_* macros. */
6866 void
6867 assert_condition (const location &loc,
6868 region_model &model,
6869 tree lhs, tree_code op, tree rhs,
6870 tristate expected)
6872 tristate actual = model.eval_condition (lhs, op, rhs, NULL);
6873 ASSERT_EQ_AT (loc, actual, expected);
6876 /* Implementation detail of ASSERT_DUMP_TREE_EQ. */
6878 static void
6879 assert_dump_tree_eq (const location &loc, tree t, const char *expected)
6881 auto_fix_quotes sentinel;
6882 pretty_printer pp;
6883 pp_format_decoder (&pp) = default_tree_printer;
6884 dump_tree (&pp, t);
6885 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
6888 /* Assert that dump_tree (T) is EXPECTED. */
6890 #define ASSERT_DUMP_TREE_EQ(T, EXPECTED) \
6891 SELFTEST_BEGIN_STMT \
6892 assert_dump_tree_eq ((SELFTEST_LOCATION), (T), (EXPECTED)); \
6893 SELFTEST_END_STMT
6895 /* Implementation detail of ASSERT_DUMP_EQ. */
6897 static void
6898 assert_dump_eq (const location &loc,
6899 const region_model &model,
6900 bool summarize,
6901 const char *expected)
6903 auto_fix_quotes sentinel;
6904 pretty_printer pp;
6905 pp_format_decoder (&pp) = default_tree_printer;
6907 model.dump_to_pp (&pp, summarize, true);
6908 ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected);
6911 /* Assert that MODEL.dump_to_pp (SUMMARIZE) is EXPECTED. */
6913 #define ASSERT_DUMP_EQ(MODEL, SUMMARIZE, EXPECTED) \
6914 SELFTEST_BEGIN_STMT \
6915 assert_dump_eq ((SELFTEST_LOCATION), (MODEL), (SUMMARIZE), (EXPECTED)); \
6916 SELFTEST_END_STMT
6918 /* Smoketest for region_model::dump_to_pp. */
6920 static void
6921 test_dump ()
6923 region_model_manager mgr;
6924 region_model model (&mgr);
6926 ASSERT_DUMP_EQ (model, false,
6927 "stack depth: 0\n"
6928 "m_called_unknown_fn: FALSE\n"
6929 "constraint_manager:\n"
6930 " equiv classes:\n"
6931 " constraints:\n");
6932 ASSERT_DUMP_EQ (model, true,
6933 "stack depth: 0\n"
6934 "m_called_unknown_fn: FALSE\n"
6935 "constraint_manager:\n"
6936 " equiv classes:\n"
6937 " constraints:\n");
6940 /* Helper function for selftests. Create a struct or union type named NAME,
6941 with the fields given by the FIELD_DECLS in FIELDS.
6942 If IS_STRUCT is true create a RECORD_TYPE (aka a struct), otherwise
6943 create a UNION_TYPE. */
6945 static tree
6946 make_test_compound_type (const char *name, bool is_struct,
6947 const auto_vec<tree> *fields)
6949 tree t = make_node (is_struct ? RECORD_TYPE : UNION_TYPE);
6950 TYPE_NAME (t) = get_identifier (name);
6951 TYPE_SIZE (t) = 0;
6953 tree fieldlist = NULL;
6954 int i;
6955 tree field;
6956 FOR_EACH_VEC_ELT (*fields, i, field)
6958 gcc_assert (TREE_CODE (field) == FIELD_DECL);
6959 DECL_CONTEXT (field) = t;
6960 fieldlist = chainon (field, fieldlist);
6962 fieldlist = nreverse (fieldlist);
6963 TYPE_FIELDS (t) = fieldlist;
6965 layout_type (t);
6966 return t;
6969 /* Selftest fixture for creating the type "struct coord {int x; int y; };". */
6971 struct coord_test
6973 coord_test ()
6975 auto_vec<tree> fields;
6976 m_x_field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
6977 get_identifier ("x"), integer_type_node);
6978 fields.safe_push (m_x_field);
6979 m_y_field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
6980 get_identifier ("y"), integer_type_node);
6981 fields.safe_push (m_y_field);
6982 m_coord_type = make_test_compound_type ("coord", true, &fields);
6985 tree m_x_field;
6986 tree m_y_field;
6987 tree m_coord_type;
6990 /* Verify usage of a struct. */
6992 static void
6993 test_struct ()
6995 coord_test ct;
6997 tree c = build_global_decl ("c", ct.m_coord_type);
6998 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
6999 c, ct.m_x_field, NULL_TREE);
7000 tree c_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7001 c, ct.m_y_field, NULL_TREE);
7003 tree int_17 = build_int_cst (integer_type_node, 17);
7004 tree int_m3 = build_int_cst (integer_type_node, -3);
7006 region_model_manager mgr;
7007 region_model model (&mgr);
7008 model.set_value (c_x, int_17, NULL);
7009 model.set_value (c_y, int_m3, NULL);
7011 /* Verify get_offset for "c.x". */
7013 const region *c_x_reg = model.get_lvalue (c_x, NULL);
7014 region_offset offset = c_x_reg->get_offset (&mgr);
7015 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, NULL));
7016 ASSERT_EQ (offset.get_bit_offset (), 0);
7019 /* Verify get_offset for "c.y". */
7021 const region *c_y_reg = model.get_lvalue (c_y, NULL);
7022 region_offset offset = c_y_reg->get_offset (&mgr);
7023 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (c, NULL));
7024 ASSERT_EQ (offset.get_bit_offset (), INT_TYPE_SIZE);
7028 /* Verify usage of an array element. */
7030 static void
7031 test_array_1 ()
7033 tree tlen = size_int (10);
7034 tree arr_type = build_array_type (char_type_node, build_index_type (tlen));
7036 tree a = build_global_decl ("a", arr_type);
7038 region_model_manager mgr;
7039 region_model model (&mgr);
7040 tree int_0 = build_int_cst (integer_type_node, 0);
7041 tree a_0 = build4 (ARRAY_REF, char_type_node,
7042 a, int_0, NULL_TREE, NULL_TREE);
7043 tree char_A = build_int_cst (char_type_node, 'A');
7044 model.set_value (a_0, char_A, NULL);
7047 /* Verify that region_model::get_representative_tree works as expected. */
7049 static void
7050 test_get_representative_tree ()
7052 region_model_manager mgr;
7054 /* STRING_CST. */
7056 tree string_cst = build_string (4, "foo");
7057 region_model m (&mgr);
7058 const svalue *str_sval = m.get_rvalue (string_cst, NULL);
7059 tree rep = m.get_representative_tree (str_sval);
7060 ASSERT_EQ (rep, string_cst);
7063 /* String literal. */
7065 tree string_cst_ptr = build_string_literal (4, "foo");
7066 region_model m (&mgr);
7067 const svalue *str_sval = m.get_rvalue (string_cst_ptr, NULL);
7068 tree rep = m.get_representative_tree (str_sval);
7069 ASSERT_DUMP_TREE_EQ (rep, "&\"foo\"[0]");
7072 /* Value of an element within an array. */
7074 tree tlen = size_int (10);
7075 tree arr_type = build_array_type (char_type_node, build_index_type (tlen));
7076 tree a = build_global_decl ("a", arr_type);
7077 placeholder_svalue test_sval (mgr.alloc_symbol_id (),
7078 char_type_node, "test value");
7080 /* Value of a[3]. */
7082 test_region_model_context ctxt;
7083 region_model model (&mgr);
7084 tree int_3 = build_int_cst (integer_type_node, 3);
7085 tree a_3 = build4 (ARRAY_REF, char_type_node,
7086 a, int_3, NULL_TREE, NULL_TREE);
7087 const region *a_3_reg = model.get_lvalue (a_3, &ctxt);
7088 model.set_value (a_3_reg, &test_sval, &ctxt);
7089 tree rep = model.get_representative_tree (&test_sval);
7090 ASSERT_DUMP_TREE_EQ (rep, "a[3]");
7093 /* Value of a[0]. */
7095 test_region_model_context ctxt;
7096 region_model model (&mgr);
7097 tree idx = build_int_cst (integer_type_node, 0);
7098 tree a_0 = build4 (ARRAY_REF, char_type_node,
7099 a, idx, NULL_TREE, NULL_TREE);
7100 const region *a_0_reg = model.get_lvalue (a_0, &ctxt);
7101 model.set_value (a_0_reg, &test_sval, &ctxt);
7102 tree rep = model.get_representative_tree (&test_sval);
7103 ASSERT_DUMP_TREE_EQ (rep, "a[0]");
7107 /* Value of a field within a struct. */
7109 coord_test ct;
7111 tree c = build_global_decl ("c", ct.m_coord_type);
7112 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7113 c, ct.m_x_field, NULL_TREE);
7114 tree c_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7115 c, ct.m_y_field, NULL_TREE);
7117 test_region_model_context ctxt;
7119 /* Value of initial field. */
7121 region_model m (&mgr);
7122 const region *c_x_reg = m.get_lvalue (c_x, &ctxt);
7123 placeholder_svalue test_sval_x (mgr.alloc_symbol_id (),
7124 integer_type_node, "test x val");
7125 m.set_value (c_x_reg, &test_sval_x, &ctxt);
7126 tree rep = m.get_representative_tree (&test_sval_x);
7127 ASSERT_DUMP_TREE_EQ (rep, "c.x");
7130 /* Value of non-initial field. */
7132 region_model m (&mgr);
7133 const region *c_y_reg = m.get_lvalue (c_y, &ctxt);
7134 placeholder_svalue test_sval_y (mgr.alloc_symbol_id (),
7135 integer_type_node, "test y val");
7136 m.set_value (c_y_reg, &test_sval_y, &ctxt);
7137 tree rep = m.get_representative_tree (&test_sval_y);
7138 ASSERT_DUMP_TREE_EQ (rep, "c.y");
7143 /* Verify that calling region_model::get_rvalue repeatedly on the same
7144 tree constant retrieves the same svalue *. */
7146 static void
7147 test_unique_constants ()
7149 tree int_0 = build_int_cst (integer_type_node, 0);
7150 tree int_42 = build_int_cst (integer_type_node, 42);
7152 test_region_model_context ctxt;
7153 region_model_manager mgr;
7154 region_model model (&mgr);
7155 ASSERT_EQ (model.get_rvalue (int_0, &ctxt), model.get_rvalue (int_0, &ctxt));
7156 ASSERT_EQ (model.get_rvalue (int_42, &ctxt),
7157 model.get_rvalue (int_42, &ctxt));
7158 ASSERT_NE (model.get_rvalue (int_0, &ctxt), model.get_rvalue (int_42, &ctxt));
7159 ASSERT_EQ (ctxt.get_num_diagnostics (), 0);
7161 /* A "(const int)42" will be a different tree from "(int)42)"... */
7162 tree const_int_type_node
7163 = build_qualified_type (integer_type_node, TYPE_QUAL_CONST);
7164 tree const_int_42 = build_int_cst (const_int_type_node, 42);
7165 ASSERT_NE (int_42, const_int_42);
7166 /* It should have a different const_svalue. */
7167 const svalue *int_42_sval = model.get_rvalue (int_42, &ctxt);
7168 const svalue *const_int_42_sval = model.get_rvalue (const_int_42, &ctxt);
7169 ASSERT_NE (int_42_sval, const_int_42_sval);
7170 /* But they should compare as equal. */
7171 ASSERT_CONDITION_TRUE (model, int_42_sval, EQ_EXPR, const_int_42_sval);
7172 ASSERT_CONDITION_FALSE (model, int_42_sval, NE_EXPR, const_int_42_sval);
7175 /* Verify that each type gets its own singleton unknown_svalue within a
7176 region_model_manager, and that NULL_TREE gets its own singleton. */
7178 static void
7179 test_unique_unknowns ()
7181 region_model_manager mgr;
7182 const svalue *unknown_int
7183 = mgr.get_or_create_unknown_svalue (integer_type_node);
7184 /* Repeated calls with the same type should get the same "unknown"
7185 svalue. */
7186 const svalue *unknown_int_2
7187 = mgr.get_or_create_unknown_svalue (integer_type_node);
7188 ASSERT_EQ (unknown_int, unknown_int_2);
7190 /* Different types (or the NULL type) should have different
7191 unknown_svalues. */
7192 const svalue *unknown_NULL_type = mgr.get_or_create_unknown_svalue (NULL);
7193 ASSERT_NE (unknown_NULL_type, unknown_int);
7195 /* Repeated calls with NULL for the type should get the same "unknown"
7196 svalue. */
7197 const svalue *unknown_NULL_type_2 = mgr.get_or_create_unknown_svalue (NULL);
7198 ASSERT_EQ (unknown_NULL_type, unknown_NULL_type_2);
7201 /* Verify that initial_svalue are handled as expected. */
7203 static void
7204 test_initial_svalue_folding ()
7206 region_model_manager mgr;
7207 tree x = build_global_decl ("x", integer_type_node);
7208 tree y = build_global_decl ("y", integer_type_node);
7210 test_region_model_context ctxt;
7211 region_model model (&mgr);
7212 const svalue *x_init = model.get_rvalue (x, &ctxt);
7213 const svalue *y_init = model.get_rvalue (y, &ctxt);
7214 ASSERT_NE (x_init, y_init);
7215 const region *x_reg = model.get_lvalue (x, &ctxt);
7216 ASSERT_EQ (x_init, mgr.get_or_create_initial_value (x_reg));
7220 /* Verify that unary ops are folded as expected. */
7222 static void
7223 test_unaryop_svalue_folding ()
7225 region_model_manager mgr;
7226 tree x = build_global_decl ("x", integer_type_node);
7227 tree y = build_global_decl ("y", integer_type_node);
7229 test_region_model_context ctxt;
7230 region_model model (&mgr);
7231 const svalue *x_init = model.get_rvalue (x, &ctxt);
7232 const svalue *y_init = model.get_rvalue (y, &ctxt);
7233 const region *x_reg = model.get_lvalue (x, &ctxt);
7234 ASSERT_EQ (x_init, mgr.get_or_create_initial_value (x_reg));
7236 /* "(int)x" -> "x". */
7237 ASSERT_EQ (x_init, mgr.get_or_create_cast (integer_type_node, x_init));
7239 /* "(void *)x" -> something other than "x". */
7240 ASSERT_NE (x_init, mgr.get_or_create_cast (ptr_type_node, x_init));
7242 /* "!(x == y)" -> "x != y". */
7243 ASSERT_EQ (mgr.get_or_create_unaryop
7244 (boolean_type_node, TRUTH_NOT_EXPR,
7245 mgr.get_or_create_binop (boolean_type_node, EQ_EXPR,
7246 x_init, y_init)),
7247 mgr.get_or_create_binop (boolean_type_node, NE_EXPR,
7248 x_init, y_init));
7249 /* "!(x > y)" -> "x <= y". */
7250 ASSERT_EQ (mgr.get_or_create_unaryop
7251 (boolean_type_node, TRUTH_NOT_EXPR,
7252 mgr.get_or_create_binop (boolean_type_node, GT_EXPR,
7253 x_init, y_init)),
7254 mgr.get_or_create_binop (boolean_type_node, LE_EXPR,
7255 x_init, y_init));
7258 /* Verify that binops on constant svalues are folded. */
7260 static void
7261 test_binop_svalue_folding ()
7263 #define NUM_CSTS 10
7264 tree cst_int[NUM_CSTS];
7265 region_model_manager mgr;
7266 const svalue *cst_sval[NUM_CSTS];
7267 for (int i = 0; i < NUM_CSTS; i++)
7269 cst_int[i] = build_int_cst (integer_type_node, i);
7270 cst_sval[i] = mgr.get_or_create_constant_svalue (cst_int[i]);
7271 ASSERT_EQ (cst_sval[i]->get_kind (), SK_CONSTANT);
7272 ASSERT_EQ (cst_sval[i]->maybe_get_constant (), cst_int[i]);
7275 for (int i = 0; i < NUM_CSTS; i++)
7276 for (int j = 0; j < NUM_CSTS; j++)
7278 if (i != j)
7279 ASSERT_NE (cst_sval[i], cst_sval[j]);
7280 if (i + j < NUM_CSTS)
7282 const svalue *sum
7283 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7284 cst_sval[i], cst_sval[j]);
7285 ASSERT_EQ (sum, cst_sval[i + j]);
7287 if (i - j >= 0)
7289 const svalue *difference
7290 = mgr.get_or_create_binop (integer_type_node, MINUS_EXPR,
7291 cst_sval[i], cst_sval[j]);
7292 ASSERT_EQ (difference, cst_sval[i - j]);
7294 if (i * j < NUM_CSTS)
7296 const svalue *product
7297 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7298 cst_sval[i], cst_sval[j]);
7299 ASSERT_EQ (product, cst_sval[i * j]);
7301 const svalue *eq = mgr.get_or_create_binop (integer_type_node, EQ_EXPR,
7302 cst_sval[i], cst_sval[j]);
7303 ASSERT_EQ (eq, i == j ? cst_sval[1] : cst_sval [0]);
7304 const svalue *neq = mgr.get_or_create_binop (integer_type_node, NE_EXPR,
7305 cst_sval[i], cst_sval[j]);
7306 ASSERT_EQ (neq, i != j ? cst_sval[1] : cst_sval [0]);
7307 // etc
7310 tree x = build_global_decl ("x", integer_type_node);
7312 test_region_model_context ctxt;
7313 region_model model (&mgr);
7314 const svalue *x_init = model.get_rvalue (x, &ctxt);
7316 /* PLUS_EXPR folding. */
7317 const svalue *x_init_plus_zero
7318 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7319 x_init, cst_sval[0]);
7320 ASSERT_EQ (x_init_plus_zero, x_init);
7321 const svalue *zero_plus_x_init
7322 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7323 cst_sval[0], x_init);
7324 ASSERT_EQ (zero_plus_x_init, x_init);
7326 /* MULT_EXPR folding. */
7327 const svalue *x_init_times_zero
7328 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7329 x_init, cst_sval[0]);
7330 ASSERT_EQ (x_init_times_zero, cst_sval[0]);
7331 const svalue *zero_times_x_init
7332 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7333 cst_sval[0], x_init);
7334 ASSERT_EQ (zero_times_x_init, cst_sval[0]);
7336 const svalue *x_init_times_one
7337 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7338 x_init, cst_sval[1]);
7339 ASSERT_EQ (x_init_times_one, x_init);
7340 const svalue *one_times_x_init
7341 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7342 cst_sval[1], x_init);
7343 ASSERT_EQ (one_times_x_init, x_init);
7345 // etc
7346 // TODO: do we want to use the match-and-simplify DSL for this?
7348 /* Verify that binops put any constants on the RHS. */
7349 const svalue *four_times_x_init
7350 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7351 cst_sval[4], x_init);
7352 const svalue *x_init_times_four
7353 = mgr.get_or_create_binop (integer_type_node, MULT_EXPR,
7354 x_init, cst_sval[4]);
7355 ASSERT_EQ (four_times_x_init, x_init_times_four);
7356 const binop_svalue *binop = four_times_x_init->dyn_cast_binop_svalue ();
7357 ASSERT_EQ (binop->get_op (), MULT_EXPR);
7358 ASSERT_EQ (binop->get_arg0 (), x_init);
7359 ASSERT_EQ (binop->get_arg1 (), cst_sval[4]);
7361 /* Verify that ((x + 1) + 1) == (x + 2). */
7362 const svalue *x_init_plus_one
7363 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7364 x_init, cst_sval[1]);
7365 const svalue *x_init_plus_two
7366 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7367 x_init, cst_sval[2]);
7368 const svalue *x_init_plus_one_plus_one
7369 = mgr.get_or_create_binop (integer_type_node, PLUS_EXPR,
7370 x_init_plus_one, cst_sval[1]);
7371 ASSERT_EQ (x_init_plus_one_plus_one, x_init_plus_two);
7373 /* Verify various binops on booleans. */
7375 const svalue *sval_true = mgr.get_or_create_int_cst (boolean_type_node, 1);
7376 const svalue *sval_false = mgr.get_or_create_int_cst (boolean_type_node, 0);
7377 const svalue *sval_unknown
7378 = mgr.get_or_create_unknown_svalue (boolean_type_node);
7379 const placeholder_svalue sval_placeholder (mgr.alloc_symbol_id (),
7380 boolean_type_node, "v");
7381 for (auto op : {BIT_IOR_EXPR, TRUTH_OR_EXPR})
7383 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7384 sval_true, sval_unknown),
7385 sval_true);
7386 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7387 sval_false, sval_unknown),
7388 sval_unknown);
7389 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7390 sval_false, &sval_placeholder),
7391 &sval_placeholder);
7393 for (auto op : {BIT_AND_EXPR, TRUTH_AND_EXPR})
7395 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7396 sval_false, sval_unknown),
7397 sval_false);
7398 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7399 sval_true, sval_unknown),
7400 sval_unknown);
7401 ASSERT_EQ (mgr.get_or_create_binop (boolean_type_node, op,
7402 sval_true, &sval_placeholder),
7403 &sval_placeholder);
7408 /* Verify that sub_svalues are folded as expected. */
7410 static void
7411 test_sub_svalue_folding ()
7413 coord_test ct;
7414 tree c = build_global_decl ("c", ct.m_coord_type);
7415 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7416 c, ct.m_x_field, NULL_TREE);
7418 region_model_manager mgr;
7419 region_model model (&mgr);
7420 test_region_model_context ctxt;
7421 const region *c_x_reg = model.get_lvalue (c_x, &ctxt);
7423 /* Verify that sub_svalue of "unknown" simply
7424 yields an unknown. */
7426 const svalue *unknown = mgr.get_or_create_unknown_svalue (ct.m_coord_type);
7427 const svalue *sub = mgr.get_or_create_sub_svalue (TREE_TYPE (ct.m_x_field),
7428 unknown, c_x_reg);
7429 ASSERT_EQ (sub->get_kind (), SK_UNKNOWN);
7430 ASSERT_EQ (sub->get_type (), TREE_TYPE (ct.m_x_field));
7433 /* Get BIT within VAL as a symbolic value within MGR. */
7435 static const svalue *
7436 get_bit (region_model_manager *mgr,
7437 bit_offset_t bit,
7438 unsigned HOST_WIDE_INT val)
7440 const svalue *inner_svalue
7441 = mgr->get_or_create_int_cst (unsigned_type_node, val);
7442 return mgr->get_or_create_bits_within (boolean_type_node,
7443 bit_range (bit, 1),
7444 inner_svalue);
7447 /* Verify that bits_within_svalues are folded as expected. */
7449 static void
7450 test_bits_within_svalue_folding ()
7452 region_model_manager mgr;
7454 const svalue *zero = mgr.get_or_create_int_cst (boolean_type_node, 0);
7455 const svalue *one = mgr.get_or_create_int_cst (boolean_type_node, 1);
7458 const unsigned val = 0x0000;
7459 for (unsigned bit = 0; bit < 16; bit++)
7460 ASSERT_EQ (get_bit (&mgr, bit, val), zero);
7464 const unsigned val = 0x0001;
7465 ASSERT_EQ (get_bit (&mgr, 0, val), one);
7466 for (unsigned bit = 1; bit < 16; bit++)
7467 ASSERT_EQ (get_bit (&mgr, bit, val), zero);
7471 const unsigned val = 0x8000;
7472 for (unsigned bit = 0; bit < 15; bit++)
7473 ASSERT_EQ (get_bit (&mgr, bit, val), zero);
7474 ASSERT_EQ (get_bit (&mgr, 15, val), one);
7478 const unsigned val = 0xFFFF;
7479 for (unsigned bit = 0; bit < 16; bit++)
7480 ASSERT_EQ (get_bit (&mgr, bit, val), one);
7484 /* Test that region::descendent_of_p works as expected. */
7486 static void
7487 test_descendent_of_p ()
7489 region_model_manager mgr;
7490 const region *stack = mgr.get_stack_region ();
7491 const region *heap = mgr.get_heap_region ();
7492 const region *code = mgr.get_code_region ();
7493 const region *globals = mgr.get_globals_region ();
7495 /* descendent_of_p should return true when used on the region itself. */
7496 ASSERT_TRUE (stack->descendent_of_p (stack));
7497 ASSERT_FALSE (stack->descendent_of_p (heap));
7498 ASSERT_FALSE (stack->descendent_of_p (code));
7499 ASSERT_FALSE (stack->descendent_of_p (globals));
7501 tree x = build_global_decl ("x", integer_type_node);
7502 const region *x_reg = mgr.get_region_for_global (x);
7503 ASSERT_TRUE (x_reg->descendent_of_p (globals));
7505 /* A cast_region should be a descendent of the original region. */
7506 const region *cast_reg = mgr.get_cast_region (x_reg, ptr_type_node);
7507 ASSERT_TRUE (cast_reg->descendent_of_p (x_reg));
7510 /* Verify that bit_range_region works as expected. */
7512 static void
7513 test_bit_range_regions ()
7515 tree x = build_global_decl ("x", integer_type_node);
7516 region_model_manager mgr;
7517 const region *x_reg = mgr.get_region_for_global (x);
7518 const region *byte0
7519 = mgr.get_bit_range (x_reg, char_type_node, bit_range (0, 8));
7520 const region *byte1
7521 = mgr.get_bit_range (x_reg, char_type_node, bit_range (8, 8));
7522 ASSERT_TRUE (byte0->descendent_of_p (x_reg));
7523 ASSERT_TRUE (byte1->descendent_of_p (x_reg));
7524 ASSERT_NE (byte0, byte1);
7527 /* Verify that simple assignments work as expected. */
7529 static void
7530 test_assignment ()
7532 tree int_0 = build_int_cst (integer_type_node, 0);
7533 tree x = build_global_decl ("x", integer_type_node);
7534 tree y = build_global_decl ("y", integer_type_node);
7536 /* "x == 0", then use of y, then "y = 0;". */
7537 region_model_manager mgr;
7538 region_model model (&mgr);
7539 ADD_SAT_CONSTRAINT (model, x, EQ_EXPR, int_0);
7540 ASSERT_CONDITION_UNKNOWN (model, y, EQ_EXPR, int_0);
7541 model.set_value (model.get_lvalue (y, NULL),
7542 model.get_rvalue (int_0, NULL),
7543 NULL);
7544 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, int_0);
7545 ASSERT_CONDITION_TRUE (model, y, EQ_EXPR, x);
7548 /* Verify that compound assignments work as expected. */
7550 static void
7551 test_compound_assignment ()
7553 coord_test ct;
7555 tree c = build_global_decl ("c", ct.m_coord_type);
7556 tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7557 c, ct.m_x_field, NULL_TREE);
7558 tree c_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7559 c, ct.m_y_field, NULL_TREE);
7560 tree d = build_global_decl ("d", ct.m_coord_type);
7561 tree d_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
7562 d, ct.m_x_field, NULL_TREE);
7563 tree d_y = build3 (COMPONENT_REF, TREE_TYPE (ct.m_y_field),
7564 d, ct.m_y_field, NULL_TREE);
7566 tree int_17 = build_int_cst (integer_type_node, 17);
7567 tree int_m3 = build_int_cst (integer_type_node, -3);
7569 region_model_manager mgr;
7570 region_model model (&mgr);
7571 model.set_value (c_x, int_17, NULL);
7572 model.set_value (c_y, int_m3, NULL);
7574 /* Copy c to d. */
7575 const svalue *sval = model.get_rvalue (c, NULL);
7576 model.set_value (model.get_lvalue (d, NULL), sval, NULL);
7578 /* Check that the fields have the same svalues. */
7579 ASSERT_EQ (model.get_rvalue (c_x, NULL), model.get_rvalue (d_x, NULL));
7580 ASSERT_EQ (model.get_rvalue (c_y, NULL), model.get_rvalue (d_y, NULL));
7583 /* Verify the details of pushing and popping stack frames. */
7585 static void
7586 test_stack_frames ()
7588 tree int_42 = build_int_cst (integer_type_node, 42);
7589 tree int_10 = build_int_cst (integer_type_node, 10);
7590 tree int_5 = build_int_cst (integer_type_node, 5);
7591 tree int_0 = build_int_cst (integer_type_node, 0);
7593 auto_vec <tree> param_types;
7594 tree parent_fndecl = make_fndecl (integer_type_node,
7595 "parent_fn",
7596 param_types);
7597 allocate_struct_function (parent_fndecl, true);
7599 tree child_fndecl = make_fndecl (integer_type_node,
7600 "child_fn",
7601 param_types);
7602 allocate_struct_function (child_fndecl, true);
7604 /* "a" and "b" in the parent frame. */
7605 tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7606 get_identifier ("a"),
7607 integer_type_node);
7608 DECL_CONTEXT (a) = parent_fndecl;
7609 tree b = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7610 get_identifier ("b"),
7611 integer_type_node);
7612 DECL_CONTEXT (b) = parent_fndecl;
7613 /* "x" and "y" in a child frame. */
7614 tree x = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7615 get_identifier ("x"),
7616 integer_type_node);
7617 DECL_CONTEXT (x) = child_fndecl;
7618 tree y = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7619 get_identifier ("y"),
7620 integer_type_node);
7621 DECL_CONTEXT (y) = child_fndecl;
7623 /* "p" global. */
7624 tree p = build_global_decl ("p", ptr_type_node);
7626 /* "q" global. */
7627 tree q = build_global_decl ("q", ptr_type_node);
7629 region_model_manager mgr;
7630 test_region_model_context ctxt;
7631 region_model model (&mgr);
7633 /* Push stack frame for "parent_fn". */
7634 const region *parent_frame_reg
7635 = model.push_frame (DECL_STRUCT_FUNCTION (parent_fndecl),
7636 NULL, &ctxt);
7637 ASSERT_EQ (model.get_current_frame (), parent_frame_reg);
7638 ASSERT_TRUE (model.region_exists_p (parent_frame_reg));
7639 const region *a_in_parent_reg = model.get_lvalue (a, &ctxt);
7640 model.set_value (a_in_parent_reg,
7641 model.get_rvalue (int_42, &ctxt),
7642 &ctxt);
7643 ASSERT_EQ (a_in_parent_reg->maybe_get_frame_region (), parent_frame_reg);
7645 model.add_constraint (b, LT_EXPR, int_10, &ctxt);
7646 ASSERT_EQ (model.eval_condition (b, LT_EXPR, int_10, &ctxt),
7647 tristate (tristate::TS_TRUE));
7649 /* Push stack frame for "child_fn". */
7650 const region *child_frame_reg
7651 = model.push_frame (DECL_STRUCT_FUNCTION (child_fndecl), NULL, &ctxt);
7652 ASSERT_EQ (model.get_current_frame (), child_frame_reg);
7653 ASSERT_TRUE (model.region_exists_p (child_frame_reg));
7654 const region *x_in_child_reg = model.get_lvalue (x, &ctxt);
7655 model.set_value (x_in_child_reg,
7656 model.get_rvalue (int_0, &ctxt),
7657 &ctxt);
7658 ASSERT_EQ (x_in_child_reg->maybe_get_frame_region (), child_frame_reg);
7660 model.add_constraint (y, NE_EXPR, int_5, &ctxt);
7661 ASSERT_EQ (model.eval_condition (y, NE_EXPR, int_5, &ctxt),
7662 tristate (tristate::TS_TRUE));
7664 /* Point a global pointer at a local in the child frame: p = &x. */
7665 const region *p_in_globals_reg = model.get_lvalue (p, &ctxt);
7666 model.set_value (p_in_globals_reg,
7667 mgr.get_ptr_svalue (ptr_type_node, x_in_child_reg),
7668 &ctxt);
7669 ASSERT_EQ (p_in_globals_reg->maybe_get_frame_region (), NULL);
7671 /* Point another global pointer at p: q = &p. */
7672 const region *q_in_globals_reg = model.get_lvalue (q, &ctxt);
7673 model.set_value (q_in_globals_reg,
7674 mgr.get_ptr_svalue (ptr_type_node, p_in_globals_reg),
7675 &ctxt);
7677 /* Test region::descendent_of_p. */
7678 ASSERT_TRUE (child_frame_reg->descendent_of_p (child_frame_reg));
7679 ASSERT_TRUE (x_in_child_reg->descendent_of_p (child_frame_reg));
7680 ASSERT_FALSE (a_in_parent_reg->descendent_of_p (child_frame_reg));
7682 /* Pop the "child_fn" frame from the stack. */
7683 model.pop_frame (NULL, NULL, &ctxt);
7684 ASSERT_FALSE (model.region_exists_p (child_frame_reg));
7685 ASSERT_TRUE (model.region_exists_p (parent_frame_reg));
7687 /* Verify that p (which was pointing at the local "x" in the popped
7688 frame) has been poisoned. */
7689 const svalue *new_p_sval = model.get_rvalue (p, NULL);
7690 ASSERT_EQ (new_p_sval->get_kind (), SK_POISONED);
7691 ASSERT_EQ (new_p_sval->dyn_cast_poisoned_svalue ()->get_poison_kind (),
7692 POISON_KIND_POPPED_STACK);
7694 /* Verify that q still points to p, in spite of the region
7695 renumbering. */
7696 const svalue *new_q_sval = model.get_rvalue (q, &ctxt);
7697 ASSERT_EQ (new_q_sval->get_kind (), SK_REGION);
7698 ASSERT_EQ (new_q_sval->maybe_get_region (),
7699 model.get_lvalue (p, &ctxt));
7701 /* Verify that top of stack has been updated. */
7702 ASSERT_EQ (model.get_current_frame (), parent_frame_reg);
7704 /* Verify locals in parent frame. */
7705 /* Verify "a" still has its value. */
7706 const svalue *new_a_sval = model.get_rvalue (a, &ctxt);
7707 ASSERT_EQ (new_a_sval->get_kind (), SK_CONSTANT);
7708 ASSERT_EQ (new_a_sval->dyn_cast_constant_svalue ()->get_constant (),
7709 int_42);
7710 /* Verify "b" still has its constraint. */
7711 ASSERT_EQ (model.eval_condition (b, LT_EXPR, int_10, &ctxt),
7712 tristate (tristate::TS_TRUE));
7715 /* Verify that get_representative_path_var works as expected, that
7716 we can map from regions to parms and back within a recursive call
7717 stack. */
7719 static void
7720 test_get_representative_path_var ()
7722 auto_vec <tree> param_types;
7723 tree fndecl = make_fndecl (integer_type_node,
7724 "factorial",
7725 param_types);
7726 allocate_struct_function (fndecl, true);
7728 /* Parm "n". */
7729 tree n = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7730 get_identifier ("n"),
7731 integer_type_node);
7732 DECL_CONTEXT (n) = fndecl;
7734 region_model_manager mgr;
7735 test_region_model_context ctxt;
7736 region_model model (&mgr);
7738 /* Push 5 stack frames for "factorial", each with a param */
7739 auto_vec<const region *> parm_regs;
7740 auto_vec<const svalue *> parm_svals;
7741 for (int depth = 0; depth < 5; depth++)
7743 const region *frame_n_reg
7744 = model.push_frame (DECL_STRUCT_FUNCTION (fndecl), NULL, &ctxt);
7745 const region *parm_n_reg = model.get_lvalue (path_var (n, depth), &ctxt);
7746 parm_regs.safe_push (parm_n_reg);
7748 ASSERT_EQ (parm_n_reg->get_parent_region (), frame_n_reg);
7749 const svalue *sval_n = mgr.get_or_create_initial_value (parm_n_reg);
7750 parm_svals.safe_push (sval_n);
7753 /* Verify that we can recognize that the regions are the parms,
7754 at every depth. */
7755 for (int depth = 0; depth < 5; depth++)
7758 svalue_set visited;
7759 ASSERT_EQ (model.get_representative_path_var (parm_regs[depth],
7760 &visited),
7761 path_var (n, depth + 1));
7763 /* ...and that we can lookup lvalues for locals for all frames,
7764 not just the top. */
7765 ASSERT_EQ (model.get_lvalue (path_var (n, depth), NULL),
7766 parm_regs[depth]);
7767 /* ...and that we can locate the svalues. */
7769 svalue_set visited;
7770 ASSERT_EQ (model.get_representative_path_var (parm_svals[depth],
7771 &visited),
7772 path_var (n, depth + 1));
7777 /* Ensure that region_model::operator== works as expected. */
7779 static void
7780 test_equality_1 ()
7782 tree int_42 = build_int_cst (integer_type_node, 42);
7783 tree int_17 = build_int_cst (integer_type_node, 17);
7785 /* Verify that "empty" region_model instances are equal to each other. */
7786 region_model_manager mgr;
7787 region_model model0 (&mgr);
7788 region_model model1 (&mgr);
7789 ASSERT_EQ (model0, model1);
7791 /* Verify that setting state in model1 makes the models non-equal. */
7792 tree x = build_global_decl ("x", integer_type_node);
7793 model0.set_value (x, int_42, NULL);
7794 ASSERT_EQ (model0.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
7795 ASSERT_NE (model0, model1);
7797 /* Verify the copy-ctor. */
7798 region_model model2 (model0);
7799 ASSERT_EQ (model0, model2);
7800 ASSERT_EQ (model2.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
7801 ASSERT_NE (model1, model2);
7803 /* Verify that models obtained from copy-ctor are independently editable
7804 w/o affecting the original model. */
7805 model2.set_value (x, int_17, NULL);
7806 ASSERT_NE (model0, model2);
7807 ASSERT_EQ (model2.get_rvalue (x, NULL)->maybe_get_constant (), int_17);
7808 ASSERT_EQ (model0.get_rvalue (x, NULL)->maybe_get_constant (), int_42);
7811 /* Verify that region models for
7812 x = 42; y = 113;
7814 y = 113; x = 42;
7815 are equal. */
7817 static void
7818 test_canonicalization_2 ()
7820 tree int_42 = build_int_cst (integer_type_node, 42);
7821 tree int_113 = build_int_cst (integer_type_node, 113);
7822 tree x = build_global_decl ("x", integer_type_node);
7823 tree y = build_global_decl ("y", integer_type_node);
7825 region_model_manager mgr;
7826 region_model model0 (&mgr);
7827 model0.set_value (model0.get_lvalue (x, NULL),
7828 model0.get_rvalue (int_42, NULL),
7829 NULL);
7830 model0.set_value (model0.get_lvalue (y, NULL),
7831 model0.get_rvalue (int_113, NULL),
7832 NULL);
7834 region_model model1 (&mgr);
7835 model1.set_value (model1.get_lvalue (y, NULL),
7836 model1.get_rvalue (int_113, NULL),
7837 NULL);
7838 model1.set_value (model1.get_lvalue (x, NULL),
7839 model1.get_rvalue (int_42, NULL),
7840 NULL);
7842 ASSERT_EQ (model0, model1);
7845 /* Verify that constraints for
7846 x > 3 && y > 42
7848 y > 42 && x > 3
7849 are equal after canonicalization. */
7851 static void
7852 test_canonicalization_3 ()
7854 tree int_3 = build_int_cst (integer_type_node, 3);
7855 tree int_42 = build_int_cst (integer_type_node, 42);
7856 tree x = build_global_decl ("x", integer_type_node);
7857 tree y = build_global_decl ("y", integer_type_node);
7859 region_model_manager mgr;
7860 region_model model0 (&mgr);
7861 model0.add_constraint (x, GT_EXPR, int_3, NULL);
7862 model0.add_constraint (y, GT_EXPR, int_42, NULL);
7864 region_model model1 (&mgr);
7865 model1.add_constraint (y, GT_EXPR, int_42, NULL);
7866 model1.add_constraint (x, GT_EXPR, int_3, NULL);
7868 model0.canonicalize ();
7869 model1.canonicalize ();
7870 ASSERT_EQ (model0, model1);
7873 /* Verify that we can canonicalize a model containing NaN and other real
7874 constants. */
7876 static void
7877 test_canonicalization_4 ()
7879 auto_vec<tree> csts;
7880 append_interesting_constants (&csts);
7882 region_model_manager mgr;
7883 region_model model (&mgr);
7885 for (tree cst : csts)
7886 model.get_rvalue (cst, NULL);
7888 model.canonicalize ();
7891 /* Assert that if we have two region_model instances
7892 with values VAL_A and VAL_B for EXPR that they are
7893 mergable. Write the merged model to *OUT_MERGED_MODEL,
7894 and the merged svalue ptr to *OUT_MERGED_SVALUE.
7895 If VAL_A or VAL_B are NULL_TREE, don't populate EXPR
7896 for that region_model. */
7898 static void
7899 assert_region_models_merge (tree expr, tree val_a, tree val_b,
7900 region_model *out_merged_model,
7901 const svalue **out_merged_svalue)
7903 region_model_manager *mgr = out_merged_model->get_manager ();
7904 program_point point (program_point::origin (*mgr));
7905 test_region_model_context ctxt;
7906 region_model model0 (mgr);
7907 region_model model1 (mgr);
7908 if (val_a)
7909 model0.set_value (model0.get_lvalue (expr, &ctxt),
7910 model0.get_rvalue (val_a, &ctxt),
7911 &ctxt);
7912 if (val_b)
7913 model1.set_value (model1.get_lvalue (expr, &ctxt),
7914 model1.get_rvalue (val_b, &ctxt),
7915 &ctxt);
7917 /* They should be mergeable. */
7918 ASSERT_TRUE (model0.can_merge_with_p (model1, point, out_merged_model));
7919 *out_merged_svalue = out_merged_model->get_rvalue (expr, &ctxt);
7922 /* Verify that we can merge region_model instances. */
7924 static void
7925 test_state_merging ()
7927 tree int_42 = build_int_cst (integer_type_node, 42);
7928 tree int_113 = build_int_cst (integer_type_node, 113);
7929 tree x = build_global_decl ("x", integer_type_node);
7930 tree y = build_global_decl ("y", integer_type_node);
7931 tree z = build_global_decl ("z", integer_type_node);
7932 tree p = build_global_decl ("p", ptr_type_node);
7934 tree addr_of_y = build1 (ADDR_EXPR, ptr_type_node, y);
7935 tree addr_of_z = build1 (ADDR_EXPR, ptr_type_node, z);
7937 auto_vec <tree> param_types;
7938 tree test_fndecl = make_fndecl (integer_type_node, "test_fn", param_types);
7939 allocate_struct_function (test_fndecl, true);
7941 /* Param "a". */
7942 tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7943 get_identifier ("a"),
7944 integer_type_node);
7945 DECL_CONTEXT (a) = test_fndecl;
7946 tree addr_of_a = build1 (ADDR_EXPR, ptr_type_node, a);
7948 /* Param "q", a pointer. */
7949 tree q = build_decl (UNKNOWN_LOCATION, PARM_DECL,
7950 get_identifier ("q"),
7951 ptr_type_node);
7952 DECL_CONTEXT (q) = test_fndecl;
7954 region_model_manager mgr;
7955 program_point point (program_point::origin (mgr));
7958 region_model model0 (&mgr);
7959 region_model model1 (&mgr);
7960 region_model merged (&mgr);
7961 /* Verify empty models can be merged. */
7962 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
7963 ASSERT_EQ (model0, merged);
7966 /* Verify that we can merge two contradictory constraints on the
7967 value for a global. */
7968 /* TODO: verify that the merged model doesn't have a value for
7969 the global */
7971 region_model model0 (&mgr);
7972 region_model model1 (&mgr);
7973 region_model merged (&mgr);
7974 test_region_model_context ctxt;
7975 model0.add_constraint (x, EQ_EXPR, int_42, &ctxt);
7976 model1.add_constraint (x, EQ_EXPR, int_113, &ctxt);
7977 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
7978 ASSERT_NE (model0, merged);
7979 ASSERT_NE (model1, merged);
7982 /* Verify handling of a PARM_DECL. */
7984 test_region_model_context ctxt;
7985 region_model model0 (&mgr);
7986 region_model model1 (&mgr);
7987 ASSERT_EQ (model0.get_stack_depth (), 0);
7988 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt);
7989 ASSERT_EQ (model0.get_stack_depth (), 1);
7990 model1.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, &ctxt);
7992 placeholder_svalue test_sval (mgr.alloc_symbol_id (),
7993 integer_type_node, "test sval");
7994 model0.set_value (model0.get_lvalue (a, &ctxt), &test_sval, &ctxt);
7995 model1.set_value (model1.get_lvalue (a, &ctxt), &test_sval, &ctxt);
7996 ASSERT_EQ (model0, model1);
7998 /* They should be mergeable, and the result should be the same. */
7999 region_model merged (&mgr);
8000 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8001 ASSERT_EQ (model0, merged);
8002 /* In particular, "a" should have the placeholder value. */
8003 ASSERT_EQ (merged.get_rvalue (a, &ctxt), &test_sval);
8006 /* Verify handling of a global. */
8008 test_region_model_context ctxt;
8009 region_model model0 (&mgr);
8010 region_model model1 (&mgr);
8012 placeholder_svalue test_sval (mgr.alloc_symbol_id (),
8013 integer_type_node, "test sval");
8014 model0.set_value (model0.get_lvalue (x, &ctxt), &test_sval, &ctxt);
8015 model1.set_value (model1.get_lvalue (x, &ctxt), &test_sval, &ctxt);
8016 ASSERT_EQ (model0, model1);
8018 /* They should be mergeable, and the result should be the same. */
8019 region_model merged (&mgr);
8020 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8021 ASSERT_EQ (model0, merged);
8022 /* In particular, "x" should have the placeholder value. */
8023 ASSERT_EQ (merged.get_rvalue (x, &ctxt), &test_sval);
8026 /* Use global-handling to verify various combinations of values. */
8028 /* Two equal constant values. */
8030 region_model merged (&mgr);
8031 const svalue *merged_x_sval;
8032 assert_region_models_merge (x, int_42, int_42, &merged, &merged_x_sval);
8034 /* In particular, there should be a constant value for "x". */
8035 ASSERT_EQ (merged_x_sval->get_kind (), SK_CONSTANT);
8036 ASSERT_EQ (merged_x_sval->dyn_cast_constant_svalue ()->get_constant (),
8037 int_42);
8040 /* Two non-equal constant values. */
8042 region_model merged (&mgr);
8043 const svalue *merged_x_sval;
8044 assert_region_models_merge (x, int_42, int_113, &merged, &merged_x_sval);
8046 /* In particular, there should be a "widening" value for "x". */
8047 ASSERT_EQ (merged_x_sval->get_kind (), SK_WIDENING);
8050 /* Initial and constant. */
8052 region_model merged (&mgr);
8053 const svalue *merged_x_sval;
8054 assert_region_models_merge (x, NULL_TREE, int_113, &merged, &merged_x_sval);
8056 /* In particular, there should be an unknown value for "x". */
8057 ASSERT_EQ (merged_x_sval->get_kind (), SK_UNKNOWN);
8060 /* Constant and initial. */
8062 region_model merged (&mgr);
8063 const svalue *merged_x_sval;
8064 assert_region_models_merge (x, int_42, NULL_TREE, &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 /* Unknown and constant. */
8071 // TODO
8073 /* Pointers: NULL and NULL. */
8074 // TODO
8076 /* Pointers: NULL and non-NULL. */
8077 // TODO
8079 /* Pointers: non-NULL and non-NULL: ptr to a local. */
8081 region_model model0 (&mgr);
8082 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8083 model0.set_value (model0.get_lvalue (p, NULL),
8084 model0.get_rvalue (addr_of_a, NULL), NULL);
8086 region_model model1 (model0);
8087 ASSERT_EQ (model0, model1);
8089 /* They should be mergeable, and the result should be the same. */
8090 region_model merged (&mgr);
8091 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8092 ASSERT_EQ (model0, merged);
8095 /* Pointers: non-NULL and non-NULL: ptr to a global. */
8097 region_model merged (&mgr);
8098 /* p == &y in both input models. */
8099 const svalue *merged_p_sval;
8100 assert_region_models_merge (p, addr_of_y, addr_of_y, &merged,
8101 &merged_p_sval);
8103 /* We should get p == &y in the merged model. */
8104 ASSERT_EQ (merged_p_sval->get_kind (), SK_REGION);
8105 const region_svalue *merged_p_ptr
8106 = merged_p_sval->dyn_cast_region_svalue ();
8107 const region *merged_p_star_reg = merged_p_ptr->get_pointee ();
8108 ASSERT_EQ (merged_p_star_reg, merged.get_lvalue (y, NULL));
8111 /* Pointers: non-NULL ptrs to different globals: should be unknown. */
8113 region_model merged (&mgr);
8114 /* x == &y vs x == &z in the input models; these are actually casts
8115 of the ptrs to "int". */
8116 const svalue *merged_x_sval;
8117 // TODO:
8118 assert_region_models_merge (x, addr_of_y, addr_of_z, &merged,
8119 &merged_x_sval);
8121 /* We should get x == unknown in the merged model. */
8122 ASSERT_EQ (merged_x_sval->get_kind (), SK_UNKNOWN);
8125 /* Pointers: non-NULL and non-NULL: ptr to a heap region. */
8127 test_region_model_context ctxt;
8128 region_model model0 (&mgr);
8129 tree size = build_int_cst (size_type_node, 1024);
8130 const svalue *size_sval = mgr.get_or_create_constant_svalue (size);
8131 const region *new_reg
8132 = model0.get_or_create_region_for_heap_alloc (size_sval, &ctxt);
8133 const svalue *ptr_sval = mgr.get_ptr_svalue (ptr_type_node, new_reg);
8134 model0.set_value (model0.get_lvalue (p, &ctxt),
8135 ptr_sval, &ctxt);
8137 region_model model1 (model0);
8139 ASSERT_EQ (model0, model1);
8141 region_model merged (&mgr);
8142 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8144 /* The merged model ought to be identical. */
8145 ASSERT_EQ (model0, merged);
8148 /* Two regions sharing the same placeholder svalue should continue sharing
8149 it after self-merger. */
8151 test_region_model_context ctxt;
8152 region_model model0 (&mgr);
8153 placeholder_svalue placeholder_sval (mgr.alloc_symbol_id (),
8154 integer_type_node, "test");
8155 model0.set_value (model0.get_lvalue (x, &ctxt),
8156 &placeholder_sval, &ctxt);
8157 model0.set_value (model0.get_lvalue (y, &ctxt), &placeholder_sval, &ctxt);
8158 region_model model1 (model0);
8160 /* They should be mergeable, and the result should be the same. */
8161 region_model merged (&mgr);
8162 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8163 ASSERT_EQ (model0, merged);
8165 /* In particular, we should have x == y. */
8166 ASSERT_EQ (merged.eval_condition (x, EQ_EXPR, y, &ctxt),
8167 tristate (tristate::TS_TRUE));
8171 region_model model0 (&mgr);
8172 region_model model1 (&mgr);
8173 test_region_model_context ctxt;
8174 model0.add_constraint (x, EQ_EXPR, int_42, &ctxt);
8175 model1.add_constraint (x, NE_EXPR, int_42, &ctxt);
8176 region_model merged (&mgr);
8177 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
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 model1.add_constraint (x, EQ_EXPR, int_113, &ctxt);
8187 region_model merged (&mgr);
8188 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8191 // TODO: what can't we merge? need at least one such test
8193 /* TODO: various things
8194 - heap regions
8195 - value merging:
8196 - every combination, but in particular
8197 - pairs of regions
8200 /* Views. */
8202 test_region_model_context ctxt;
8203 region_model model0 (&mgr);
8205 const region *x_reg = model0.get_lvalue (x, &ctxt);
8206 const region *x_as_ptr = mgr.get_cast_region (x_reg, ptr_type_node);
8207 model0.set_value (x_as_ptr, model0.get_rvalue (addr_of_y, &ctxt), &ctxt);
8209 region_model model1 (model0);
8210 ASSERT_EQ (model1, model0);
8212 /* They should be mergeable, and the result should be the same. */
8213 region_model merged (&mgr);
8214 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8217 /* Verify that we can merge a model in which a local in an older stack
8218 frame points to a local in a more recent stack frame. */
8220 region_model model0 (&mgr);
8221 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8222 const region *q_in_first_frame = model0.get_lvalue (q, NULL);
8224 /* Push a second frame. */
8225 const region *reg_2nd_frame
8226 = model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8228 /* Have a pointer in the older frame point to a local in the
8229 more recent frame. */
8230 const svalue *sval_ptr = model0.get_rvalue (addr_of_a, NULL);
8231 model0.set_value (q_in_first_frame, sval_ptr, NULL);
8233 /* Verify that it's pointing at the newer frame. */
8234 const region *reg_pointee = sval_ptr->maybe_get_region ();
8235 ASSERT_EQ (reg_pointee->get_parent_region (), reg_2nd_frame);
8237 model0.canonicalize ();
8239 region_model model1 (model0);
8240 ASSERT_EQ (model0, model1);
8242 /* They should be mergeable, and the result should be the same
8243 (after canonicalization, at least). */
8244 region_model merged (&mgr);
8245 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8246 merged.canonicalize ();
8247 ASSERT_EQ (model0, merged);
8250 /* Verify that we can merge a model in which a local points to a global. */
8252 region_model model0 (&mgr);
8253 model0.push_frame (DECL_STRUCT_FUNCTION (test_fndecl), NULL, NULL);
8254 model0.set_value (model0.get_lvalue (q, NULL),
8255 model0.get_rvalue (addr_of_y, NULL), NULL);
8257 region_model model1 (model0);
8258 ASSERT_EQ (model0, model1);
8260 /* They should be mergeable, and the result should be the same
8261 (after canonicalization, at least). */
8262 region_model merged (&mgr);
8263 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8264 ASSERT_EQ (model0, merged);
8268 /* Verify that constraints are correctly merged when merging region_model
8269 instances. */
8271 static void
8272 test_constraint_merging ()
8274 tree int_0 = build_int_cst (integer_type_node, 0);
8275 tree int_5 = build_int_cst (integer_type_node, 5);
8276 tree x = build_global_decl ("x", integer_type_node);
8277 tree y = build_global_decl ("y", integer_type_node);
8278 tree z = build_global_decl ("z", integer_type_node);
8279 tree n = build_global_decl ("n", integer_type_node);
8281 region_model_manager mgr;
8282 test_region_model_context ctxt;
8284 /* model0: 0 <= (x == y) < n. */
8285 region_model model0 (&mgr);
8286 model0.add_constraint (x, EQ_EXPR, y, &ctxt);
8287 model0.add_constraint (x, GE_EXPR, int_0, NULL);
8288 model0.add_constraint (x, LT_EXPR, n, NULL);
8290 /* model1: z != 5 && (0 <= x < n). */
8291 region_model model1 (&mgr);
8292 model1.add_constraint (z, NE_EXPR, int_5, NULL);
8293 model1.add_constraint (x, GE_EXPR, int_0, NULL);
8294 model1.add_constraint (x, LT_EXPR, n, NULL);
8296 /* They should be mergeable; the merged constraints should
8297 be: (0 <= x < n). */
8298 program_point point (program_point::origin (mgr));
8299 region_model merged (&mgr);
8300 ASSERT_TRUE (model0.can_merge_with_p (model1, point, &merged));
8302 ASSERT_EQ (merged.eval_condition (x, GE_EXPR, int_0, &ctxt),
8303 tristate (tristate::TS_TRUE));
8304 ASSERT_EQ (merged.eval_condition (x, LT_EXPR, n, &ctxt),
8305 tristate (tristate::TS_TRUE));
8307 ASSERT_EQ (merged.eval_condition (z, NE_EXPR, int_5, &ctxt),
8308 tristate (tristate::TS_UNKNOWN));
8309 ASSERT_EQ (merged.eval_condition (x, LT_EXPR, y, &ctxt),
8310 tristate (tristate::TS_UNKNOWN));
8313 /* Verify that widening_svalue::eval_condition_without_cm works as
8314 expected. */
8316 static void
8317 test_widening_constraints ()
8319 region_model_manager mgr;
8320 function_point point (program_point::origin (mgr).get_function_point ());
8321 tree int_0 = build_int_cst (integer_type_node, 0);
8322 tree int_m1 = build_int_cst (integer_type_node, -1);
8323 tree int_1 = build_int_cst (integer_type_node, 1);
8324 tree int_256 = build_int_cst (integer_type_node, 256);
8325 test_region_model_context ctxt;
8326 const svalue *int_0_sval = mgr.get_or_create_constant_svalue (int_0);
8327 const svalue *int_1_sval = mgr.get_or_create_constant_svalue (int_1);
8328 const svalue *w_zero_then_one_sval
8329 = mgr.get_or_create_widening_svalue (integer_type_node, point,
8330 int_0_sval, int_1_sval);
8331 const widening_svalue *w_zero_then_one
8332 = w_zero_then_one_sval->dyn_cast_widening_svalue ();
8333 ASSERT_EQ (w_zero_then_one->get_direction (),
8334 widening_svalue::DIR_ASCENDING);
8335 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_m1),
8336 tristate::TS_FALSE);
8337 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_0),
8338 tristate::TS_FALSE);
8339 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_1),
8340 tristate::TS_UNKNOWN);
8341 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LT_EXPR, int_256),
8342 tristate::TS_UNKNOWN);
8344 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_m1),
8345 tristate::TS_FALSE);
8346 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_0),
8347 tristate::TS_UNKNOWN);
8348 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_1),
8349 tristate::TS_UNKNOWN);
8350 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (LE_EXPR, int_256),
8351 tristate::TS_UNKNOWN);
8353 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_m1),
8354 tristate::TS_TRUE);
8355 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_0),
8356 tristate::TS_UNKNOWN);
8357 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_1),
8358 tristate::TS_UNKNOWN);
8359 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GT_EXPR, int_256),
8360 tristate::TS_UNKNOWN);
8362 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_m1),
8363 tristate::TS_TRUE);
8364 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_0),
8365 tristate::TS_TRUE);
8366 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_1),
8367 tristate::TS_UNKNOWN);
8368 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (GE_EXPR, int_256),
8369 tristate::TS_UNKNOWN);
8371 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_m1),
8372 tristate::TS_FALSE);
8373 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_0),
8374 tristate::TS_UNKNOWN);
8375 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_1),
8376 tristate::TS_UNKNOWN);
8377 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (EQ_EXPR, int_256),
8378 tristate::TS_UNKNOWN);
8380 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_m1),
8381 tristate::TS_TRUE);
8382 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_0),
8383 tristate::TS_UNKNOWN);
8384 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_1),
8385 tristate::TS_UNKNOWN);
8386 ASSERT_EQ (w_zero_then_one->eval_condition_without_cm (NE_EXPR, int_256),
8387 tristate::TS_UNKNOWN);
8390 /* Verify merging constraints for states simulating successive iterations
8391 of a loop.
8392 Simulate:
8393 for (i = 0; i < 256; i++)
8394 [...body...]
8395 i.e. this gimple:.
8396 i_15 = 0;
8397 goto <bb 4>;
8399 <bb 4> :
8400 i_11 = PHI <i_15(2), i_23(3)>
8401 if (i_11 <= 255)
8402 goto <bb 3>;
8403 else
8404 goto [AFTER LOOP]
8406 <bb 3> :
8407 [LOOP BODY]
8408 i_23 = i_11 + 1;
8410 and thus these ops (and resultant states):
8411 i_11 = PHI()
8412 {i_11: 0}
8413 add_constraint (i_11 <= 255) [for the true edge]
8414 {i_11: 0} [constraint was a no-op]
8415 i_23 = i_11 + 1;
8416 {i_22: 1}
8417 i_11 = PHI()
8418 {i_11: WIDENED (at phi, 0, 1)}
8419 add_constraint (i_11 <= 255) [for the true edge]
8420 {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}
8421 i_23 = i_11 + 1;
8422 {i_23: (WIDENED (at phi, 0, 1) + 1); WIDENED <= 255}
8423 i_11 = PHI(); merge with state at phi above
8424 {i_11: WIDENED (at phi, 0, 1); WIDENED <= 256}
8425 [changing meaning of "WIDENED" here]
8426 if (i_11 <= 255)
8427 T: {i_11: WIDENED (at phi, 0, 1); WIDENED <= 255}; cache hit
8428 F: {i_11: 256}
8431 static void
8432 test_iteration_1 ()
8434 region_model_manager mgr;
8435 program_point point (program_point::origin (mgr));
8437 tree int_0 = build_int_cst (integer_type_node, 0);
8438 tree int_1 = build_int_cst (integer_type_node, 1);
8439 tree int_256 = build_int_cst (integer_type_node, 256);
8440 tree i = build_global_decl ("i", integer_type_node);
8442 test_region_model_context ctxt;
8444 /* model0: i: 0. */
8445 region_model model0 (&mgr);
8446 model0.set_value (i, int_0, &ctxt);
8448 /* model1: i: 1. */
8449 region_model model1 (&mgr);
8450 model1.set_value (i, int_1, &ctxt);
8452 /* Should merge "i" to a widened value. */
8453 region_model model2 (&mgr);
8454 ASSERT_TRUE (model1.can_merge_with_p (model0, point, &model2));
8455 const svalue *merged_i = model2.get_rvalue (i, &ctxt);
8456 ASSERT_EQ (merged_i->get_kind (), SK_WIDENING);
8457 const widening_svalue *w = merged_i->dyn_cast_widening_svalue ();
8458 ASSERT_EQ (w->get_direction (), widening_svalue::DIR_ASCENDING);
8460 /* Add constraint: i < 256 */
8461 model2.add_constraint (i, LT_EXPR, int_256, &ctxt);
8462 ASSERT_EQ (model2.eval_condition (i, LT_EXPR, int_256, &ctxt),
8463 tristate (tristate::TS_TRUE));
8464 ASSERT_EQ (model2.eval_condition (i, GE_EXPR, int_0, &ctxt),
8465 tristate (tristate::TS_TRUE));
8467 /* Try merging with the initial state. */
8468 region_model model3 (&mgr);
8469 ASSERT_TRUE (model2.can_merge_with_p (model0, point, &model3));
8470 /* Merging the merged value with the initial value should be idempotent,
8471 so that the analysis converges. */
8472 ASSERT_EQ (model3.get_rvalue (i, &ctxt), merged_i);
8473 /* Merger of 0 and a widening value with constraint < CST
8474 should retain the constraint, even though it was implicit
8475 for the 0 case. */
8476 ASSERT_EQ (model3.eval_condition (i, LT_EXPR, int_256, &ctxt),
8477 tristate (tristate::TS_TRUE));
8478 /* ...and we should have equality: the analysis should have converged. */
8479 ASSERT_EQ (model3, model2);
8481 /* "i_23 = i_11 + 1;" */
8482 region_model model4 (model3);
8483 ASSERT_EQ (model4, model2);
8484 model4.set_value (i, build2 (PLUS_EXPR, integer_type_node, i, int_1), &ctxt);
8485 const svalue *plus_one = model4.get_rvalue (i, &ctxt);
8486 ASSERT_EQ (plus_one->get_kind (), SK_BINOP);
8488 /* Try merging with the "i: 1" state. */
8489 region_model model5 (&mgr);
8490 ASSERT_TRUE (model4.can_merge_with_p (model1, point, &model5));
8491 ASSERT_EQ (model5.get_rvalue (i, &ctxt), plus_one);
8492 ASSERT_EQ (model5, model4);
8494 /* "i_11 = PHI();" merge with state at phi above.
8495 For i, we should have a merger of WIDENING with WIDENING + 1,
8496 and this should be WIDENING again. */
8497 region_model model6 (&mgr);
8498 ASSERT_TRUE (model5.can_merge_with_p (model2, point, &model6));
8499 const svalue *merged_widening = model6.get_rvalue (i, &ctxt);
8500 ASSERT_EQ (merged_widening->get_kind (), SK_WIDENING);
8503 /* Verify that if we mark a pointer to a malloc-ed region as non-NULL,
8504 all cast pointers to that region are also known to be non-NULL. */
8506 static void
8507 test_malloc_constraints ()
8509 region_model_manager mgr;
8510 region_model model (&mgr);
8511 tree p = build_global_decl ("p", ptr_type_node);
8512 tree char_star = build_pointer_type (char_type_node);
8513 tree q = build_global_decl ("q", char_star);
8514 tree null_ptr = build_int_cst (ptr_type_node, 0);
8516 const svalue *size_in_bytes
8517 = mgr.get_or_create_unknown_svalue (size_type_node);
8518 const region *reg
8519 = model.get_or_create_region_for_heap_alloc (size_in_bytes, NULL);
8520 const svalue *sval = mgr.get_ptr_svalue (ptr_type_node, reg);
8521 model.set_value (model.get_lvalue (p, NULL), sval, NULL);
8522 model.set_value (q, p, NULL);
8524 ASSERT_CONDITION_UNKNOWN (model, p, NE_EXPR, null_ptr);
8525 ASSERT_CONDITION_UNKNOWN (model, p, EQ_EXPR, null_ptr);
8526 ASSERT_CONDITION_UNKNOWN (model, q, NE_EXPR, null_ptr);
8527 ASSERT_CONDITION_UNKNOWN (model, q, EQ_EXPR, null_ptr);
8529 model.add_constraint (p, NE_EXPR, null_ptr, NULL);
8531 ASSERT_CONDITION_TRUE (model, p, NE_EXPR, null_ptr);
8532 ASSERT_CONDITION_FALSE (model, p, EQ_EXPR, null_ptr);
8533 ASSERT_CONDITION_TRUE (model, q, NE_EXPR, null_ptr);
8534 ASSERT_CONDITION_FALSE (model, q, EQ_EXPR, null_ptr);
8537 /* Smoketest of getting and setting the value of a variable. */
8539 static void
8540 test_var ()
8542 /* "int i;" */
8543 tree i = build_global_decl ("i", integer_type_node);
8545 tree int_17 = build_int_cst (integer_type_node, 17);
8546 tree int_m3 = build_int_cst (integer_type_node, -3);
8548 region_model_manager mgr;
8549 region_model model (&mgr);
8551 const region *i_reg = model.get_lvalue (i, NULL);
8552 ASSERT_EQ (i_reg->get_kind (), RK_DECL);
8554 /* Reading "i" should give a symbolic "initial value". */
8555 const svalue *sval_init = model.get_rvalue (i, NULL);
8556 ASSERT_EQ (sval_init->get_kind (), SK_INITIAL);
8557 ASSERT_EQ (sval_init->dyn_cast_initial_svalue ()->get_region (), i_reg);
8558 /* ..and doing it again should give the same "initial value". */
8559 ASSERT_EQ (model.get_rvalue (i, NULL), sval_init);
8561 /* "i = 17;". */
8562 model.set_value (i, int_17, NULL);
8563 ASSERT_EQ (model.get_rvalue (i, NULL),
8564 model.get_rvalue (int_17, NULL));
8566 /* "i = -3;". */
8567 model.set_value (i, int_m3, NULL);
8568 ASSERT_EQ (model.get_rvalue (i, NULL),
8569 model.get_rvalue (int_m3, NULL));
8571 /* Verify get_offset for "i". */
8573 region_offset offset = i_reg->get_offset (&mgr);
8574 ASSERT_EQ (offset.get_base_region (), i_reg);
8575 ASSERT_EQ (offset.get_bit_offset (), 0);
8579 static void
8580 test_array_2 ()
8582 /* "int arr[10];" */
8583 tree tlen = size_int (10);
8584 tree arr_type
8585 = build_array_type (integer_type_node, build_index_type (tlen));
8586 tree arr = build_global_decl ("arr", arr_type);
8588 /* "int i;" */
8589 tree i = build_global_decl ("i", integer_type_node);
8591 tree int_0 = build_int_cst (integer_type_node, 0);
8592 tree int_1 = build_int_cst (integer_type_node, 1);
8594 tree arr_0 = build4 (ARRAY_REF, integer_type_node,
8595 arr, int_0, NULL_TREE, NULL_TREE);
8596 tree arr_1 = build4 (ARRAY_REF, integer_type_node,
8597 arr, int_1, NULL_TREE, NULL_TREE);
8598 tree arr_i = build4 (ARRAY_REF, integer_type_node,
8599 arr, i, NULL_TREE, NULL_TREE);
8601 tree int_17 = build_int_cst (integer_type_node, 17);
8602 tree int_42 = build_int_cst (integer_type_node, 42);
8603 tree int_m3 = build_int_cst (integer_type_node, -3);
8605 region_model_manager mgr;
8606 region_model model (&mgr);
8607 /* "arr[0] = 17;". */
8608 model.set_value (arr_0, int_17, NULL);
8609 /* "arr[1] = -3;". */
8610 model.set_value (arr_1, int_m3, NULL);
8612 ASSERT_EQ (model.get_rvalue (arr_0, NULL), model.get_rvalue (int_17, NULL));
8613 ASSERT_EQ (model.get_rvalue (arr_1, NULL), model.get_rvalue (int_m3, NULL));
8615 /* Overwrite a pre-existing binding: "arr[1] = 42;". */
8616 model.set_value (arr_1, int_42, NULL);
8617 ASSERT_EQ (model.get_rvalue (arr_1, NULL), model.get_rvalue (int_42, NULL));
8619 /* Verify get_offset for "arr[0]". */
8621 const region *arr_0_reg = model.get_lvalue (arr_0, NULL);
8622 region_offset offset = arr_0_reg->get_offset (&mgr);
8623 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
8624 ASSERT_EQ (offset.get_bit_offset (), 0);
8627 /* Verify get_offset for "arr[1]". */
8629 const region *arr_1_reg = model.get_lvalue (arr_1, NULL);
8630 region_offset offset = arr_1_reg->get_offset (&mgr);
8631 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
8632 ASSERT_EQ (offset.get_bit_offset (), INT_TYPE_SIZE);
8635 /* Verify get_offset for "arr[i]". */
8637 const region *arr_i_reg = model.get_lvalue (arr_i, NULL);
8638 region_offset offset = arr_i_reg->get_offset (&mgr);
8639 ASSERT_EQ (offset.get_base_region (), model.get_lvalue (arr, NULL));
8640 ASSERT_EQ (offset.get_symbolic_byte_offset ()->get_kind (), SK_BINOP);
8643 /* "arr[i] = i;" - this should remove the earlier bindings. */
8644 model.set_value (arr_i, i, NULL);
8645 ASSERT_EQ (model.get_rvalue (arr_i, NULL), model.get_rvalue (i, NULL));
8646 ASSERT_EQ (model.get_rvalue (arr_0, NULL)->get_kind (), SK_UNKNOWN);
8648 /* "arr[0] = 17;" - this should remove the arr[i] binding. */
8649 model.set_value (arr_0, int_17, NULL);
8650 ASSERT_EQ (model.get_rvalue (arr_0, NULL), model.get_rvalue (int_17, NULL));
8651 ASSERT_EQ (model.get_rvalue (arr_i, NULL)->get_kind (), SK_UNKNOWN);
8654 /* Smoketest of dereferencing a pointer via MEM_REF. */
8656 static void
8657 test_mem_ref ()
8660 x = 17;
8661 p = &x;
8664 tree x = build_global_decl ("x", integer_type_node);
8665 tree int_star = build_pointer_type (integer_type_node);
8666 tree p = build_global_decl ("p", int_star);
8668 tree int_17 = build_int_cst (integer_type_node, 17);
8669 tree addr_of_x = build1 (ADDR_EXPR, int_star, x);
8670 tree offset_0 = build_int_cst (integer_type_node, 0);
8671 tree star_p = build2 (MEM_REF, integer_type_node, p, offset_0);
8673 region_model_manager mgr;
8674 region_model model (&mgr);
8676 /* "x = 17;". */
8677 model.set_value (x, int_17, NULL);
8679 /* "p = &x;". */
8680 model.set_value (p, addr_of_x, NULL);
8682 const svalue *sval = model.get_rvalue (star_p, NULL);
8683 ASSERT_EQ (sval->maybe_get_constant (), int_17);
8686 /* Test for a POINTER_PLUS_EXPR followed by a MEM_REF.
8687 Analogous to this code:
8688 void test_6 (int a[10])
8690 __analyzer_eval (a[3] == 42); [should be UNKNOWN]
8691 a[3] = 42;
8692 __analyzer_eval (a[3] == 42); [should be TRUE]
8694 from data-model-1.c, which looks like this at the gimple level:
8695 # __analyzer_eval (a[3] == 42); [should be UNKNOWN]
8696 int *_1 = a_10(D) + 12; # POINTER_PLUS_EXPR
8697 int _2 = *_1; # MEM_REF
8698 _Bool _3 = _2 == 42;
8699 int _4 = (int) _3;
8700 __analyzer_eval (_4);
8702 # a[3] = 42;
8703 int *_5 = a_10(D) + 12; # POINTER_PLUS_EXPR
8704 *_5 = 42; # MEM_REF
8706 # __analyzer_eval (a[3] == 42); [should be TRUE]
8707 int *_6 = a_10(D) + 12; # POINTER_PLUS_EXPR
8708 int _7 = *_6; # MEM_REF
8709 _Bool _8 = _7 == 42;
8710 int _9 = (int) _8;
8711 __analyzer_eval (_9); */
8713 static void
8714 test_POINTER_PLUS_EXPR_then_MEM_REF ()
8716 tree int_star = build_pointer_type (integer_type_node);
8717 tree a = build_global_decl ("a", int_star);
8718 tree offset_12 = build_int_cst (size_type_node, 12);
8719 tree pointer_plus_expr = build2 (POINTER_PLUS_EXPR, int_star, a, offset_12);
8720 tree offset_0 = build_int_cst (integer_type_node, 0);
8721 tree mem_ref = build2 (MEM_REF, integer_type_node,
8722 pointer_plus_expr, offset_0);
8723 region_model_manager mgr;
8724 region_model m (&mgr);
8726 tree int_42 = build_int_cst (integer_type_node, 42);
8727 m.set_value (mem_ref, int_42, NULL);
8728 ASSERT_EQ (m.get_rvalue (mem_ref, NULL)->maybe_get_constant (), int_42);
8731 /* Verify that malloc works. */
8733 static void
8734 test_malloc ()
8736 tree int_star = build_pointer_type (integer_type_node);
8737 tree p = build_global_decl ("p", int_star);
8738 tree n = build_global_decl ("n", integer_type_node);
8739 tree n_times_4 = build2 (MULT_EXPR, size_type_node,
8740 n, build_int_cst (size_type_node, 4));
8742 region_model_manager mgr;
8743 test_region_model_context ctxt;
8744 region_model model (&mgr);
8746 /* "p = malloc (n * 4);". */
8747 const svalue *size_sval = model.get_rvalue (n_times_4, &ctxt);
8748 const region *reg
8749 = model.get_or_create_region_for_heap_alloc (size_sval, &ctxt);
8750 const svalue *ptr = mgr.get_ptr_svalue (int_star, reg);
8751 model.set_value (model.get_lvalue (p, &ctxt), ptr, &ctxt);
8752 ASSERT_EQ (model.get_capacity (reg), size_sval);
8755 /* Verify that alloca works. */
8757 static void
8758 test_alloca ()
8760 auto_vec <tree> param_types;
8761 tree fndecl = make_fndecl (integer_type_node,
8762 "test_fn",
8763 param_types);
8764 allocate_struct_function (fndecl, true);
8767 tree int_star = build_pointer_type (integer_type_node);
8768 tree p = build_global_decl ("p", int_star);
8769 tree n = build_global_decl ("n", integer_type_node);
8770 tree n_times_4 = build2 (MULT_EXPR, size_type_node,
8771 n, build_int_cst (size_type_node, 4));
8773 region_model_manager mgr;
8774 test_region_model_context ctxt;
8775 region_model model (&mgr);
8777 /* Push stack frame. */
8778 const region *frame_reg
8779 = model.push_frame (DECL_STRUCT_FUNCTION (fndecl),
8780 NULL, &ctxt);
8781 /* "p = alloca (n * 4);". */
8782 const svalue *size_sval = model.get_rvalue (n_times_4, &ctxt);
8783 const region *reg = model.create_region_for_alloca (size_sval, &ctxt);
8784 ASSERT_EQ (reg->get_parent_region (), frame_reg);
8785 const svalue *ptr = mgr.get_ptr_svalue (int_star, reg);
8786 model.set_value (model.get_lvalue (p, &ctxt), ptr, &ctxt);
8787 ASSERT_EQ (model.get_capacity (reg), size_sval);
8789 /* Verify that the pointers to the alloca region are replaced by
8790 poisoned values when the frame is popped. */
8791 model.pop_frame (NULL, NULL, &ctxt);
8792 ASSERT_EQ (model.get_rvalue (p, NULL)->get_kind (), SK_POISONED);
8795 /* Verify that svalue::involves_p works. */
8797 static void
8798 test_involves_p ()
8800 region_model_manager mgr;
8801 tree int_star = build_pointer_type (integer_type_node);
8802 tree p = build_global_decl ("p", int_star);
8803 tree q = build_global_decl ("q", int_star);
8805 test_region_model_context ctxt;
8806 region_model model (&mgr);
8807 const svalue *p_init = model.get_rvalue (p, &ctxt);
8808 const svalue *q_init = model.get_rvalue (q, &ctxt);
8810 ASSERT_TRUE (p_init->involves_p (p_init));
8811 ASSERT_FALSE (p_init->involves_p (q_init));
8813 const region *star_p_reg = mgr.get_symbolic_region (p_init);
8814 const region *star_q_reg = mgr.get_symbolic_region (q_init);
8816 const svalue *init_star_p = mgr.get_or_create_initial_value (star_p_reg);
8817 const svalue *init_star_q = mgr.get_or_create_initial_value (star_q_reg);
8819 ASSERT_TRUE (init_star_p->involves_p (p_init));
8820 ASSERT_FALSE (p_init->involves_p (init_star_p));
8821 ASSERT_FALSE (init_star_p->involves_p (q_init));
8822 ASSERT_TRUE (init_star_q->involves_p (q_init));
8823 ASSERT_FALSE (init_star_q->involves_p (p_init));
8826 /* Run all of the selftests within this file. */
8828 void
8829 analyzer_region_model_cc_tests ()
8831 test_tree_cmp_on_constants ();
8832 test_dump ();
8833 test_struct ();
8834 test_array_1 ();
8835 test_get_representative_tree ();
8836 test_unique_constants ();
8837 test_unique_unknowns ();
8838 test_initial_svalue_folding ();
8839 test_unaryop_svalue_folding ();
8840 test_binop_svalue_folding ();
8841 test_sub_svalue_folding ();
8842 test_bits_within_svalue_folding ();
8843 test_descendent_of_p ();
8844 test_bit_range_regions ();
8845 test_assignment ();
8846 test_compound_assignment ();
8847 test_stack_frames ();
8848 test_get_representative_path_var ();
8849 test_equality_1 ();
8850 test_canonicalization_2 ();
8851 test_canonicalization_3 ();
8852 test_canonicalization_4 ();
8853 test_state_merging ();
8854 test_constraint_merging ();
8855 test_widening_constraints ();
8856 test_iteration_1 ();
8857 test_malloc_constraints ();
8858 test_var ();
8859 test_array_2 ();
8860 test_mem_ref ();
8861 test_POINTER_PLUS_EXPR_then_MEM_REF ();
8862 test_malloc ();
8863 test_alloca ();
8864 test_involves_p ();
8867 } // namespace selftest
8869 #endif /* CHECKING_P */
8871 } // namespace ana
8873 #endif /* #if ENABLE_ANALYZER */