Branch data Line data Source code
1 : : /* Classes for modeling the state of memory.
2 : : Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 : : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 : :
5 : : This file is part of GCC.
6 : :
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.
11 : :
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.
16 : :
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/>. */
20 : :
21 : : #include "config.h"
22 : : #define INCLUDE_ALGORITHM
23 : : #define INCLUDE_VECTOR
24 : : #include "system.h"
25 : : #include "coretypes.h"
26 : : #include "make-unique.h"
27 : : #include "tree.h"
28 : : #include "function.h"
29 : : #include "basic-block.h"
30 : : #include "gimple.h"
31 : : #include "gimple-iterator.h"
32 : : #include "diagnostic-core.h"
33 : : #include "graphviz.h"
34 : : #include "options.h"
35 : : #include "cgraph.h"
36 : : #include "tree-dfa.h"
37 : : #include "stringpool.h"
38 : : #include "convert.h"
39 : : #include "target.h"
40 : : #include "fold-const.h"
41 : : #include "tree-pretty-print.h"
42 : : #include "diagnostic-color.h"
43 : : #include "bitmap.h"
44 : : #include "selftest.h"
45 : : #include "selftest-tree.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"
82 : : #include "diagnostic-format-sarif.h"
83 : : #include "text-art/tree-widget.h"
84 : :
85 : : #if ENABLE_ANALYZER
86 : :
87 : : namespace ana {
88 : :
89 : : auto_vec<pop_frame_callback> region_model::pop_frame_callbacks;
90 : :
91 : : /* Dump T to PP in language-independent form, for debugging/logging/dumping
92 : : purposes. */
93 : :
94 : : void
95 : 33299 : dump_tree (pretty_printer *pp, tree t)
96 : : {
97 : 33299 : dump_generic_node (pp, t, 0, TDF_SLIM, 0);
98 : 33299 : }
99 : :
100 : : /* Dump T to PP in language-independent form in quotes, for
101 : : debugging/logging/dumping purposes. */
102 : :
103 : : void
104 : 1389 : dump_quoted_tree (pretty_printer *pp, tree t)
105 : : {
106 : 1389 : pp_begin_quote (pp, pp_show_color (pp));
107 : 1389 : dump_tree (pp, t);
108 : 1389 : pp_end_quote (pp, pp_show_color (pp));
109 : 1389 : }
110 : :
111 : : /* Equivalent to pp_printf (pp, "%qT", t), to avoid nesting pp_printf
112 : : calls within other pp_printf calls.
113 : :
114 : : default_tree_printer handles 'T' and some other codes by calling
115 : : dump_generic_node (pp, t, 0, TDF_SLIM, 0);
116 : : dump_generic_node calls pp_printf in various places, leading to
117 : : garbled output.
118 : :
119 : : Ideally pp_printf could be made to be reentrant, but in the meantime
120 : : this function provides a workaround. */
121 : :
122 : : void
123 : 4485 : print_quoted_type (pretty_printer *pp, tree t)
124 : : {
125 : 4485 : if (!t)
126 : : return;
127 : 4481 : pp_begin_quote (pp, pp_show_color (pp));
128 : 4481 : dump_generic_node (pp, t, 0, TDF_SLIM, 0);
129 : 4481 : pp_end_quote (pp, pp_show_color (pp));
130 : : }
131 : :
132 : : /* Print EXPR to PP, without quotes.
133 : : For use within svalue::maybe_print_for_user
134 : : and region::maybe_print_for_user. */
135 : :
136 : : void
137 : 38 : print_expr_for_user (pretty_printer *pp, tree expr)
138 : : {
139 : : /* Workaround for C++'s lang_hooks.decl_printable_name,
140 : : which unhelpfully (for us) prefixes the decl with its
141 : : type. */
142 : 38 : if (DECL_P (expr))
143 : 38 : dump_generic_node (pp, expr, 0, TDF_SLIM, 0);
144 : : else
145 : 0 : pp_printf (pp, "%E", expr);
146 : 38 : }
147 : :
148 : : /* class region_to_value_map. */
149 : :
150 : : /* Assignment operator for region_to_value_map. */
151 : :
152 : : region_to_value_map &
153 : 17527 : region_to_value_map::operator= (const region_to_value_map &other)
154 : : {
155 : 17527 : m_hash_map.empty ();
156 : 29644 : for (auto iter : other.m_hash_map)
157 : : {
158 : 12117 : const region *reg = iter.first;
159 : 12117 : const svalue *sval = iter.second;
160 : 12117 : m_hash_map.put (reg, sval);
161 : : }
162 : 17527 : return *this;
163 : : }
164 : :
165 : : /* Equality operator for region_to_value_map. */
166 : :
167 : : bool
168 : 657820 : region_to_value_map::operator== (const region_to_value_map &other) const
169 : : {
170 : 657820 : if (m_hash_map.elements () != other.m_hash_map.elements ())
171 : : return false;
172 : :
173 : 1165075 : for (auto iter : *this)
174 : : {
175 : 262171 : const region *reg = iter.first;
176 : 262171 : const svalue *sval = iter.second;
177 : 262171 : const svalue * const *other_slot = other.get (reg);
178 : 262171 : if (other_slot == NULL)
179 : 130 : return false;
180 : 262131 : if (sval != *other_slot)
181 : : return false;
182 : : }
183 : :
184 : 640863 : return true;
185 : : }
186 : :
187 : : /* Dump this object to PP. */
188 : :
189 : : void
190 : 552 : region_to_value_map::dump_to_pp (pretty_printer *pp, bool simple,
191 : : bool multiline) const
192 : : {
193 : 552 : auto_vec<const region *> regs;
194 : 1656 : for (iterator iter = begin (); iter != end (); ++iter)
195 : 552 : regs.safe_push ((*iter).first);
196 : 552 : regs.qsort (region::cmp_ptr_ptr);
197 : 552 : if (multiline)
198 : 552 : pp_newline (pp);
199 : : else
200 : 0 : pp_string (pp, " {");
201 : : unsigned i;
202 : : const region *reg;
203 : 1104 : FOR_EACH_VEC_ELT (regs, i, reg)
204 : : {
205 : 552 : if (multiline)
206 : 552 : pp_string (pp, " ");
207 : 0 : else if (i > 0)
208 : 0 : pp_string (pp, ", ");
209 : 552 : reg->dump_to_pp (pp, simple);
210 : 552 : pp_string (pp, ": ");
211 : 552 : const svalue *sval = *get (reg);
212 : 552 : sval->dump_to_pp (pp, true);
213 : 552 : if (multiline)
214 : 552 : pp_newline (pp);
215 : : }
216 : 552 : if (!multiline)
217 : 0 : pp_string (pp, "}");
218 : 552 : }
219 : :
220 : : /* Dump this object to stderr. */
221 : :
222 : : DEBUG_FUNCTION void
223 : 0 : region_to_value_map::dump (bool simple) const
224 : : {
225 : 0 : tree_dump_pretty_printer pp (stderr);
226 : 0 : dump_to_pp (&pp, simple, true);
227 : 0 : pp_newline (&pp);
228 : 0 : }
229 : :
230 : : /* Generate a JSON value for this region_to_value_map.
231 : : This is intended for debugging the analyzer rather than
232 : : serialization. */
233 : :
234 : : std::unique_ptr<json::object>
235 : 4 : region_to_value_map::to_json () const
236 : : {
237 : 4 : auto map_obj = ::make_unique<json::object> ();
238 : :
239 : 4 : auto_vec<const region *> regs;
240 : 4 : for (iterator iter = begin (); iter != end (); ++iter)
241 : 0 : regs.safe_push ((*iter).first);
242 : 4 : regs.qsort (region::cmp_ptr_ptr);
243 : :
244 : : unsigned i;
245 : : const region *reg;
246 : 4 : FOR_EACH_VEC_ELT (regs, i, reg)
247 : : {
248 : 0 : label_text reg_desc = reg->get_desc ();
249 : 0 : const svalue *sval = *get (reg);
250 : 0 : map_obj->set (reg_desc.get (), sval->to_json ());
251 : 0 : }
252 : :
253 : 4 : return map_obj;
254 : 4 : }
255 : :
256 : : std::unique_ptr<text_art::tree_widget>
257 : 4 : region_to_value_map::
258 : : make_dump_widget (const text_art::dump_widget_info &dwi) const
259 : : {
260 : 4 : if (is_empty ())
261 : 4 : return nullptr;
262 : :
263 : 0 : std::unique_ptr<text_art::tree_widget> w
264 : 0 : (text_art::tree_widget::make (dwi, "Dynamic Extents"));
265 : :
266 : 0 : auto_vec<const region *> regs;
267 : 0 : for (iterator iter = begin (); iter != end (); ++iter)
268 : 0 : regs.safe_push ((*iter).first);
269 : 0 : regs.qsort (region::cmp_ptr_ptr);
270 : :
271 : : unsigned i;
272 : : const region *reg;
273 : 0 : FOR_EACH_VEC_ELT (regs, i, reg)
274 : : {
275 : 0 : pretty_printer the_pp;
276 : 0 : pretty_printer * const pp = &the_pp;
277 : 0 : pp_format_decoder (pp) = default_tree_printer;
278 : 0 : const bool simple = true;
279 : :
280 : 0 : reg->dump_to_pp (pp, simple);
281 : 0 : pp_string (pp, ": ");
282 : 0 : const svalue *sval = *get (reg);
283 : 0 : sval->dump_to_pp (pp, true);
284 : 0 : w->add_child (text_art::tree_widget::make (dwi, pp));
285 : 0 : }
286 : 0 : return w;
287 : 0 : }
288 : :
289 : : /* Attempt to merge THIS with OTHER, writing the result
290 : : to OUT.
291 : :
292 : : For now, write (region, value) mappings that are in common between THIS
293 : : and OTHER to OUT, effectively taking the intersection.
294 : :
295 : : Reject merger of different values. */
296 : :
297 : : bool
298 : 66551 : region_to_value_map::can_merge_with_p (const region_to_value_map &other,
299 : : region_to_value_map *out) const
300 : : {
301 : 92711 : for (auto iter : *this)
302 : : {
303 : 17295 : const region *iter_reg = iter.first;
304 : 17295 : const svalue *iter_sval = iter.second;
305 : 17295 : const svalue * const * other_slot = other.get (iter_reg);
306 : 17295 : if (other_slot)
307 : : {
308 : 16868 : if (iter_sval == *other_slot)
309 : 12653 : out->put (iter_reg, iter_sval);
310 : : else
311 : 4215 : return false;
312 : : }
313 : : }
314 : 62336 : return true;
315 : : }
316 : :
317 : : /* Purge any state involving SVAL. */
318 : :
319 : : void
320 : 34405 : region_to_value_map::purge_state_involving (const svalue *sval)
321 : : {
322 : 34405 : auto_vec<const region *> to_purge;
323 : 113321 : for (auto iter : *this)
324 : : {
325 : 39458 : const region *iter_reg = iter.first;
326 : 39458 : const svalue *iter_sval = iter.second;
327 : 39458 : if (iter_reg->involves_p (sval) || iter_sval->involves_p (sval))
328 : 56 : to_purge.safe_push (iter_reg);
329 : : }
330 : 34573 : for (auto iter : to_purge)
331 : 56 : m_hash_map.remove (iter);
332 : 34405 : }
333 : :
334 : : /* class region_model. */
335 : :
336 : : /* Ctor for region_model: construct an "empty" model. */
337 : :
338 : 338548 : region_model::region_model (region_model_manager *mgr)
339 : 338548 : : m_mgr (mgr), m_store (), m_current_frame (NULL),
340 : 338548 : m_dynamic_extents ()
341 : : {
342 : 338548 : m_constraints = new constraint_manager (mgr);
343 : 338548 : }
344 : :
345 : : /* region_model's copy ctor. */
346 : :
347 : 3527289 : region_model::region_model (const region_model &other)
348 : 3527289 : : m_mgr (other.m_mgr), m_store (other.m_store),
349 : 3527289 : m_constraints (new constraint_manager (*other.m_constraints)),
350 : 3527289 : m_current_frame (other.m_current_frame),
351 : 3527289 : m_dynamic_extents (other.m_dynamic_extents)
352 : : {
353 : 3527289 : }
354 : :
355 : : /* region_model's dtor. */
356 : :
357 : 3865837 : region_model::~region_model ()
358 : : {
359 : 3865837 : delete m_constraints;
360 : 3865837 : }
361 : :
362 : : /* region_model's assignment operator. */
363 : :
364 : : region_model &
365 : 17527 : region_model::operator= (const region_model &other)
366 : : {
367 : : /* m_mgr is const. */
368 : 17527 : gcc_assert (m_mgr == other.m_mgr);
369 : :
370 : 17527 : m_store = other.m_store;
371 : :
372 : 17527 : delete m_constraints;
373 : 17527 : m_constraints = new constraint_manager (*other.m_constraints);
374 : :
375 : 17527 : m_current_frame = other.m_current_frame;
376 : :
377 : 17527 : m_dynamic_extents = other.m_dynamic_extents;
378 : :
379 : 17527 : return *this;
380 : : }
381 : :
382 : : /* Equality operator for region_model.
383 : :
384 : : Amongst other things this directly compares the stores and the constraint
385 : : managers, so for this to be meaningful both this and OTHER should
386 : : have been canonicalized. */
387 : :
388 : : bool
389 : 431154 : region_model::operator== (const region_model &other) const
390 : : {
391 : : /* We can only compare instances that use the same manager. */
392 : 431154 : gcc_assert (m_mgr == other.m_mgr);
393 : :
394 : 431154 : if (m_store != other.m_store)
395 : : return false;
396 : :
397 : 371678 : if (*m_constraints != *other.m_constraints)
398 : : return false;
399 : :
400 : 368180 : if (m_current_frame != other.m_current_frame)
401 : : return false;
402 : :
403 : 368180 : if (m_dynamic_extents != other.m_dynamic_extents)
404 : : return false;
405 : :
406 : 367688 : gcc_checking_assert (hash () == other.hash ());
407 : :
408 : : return true;
409 : : }
410 : :
411 : : /* Generate a hash value for this region_model. */
412 : :
413 : : hashval_t
414 : 1164812 : region_model::hash () const
415 : : {
416 : 1164812 : hashval_t result = m_store.hash ();
417 : 1164812 : result ^= m_constraints->hash ();
418 : 1164812 : return result;
419 : : }
420 : :
421 : : /* Dump a representation of this model to PP, showing the
422 : : stack, the store, and any constraints.
423 : : Use SIMPLE to control how svalues and regions are printed. */
424 : :
425 : : void
426 : 1952 : region_model::dump_to_pp (pretty_printer *pp, bool simple,
427 : : bool multiline) const
428 : : {
429 : : /* Dump stack. */
430 : 1952 : pp_printf (pp, "stack depth: %i", get_stack_depth ());
431 : 1952 : if (multiline)
432 : 856 : pp_newline (pp);
433 : : else
434 : 1096 : pp_string (pp, " {");
435 : 3953 : for (const frame_region *iter_frame = m_current_frame; iter_frame;
436 : 2001 : iter_frame = iter_frame->get_calling_frame ())
437 : : {
438 : 2001 : if (multiline)
439 : 916 : pp_string (pp, " ");
440 : 1085 : else if (iter_frame != m_current_frame)
441 : 0 : pp_string (pp, ", ");
442 : 2001 : pp_printf (pp, "frame (index %i): ", iter_frame->get_index ());
443 : 2001 : iter_frame->dump_to_pp (pp, simple);
444 : 2001 : if (multiline)
445 : 916 : pp_newline (pp);
446 : : }
447 : 1952 : if (!multiline)
448 : 1096 : pp_string (pp, "}");
449 : :
450 : : /* Dump store. */
451 : 1096 : if (!multiline)
452 : 1096 : pp_string (pp, ", {");
453 : 1952 : m_store.dump_to_pp (pp, simple, multiline,
454 : 1952 : m_mgr->get_store_manager ());
455 : 1952 : if (!multiline)
456 : 1096 : pp_string (pp, "}");
457 : :
458 : : /* Dump constraints. */
459 : 1952 : pp_string (pp, "constraint_manager:");
460 : 1952 : if (multiline)
461 : 856 : pp_newline (pp);
462 : : else
463 : 1096 : pp_string (pp, " {");
464 : 1952 : m_constraints->dump_to_pp (pp, multiline);
465 : 1952 : if (!multiline)
466 : 1096 : pp_string (pp, "}");
467 : :
468 : : /* Dump sizes of dynamic regions, if any are known. */
469 : 1952 : if (!m_dynamic_extents.is_empty ())
470 : : {
471 : 552 : pp_string (pp, "dynamic_extents:");
472 : 552 : m_dynamic_extents.dump_to_pp (pp, simple, multiline);
473 : : }
474 : 1952 : }
475 : :
476 : : /* Dump a representation of this model to FILE. */
477 : :
478 : : void
479 : 0 : region_model::dump (FILE *fp, bool simple, bool multiline) const
480 : : {
481 : 0 : tree_dump_pretty_printer pp (fp);
482 : 0 : dump_to_pp (&pp, simple, multiline);
483 : 0 : pp_newline (&pp);
484 : 0 : }
485 : :
486 : : /* Dump a multiline representation of this model to stderr. */
487 : :
488 : : DEBUG_FUNCTION void
489 : 0 : region_model::dump (bool simple) const
490 : : {
491 : 0 : dump (stderr, simple, true);
492 : 0 : }
493 : :
494 : : /* Dump a tree-like representation of this state to stderr. */
495 : :
496 : : DEBUG_FUNCTION void
497 : 0 : region_model::dump () const
498 : : {
499 : 0 : text_art::dump (*this);
500 : 0 : }
501 : :
502 : : /* Dump a multiline representation of this model to stderr. */
503 : :
504 : : DEBUG_FUNCTION void
505 : 0 : region_model::debug () const
506 : : {
507 : 0 : dump (true);
508 : 0 : }
509 : :
510 : : /* Generate a JSON value for this region_model.
511 : : This is intended for debugging the analyzer rather than
512 : : serialization. */
513 : :
514 : : std::unique_ptr<json::object>
515 : 4 : region_model::to_json () const
516 : : {
517 : 4 : auto model_obj = ::make_unique<json::object> ();
518 : 4 : model_obj->set ("store", m_store.to_json ());
519 : 4 : model_obj->set ("constraints", m_constraints->to_json ());
520 : 4 : if (m_current_frame)
521 : 4 : model_obj->set ("current_frame", m_current_frame->to_json ());
522 : 4 : model_obj->set ("dynamic_extents", m_dynamic_extents.to_json ());
523 : 4 : return model_obj;
524 : : }
525 : :
526 : : std::unique_ptr<text_art::tree_widget>
527 : 4 : region_model::make_dump_widget (const text_art::dump_widget_info &dwi) const
528 : : {
529 : 4 : using text_art::tree_widget;
530 : 4 : std::unique_ptr<tree_widget> model_widget
531 : 4 : (tree_widget::from_fmt (dwi, nullptr, "Region Model"));
532 : :
533 : 4 : if (m_current_frame)
534 : : {
535 : 0 : pretty_printer the_pp;
536 : 0 : pretty_printer * const pp = &the_pp;
537 : 0 : pp_format_decoder (pp) = default_tree_printer;
538 : 0 : pp_show_color (pp) = true;
539 : 0 : const bool simple = true;
540 : :
541 : 0 : pp_string (pp, "Current Frame: ");
542 : 0 : m_current_frame->dump_to_pp (pp, simple);
543 : 0 : model_widget->add_child (tree_widget::make (dwi, pp));
544 : 0 : }
545 : 4 : model_widget->add_child
546 : 8 : (m_store.make_dump_widget (dwi,
547 : 4 : m_mgr->get_store_manager ()));
548 : 4 : model_widget->add_child (m_constraints->make_dump_widget (dwi));
549 : 4 : model_widget->add_child (m_dynamic_extents.make_dump_widget (dwi));
550 : 4 : return model_widget;
551 : : }
552 : :
553 : : /* Assert that this object is valid. */
554 : :
555 : : void
556 : 1644532 : region_model::validate () const
557 : : {
558 : 1644532 : m_store.validate ();
559 : 1644532 : }
560 : :
561 : : /* Canonicalize the store and constraints, to maximize the chance of
562 : : equality between region_model instances. */
563 : :
564 : : void
565 : 1019595 : region_model::canonicalize ()
566 : : {
567 : 1019595 : m_store.canonicalize (m_mgr->get_store_manager ());
568 : 1019595 : m_constraints->canonicalize ();
569 : 1019595 : }
570 : :
571 : : /* Return true if this region_model is in canonical form. */
572 : :
573 : : bool
574 : 358097 : region_model::canonicalized_p () const
575 : : {
576 : 358097 : region_model copy (*this);
577 : 358097 : copy.canonicalize ();
578 : 358097 : return *this == copy;
579 : 358097 : }
580 : :
581 : : /* See the comment for store::loop_replay_fixup. */
582 : :
583 : : void
584 : 9119 : region_model::loop_replay_fixup (const region_model *dst_state)
585 : : {
586 : 9119 : m_store.loop_replay_fixup (dst_state->get_store (), m_mgr);
587 : 9119 : }
588 : :
589 : : /* A subclass of pending_diagnostic for complaining about uses of
590 : : poisoned values. */
591 : :
592 : : class poisoned_value_diagnostic
593 : : : public pending_diagnostic_subclass<poisoned_value_diagnostic>
594 : : {
595 : : public:
596 : 1732 : poisoned_value_diagnostic (tree expr, enum poison_kind pkind,
597 : : const region *src_region,
598 : : tree check_expr)
599 : 1732 : : m_expr (expr), m_pkind (pkind),
600 : 1732 : m_src_region (src_region),
601 : 1732 : m_check_expr (check_expr)
602 : : {}
603 : :
604 : 4352 : const char *get_kind () const final override { return "poisoned_value_diagnostic"; }
605 : :
606 : 58 : bool use_of_uninit_p () const final override
607 : : {
608 : 58 : return m_pkind == POISON_KIND_UNINIT;
609 : : }
610 : :
611 : 1204 : bool operator== (const poisoned_value_diagnostic &other) const
612 : : {
613 : 1204 : return (m_expr == other.m_expr
614 : 1197 : && m_pkind == other.m_pkind
615 : 2401 : && m_src_region == other.m_src_region);
616 : : }
617 : :
618 : 1930 : int get_controlling_option () const final override
619 : : {
620 : 1930 : switch (m_pkind)
621 : : {
622 : 0 : default:
623 : 0 : gcc_unreachable ();
624 : : case POISON_KIND_UNINIT:
625 : : return OPT_Wanalyzer_use_of_uninitialized_value;
626 : : case POISON_KIND_FREED:
627 : : case POISON_KIND_DELETED:
628 : : return OPT_Wanalyzer_use_after_free;
629 : : case POISON_KIND_POPPED_STACK:
630 : : return OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame;
631 : : }
632 : : }
633 : :
634 : 1375 : bool terminate_path_p () const final override { return true; }
635 : :
636 : 555 : bool emit (diagnostic_emission_context &ctxt) final override
637 : : {
638 : 555 : switch (m_pkind)
639 : : {
640 : 0 : default:
641 : 0 : gcc_unreachable ();
642 : 528 : case POISON_KIND_UNINIT:
643 : 528 : {
644 : 528 : ctxt.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
645 : 528 : return ctxt.warn ("use of uninitialized value %qE",
646 : 528 : m_expr);
647 : : }
648 : 3 : break;
649 : 3 : case POISON_KIND_FREED:
650 : 3 : {
651 : 3 : ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
652 : 3 : return ctxt.warn ("use after %<free%> of %qE",
653 : 3 : m_expr);
654 : : }
655 : 9 : break;
656 : 9 : case POISON_KIND_DELETED:
657 : 9 : {
658 : 9 : ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
659 : 9 : return ctxt.warn ("use after %<delete%> of %qE",
660 : 9 : m_expr);
661 : : }
662 : 15 : break;
663 : 15 : case POISON_KIND_POPPED_STACK:
664 : 15 : {
665 : : /* TODO: which CWE? */
666 : 15 : return ctxt.warn
667 : 15 : ("dereferencing pointer %qE to within stale stack frame",
668 : 15 : m_expr);
669 : : }
670 : : break;
671 : : }
672 : : }
673 : :
674 : : bool
675 : 1110 : describe_final_event (pretty_printer &pp,
676 : : const evdesc::final_event &) final override
677 : : {
678 : 1110 : switch (m_pkind)
679 : : {
680 : 0 : default:
681 : 0 : gcc_unreachable ();
682 : 1056 : case POISON_KIND_UNINIT:
683 : 1056 : {
684 : 1056 : pp_printf (&pp,
685 : : "use of uninitialized value %qE here",
686 : : m_expr);
687 : 1056 : return true;
688 : : }
689 : 6 : case POISON_KIND_FREED:
690 : 6 : {
691 : 6 : pp_printf (&pp,
692 : : "use after %<free%> of %qE here",
693 : : m_expr);
694 : 6 : return true;
695 : : }
696 : 18 : case POISON_KIND_DELETED:
697 : 18 : {
698 : 18 : pp_printf (&pp,
699 : : "use after %<delete%> of %qE here",
700 : : m_expr);
701 : 18 : return true;
702 : : }
703 : 30 : case POISON_KIND_POPPED_STACK:
704 : 30 : {
705 : 30 : pp_printf (&pp,
706 : : "dereferencing pointer %qE to within stale stack frame",
707 : : m_expr);
708 : 30 : return true;
709 : : }
710 : : }
711 : : }
712 : :
713 : 555 : void mark_interesting_stuff (interesting_t *interest) final override
714 : : {
715 : 555 : if (m_src_region)
716 : 532 : interest->add_region_creation (m_src_region);
717 : 555 : }
718 : :
719 : : /* Attempt to suppress false positives.
720 : : Reject paths where the value of the underlying region isn't poisoned.
721 : : This can happen due to state merging when exploring the exploded graph,
722 : : where the more precise analysis during feasibility analysis finds that
723 : : the region is in fact valid.
724 : : To do this we need to get the value from the fgraph. Unfortunately
725 : : we can't simply query the state of m_src_region (from the enode),
726 : : since it might be a different region in the fnode state (e.g. with
727 : : heap-allocated regions, the numbering could be different).
728 : : Hence we access m_check_expr, if available. */
729 : :
730 : 1233 : bool check_valid_fpath_p (const feasible_node &fnode,
731 : : const gimple *emission_stmt)
732 : : const final override
733 : : {
734 : 1233 : if (!m_check_expr)
735 : : return true;
736 : :
737 : : /* We've reached the enode, but not necessarily the right function_point.
738 : : Try to get the state at the correct stmt. */
739 : 1131 : region_model emission_model (fnode.get_model ().get_manager());
740 : 1131 : if (!fnode.get_state_at_stmt (emission_stmt, &emission_model))
741 : : /* Couldn't get state; accept this diagnostic. */
742 : : return true;
743 : :
744 : 1021 : const svalue *fsval = emission_model.get_rvalue (m_check_expr, NULL);
745 : : /* Check to see if the expr is also poisoned in FNODE (and in the
746 : : same way). */
747 : 1021 : const poisoned_svalue * fspval = fsval->dyn_cast_poisoned_svalue ();
748 : 1021 : if (!fspval)
749 : : return false;
750 : 969 : if (fspval->get_poison_kind () != m_pkind)
751 : : return false;
752 : : return true;
753 : 1131 : }
754 : :
755 : : private:
756 : : tree m_expr;
757 : : enum poison_kind m_pkind;
758 : : const region *m_src_region;
759 : : tree m_check_expr;
760 : : };
761 : :
762 : : /* A subclass of pending_diagnostic for complaining about shifts
763 : : by negative counts. */
764 : :
765 : : class shift_count_negative_diagnostic
766 : : : public pending_diagnostic_subclass<shift_count_negative_diagnostic>
767 : : {
768 : : public:
769 : 16 : shift_count_negative_diagnostic (const gassign *assign, tree count_cst)
770 : 16 : : m_assign (assign), m_count_cst (count_cst)
771 : : {}
772 : :
773 : 56 : const char *get_kind () const final override
774 : : {
775 : 56 : return "shift_count_negative_diagnostic";
776 : : }
777 : :
778 : 16 : bool operator== (const shift_count_negative_diagnostic &other) const
779 : : {
780 : 16 : return (m_assign == other.m_assign
781 : 16 : && same_tree_p (m_count_cst, other.m_count_cst));
782 : : }
783 : :
784 : 24 : int get_controlling_option () const final override
785 : : {
786 : 24 : return OPT_Wanalyzer_shift_count_negative;
787 : : }
788 : :
789 : 8 : bool emit (diagnostic_emission_context &ctxt) final override
790 : : {
791 : 8 : return ctxt.warn ("shift by negative count (%qE)", m_count_cst);
792 : : }
793 : :
794 : : bool
795 : 16 : describe_final_event (pretty_printer &pp,
796 : : const evdesc::final_event &) final override
797 : : {
798 : 16 : pp_printf (&pp,
799 : : "shift by negative amount here (%qE)",
800 : : m_count_cst);
801 : 16 : return true;
802 : : }
803 : :
804 : : private:
805 : : const gassign *m_assign;
806 : : tree m_count_cst;
807 : : };
808 : :
809 : : /* A subclass of pending_diagnostic for complaining about shifts
810 : : by counts >= the width of the operand type. */
811 : :
812 : : class shift_count_overflow_diagnostic
813 : : : public pending_diagnostic_subclass<shift_count_overflow_diagnostic>
814 : : {
815 : : public:
816 : 8 : shift_count_overflow_diagnostic (const gassign *assign,
817 : : int operand_precision,
818 : : tree count_cst)
819 : 8 : : m_assign (assign), m_operand_precision (operand_precision),
820 : 8 : m_count_cst (count_cst)
821 : : {}
822 : :
823 : 28 : const char *get_kind () const final override
824 : : {
825 : 28 : return "shift_count_overflow_diagnostic";
826 : : }
827 : :
828 : 8 : bool operator== (const shift_count_overflow_diagnostic &other) const
829 : : {
830 : 8 : return (m_assign == other.m_assign
831 : 8 : && m_operand_precision == other.m_operand_precision
832 : 16 : && same_tree_p (m_count_cst, other.m_count_cst));
833 : : }
834 : :
835 : 12 : int get_controlling_option () const final override
836 : : {
837 : 12 : return OPT_Wanalyzer_shift_count_overflow;
838 : : }
839 : :
840 : 4 : bool emit (diagnostic_emission_context &ctxt) final override
841 : : {
842 : 4 : return ctxt.warn ("shift by count (%qE) >= precision of type (%qi)",
843 : 4 : m_count_cst, m_operand_precision);
844 : : }
845 : :
846 : : bool
847 : 8 : describe_final_event (pretty_printer &pp,
848 : : const evdesc::final_event &) final override
849 : : {
850 : 8 : pp_printf (&pp,
851 : : "shift by count %qE here",
852 : : m_count_cst);
853 : 8 : return true;
854 : : }
855 : :
856 : : private:
857 : : const gassign *m_assign;
858 : : int m_operand_precision;
859 : : tree m_count_cst;
860 : : };
861 : :
862 : : /* A subclass of pending_diagnostic for complaining about pointer
863 : : subtractions involving unrelated buffers. */
864 : :
865 : : class undefined_ptrdiff_diagnostic
866 : : : public pending_diagnostic_subclass<undefined_ptrdiff_diagnostic>
867 : : {
868 : : public:
869 : : /* Region_creation_event subclass to give a custom wording when
870 : : talking about creation of buffers for LHS and RHS of the
871 : : subtraction. */
872 : : class ptrdiff_region_creation_event : public region_creation_event
873 : : {
874 : : public:
875 : 56 : ptrdiff_region_creation_event (const event_loc_info &loc_info,
876 : : bool is_lhs)
877 : 56 : : region_creation_event (loc_info),
878 : 56 : m_is_lhs (is_lhs)
879 : : {
880 : : }
881 : :
882 : 112 : void print_desc (pretty_printer &pp) const final override
883 : : {
884 : 112 : if (m_is_lhs)
885 : 56 : pp_string (&pp,
886 : : "underlying object for left-hand side"
887 : : " of subtraction created here");
888 : : else
889 : 56 : pp_string (&pp,
890 : : "underlying object for right-hand side"
891 : : " of subtraction created here");
892 : 112 : }
893 : :
894 : : private:
895 : : bool m_is_lhs;
896 : : };
897 : :
898 : 56 : undefined_ptrdiff_diagnostic (const gassign *assign,
899 : : const svalue *sval_a,
900 : : const svalue *sval_b,
901 : : const region *base_reg_a,
902 : : const region *base_reg_b)
903 : 56 : : m_assign (assign),
904 : 56 : m_sval_a (sval_a),
905 : 56 : m_sval_b (sval_b),
906 : 56 : m_base_reg_a (base_reg_a),
907 : 56 : m_base_reg_b (base_reg_b)
908 : : {
909 : 56 : gcc_assert (m_base_reg_a != m_base_reg_b);
910 : : }
911 : :
912 : 196 : const char *get_kind () const final override
913 : : {
914 : 196 : return "undefined_ptrdiff_diagnostic";
915 : : }
916 : :
917 : 56 : bool operator== (const undefined_ptrdiff_diagnostic &other) const
918 : : {
919 : 56 : return (m_assign == other.m_assign
920 : 56 : && m_sval_a == other.m_sval_a
921 : 56 : && m_sval_b == other.m_sval_b
922 : 56 : && m_base_reg_a == other.m_base_reg_a
923 : 112 : && m_base_reg_b == other.m_base_reg_b);
924 : : }
925 : :
926 : 84 : int get_controlling_option () const final override
927 : : {
928 : 84 : return OPT_Wanalyzer_undefined_behavior_ptrdiff;
929 : : }
930 : :
931 : 28 : bool emit (diagnostic_emission_context &ctxt) final override
932 : : {
933 : : /* CWE-469: Use of Pointer Subtraction to Determine Size. */
934 : 28 : ctxt.add_cwe (469);
935 : 28 : return ctxt.warn ("undefined behavior when subtracting pointers");
936 : : }
937 : :
938 : 56 : void add_region_creation_events (const region *reg,
939 : : tree /*capacity*/,
940 : : const event_loc_info &loc_info,
941 : : checker_path &emission_path) final override
942 : : {
943 : 56 : if (reg == m_base_reg_a)
944 : 28 : emission_path.add_event
945 : 28 : (make_unique<ptrdiff_region_creation_event> (loc_info, true));
946 : 28 : else if (reg == m_base_reg_b)
947 : 28 : emission_path.add_event
948 : 28 : (make_unique<ptrdiff_region_creation_event> (loc_info, false));
949 : 56 : }
950 : :
951 : : bool
952 : 56 : describe_final_event (pretty_printer &pp,
953 : : const evdesc::final_event &) final override
954 : : {
955 : 56 : pp_string (&pp,
956 : : "subtraction of pointers has undefined behavior if"
957 : : " they do not point into the same array object");
958 : 56 : return true;
959 : : }
960 : :
961 : 28 : void mark_interesting_stuff (interesting_t *interesting) final override
962 : : {
963 : 28 : interesting->add_region_creation (m_base_reg_a);
964 : 28 : interesting->add_region_creation (m_base_reg_b);
965 : 28 : }
966 : :
967 : : private:
968 : : const gassign *m_assign;
969 : : const svalue *m_sval_a;
970 : : const svalue *m_sval_b;
971 : : const region *m_base_reg_a;
972 : : const region *m_base_reg_b;
973 : : };
974 : :
975 : : /* Check the pointer subtraction SVAL_A - SVAL_B at ASSIGN and add
976 : : a warning to CTXT if they're not within the same base region. */
977 : :
978 : : static void
979 : 618 : check_for_invalid_ptrdiff (const gassign *assign,
980 : : region_model_context &ctxt,
981 : : const svalue *sval_a, const svalue *sval_b)
982 : : {
983 : 618 : const region *base_reg_a = sval_a->maybe_get_deref_base_region ();
984 : 618 : if (!base_reg_a)
985 : 562 : return;
986 : 80 : const region *base_reg_b = sval_b->maybe_get_deref_base_region ();
987 : 80 : if (!base_reg_b)
988 : : return;
989 : :
990 : 56 : if (base_reg_a == base_reg_b)
991 : : return;
992 : :
993 : 56 : if (base_reg_a->get_kind () == RK_SYMBOLIC)
994 : : return;
995 : 56 : if (base_reg_b->get_kind () == RK_SYMBOLIC)
996 : : return;
997 : :
998 : 56 : ctxt.warn (make_unique<undefined_ptrdiff_diagnostic> (assign,
999 : : sval_a,
1000 : : sval_b,
1001 : : base_reg_a,
1002 : : base_reg_b));
1003 : : }
1004 : :
1005 : : /* If ASSIGN is a stmt that can be modelled via
1006 : : set_value (lhs_reg, SVALUE, CTXT)
1007 : : for some SVALUE, get the SVALUE.
1008 : : Otherwise return NULL. */
1009 : :
1010 : : const svalue *
1011 : 367338 : region_model::get_gassign_result (const gassign *assign,
1012 : : region_model_context *ctxt)
1013 : : {
1014 : 367338 : tree lhs = gimple_assign_lhs (assign);
1015 : :
1016 : 367338 : if (gimple_has_volatile_ops (assign)
1017 : 367338 : && !gimple_clobber_p (assign))
1018 : : {
1019 : 120 : conjured_purge p (this, ctxt);
1020 : 120 : return m_mgr->get_or_create_conjured_svalue (TREE_TYPE (lhs),
1021 : : assign,
1022 : : get_lvalue (lhs, ctxt),
1023 : : p);
1024 : : }
1025 : :
1026 : 367218 : tree rhs1 = gimple_assign_rhs1 (assign);
1027 : 367218 : enum tree_code op = gimple_assign_rhs_code (assign);
1028 : 367218 : switch (op)
1029 : : {
1030 : : default:
1031 : : return NULL;
1032 : :
1033 : 27496 : case POINTER_PLUS_EXPR:
1034 : 27496 : {
1035 : : /* e.g. "_1 = a_10(D) + 12;" */
1036 : 27496 : tree ptr = rhs1;
1037 : 27496 : tree offset = gimple_assign_rhs2 (assign);
1038 : :
1039 : 27496 : const svalue *ptr_sval = get_rvalue (ptr, ctxt);
1040 : 27496 : const svalue *offset_sval = get_rvalue (offset, ctxt);
1041 : : /* Quoting tree.def, "the second operand [of a POINTER_PLUS_EXPR]
1042 : : is an integer of type sizetype". */
1043 : 27496 : offset_sval = m_mgr->get_or_create_cast (size_type_node, offset_sval);
1044 : :
1045 : 27496 : const svalue *sval_binop
1046 : 27496 : = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
1047 : : ptr_sval, offset_sval);
1048 : 27496 : return sval_binop;
1049 : : }
1050 : 930 : break;
1051 : :
1052 : 930 : case POINTER_DIFF_EXPR:
1053 : 930 : {
1054 : : /* e.g. "_1 = p_2(D) - q_3(D);". */
1055 : 930 : tree rhs2 = gimple_assign_rhs2 (assign);
1056 : 930 : const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
1057 : 930 : const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
1058 : :
1059 : : // TODO: perhaps fold to zero if they're known to be equal?
1060 : :
1061 : 930 : if (ctxt)
1062 : 618 : check_for_invalid_ptrdiff (assign, *ctxt, rhs1_sval, rhs2_sval);
1063 : :
1064 : 930 : const svalue *sval_binop
1065 : 930 : = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
1066 : : rhs1_sval, rhs2_sval);
1067 : 930 : return sval_binop;
1068 : : }
1069 : 209690 : break;
1070 : :
1071 : : /* Assignments of the form
1072 : : set_value (lvalue (LHS), rvalue (EXPR))
1073 : : for various EXPR.
1074 : : We already have the lvalue for the LHS above, as "lhs_reg". */
1075 : 209690 : case ADDR_EXPR: /* LHS = &RHS; */
1076 : 209690 : case BIT_FIELD_REF:
1077 : 209690 : case COMPONENT_REF: /* LHS = op0.op1; */
1078 : 209690 : case MEM_REF:
1079 : 209690 : case REAL_CST:
1080 : 209690 : case COMPLEX_CST:
1081 : 209690 : case VECTOR_CST:
1082 : 209690 : case INTEGER_CST:
1083 : 209690 : case ARRAY_REF:
1084 : 209690 : case SSA_NAME: /* LHS = VAR; */
1085 : 209690 : case VAR_DECL: /* LHS = VAR; */
1086 : 209690 : case PARM_DECL:/* LHS = VAR; */
1087 : 209690 : case REALPART_EXPR:
1088 : 209690 : case IMAGPART_EXPR:
1089 : 209690 : return get_rvalue (rhs1, ctxt);
1090 : :
1091 : 39648 : case ABS_EXPR:
1092 : 39648 : case ABSU_EXPR:
1093 : 39648 : case CONJ_EXPR:
1094 : 39648 : case BIT_NOT_EXPR:
1095 : 39648 : case FIX_TRUNC_EXPR:
1096 : 39648 : case FLOAT_EXPR:
1097 : 39648 : case NEGATE_EXPR:
1098 : 39648 : case NOP_EXPR:
1099 : 39648 : case VIEW_CONVERT_EXPR:
1100 : 39648 : {
1101 : : /* Unary ops. */
1102 : 39648 : const svalue *rhs_sval = get_rvalue (rhs1, ctxt);
1103 : 39648 : const svalue *sval_unaryop
1104 : 39648 : = m_mgr->get_or_create_unaryop (TREE_TYPE (lhs), op, rhs_sval);
1105 : 39648 : return sval_unaryop;
1106 : : }
1107 : :
1108 : 15153 : case EQ_EXPR:
1109 : 15153 : case GE_EXPR:
1110 : 15153 : case LE_EXPR:
1111 : 15153 : case NE_EXPR:
1112 : 15153 : case GT_EXPR:
1113 : 15153 : case LT_EXPR:
1114 : 15153 : case UNORDERED_EXPR:
1115 : 15153 : case ORDERED_EXPR:
1116 : 15153 : {
1117 : 15153 : tree rhs2 = gimple_assign_rhs2 (assign);
1118 : :
1119 : 15153 : const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
1120 : 15153 : const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
1121 : :
1122 : 15153 : if (TREE_TYPE (lhs) == boolean_type_node)
1123 : : {
1124 : : /* Consider constraints between svalues. */
1125 : 14885 : tristate t = eval_condition (rhs1_sval, op, rhs2_sval);
1126 : 14885 : if (t.is_known ())
1127 : 8130 : return m_mgr->get_or_create_constant_svalue
1128 : 8130 : (t.is_true () ? boolean_true_node : boolean_false_node);
1129 : : }
1130 : :
1131 : : /* Otherwise, generate a symbolic binary op. */
1132 : 7023 : const svalue *sval_binop
1133 : 7023 : = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
1134 : : rhs1_sval, rhs2_sval);
1135 : 7023 : return sval_binop;
1136 : : }
1137 : 61749 : break;
1138 : :
1139 : 61749 : case PLUS_EXPR:
1140 : 61749 : case MINUS_EXPR:
1141 : 61749 : case MULT_EXPR:
1142 : 61749 : case MULT_HIGHPART_EXPR:
1143 : 61749 : case TRUNC_DIV_EXPR:
1144 : 61749 : case CEIL_DIV_EXPR:
1145 : 61749 : case FLOOR_DIV_EXPR:
1146 : 61749 : case ROUND_DIV_EXPR:
1147 : 61749 : case TRUNC_MOD_EXPR:
1148 : 61749 : case CEIL_MOD_EXPR:
1149 : 61749 : case FLOOR_MOD_EXPR:
1150 : 61749 : case ROUND_MOD_EXPR:
1151 : 61749 : case RDIV_EXPR:
1152 : 61749 : case EXACT_DIV_EXPR:
1153 : 61749 : case LSHIFT_EXPR:
1154 : 61749 : case RSHIFT_EXPR:
1155 : 61749 : case LROTATE_EXPR:
1156 : 61749 : case RROTATE_EXPR:
1157 : 61749 : case BIT_IOR_EXPR:
1158 : 61749 : case BIT_XOR_EXPR:
1159 : 61749 : case BIT_AND_EXPR:
1160 : 61749 : case MIN_EXPR:
1161 : 61749 : case MAX_EXPR:
1162 : 61749 : case COMPLEX_EXPR:
1163 : 61749 : {
1164 : : /* Binary ops. */
1165 : 61749 : tree rhs2 = gimple_assign_rhs2 (assign);
1166 : :
1167 : 61749 : const svalue *rhs1_sval = get_rvalue (rhs1, ctxt);
1168 : 61749 : const svalue *rhs2_sval = get_rvalue (rhs2, ctxt);
1169 : :
1170 : 61749 : if (ctxt && (op == LSHIFT_EXPR || op == RSHIFT_EXPR))
1171 : : {
1172 : : /* "INT34-C. Do not shift an expression by a negative number of bits
1173 : : or by greater than or equal to the number of bits that exist in
1174 : : the operand." */
1175 : 1944 : if (const tree rhs2_cst = rhs2_sval->maybe_get_constant ())
1176 : 1692 : if (TREE_CODE (rhs2_cst) == INTEGER_CST
1177 : 1692 : && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
1178 : : {
1179 : 1690 : if (tree_int_cst_sgn (rhs2_cst) < 0)
1180 : 16 : ctxt->warn
1181 : 16 : (make_unique<shift_count_negative_diagnostic>
1182 : 32 : (assign, rhs2_cst));
1183 : 1674 : else if (compare_tree_int (rhs2_cst,
1184 : 1674 : TYPE_PRECISION (TREE_TYPE (rhs1)))
1185 : : >= 0)
1186 : 8 : ctxt->warn
1187 : 8 : (make_unique<shift_count_overflow_diagnostic>
1188 : 16 : (assign,
1189 : 16 : int (TYPE_PRECISION (TREE_TYPE (rhs1))),
1190 : : rhs2_cst));
1191 : : }
1192 : : }
1193 : :
1194 : 61749 : const svalue *sval_binop
1195 : 61749 : = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op,
1196 : : rhs1_sval, rhs2_sval);
1197 : 61749 : return sval_binop;
1198 : : }
1199 : :
1200 : : /* Vector expressions. In theory we could implement these elementwise,
1201 : : but for now, simply return unknown values. */
1202 : 0 : case VEC_DUPLICATE_EXPR:
1203 : 0 : case VEC_SERIES_EXPR:
1204 : 0 : case VEC_COND_EXPR:
1205 : 0 : case VEC_PERM_EXPR:
1206 : 0 : case VEC_WIDEN_MULT_HI_EXPR:
1207 : 0 : case VEC_WIDEN_MULT_LO_EXPR:
1208 : 0 : case VEC_WIDEN_MULT_EVEN_EXPR:
1209 : 0 : case VEC_WIDEN_MULT_ODD_EXPR:
1210 : 0 : case VEC_UNPACK_HI_EXPR:
1211 : 0 : case VEC_UNPACK_LO_EXPR:
1212 : 0 : case VEC_UNPACK_FLOAT_HI_EXPR:
1213 : 0 : case VEC_UNPACK_FLOAT_LO_EXPR:
1214 : 0 : case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
1215 : 0 : case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
1216 : 0 : case VEC_PACK_TRUNC_EXPR:
1217 : 0 : case VEC_PACK_SAT_EXPR:
1218 : 0 : case VEC_PACK_FIX_TRUNC_EXPR:
1219 : 0 : case VEC_PACK_FLOAT_EXPR:
1220 : 0 : case VEC_WIDEN_LSHIFT_HI_EXPR:
1221 : 0 : case VEC_WIDEN_LSHIFT_LO_EXPR:
1222 : 0 : return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (lhs));
1223 : : }
1224 : : }
1225 : :
1226 : : /* Workaround for discarding certain false positives from
1227 : : -Wanalyzer-use-of-uninitialized-value
1228 : : of the form:
1229 : : ((A OR-IF B) OR-IF C)
1230 : : and:
1231 : : ((A AND-IF B) AND-IF C)
1232 : : where evaluating B is redundant, but could involve simple accesses of
1233 : : uninitialized locals.
1234 : :
1235 : : When optimization is turned on the FE can immediately fold compound
1236 : : conditionals. Specifically, c_parser_condition parses this condition:
1237 : : ((A OR-IF B) OR-IF C)
1238 : : and calls c_fully_fold on the condition.
1239 : : Within c_fully_fold, fold_truth_andor is called, which bails when
1240 : : optimization is off, but if any optimization is turned on can convert the
1241 : : ((A OR-IF B) OR-IF C)
1242 : : into:
1243 : : ((A OR B) OR_IF C)
1244 : : for sufficiently simple B
1245 : : i.e. the inner OR-IF becomes an OR.
1246 : : At gimplification time the inner OR becomes BIT_IOR_EXPR (in gimplify_expr),
1247 : : giving this for the inner condition:
1248 : : tmp = A | B;
1249 : : if (tmp)
1250 : : thus effectively synthesizing a redundant access of B when optimization
1251 : : is turned on, when compared to:
1252 : : if (A) goto L1; else goto L4;
1253 : : L1: if (B) goto L2; else goto L4;
1254 : : L2: if (C) goto L3; else goto L4;
1255 : : for the unoptimized case.
1256 : :
1257 : : Return true if CTXT appears to be handling such a short-circuitable stmt,
1258 : : such as the def-stmt for B for the:
1259 : : tmp = A | B;
1260 : : case above, for the case where A is true and thus B would have been
1261 : : short-circuited without optimization, using MODEL for the value of A. */
1262 : :
1263 : : static bool
1264 : 906 : within_short_circuited_stmt_p (const region_model *model,
1265 : : const gassign *assign_stmt)
1266 : : {
1267 : : /* We must have an assignment to a temporary of _Bool type. */
1268 : 906 : tree lhs = gimple_assign_lhs (assign_stmt);
1269 : 906 : if (TREE_TYPE (lhs) != boolean_type_node)
1270 : : return false;
1271 : 42 : if (TREE_CODE (lhs) != SSA_NAME)
1272 : : return false;
1273 : 42 : if (SSA_NAME_VAR (lhs) != NULL_TREE)
1274 : : return false;
1275 : :
1276 : : /* The temporary bool must be used exactly once: as the second arg of
1277 : : a BIT_IOR_EXPR or BIT_AND_EXPR. */
1278 : 42 : use_operand_p use_op;
1279 : 42 : gimple *use_stmt;
1280 : 42 : if (!single_imm_use (lhs, &use_op, &use_stmt))
1281 : : return false;
1282 : 936 : const gassign *use_assign = dyn_cast <const gassign *> (use_stmt);
1283 : 42 : if (!use_assign)
1284 : : return false;
1285 : 42 : enum tree_code op = gimple_assign_rhs_code (use_assign);
1286 : 42 : if (!(op == BIT_IOR_EXPR ||op == BIT_AND_EXPR))
1287 : : return false;
1288 : 28 : if (!(gimple_assign_rhs1 (use_assign) != lhs
1289 : 28 : && gimple_assign_rhs2 (use_assign) == lhs))
1290 : : return false;
1291 : :
1292 : : /* The first arg of the bitwise stmt must have a known value in MODEL
1293 : : that implies that the value of the second arg doesn't matter, i.e.
1294 : : 1 for bitwise or, 0 for bitwise and. */
1295 : 28 : tree other_arg = gimple_assign_rhs1 (use_assign);
1296 : : /* Use a NULL ctxt here to avoid generating warnings. */
1297 : 28 : const svalue *other_arg_sval = model->get_rvalue (other_arg, NULL);
1298 : 28 : tree other_arg_cst = other_arg_sval->maybe_get_constant ();
1299 : 28 : if (!other_arg_cst)
1300 : : return false;
1301 : 12 : switch (op)
1302 : : {
1303 : 0 : default:
1304 : 0 : gcc_unreachable ();
1305 : 12 : case BIT_IOR_EXPR:
1306 : 12 : if (zerop (other_arg_cst))
1307 : : return false;
1308 : : break;
1309 : 0 : case BIT_AND_EXPR:
1310 : 0 : if (!zerop (other_arg_cst))
1311 : : return false;
1312 : : break;
1313 : : }
1314 : :
1315 : : /* All tests passed. We appear to be in a stmt that generates a boolean
1316 : : temporary with a value that won't matter. */
1317 : : return true;
1318 : : }
1319 : :
1320 : : /* Workaround for discarding certain false positives from
1321 : : -Wanalyzer-use-of-uninitialized-value
1322 : : seen with -ftrivial-auto-var-init=.
1323 : :
1324 : : -ftrivial-auto-var-init= will generate calls to IFN_DEFERRED_INIT.
1325 : :
1326 : : If the address of the var is taken, gimplification will give us
1327 : : something like:
1328 : :
1329 : : _1 = .DEFERRED_INIT (4, 2, &"len"[0]);
1330 : : len = _1;
1331 : :
1332 : : The result of DEFERRED_INIT will be an uninit value; we don't
1333 : : want to emit a false positive for "len = _1;"
1334 : :
1335 : : Return true if ASSIGN_STMT is such a stmt. */
1336 : :
1337 : : static bool
1338 : 894 : due_to_ifn_deferred_init_p (const gassign *assign_stmt)
1339 : :
1340 : : {
1341 : : /* We must have an assignment to a decl from an SSA name that's the
1342 : : result of a IFN_DEFERRED_INIT call. */
1343 : 1618 : if (gimple_assign_rhs_code (assign_stmt) != SSA_NAME)
1344 : : return false;
1345 : 103 : tree lhs = gimple_assign_lhs (assign_stmt);
1346 : 103 : if (TREE_CODE (lhs) != VAR_DECL)
1347 : : return false;
1348 : 30 : tree rhs = gimple_assign_rhs1 (assign_stmt);
1349 : 30 : if (TREE_CODE (rhs) != SSA_NAME)
1350 : : return false;
1351 : 30 : const gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
1352 : 30 : const gcall *call = dyn_cast <const gcall *> (def_stmt);
1353 : 30 : if (!call)
1354 : : return false;
1355 : 30 : if (gimple_call_internal_p (call)
1356 : 30 : && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1357 : 30 : return true;
1358 : : return false;
1359 : : }
1360 : :
1361 : : /* Check for SVAL being poisoned, adding a warning to CTXT.
1362 : : Return SVAL, or, if a warning is added, another value, to avoid
1363 : : repeatedly complaining about the same poisoned value in followup code.
1364 : : SRC_REGION is a hint about where SVAL came from, and can be NULL. */
1365 : :
1366 : : const svalue *
1367 : 2986886 : region_model::check_for_poison (const svalue *sval,
1368 : : tree expr,
1369 : : const region *src_region,
1370 : : region_model_context *ctxt) const
1371 : : {
1372 : 2986886 : if (!ctxt)
1373 : : return sval;
1374 : :
1375 : 1417862 : if (const poisoned_svalue *poisoned_sval = sval->dyn_cast_poisoned_svalue ())
1376 : : {
1377 : 1863 : enum poison_kind pkind = poisoned_sval->get_poison_kind ();
1378 : :
1379 : : /* Ignore uninitialized uses of empty types; there's nothing
1380 : : to initialize. */
1381 : 1863 : if (pkind == POISON_KIND_UNINIT
1382 : 1822 : && sval->get_type ()
1383 : 3583 : && is_empty_type (sval->get_type ()))
1384 : : return sval;
1385 : :
1386 : 1738 : if (pkind == POISON_KIND_UNINIT)
1387 : 1697 : if (const gimple *curr_stmt = ctxt->get_stmt ())
1388 : 1352 : if (const gassign *assign_stmt
1389 : 2602 : = dyn_cast <const gassign *> (curr_stmt))
1390 : : {
1391 : : /* Special case to avoid certain false positives. */
1392 : 906 : if (within_short_circuited_stmt_p (this, assign_stmt))
1393 : : return sval;
1394 : :
1395 : : /* Special case to avoid false positive on
1396 : : -ftrivial-auto-var-init=. */
1397 : 894 : if (due_to_ifn_deferred_init_p (assign_stmt))
1398 : : return sval;
1399 : : }
1400 : :
1401 : : /* If we have an SSA name for a temporary, we don't want to print
1402 : : '<unknown>'.
1403 : : Poisoned values are shared by type, and so we can't reconstruct
1404 : : the tree other than via the def stmts, using
1405 : : fixup_tree_for_diagnostic. */
1406 : 1696 : tree diag_arg = fixup_tree_for_diagnostic (expr);
1407 : 1696 : if (src_region == NULL && pkind == POISON_KIND_UNINIT)
1408 : 1611 : src_region = get_region_for_poisoned_expr (expr);
1409 : :
1410 : : /* Can we reliably get the poisoned value from "expr"?
1411 : : This is for use by poisoned_value_diagnostic::check_valid_fpath_p.
1412 : : Unfortunately, we might not have a reliable value for EXPR.
1413 : : Hence we only query its value now, and only use it if we get the
1414 : : poisoned value back again. */
1415 : 1696 : tree check_expr = expr;
1416 : 1696 : const svalue *foo_sval = get_rvalue (expr, NULL);
1417 : 1696 : if (foo_sval == sval)
1418 : : check_expr = expr;
1419 : : else
1420 : 102 : check_expr = NULL;
1421 : 1696 : if (ctxt->warn (make_unique<poisoned_value_diagnostic> (diag_arg,
1422 : : pkind,
1423 : : src_region,
1424 : : check_expr)))
1425 : : {
1426 : : /* We only want to report use of a poisoned value at the first
1427 : : place it gets used; return an unknown value to avoid generating
1428 : : a chain of followup warnings. */
1429 : 1251 : sval = m_mgr->get_or_create_unknown_svalue (sval->get_type ());
1430 : : }
1431 : :
1432 : 1696 : return sval;
1433 : : }
1434 : :
1435 : : return sval;
1436 : : }
1437 : :
1438 : : /* Attempt to get a region for describing EXPR, the source of region of
1439 : : a poisoned_svalue for use in a poisoned_value_diagnostic.
1440 : : Return NULL if there is no good region to use. */
1441 : :
1442 : : const region *
1443 : 1611 : region_model::get_region_for_poisoned_expr (tree expr) const
1444 : : {
1445 : 1611 : if (TREE_CODE (expr) == SSA_NAME)
1446 : : {
1447 : 774 : tree decl = SSA_NAME_VAR (expr);
1448 : 772 : if (decl && DECL_P (decl))
1449 : : expr = decl;
1450 : : else
1451 : : return NULL;
1452 : : }
1453 : 1609 : return get_lvalue (expr, NULL);
1454 : : }
1455 : :
1456 : : /* Update this model for the ASSIGN stmt, using CTXT to report any
1457 : : diagnostics. */
1458 : :
1459 : : void
1460 : 212517 : region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
1461 : : {
1462 : 212517 : tree lhs = gimple_assign_lhs (assign);
1463 : 212517 : tree rhs1 = gimple_assign_rhs1 (assign);
1464 : :
1465 : 212517 : const region *lhs_reg = get_lvalue (lhs, ctxt);
1466 : :
1467 : : /* Any writes other than to the stack are treated
1468 : : as externally visible. */
1469 : 212517 : if (ctxt)
1470 : : {
1471 : 125011 : enum memory_space memspace = lhs_reg->get_memory_space ();
1472 : 125011 : if (memspace != MEMSPACE_STACK)
1473 : 13096 : ctxt->maybe_did_work ();
1474 : : }
1475 : :
1476 : : /* Most assignments are handled by:
1477 : : set_value (lhs_reg, SVALUE, CTXT)
1478 : : for some SVALUE. */
1479 : 212517 : if (const svalue *sval = get_gassign_result (assign, ctxt))
1480 : : {
1481 : 205961 : tree expr = get_diagnostic_tree_for_gassign (assign);
1482 : 205961 : check_for_poison (sval, expr, NULL, ctxt);
1483 : 205961 : set_value (lhs_reg, sval, ctxt);
1484 : 205961 : return;
1485 : : }
1486 : :
1487 : 6556 : enum tree_code op = gimple_assign_rhs_code (assign);
1488 : 6556 : switch (op)
1489 : : {
1490 : 0 : default:
1491 : 0 : {
1492 : 0 : if (0)
1493 : : sorry_at (assign->location, "unhandled assignment op: %qs",
1494 : : get_tree_code_name (op));
1495 : 0 : const svalue *unknown_sval
1496 : 0 : = m_mgr->get_or_create_unknown_svalue (TREE_TYPE (lhs));
1497 : 0 : set_value (lhs_reg, unknown_sval, ctxt);
1498 : : }
1499 : 0 : break;
1500 : :
1501 : 6285 : case CONSTRUCTOR:
1502 : 6285 : {
1503 : 6285 : if (TREE_CLOBBER_P (rhs1))
1504 : : {
1505 : : /* e.g. "x ={v} {CLOBBER};" */
1506 : 6152 : clobber_region (lhs_reg);
1507 : : }
1508 : : else
1509 : : {
1510 : : /* Any CONSTRUCTOR that survives to this point is either
1511 : : just a zero-init of everything, or a vector. */
1512 : 133 : if (!CONSTRUCTOR_NO_CLEARING (rhs1))
1513 : 133 : zero_fill_region (lhs_reg, ctxt);
1514 : : unsigned ix;
1515 : : tree index;
1516 : : tree val;
1517 : 295 : FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs1), ix, index, val)
1518 : : {
1519 : 162 : gcc_assert (TREE_CODE (TREE_TYPE (rhs1)) == VECTOR_TYPE);
1520 : 162 : if (!index)
1521 : 22 : index = build_int_cst (integer_type_node, ix);
1522 : 162 : gcc_assert (TREE_CODE (index) == INTEGER_CST);
1523 : 162 : const svalue *index_sval
1524 : 162 : = m_mgr->get_or_create_constant_svalue (index);
1525 : 162 : gcc_assert (index_sval);
1526 : 162 : const region *sub_reg
1527 : 162 : = m_mgr->get_element_region (lhs_reg,
1528 : 162 : TREE_TYPE (val),
1529 : : index_sval);
1530 : 162 : const svalue *val_sval = get_rvalue (val, ctxt);
1531 : 162 : set_value (sub_reg, val_sval, ctxt);
1532 : : }
1533 : : }
1534 : : }
1535 : : break;
1536 : :
1537 : 271 : case STRING_CST:
1538 : 271 : {
1539 : : /* e.g. "struct s2 x = {{'A', 'B', 'C', 'D'}};". */
1540 : 271 : const svalue *rhs_sval = get_rvalue (rhs1, ctxt);
1541 : 399 : m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
1542 : 128 : ctxt ? ctxt->get_uncertainty () : NULL);
1543 : : }
1544 : 271 : break;
1545 : : }
1546 : : }
1547 : :
1548 : : /* Handle the pre-sm-state part of STMT, modifying this object in-place.
1549 : : Write true to *OUT_UNKNOWN_SIDE_EFFECTS if the stmt has unknown
1550 : : side effects. */
1551 : :
1552 : : void
1553 : 237726 : region_model::on_stmt_pre (const gimple *stmt,
1554 : : bool *out_unknown_side_effects,
1555 : : region_model_context *ctxt)
1556 : : {
1557 : 237726 : switch (gimple_code (stmt))
1558 : : {
1559 : : default:
1560 : : /* No-op for now. */
1561 : : break;
1562 : :
1563 : 0 : case GIMPLE_DEBUG:
1564 : : /* We should have stripped these out when building the supergraph. */
1565 : 0 : gcc_unreachable ();
1566 : 125011 : break;
1567 : :
1568 : 125011 : case GIMPLE_ASSIGN:
1569 : 125011 : {
1570 : 125011 : const gassign *assign = as_a <const gassign *> (stmt);
1571 : 125011 : on_assignment (assign, ctxt);
1572 : : }
1573 : 125011 : break;
1574 : :
1575 : 356 : case GIMPLE_ASM:
1576 : 356 : {
1577 : 356 : const gasm *asm_stmt = as_a <const gasm *> (stmt);
1578 : 356 : on_asm_stmt (asm_stmt, ctxt);
1579 : 356 : if (ctxt)
1580 : 356 : ctxt->maybe_did_work ();
1581 : : }
1582 : : break;
1583 : :
1584 : 55206 : case GIMPLE_CALL:
1585 : 55206 : {
1586 : : /* Track whether we have a gcall to a function that's not recognized by
1587 : : anything, for which we don't have a function body, or for which we
1588 : : don't know the fndecl. */
1589 : 55206 : const gcall *call = as_a <const gcall *> (stmt);
1590 : 55206 : *out_unknown_side_effects = on_call_pre (call, ctxt);
1591 : : }
1592 : 55206 : break;
1593 : :
1594 : 16175 : case GIMPLE_RETURN:
1595 : 16175 : {
1596 : 16175 : const greturn *return_ = as_a <const greturn *> (stmt);
1597 : 16175 : on_return (return_, ctxt);
1598 : : }
1599 : 16175 : break;
1600 : : }
1601 : 237726 : }
1602 : :
1603 : : /* Given a call CD with function attribute FORMAT_ATTR, check that the
1604 : : format arg to the call is a valid null-terminated string. */
1605 : :
1606 : : void
1607 : 1593 : region_model::check_call_format_attr (const call_details &cd,
1608 : : tree format_attr) const
1609 : : {
1610 : : /* We assume that FORMAT_ATTR has already been validated. */
1611 : :
1612 : : /* arg0 of the attribute should be kind of format strings
1613 : : that this function expects (e.g. "printf"). */
1614 : 1593 : const tree arg0_tree_list = TREE_VALUE (format_attr);
1615 : 1593 : if (!arg0_tree_list)
1616 : 0 : return;
1617 : :
1618 : : /* arg1 of the attribute should be the 1-based parameter index
1619 : : to treat as the format string. */
1620 : 1593 : const tree arg1_tree_list = TREE_CHAIN (arg0_tree_list);
1621 : 1593 : if (!arg1_tree_list)
1622 : : return;
1623 : 1593 : const tree arg1_value = TREE_VALUE (arg1_tree_list);
1624 : 1593 : if (!arg1_value)
1625 : : return;
1626 : :
1627 : 1593 : unsigned format_arg_idx = TREE_INT_CST_LOW (arg1_value) - 1;
1628 : 1593 : if (cd.num_args () <= format_arg_idx)
1629 : : return;
1630 : :
1631 : : /* Subclass of annotating_context that
1632 : : adds a note about the format attr to any saved diagnostics. */
1633 : 1593 : class annotating_ctxt : public annotating_context
1634 : : {
1635 : : public:
1636 : 1593 : annotating_ctxt (const call_details &cd,
1637 : : unsigned fmt_param_idx)
1638 : 1593 : : annotating_context (cd.get_ctxt ()),
1639 : 1593 : m_cd (cd),
1640 : 1593 : m_fmt_param_idx (fmt_param_idx)
1641 : : {
1642 : : }
1643 : 14 : void add_annotations () final override
1644 : : {
1645 : 0 : class reason_format_attr
1646 : : : public pending_note_subclass<reason_format_attr>
1647 : : {
1648 : : public:
1649 : 14 : reason_format_attr (const call_arg_details &arg_details)
1650 : 14 : : m_arg_details (arg_details)
1651 : : {
1652 : : }
1653 : :
1654 : 94 : const char *get_kind () const final override
1655 : : {
1656 : 94 : return "reason_format_attr";
1657 : : }
1658 : :
1659 : 13 : void emit () const final override
1660 : : {
1661 : 13 : inform (DECL_SOURCE_LOCATION (m_arg_details.m_called_fndecl),
1662 : : "parameter %i of %qD marked as a format string"
1663 : : " via %qs attribute",
1664 : 13 : m_arg_details.m_arg_idx + 1, m_arg_details.m_called_fndecl,
1665 : : "format");
1666 : 13 : }
1667 : :
1668 : 47 : bool operator== (const reason_format_attr &other) const
1669 : : {
1670 : 47 : return m_arg_details == other.m_arg_details;
1671 : : }
1672 : :
1673 : : private:
1674 : : call_arg_details m_arg_details;
1675 : : };
1676 : :
1677 : 14 : call_arg_details arg_details (m_cd, m_fmt_param_idx);
1678 : 14 : add_note (make_unique<reason_format_attr> (arg_details));
1679 : 14 : }
1680 : : private:
1681 : : const call_details &m_cd;
1682 : : unsigned m_fmt_param_idx;
1683 : : };
1684 : :
1685 : 1593 : annotating_ctxt my_ctxt (cd, format_arg_idx);
1686 : 1593 : call_details my_cd (cd, &my_ctxt);
1687 : 1593 : my_cd.check_for_null_terminated_string_arg (format_arg_idx);
1688 : : }
1689 : :
1690 : : /* Ensure that all arguments at the call described by CD are checked
1691 : : for poisoned values, by calling get_rvalue on each argument.
1692 : :
1693 : : Check that calls to functions with "format" attribute have valid
1694 : : null-terminated strings for their format argument. */
1695 : :
1696 : : void
1697 : 55179 : region_model::check_call_args (const call_details &cd) const
1698 : : {
1699 : 126107 : for (unsigned arg_idx = 0; arg_idx < cd.num_args (); arg_idx++)
1700 : 70928 : cd.get_arg_svalue (arg_idx);
1701 : :
1702 : : /* Handle attribute "format". */
1703 : 55179 : if (tree format_attr = cd.lookup_function_attribute ("format"))
1704 : 1593 : check_call_format_attr (cd, format_attr);
1705 : 55179 : }
1706 : :
1707 : : /* Update this model for an outcome of a call that returns a specific
1708 : : integer constant.
1709 : : If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1710 : : the state-merger code from merging success and failure outcomes. */
1711 : :
1712 : : void
1713 : 999 : region_model::update_for_int_cst_return (const call_details &cd,
1714 : : int retval,
1715 : : bool unmergeable)
1716 : : {
1717 : 999 : if (!cd.get_lhs_type ())
1718 : : return;
1719 : 711 : if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1720 : : return;
1721 : 705 : const svalue *result
1722 : 705 : = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), retval);
1723 : 705 : if (unmergeable)
1724 : 705 : result = m_mgr->get_or_create_unmergeable (result);
1725 : 705 : set_value (cd.get_lhs_region (), result, cd.get_ctxt ());
1726 : : }
1727 : :
1728 : : /* Update this model for an outcome of a call that returns zero.
1729 : : If UNMERGEABLE, then make the result unmergeable, e.g. to prevent
1730 : : the state-merger code from merging success and failure outcomes. */
1731 : :
1732 : : void
1733 : 399 : region_model::update_for_zero_return (const call_details &cd,
1734 : : bool unmergeable)
1735 : : {
1736 : 399 : update_for_int_cst_return (cd, 0, unmergeable);
1737 : 399 : }
1738 : :
1739 : : /* Update this model for an outcome of a call that returns non-zero.
1740 : : Specifically, assign an svalue to the LHS, and add a constraint that
1741 : : that svalue is non-zero. */
1742 : :
1743 : : void
1744 : 133 : region_model::update_for_nonzero_return (const call_details &cd)
1745 : : {
1746 : 133 : if (!cd.get_lhs_type ())
1747 : : return;
1748 : 97 : if (TREE_CODE (cd.get_lhs_type ()) != INTEGER_TYPE)
1749 : : return;
1750 : 97 : cd.set_any_lhs_with_defaults ();
1751 : 97 : const svalue *zero
1752 : 97 : = m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
1753 : 97 : const svalue *result
1754 : 97 : = get_store_value (cd.get_lhs_region (), cd.get_ctxt ());
1755 : 97 : add_constraint (result, NE_EXPR, zero, cd.get_ctxt ());
1756 : : }
1757 : :
1758 : : /* Subroutine of region_model::maybe_get_copy_bounds.
1759 : : The Linux kernel commonly uses
1760 : : min_t([unsigned] long, VAR, sizeof(T));
1761 : : to set an upper bound on the size of a copy_to_user.
1762 : : Attempt to simplify such sizes by trying to get the upper bound as a
1763 : : constant.
1764 : : Return the simplified svalue if possible, or NULL otherwise. */
1765 : :
1766 : : static const svalue *
1767 : 103 : maybe_simplify_upper_bound (const svalue *num_bytes_sval,
1768 : : region_model_manager *mgr)
1769 : : {
1770 : 103 : tree type = num_bytes_sval->get_type ();
1771 : 137 : while (const svalue *raw = num_bytes_sval->maybe_undo_cast ())
1772 : : num_bytes_sval = raw;
1773 : 103 : if (const binop_svalue *binop_sval = num_bytes_sval->dyn_cast_binop_svalue ())
1774 : 76 : if (binop_sval->get_op () == MIN_EXPR)
1775 : 16 : if (binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT)
1776 : : {
1777 : 16 : return mgr->get_or_create_cast (type, binop_sval->get_arg1 ());
1778 : : /* TODO: we might want to also capture the constraint
1779 : : when recording the diagnostic, or note that we're using
1780 : : the upper bound. */
1781 : : }
1782 : : return NULL;
1783 : : }
1784 : :
1785 : : /* Attempt to get an upper bound for the size of a copy when simulating a
1786 : : copy function.
1787 : :
1788 : : NUM_BYTES_SVAL is the symbolic value for the size of the copy.
1789 : : Use it if it's constant, otherwise try to simplify it. Failing
1790 : : that, use the size of SRC_REG if constant.
1791 : :
1792 : : Return a symbolic value for an upper limit on the number of bytes
1793 : : copied, or NULL if no such value could be determined. */
1794 : :
1795 : : const svalue *
1796 : 264 : region_model::maybe_get_copy_bounds (const region *src_reg,
1797 : : const svalue *num_bytes_sval)
1798 : : {
1799 : 264 : if (num_bytes_sval->maybe_get_constant ())
1800 : : return num_bytes_sval;
1801 : :
1802 : 206 : if (const svalue *simplified
1803 : 103 : = maybe_simplify_upper_bound (num_bytes_sval, m_mgr))
1804 : 16 : num_bytes_sval = simplified;
1805 : :
1806 : 103 : if (num_bytes_sval->maybe_get_constant ())
1807 : : return num_bytes_sval;
1808 : :
1809 : : /* For now, try just guessing the size as the capacity of the
1810 : : base region of the src.
1811 : : This is a hack; we might get too large a value. */
1812 : 87 : const region *src_base_reg = src_reg->get_base_region ();
1813 : 87 : num_bytes_sval = get_capacity (src_base_reg);
1814 : :
1815 : 87 : if (num_bytes_sval->maybe_get_constant ())
1816 : 22 : return num_bytes_sval;
1817 : :
1818 : : /* Non-constant: give up. */
1819 : : return NULL;
1820 : : }
1821 : :
1822 : : /* Get any known_function for FNDECL for call CD.
1823 : :
1824 : : The call must match all assumptions made by the known_function (such as
1825 : : e.g. "argument 1's type must be a pointer type").
1826 : :
1827 : : Return NULL if no known_function is found, or it does not match the
1828 : : assumption(s). */
1829 : :
1830 : : const known_function *
1831 : 354590 : region_model::get_known_function (tree fndecl, const call_details &cd) const
1832 : : {
1833 : 354590 : known_function_manager *known_fn_mgr = m_mgr->get_known_function_manager ();
1834 : 354590 : return known_fn_mgr->get_match (fndecl, cd);
1835 : : }
1836 : :
1837 : : /* Get any known_function for IFN, or NULL. */
1838 : :
1839 : : const known_function *
1840 : 1327 : region_model::get_known_function (enum internal_fn ifn) const
1841 : : {
1842 : 1327 : known_function_manager *known_fn_mgr = m_mgr->get_known_function_manager ();
1843 : 1327 : return known_fn_mgr->get_internal_fn (ifn);
1844 : : }
1845 : :
1846 : : /* Get any builtin_known_function for CALL and emit any warning to CTXT
1847 : : if not NULL.
1848 : :
1849 : : The call must match all assumptions made by the known_function (such as
1850 : : e.g. "argument 1's type must be a pointer type").
1851 : :
1852 : : Return NULL if no builtin_known_function is found, or it does
1853 : : not match the assumption(s).
1854 : :
1855 : : Internally calls get_known_function to find a known_function and cast it
1856 : : to a builtin_known_function.
1857 : :
1858 : : For instance, calloc is a C builtin, defined in gcc/builtins.def
1859 : : by the DEF_LIB_BUILTIN macro. Such builtins are recognized by the
1860 : : analyzer by their name, so that even in C++ or if the user redeclares
1861 : : them but mismatch their signature, they are still recognized as builtins.
1862 : :
1863 : : Cases when a supposed builtin is not flagged as one by the FE:
1864 : :
1865 : : The C++ FE does not recognize calloc as a builtin if it has not been
1866 : : included from a standard header, but the C FE does. Hence in C++ if
1867 : : CALL comes from a calloc and stdlib is not included,
1868 : : gcc/tree.h:fndecl_built_in_p (CALL) would be false.
1869 : :
1870 : : In C code, a __SIZE_TYPE__ calloc (__SIZE_TYPE__, __SIZE_TYPE__) user
1871 : : declaration has obviously a mismatching signature from the standard, and
1872 : : its function_decl tree won't be unified by
1873 : : gcc/c-decl.cc:match_builtin_function_types.
1874 : :
1875 : : Yet in both cases the analyzer should treat the calls as a builtin calloc
1876 : : so that extra attributes unspecified by the standard but added by GCC
1877 : : (e.g. sprintf attributes in gcc/builtins.def), useful for the detection of
1878 : : dangerous behavior, are indeed processed.
1879 : :
1880 : : Therefore for those cases when a "builtin flag" is not added by the FE,
1881 : : builtins' kf are derived from builtin_known_function, whose method
1882 : : builtin_known_function::builtin_decl returns the builtin's
1883 : : function_decl tree as defined in gcc/builtins.def, with all the extra
1884 : : attributes. */
1885 : :
1886 : : const builtin_known_function *
1887 : 194620 : region_model::get_builtin_kf (const gcall *call,
1888 : : region_model_context *ctxt /* = NULL */) const
1889 : : {
1890 : 194620 : region_model *mut_this = const_cast <region_model *> (this);
1891 : 194620 : tree callee_fndecl = mut_this->get_fndecl_for_call (call, ctxt);
1892 : 194620 : if (! callee_fndecl)
1893 : : return NULL;
1894 : :
1895 : 194620 : call_details cd (call, mut_this, ctxt);
1896 : 194620 : if (const known_function *kf = get_known_function (callee_fndecl, cd))
1897 : 114376 : return kf->dyn_cast_builtin_kf ();
1898 : :
1899 : : return NULL;
1900 : : }
1901 : :
1902 : : /* Update this model for the CALL stmt, using CTXT to report any
1903 : : diagnostics - the first half.
1904 : :
1905 : : Updates to the region_model that should be made *before* sm-states
1906 : : are updated are done here; other updates to the region_model are done
1907 : : in region_model::on_call_post.
1908 : :
1909 : : Return true if the function call has unknown side effects (it wasn't
1910 : : recognized and we don't have a body for it, or are unable to tell which
1911 : : fndecl it is). */
1912 : :
1913 : : bool
1914 : 81790 : region_model::on_call_pre (const gcall *call, region_model_context *ctxt)
1915 : : {
1916 : 81790 : call_details cd (call, this, ctxt);
1917 : :
1918 : : /* Special-case for IFN_DEFERRED_INIT.
1919 : : We want to report uninitialized variables with -fanalyzer (treating
1920 : : -ftrivial-auto-var-init= as purely a mitigation feature).
1921 : : Handle IFN_DEFERRED_INIT by treating it as no-op: don't touch the
1922 : : lhs of the call, so that it is still uninitialized from the point of
1923 : : view of the analyzer. */
1924 : 81790 : if (gimple_call_internal_p (call)
1925 : 81790 : && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT)
1926 : : return false; /* No side effects. */
1927 : :
1928 : : /* Get svalues for all of the arguments at the callsite, to ensure that we
1929 : : complain about any uninitialized arguments. This might lead to
1930 : : duplicates if any of the handling below also looks up the svalues,
1931 : : but the deduplication code should deal with that. */
1932 : 81733 : if (ctxt)
1933 : 55179 : check_call_args (cd);
1934 : :
1935 : 81733 : tree callee_fndecl = get_fndecl_for_call (call, ctxt);
1936 : :
1937 : 81733 : if (gimple_call_internal_p (call))
1938 : 2654 : if (const known_function *kf
1939 : 1327 : = get_known_function (gimple_call_internal_fn (call)))
1940 : : {
1941 : 1249 : kf->impl_call_pre (cd);
1942 : 1249 : return false; /* No further side effects. */
1943 : : }
1944 : :
1945 : 80484 : if (!callee_fndecl)
1946 : : {
1947 : 567 : cd.set_any_lhs_with_defaults ();
1948 : 567 : return true; /* Unknown side effects. */
1949 : : }
1950 : :
1951 : 79917 : if (const known_function *kf = get_known_function (callee_fndecl, cd))
1952 : : {
1953 : 48562 : kf->impl_call_pre (cd);
1954 : 48562 : return false; /* No further side effects. */
1955 : : }
1956 : :
1957 : 31355 : cd.set_any_lhs_with_defaults ();
1958 : :
1959 : 31355 : const int callee_fndecl_flags = flags_from_decl_or_type (callee_fndecl);
1960 : 31355 : if (callee_fndecl_flags & (ECF_CONST | ECF_PURE))
1961 : : return false; /* No side effects. */
1962 : :
1963 : 29671 : if (fndecl_built_in_p (callee_fndecl))
1964 : : return true; /* Unknown side effects. */
1965 : :
1966 : 28824 : if (!fndecl_has_gimple_body_p (callee_fndecl))
1967 : : return true; /* Unknown side effects. */
1968 : :
1969 : : return false; /* No side effects. */
1970 : : }
1971 : :
1972 : : /* Update this model for the CALL stmt, using CTXT to report any
1973 : : diagnostics - the second half.
1974 : :
1975 : : Updates to the region_model that should be made *after* sm-states
1976 : : are updated are done here; other updates to the region_model are done
1977 : : in region_model::on_call_pre.
1978 : :
1979 : : If UNKNOWN_SIDE_EFFECTS is true, also call handle_unrecognized_call
1980 : : to purge state. */
1981 : :
1982 : : void
1983 : 81895 : region_model::on_call_post (const gcall *call,
1984 : : bool unknown_side_effects,
1985 : : region_model_context *ctxt)
1986 : : {
1987 : 81895 : if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
1988 : : {
1989 : 80053 : call_details cd (call, this, ctxt);
1990 : 80053 : if (const known_function *kf = get_known_function (callee_fndecl, cd))
1991 : : {
1992 : 48391 : kf->impl_call_post (cd);
1993 : 97295 : return;
1994 : : }
1995 : : /* Was this fndecl referenced by
1996 : : __attribute__((malloc(FOO)))? */
1997 : 31662 : if (lookup_attribute ("*dealloc", DECL_ATTRIBUTES (callee_fndecl)))
1998 : : {
1999 : 513 : impl_deallocation_call (cd);
2000 : 513 : return;
2001 : : }
2002 : : }
2003 : :
2004 : 32991 : if (unknown_side_effects)
2005 : : {
2006 : 18460 : handle_unrecognized_call (call, ctxt);
2007 : 18460 : if (ctxt)
2008 : 12378 : ctxt->maybe_did_work ();
2009 : : }
2010 : : }
2011 : :
2012 : : /* Purge state involving SVAL from this region_model, using CTXT
2013 : : (if non-NULL) to purge other state in a program_state.
2014 : :
2015 : : For example, if we're at the def-stmt of an SSA name, then we need to
2016 : : purge any state for svalues that involve that SSA name. This avoids
2017 : : false positives in loops, since a symbolic value referring to the
2018 : : SSA name will be referring to the previous value of that SSA name.
2019 : :
2020 : : For example, in:
2021 : : while ((e = hashmap_iter_next(&iter))) {
2022 : : struct oid2strbuf *e_strbuf = (struct oid2strbuf *)e;
2023 : : free (e_strbuf->value);
2024 : : }
2025 : : at the def-stmt of e_8:
2026 : : e_8 = hashmap_iter_next (&iter);
2027 : : we should purge the "freed" state of:
2028 : : INIT_VAL(CAST_REG(‘struct oid2strbuf’, (*INIT_VAL(e_8))).value)
2029 : : which is the "e_strbuf->value" value from the previous iteration,
2030 : : or we will erroneously report a double-free - the "e_8" within it
2031 : : refers to the previous value. */
2032 : :
2033 : : void
2034 : 34405 : region_model::purge_state_involving (const svalue *sval,
2035 : : region_model_context *ctxt)
2036 : : {
2037 : 34405 : if (!sval->can_have_associated_state_p ())
2038 : : return;
2039 : 34405 : m_store.purge_state_involving (sval, m_mgr);
2040 : 34405 : m_constraints->purge_state_involving (sval);
2041 : 34405 : m_dynamic_extents.purge_state_involving (sval);
2042 : 34405 : if (ctxt)
2043 : 18067 : ctxt->purge_state_involving (sval);
2044 : : }
2045 : :
2046 : : /* A pending_note subclass for adding a note about an
2047 : : __attribute__((access, ...)) to a diagnostic. */
2048 : :
2049 : : class reason_attr_access : public pending_note_subclass<reason_attr_access>
2050 : : {
2051 : : public:
2052 : 22 : reason_attr_access (tree callee_fndecl, const attr_access &access)
2053 : 22 : : m_callee_fndecl (callee_fndecl),
2054 : 22 : m_ptr_argno (access.ptrarg),
2055 : 22 : m_access_str (TREE_STRING_POINTER (access.to_external_string ()))
2056 : : {
2057 : 22 : }
2058 : :
2059 : 136 : const char *get_kind () const final override { return "reason_attr_access"; }
2060 : :
2061 : 18 : void emit () const final override
2062 : : {
2063 : 18 : inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
2064 : : "parameter %i of %qD marked with attribute %qs",
2065 : 18 : m_ptr_argno + 1, m_callee_fndecl, m_access_str);
2066 : 18 : }
2067 : :
2068 : 68 : bool operator== (const reason_attr_access &other) const
2069 : : {
2070 : 68 : return (m_callee_fndecl == other.m_callee_fndecl
2071 : 22 : && m_ptr_argno == other.m_ptr_argno
2072 : 90 : && !strcmp (m_access_str, other.m_access_str));
2073 : : }
2074 : :
2075 : : private:
2076 : : tree m_callee_fndecl;
2077 : : unsigned m_ptr_argno;
2078 : : const char *m_access_str;
2079 : : };
2080 : :
2081 : : /* Check CALL a call to external function CALLEE_FNDECL based on
2082 : : any __attribute__ ((access, ....) on the latter, complaining to
2083 : : CTXT about any issues.
2084 : :
2085 : : Currently we merely call check_region_for_write on any regions
2086 : : pointed to by arguments marked with a "write_only" or "read_write"
2087 : : attribute. */
2088 : :
2089 : : void
2090 : 1223 : region_model::check_function_attr_access (const gcall *call,
2091 : : tree callee_fndecl,
2092 : : region_model_context *ctxt,
2093 : : rdwr_map &rdwr_idx) const
2094 : : {
2095 : 1223 : gcc_assert (call);
2096 : 1223 : gcc_assert (callee_fndecl);
2097 : 1223 : gcc_assert (ctxt);
2098 : :
2099 : 1223 : tree fntype = TREE_TYPE (callee_fndecl);
2100 : 1223 : gcc_assert (fntype);
2101 : :
2102 : 1223 : unsigned argno = 0;
2103 : :
2104 : 4568 : for (tree iter = TYPE_ARG_TYPES (fntype); iter;
2105 : 3345 : iter = TREE_CHAIN (iter), ++argno)
2106 : : {
2107 : 3345 : const attr_access* access = rdwr_idx.get (argno);
2108 : 3345 : if (!access)
2109 : 3075 : continue;
2110 : :
2111 : : /* Ignore any duplicate entry in the map for the size argument. */
2112 : 270 : if (access->ptrarg != argno)
2113 : 109 : continue;
2114 : :
2115 : 161 : if (access->mode == access_write_only
2116 : 161 : || access->mode == access_read_write)
2117 : : {
2118 : : /* Subclass of annotating_context that
2119 : : adds a note about the attr access to any saved diagnostics. */
2120 : 42 : class annotating_ctxt : public annotating_context
2121 : : {
2122 : : public:
2123 : 42 : annotating_ctxt (tree callee_fndecl,
2124 : : const attr_access &access,
2125 : : region_model_context *ctxt)
2126 : 42 : : annotating_context (ctxt),
2127 : 42 : m_callee_fndecl (callee_fndecl),
2128 : 42 : m_access (access)
2129 : : {
2130 : : }
2131 : 22 : void add_annotations () final override
2132 : : {
2133 : 22 : add_note (make_unique<reason_attr_access>
2134 : 44 : (m_callee_fndecl, m_access));
2135 : 22 : }
2136 : : private:
2137 : : tree m_callee_fndecl;
2138 : : const attr_access &m_access;
2139 : : };
2140 : :
2141 : : /* Use this ctxt below so that any diagnostics get the
2142 : : note added to them. */
2143 : 42 : annotating_ctxt my_ctxt (callee_fndecl, *access, ctxt);
2144 : :
2145 : 42 : tree ptr_tree = gimple_call_arg (call, access->ptrarg);
2146 : 42 : const svalue *ptr_sval = get_rvalue (ptr_tree, &my_ctxt);
2147 : 42 : const region *reg = deref_rvalue (ptr_sval, ptr_tree, &my_ctxt);
2148 : 42 : check_region_for_write (reg, nullptr, &my_ctxt);
2149 : : /* We don't use the size arg for now. */
2150 : : }
2151 : : }
2152 : 1223 : }
2153 : :
2154 : : /* Subroutine of region_model::check_function_attr_null_terminated_string_arg,
2155 : : checking one instance of __attribute__((null_terminated_string_arg)). */
2156 : :
2157 : : void
2158 : 184 : region_model::
2159 : : check_one_function_attr_null_terminated_string_arg (const gcall *call,
2160 : : tree callee_fndecl,
2161 : : region_model_context *ctxt,
2162 : : rdwr_map &rdwr_idx,
2163 : : tree attr)
2164 : : {
2165 : 184 : gcc_assert (call);
2166 : 184 : gcc_assert (callee_fndecl);
2167 : 184 : gcc_assert (ctxt);
2168 : 184 : gcc_assert (attr);
2169 : :
2170 : 184 : tree arg = TREE_VALUE (attr);
2171 : 184 : if (!arg)
2172 : 68 : return;
2173 : :
2174 : : /* Convert from 1-based to 0-based index. */
2175 : 184 : unsigned int arg_idx = TREE_INT_CST_LOW (TREE_VALUE (arg)) - 1;
2176 : :
2177 : : /* If there's also an "access" attribute on the ptr param
2178 : : for reading with a size param specified, then that size
2179 : : limits the size of the possible read from the pointer. */
2180 : 184 : if (const attr_access* access = rdwr_idx.get (arg_idx))
2181 : 96 : if ((access->mode == access_read_only
2182 : 96 : || access->mode == access_read_write)
2183 : 96 : && access->sizarg != UINT_MAX)
2184 : : {
2185 : 68 : call_details cd_checked (call, this, ctxt);
2186 : 68 : const svalue *limit_sval
2187 : 68 : = cd_checked.get_arg_svalue (access->sizarg);
2188 : 68 : const svalue *ptr_sval
2189 : 68 : = cd_checked.get_arg_svalue (arg_idx);
2190 : : /* Try reading all of the bytes expressed by the size param,
2191 : : but without emitting warnings (via a null context). */
2192 : 68 : const svalue *limited_sval
2193 : 68 : = read_bytes (deref_rvalue (ptr_sval, NULL_TREE, nullptr),
2194 : : NULL_TREE,
2195 : : limit_sval,
2196 : : nullptr);
2197 : 68 : if (limited_sval->get_kind () == SK_POISONED)
2198 : : {
2199 : : /* Reading up to the truncation limit caused issues.
2200 : : Assume that the string is meant to be terminated
2201 : : before then, so perform a *checked* check for the
2202 : : terminator. */
2203 : 24 : check_for_null_terminated_string_arg (cd_checked,
2204 : : arg_idx);
2205 : : }
2206 : : else
2207 : : {
2208 : : /* Reading up to the truncation limit seems OK; repeat
2209 : : the read, but with checking enabled. */
2210 : 44 : read_bytes (deref_rvalue (ptr_sval, NULL_TREE, ctxt),
2211 : : NULL_TREE,
2212 : : limit_sval,
2213 : : ctxt);
2214 : : }
2215 : 68 : return;
2216 : : }
2217 : :
2218 : : /* Otherwise, we don't have an access-attribute limiting the read.
2219 : : Simulate a read up to the null terminator (if any). */
2220 : :
2221 : 116 : call_details cd (call, this, ctxt);
2222 : 116 : check_for_null_terminated_string_arg (cd, arg_idx);
2223 : : }
2224 : :
2225 : : /* Check CALL a call to external function CALLEE_FNDECL for any uses
2226 : : of __attribute__ ((null_terminated_string_arg)), compaining
2227 : : to CTXT about any issues.
2228 : :
2229 : : Use RDWR_IDX for tracking uses of __attribute__ ((access, ....). */
2230 : :
2231 : : void
2232 : 1223 : region_model::
2233 : : check_function_attr_null_terminated_string_arg (const gcall *call,
2234 : : tree callee_fndecl,
2235 : : region_model_context *ctxt,
2236 : : rdwr_map &rdwr_idx)
2237 : : {
2238 : 1223 : gcc_assert (call);
2239 : 1223 : gcc_assert (callee_fndecl);
2240 : 1223 : gcc_assert (ctxt);
2241 : :
2242 : 1223 : tree fntype = TREE_TYPE (callee_fndecl);
2243 : 1223 : gcc_assert (fntype);
2244 : :
2245 : : /* A function declaration can specify multiple attribute
2246 : : null_terminated_string_arg, each with one argument. */
2247 : 1407 : for (tree attr = TYPE_ATTRIBUTES (fntype); attr; attr = TREE_CHAIN (attr))
2248 : : {
2249 : 1247 : attr = lookup_attribute ("null_terminated_string_arg", attr);
2250 : 1247 : if (!attr)
2251 : : return;
2252 : :
2253 : 184 : check_one_function_attr_null_terminated_string_arg (call, callee_fndecl,
2254 : : ctxt, rdwr_idx,
2255 : : attr);
2256 : : }
2257 : : }
2258 : :
2259 : : /* Check CALL a call to external function CALLEE_FNDECL for any
2260 : : function attributes, complaining to CTXT about any issues. */
2261 : :
2262 : : void
2263 : 11924 : region_model::check_function_attrs (const gcall *call,
2264 : : tree callee_fndecl,
2265 : : region_model_context *ctxt)
2266 : : {
2267 : 11924 : gcc_assert (call);
2268 : 11924 : gcc_assert (callee_fndecl);
2269 : 11924 : gcc_assert (ctxt);
2270 : :
2271 : 11924 : tree fntype = TREE_TYPE (callee_fndecl);
2272 : 11924 : if (!fntype)
2273 : 10701 : return;
2274 : :
2275 : 11924 : if (!TYPE_ATTRIBUTES (fntype))
2276 : : return;
2277 : :
2278 : : /* Initialize a map of attribute access specifications for arguments
2279 : : to the function call. */
2280 : 1223 : rdwr_map rdwr_idx;
2281 : 1223 : init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype));
2282 : :
2283 : 1223 : check_function_attr_access (call, callee_fndecl, ctxt, rdwr_idx);
2284 : 1223 : check_function_attr_null_terminated_string_arg (call, callee_fndecl,
2285 : : ctxt, rdwr_idx);
2286 : 1223 : }
2287 : :
2288 : : /* Handle a call CALL to a function with unknown behavior.
2289 : :
2290 : : Traverse the regions in this model, determining what regions are
2291 : : reachable from pointer arguments to CALL and from global variables,
2292 : : recursively.
2293 : :
2294 : : Set all reachable regions to new unknown values and purge sm-state
2295 : : from their values, and from values that point to them. */
2296 : :
2297 : : void
2298 : 18460 : region_model::handle_unrecognized_call (const gcall *call,
2299 : : region_model_context *ctxt)
2300 : : {
2301 : 18460 : tree fndecl = get_fndecl_for_call (call, ctxt);
2302 : :
2303 : 18460 : if (fndecl && ctxt)
2304 : 11924 : check_function_attrs (call, fndecl, ctxt);
2305 : :
2306 : 18460 : reachable_regions reachable_regs (this);
2307 : :
2308 : : /* Determine the reachable regions and their mutability. */
2309 : 18460 : {
2310 : : /* Add globals and regions that already escaped in previous
2311 : : unknown calls. */
2312 : 18460 : m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2313 : : &reachable_regs);
2314 : :
2315 : : /* Params that are pointers. */
2316 : 18460 : tree iter_param_types = NULL_TREE;
2317 : 18460 : if (fndecl)
2318 : 17898 : iter_param_types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
2319 : 40152 : for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
2320 : : {
2321 : : /* Track expected param type, where available. */
2322 : 21692 : tree param_type = NULL_TREE;
2323 : 21692 : if (iter_param_types)
2324 : : {
2325 : 20084 : param_type = TREE_VALUE (iter_param_types);
2326 : 20084 : gcc_assert (param_type);
2327 : 20084 : iter_param_types = TREE_CHAIN (iter_param_types);
2328 : : }
2329 : :
2330 : 21692 : tree parm = gimple_call_arg (call, arg_idx);
2331 : 21692 : const svalue *parm_sval = get_rvalue (parm, ctxt);
2332 : 21692 : reachable_regs.handle_parm (parm_sval, param_type);
2333 : : }
2334 : : }
2335 : :
2336 : 18460 : uncertainty_t *uncertainty = ctxt ? ctxt->get_uncertainty () : NULL;
2337 : :
2338 : : /* Purge sm-state for the svalues that were reachable,
2339 : : both in non-mutable and mutable form. */
2340 : 52138 : for (svalue_set::iterator iter
2341 : 18460 : = reachable_regs.begin_reachable_svals ();
2342 : 85816 : iter != reachable_regs.end_reachable_svals (); ++iter)
2343 : : {
2344 : 33678 : const svalue *sval = (*iter);
2345 : 33678 : if (ctxt)
2346 : 24420 : ctxt->on_unknown_change (sval, false);
2347 : : }
2348 : 65866 : for (svalue_set::iterator iter
2349 : 18460 : = reachable_regs.begin_mutable_svals ();
2350 : 113272 : iter != reachable_regs.end_mutable_svals (); ++iter)
2351 : : {
2352 : 47406 : const svalue *sval = (*iter);
2353 : 47406 : if (ctxt)
2354 : 35498 : ctxt->on_unknown_change (sval, true);
2355 : 47406 : if (uncertainty)
2356 : 35498 : uncertainty->on_mutable_sval_at_unknown_call (sval);
2357 : : }
2358 : :
2359 : : /* Mark any clusters that have escaped. */
2360 : 18460 : reachable_regs.mark_escaped_clusters (ctxt);
2361 : :
2362 : : /* Update bindings for all clusters that have escaped, whether above,
2363 : : or previously. */
2364 : 18460 : m_store.on_unknown_fncall (call, m_mgr->get_store_manager (),
2365 : 18460 : conjured_purge (this, ctxt));
2366 : :
2367 : : /* Purge dynamic extents from any regions that have escaped mutably:
2368 : : realloc could have been called on them. */
2369 : 50805 : for (hash_set<const region *>::iterator
2370 : 18460 : iter = reachable_regs.begin_mutable_base_regs ();
2371 : 50805 : iter != reachable_regs.end_mutable_base_regs ();
2372 : 32345 : ++iter)
2373 : : {
2374 : 32345 : const region *base_reg = (*iter);
2375 : 32345 : unset_dynamic_extents (base_reg);
2376 : : }
2377 : 18460 : }
2378 : :
2379 : : /* Traverse the regions in this model, determining what regions are
2380 : : reachable from the store and populating *OUT.
2381 : :
2382 : : If EXTRA_SVAL is non-NULL, treat it as an additional "root"
2383 : : for reachability (for handling return values from functions when
2384 : : analyzing return of the only function on the stack).
2385 : :
2386 : : If UNCERTAINTY is non-NULL, treat any svalues that were recorded
2387 : : within it as being maybe-bound as additional "roots" for reachability.
2388 : :
2389 : : Find svalues that haven't leaked. */
2390 : :
2391 : : void
2392 : 1147478 : region_model::get_reachable_svalues (svalue_set *out,
2393 : : const svalue *extra_sval,
2394 : : const uncertainty_t *uncertainty)
2395 : : {
2396 : 1147478 : reachable_regions reachable_regs (this);
2397 : :
2398 : : /* Add globals and regions that already escaped in previous
2399 : : unknown calls. */
2400 : 1147478 : m_store.for_each_cluster (reachable_regions::init_cluster_cb,
2401 : : &reachable_regs);
2402 : :
2403 : 1147478 : if (extra_sval)
2404 : 4916 : reachable_regs.handle_sval (extra_sval);
2405 : :
2406 : 1147478 : if (uncertainty)
2407 : 663256 : for (uncertainty_t::iterator iter
2408 : 573739 : = uncertainty->begin_maybe_bound_svals ();
2409 : 1326512 : iter != uncertainty->end_maybe_bound_svals (); ++iter)
2410 : 89517 : reachable_regs.handle_sval (*iter);
2411 : :
2412 : : /* Get regions for locals that have explicitly bound values. */
2413 : 8580262 : for (store::cluster_map_t::iterator iter = m_store.begin ();
2414 : 16013046 : iter != m_store.end (); ++iter)
2415 : : {
2416 : 7432784 : const region *base_reg = (*iter).first;
2417 : 7432784 : if (const region *parent = base_reg->get_parent_region ())
2418 : 7432784 : if (parent->get_kind () == RK_FRAME)
2419 : 4184955 : reachable_regs.add (base_reg, false);
2420 : : }
2421 : :
2422 : : /* Populate *OUT based on the values that were reachable. */
2423 : 1147478 : for (svalue_set::iterator iter
2424 : 1147478 : = reachable_regs.begin_reachable_svals ();
2425 : 13320512 : iter != reachable_regs.end_reachable_svals (); ++iter)
2426 : 6086517 : out->add (*iter);
2427 : 1147478 : }
2428 : :
2429 : : /* Update this model for the RETURN_STMT, using CTXT to report any
2430 : : diagnostics. */
2431 : :
2432 : : void
2433 : 19251 : region_model::on_return (const greturn *return_stmt, region_model_context *ctxt)
2434 : : {
2435 : 19251 : tree callee = get_current_function ()->decl;
2436 : 19251 : tree lhs = DECL_RESULT (callee);
2437 : 19251 : tree rhs = gimple_return_retval (return_stmt);
2438 : :
2439 : 19251 : if (lhs && rhs)
2440 : : {
2441 : 9045 : const svalue *sval = get_rvalue (rhs, ctxt);
2442 : 9045 : const region *ret_reg = get_lvalue (lhs, ctxt);
2443 : 9045 : set_value (ret_reg, sval, ctxt);
2444 : : }
2445 : 19251 : }
2446 : :
2447 : : /* Update this model for a call and return of setjmp/sigsetjmp at CALL within
2448 : : ENODE, using CTXT to report any diagnostics.
2449 : :
2450 : : This is for the initial direct invocation of setjmp/sigsetjmp (which returns
2451 : : 0), as opposed to any second return due to longjmp/sigsetjmp. */
2452 : :
2453 : : void
2454 : 34 : region_model::on_setjmp (const gcall *call, const exploded_node *enode,
2455 : : region_model_context *ctxt)
2456 : : {
2457 : 34 : const svalue *buf_ptr = get_rvalue (gimple_call_arg (call, 0), ctxt);
2458 : 34 : const region *buf_reg = deref_rvalue (buf_ptr, gimple_call_arg (call, 0),
2459 : : ctxt);
2460 : :
2461 : : /* Create a setjmp_svalue for this call and store it in BUF_REG's
2462 : : region. */
2463 : 34 : if (buf_reg)
2464 : : {
2465 : 34 : setjmp_record r (enode, call);
2466 : 34 : const svalue *sval
2467 : 34 : = m_mgr->get_or_create_setjmp_svalue (r, buf_reg->get_type ());
2468 : 34 : set_value (buf_reg, sval, ctxt);
2469 : : }
2470 : :
2471 : : /* Direct calls to setjmp return 0. */
2472 : 34 : if (tree lhs = gimple_call_lhs (call))
2473 : : {
2474 : 16 : const svalue *new_sval
2475 : 16 : = m_mgr->get_or_create_int_cst (TREE_TYPE (lhs), 0);
2476 : 16 : const region *lhs_reg = get_lvalue (lhs, ctxt);
2477 : 16 : set_value (lhs_reg, new_sval, ctxt);
2478 : : }
2479 : 34 : }
2480 : :
2481 : : /* Update this region_model for rewinding from a "longjmp" at LONGJMP_CALL
2482 : : to a "setjmp" at SETJMP_CALL where the final stack depth should be
2483 : : SETJMP_STACK_DEPTH. Pop any stack frames. Leak detection is *not*
2484 : : done, and should be done by the caller. */
2485 : :
2486 : : void
2487 : 31 : region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
2488 : : int setjmp_stack_depth, region_model_context *ctxt)
2489 : : {
2490 : : /* Evaluate the val, using the frame of the "longjmp". */
2491 : 31 : tree fake_retval = gimple_call_arg (longjmp_call, 1);
2492 : 31 : const svalue *fake_retval_sval = get_rvalue (fake_retval, ctxt);
2493 : :
2494 : : /* Pop any frames until we reach the stack depth of the function where
2495 : : setjmp was called. */
2496 : 31 : gcc_assert (get_stack_depth () >= setjmp_stack_depth);
2497 : 61 : while (get_stack_depth () > setjmp_stack_depth)
2498 : 30 : pop_frame (NULL, NULL, ctxt, nullptr, false);
2499 : :
2500 : 31 : gcc_assert (get_stack_depth () == setjmp_stack_depth);
2501 : :
2502 : : /* Assign to LHS of "setjmp" in new_state. */
2503 : 31 : if (tree lhs = gimple_call_lhs (setjmp_call))
2504 : : {
2505 : : /* Passing 0 as the val to longjmp leads to setjmp returning 1. */
2506 : 27 : const svalue *zero_sval
2507 : 27 : = m_mgr->get_or_create_int_cst (TREE_TYPE (fake_retval), 0);
2508 : 27 : tristate eq_zero = eval_condition (fake_retval_sval, EQ_EXPR, zero_sval);
2509 : : /* If we have 0, use 1. */
2510 : 27 : if (eq_zero.is_true ())
2511 : : {
2512 : 2 : const svalue *one_sval
2513 : 2 : = m_mgr->get_or_create_int_cst (TREE_TYPE (fake_retval), 1);
2514 : 2 : fake_retval_sval = one_sval;
2515 : : }
2516 : : else
2517 : : {
2518 : : /* Otherwise note that the value is nonzero. */
2519 : 25 : m_constraints->add_constraint (fake_retval_sval, NE_EXPR, zero_sval);
2520 : : }
2521 : :
2522 : : /* Decorate the return value from setjmp as being unmergeable,
2523 : : so that we don't attempt to merge states with it as zero
2524 : : with states in which it's nonzero, leading to a clean distinction
2525 : : in the exploded_graph betweeen the first return and the second
2526 : : return. */
2527 : 27 : fake_retval_sval = m_mgr->get_or_create_unmergeable (fake_retval_sval);
2528 : :
2529 : 27 : const region *lhs_reg = get_lvalue (lhs, ctxt);
2530 : 27 : set_value (lhs_reg, fake_retval_sval, ctxt);
2531 : : }
2532 : 31 : }
2533 : :
2534 : : /* Update this region_model for a phi stmt of the form
2535 : : LHS = PHI <...RHS...>.
2536 : : where RHS is for the appropriate edge.
2537 : : Get state from OLD_STATE so that all of the phi stmts for a basic block
2538 : : are effectively handled simultaneously. */
2539 : :
2540 : : void
2541 : 76646 : region_model::handle_phi (const gphi *phi,
2542 : : tree lhs, tree rhs,
2543 : : const region_model &old_state,
2544 : : hash_set<const svalue *> &svals_changing_meaning,
2545 : : region_model_context *ctxt)
2546 : : {
2547 : : /* For now, don't bother tracking the .MEM SSA names. */
2548 : 76646 : if (tree var = SSA_NAME_VAR (lhs))
2549 : 66406 : if (TREE_CODE (var) == VAR_DECL)
2550 : 64283 : if (VAR_DECL_IS_VIRTUAL_OPERAND (var))
2551 : 35607 : return;
2552 : :
2553 : 41039 : const svalue *src_sval = old_state.get_rvalue (rhs, ctxt);
2554 : 41039 : const region *dst_reg = old_state.get_lvalue (lhs, ctxt);
2555 : :
2556 : 41039 : const svalue *sval = old_state.get_rvalue (lhs, nullptr);
2557 : 41039 : if (sval->get_kind () == SK_WIDENING)
2558 : 1660 : svals_changing_meaning.add (sval);
2559 : :
2560 : 41039 : set_value (dst_reg, src_sval, ctxt);
2561 : :
2562 : 41039 : if (ctxt)
2563 : 31050 : ctxt->on_phi (phi, rhs);
2564 : : }
2565 : :
2566 : : /* Implementation of region_model::get_lvalue; the latter adds type-checking.
2567 : :
2568 : : Get the id of the region for PV within this region_model,
2569 : : emitting any diagnostics to CTXT. */
2570 : :
2571 : : const region *
2572 : 2374411 : region_model::get_lvalue_1 (path_var pv, region_model_context *ctxt) const
2573 : : {
2574 : 2374411 : tree expr = pv.m_tree;
2575 : :
2576 : 2374411 : gcc_assert (expr);
2577 : :
2578 : 2374411 : switch (TREE_CODE (expr))
2579 : : {
2580 : 54 : default:
2581 : 54 : return m_mgr->get_region_for_unexpected_tree_code (ctxt, expr,
2582 : 54 : dump_location_t ());
2583 : :
2584 : 14843 : case ARRAY_REF:
2585 : 14843 : {
2586 : 14843 : tree array = TREE_OPERAND (expr, 0);
2587 : 14843 : tree index = TREE_OPERAND (expr, 1);
2588 : :
2589 : 14843 : const region *array_reg = get_lvalue (array, ctxt);
2590 : 14843 : const svalue *index_sval = get_rvalue (index, ctxt);
2591 : 14843 : return m_mgr->get_element_region (array_reg,
2592 : 14843 : TREE_TYPE (TREE_TYPE (array)),
2593 : 14843 : index_sval);
2594 : : }
2595 : 184 : break;
2596 : :
2597 : 184 : case BIT_FIELD_REF:
2598 : 184 : {
2599 : 184 : tree inner_expr = TREE_OPERAND (expr, 0);
2600 : 184 : const region *inner_reg = get_lvalue (inner_expr, ctxt);
2601 : 184 : tree num_bits = TREE_OPERAND (expr, 1);
2602 : 184 : tree first_bit_offset = TREE_OPERAND (expr, 2);
2603 : 184 : gcc_assert (TREE_CODE (num_bits) == INTEGER_CST);
2604 : 184 : gcc_assert (TREE_CODE (first_bit_offset) == INTEGER_CST);
2605 : 184 : bit_range bits (TREE_INT_CST_LOW (first_bit_offset),
2606 : 368 : TREE_INT_CST_LOW (num_bits));
2607 : 184 : return m_mgr->get_bit_range (inner_reg, TREE_TYPE (expr), bits);
2608 : : }
2609 : 77882 : break;
2610 : :
2611 : 77882 : case MEM_REF:
2612 : 77882 : {
2613 : 77882 : tree ptr = TREE_OPERAND (expr, 0);
2614 : 77882 : tree offset = TREE_OPERAND (expr, 1);
2615 : 77882 : const svalue *ptr_sval = get_rvalue (ptr, ctxt);
2616 : 77882 : const svalue *offset_sval = get_rvalue (offset, ctxt);
2617 : 77882 : const region *star_ptr = deref_rvalue (ptr_sval, ptr, ctxt);
2618 : 77882 : return m_mgr->get_offset_region (star_ptr,
2619 : 77882 : TREE_TYPE (expr),
2620 : 77882 : offset_sval);
2621 : : }
2622 : 862053 : break;
2623 : :
2624 : 862053 : case FUNCTION_DECL:
2625 : 862053 : return m_mgr->get_region_for_fndecl (expr);
2626 : :
2627 : 314 : case LABEL_DECL:
2628 : 314 : return m_mgr->get_region_for_label (expr);
2629 : :
2630 : 134893 : case VAR_DECL:
2631 : : /* Handle globals. */
2632 : 134893 : if (is_global_var (expr))
2633 : 58581 : return m_mgr->get_region_for_global (expr);
2634 : :
2635 : : /* Fall through. */
2636 : :
2637 : 1287127 : case SSA_NAME:
2638 : 1287127 : case PARM_DECL:
2639 : 1287127 : case RESULT_DECL:
2640 : 1287127 : {
2641 : 1287127 : gcc_assert (TREE_CODE (expr) == SSA_NAME
2642 : : || TREE_CODE (expr) == PARM_DECL
2643 : : || VAR_P (expr)
2644 : : || TREE_CODE (expr) == RESULT_DECL);
2645 : :
2646 : 1287127 : int stack_index = pv.m_stack_depth;
2647 : 1287127 : const frame_region *frame = get_frame_at_index (stack_index);
2648 : 1287127 : gcc_assert (frame);
2649 : 1287127 : return frame->get_region_for_local (m_mgr, expr, ctxt);
2650 : : }
2651 : :
2652 : 55964 : case COMPONENT_REF:
2653 : 55964 : {
2654 : : /* obj.field */
2655 : 55964 : tree obj = TREE_OPERAND (expr, 0);
2656 : 55964 : tree field = TREE_OPERAND (expr, 1);
2657 : 55964 : const region *obj_reg = get_lvalue (obj, ctxt);
2658 : 55964 : return m_mgr->get_field_region (obj_reg, field);
2659 : : }
2660 : 17409 : break;
2661 : :
2662 : 17409 : case STRING_CST:
2663 : 17409 : return m_mgr->get_region_for_string (expr);
2664 : : }
2665 : : }
2666 : :
2667 : : /* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op. */
2668 : :
2669 : : static void
2670 : 5162999 : assert_compat_types (tree src_type, tree dst_type)
2671 : : {
2672 : 5162999 : if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2673 : : {
2674 : : #if CHECKING_P
2675 : 5162637 : if (!(useless_type_conversion_p (src_type, dst_type)))
2676 : 0 : internal_error ("incompatible types: %qT and %qT", src_type, dst_type);
2677 : : #endif
2678 : : }
2679 : 5162999 : }
2680 : :
2681 : : /* Return true if SRC_TYPE can be converted to DST_TYPE as a no-op. */
2682 : :
2683 : : bool
2684 : 14053 : compat_types_p (tree src_type, tree dst_type)
2685 : : {
2686 : 14053 : if (src_type && dst_type && !VOID_TYPE_P (dst_type))
2687 : 14053 : if (!(useless_type_conversion_p (src_type, dst_type)))
2688 : : return false;
2689 : : return true;
2690 : : }
2691 : :
2692 : : /* Get the region for PV within this region_model,
2693 : : emitting any diagnostics to CTXT. */
2694 : :
2695 : : const region *
2696 : 2374411 : region_model::get_lvalue (path_var pv, region_model_context *ctxt) const
2697 : : {
2698 : 2374411 : if (pv.m_tree == NULL_TREE)
2699 : : return NULL;
2700 : :
2701 : 2374411 : const region *result_reg = get_lvalue_1 (pv, ctxt);
2702 : 2374411 : assert_compat_types (result_reg->get_type (), TREE_TYPE (pv.m_tree));
2703 : 2374411 : return result_reg;
2704 : : }
2705 : :
2706 : : /* Get the region for EXPR within this region_model (assuming the most
2707 : : recent stack frame if it's a local). */
2708 : :
2709 : : const region *
2710 : 1479962 : region_model::get_lvalue (tree expr, region_model_context *ctxt) const
2711 : : {
2712 : 1479962 : return get_lvalue (path_var (expr, get_stack_depth () - 1), ctxt);
2713 : : }
2714 : :
2715 : : /* Implementation of region_model::get_rvalue; the latter adds type-checking.
2716 : :
2717 : : Get the value of PV within this region_model,
2718 : : emitting any diagnostics to CTXT. */
2719 : :
2720 : : const svalue *
2721 : 2774803 : region_model::get_rvalue_1 (path_var pv, region_model_context *ctxt) const
2722 : : {
2723 : 2774803 : gcc_assert (pv.m_tree);
2724 : :
2725 : 2774803 : switch (TREE_CODE (pv.m_tree))
2726 : : {
2727 : 46 : default:
2728 : 46 : return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2729 : :
2730 : 912183 : case ADDR_EXPR:
2731 : 912183 : {
2732 : : /* "&EXPR". */
2733 : 912183 : tree expr = pv.m_tree;
2734 : 912183 : tree op0 = TREE_OPERAND (expr, 0);
2735 : 912183 : const region *expr_reg = get_lvalue (op0, ctxt);
2736 : 912183 : return m_mgr->get_ptr_svalue (TREE_TYPE (expr), expr_reg);
2737 : : }
2738 : 138 : break;
2739 : :
2740 : 138 : case BIT_FIELD_REF:
2741 : 138 : {
2742 : 138 : tree expr = pv.m_tree;
2743 : 138 : tree op0 = TREE_OPERAND (expr, 0);
2744 : 138 : const region *reg = get_lvalue (op0, ctxt);
2745 : 138 : tree num_bits = TREE_OPERAND (expr, 1);
2746 : 138 : tree first_bit_offset = TREE_OPERAND (expr, 2);
2747 : 138 : gcc_assert (TREE_CODE (num_bits) == INTEGER_CST);
2748 : 138 : gcc_assert (TREE_CODE (first_bit_offset) == INTEGER_CST);
2749 : 138 : bit_range bits (TREE_INT_CST_LOW (first_bit_offset),
2750 : 276 : TREE_INT_CST_LOW (num_bits));
2751 : 138 : return get_rvalue_for_bits (TREE_TYPE (expr), reg, bits, ctxt);
2752 : : }
2753 : :
2754 : 41961 : case VAR_DECL:
2755 : 41961 : if (DECL_HARD_REGISTER (pv.m_tree))
2756 : : {
2757 : : /* If it has a hard register, it doesn't have a memory region
2758 : : and can't be referred to as an lvalue. */
2759 : 35 : return m_mgr->get_or_create_unknown_svalue (TREE_TYPE (pv.m_tree));
2760 : : }
2761 : : /* Fall through. */
2762 : 831665 : case PARM_DECL:
2763 : 831665 : case SSA_NAME:
2764 : 831665 : case RESULT_DECL:
2765 : 831665 : case ARRAY_REF:
2766 : 831665 : {
2767 : 831665 : const region *reg = get_lvalue (pv, ctxt);
2768 : 831665 : return get_store_value (reg, ctxt);
2769 : : }
2770 : :
2771 : 178 : case REALPART_EXPR:
2772 : 178 : case IMAGPART_EXPR:
2773 : 178 : case VIEW_CONVERT_EXPR:
2774 : 178 : {
2775 : 178 : tree expr = pv.m_tree;
2776 : 178 : tree arg = TREE_OPERAND (expr, 0);
2777 : 178 : const svalue *arg_sval = get_rvalue (arg, ctxt);
2778 : 178 : const svalue *sval_unaryop
2779 : 178 : = m_mgr->get_or_create_unaryop (TREE_TYPE (expr), TREE_CODE (expr),
2780 : : arg_sval);
2781 : 178 : return sval_unaryop;
2782 : 965459 : };
2783 : :
2784 : 965459 : case INTEGER_CST:
2785 : 965459 : case REAL_CST:
2786 : 965459 : case COMPLEX_CST:
2787 : 965459 : case VECTOR_CST:
2788 : 965459 : case STRING_CST:
2789 : 965459 : return m_mgr->get_or_create_constant_svalue (pv.m_tree);
2790 : :
2791 : 8 : case POINTER_PLUS_EXPR:
2792 : 8 : {
2793 : 8 : tree expr = pv.m_tree;
2794 : 8 : tree ptr = TREE_OPERAND (expr, 0);
2795 : 8 : tree offset = TREE_OPERAND (expr, 1);
2796 : 8 : const svalue *ptr_sval = get_rvalue (ptr, ctxt);
2797 : 8 : const svalue *offset_sval = get_rvalue (offset, ctxt);
2798 : 8 : const svalue *sval_binop
2799 : 8 : = m_mgr->get_or_create_binop (TREE_TYPE (expr), POINTER_PLUS_EXPR,
2800 : : ptr_sval, offset_sval);
2801 : 8 : return sval_binop;
2802 : : }
2803 : :
2804 : : /* Binary ops. */
2805 : 94 : case PLUS_EXPR:
2806 : 94 : case MULT_EXPR:
2807 : 94 : case BIT_AND_EXPR:
2808 : 94 : case BIT_IOR_EXPR:
2809 : 94 : case BIT_XOR_EXPR:
2810 : 94 : {
2811 : 94 : tree expr = pv.m_tree;
2812 : 94 : tree arg0 = TREE_OPERAND (expr, 0);
2813 : 94 : tree arg1 = TREE_OPERAND (expr, 1);
2814 : 94 : const svalue *arg0_sval = get_rvalue (arg0, ctxt);
2815 : 94 : const svalue *arg1_sval = get_rvalue (arg1, ctxt);
2816 : 94 : const svalue *sval_binop
2817 : 94 : = m_mgr->get_or_create_binop (TREE_TYPE (expr), TREE_CODE (expr),
2818 : : arg0_sval, arg1_sval);
2819 : 94 : return sval_binop;
2820 : : }
2821 : :
2822 : 62744 : case COMPONENT_REF:
2823 : 62744 : case MEM_REF:
2824 : 62744 : {
2825 : 62744 : const region *ref_reg = get_lvalue (pv, ctxt);
2826 : 62744 : return get_store_value (ref_reg, ctxt);
2827 : : }
2828 : 2253 : case OBJ_TYPE_REF:
2829 : 2253 : {
2830 : 2253 : tree expr = OBJ_TYPE_REF_EXPR (pv.m_tree);
2831 : 2253 : return get_rvalue (expr, ctxt);
2832 : : }
2833 : : }
2834 : : }
2835 : :
2836 : : /* Get the value of PV within this region_model,
2837 : : emitting any diagnostics to CTXT. */
2838 : :
2839 : : const svalue *
2840 : 2816618 : region_model::get_rvalue (path_var pv, region_model_context *ctxt) const
2841 : : {
2842 : 2816618 : if (pv.m_tree == NULL_TREE)
2843 : : return NULL;
2844 : :
2845 : 2774803 : const svalue *result_sval = get_rvalue_1 (pv, ctxt);
2846 : :
2847 : 2774803 : assert_compat_types (result_sval->get_type (), TREE_TYPE (pv.m_tree));
2848 : :
2849 : 2774803 : result_sval = check_for_poison (result_sval, pv.m_tree, NULL, ctxt);
2850 : :
2851 : 2774803 : return result_sval;
2852 : : }
2853 : :
2854 : : /* Get the value of EXPR within this region_model (assuming the most
2855 : : recent stack frame if it's a local). */
2856 : :
2857 : : const svalue *
2858 : 2816143 : region_model::get_rvalue (tree expr, region_model_context *ctxt) const
2859 : : {
2860 : 2816143 : return get_rvalue (path_var (expr, get_stack_depth () - 1), ctxt);
2861 : : }
2862 : :
2863 : : /* Return true if this model is on a path with "main" as the entrypoint
2864 : : (as opposed to one in which we're merely analyzing a subset of the
2865 : : path through the code). */
2866 : :
2867 : : bool
2868 : 285951 : region_model::called_from_main_p () const
2869 : : {
2870 : 285951 : if (!m_current_frame)
2871 : : return false;
2872 : : /* Determine if the oldest stack frame in this model is for "main". */
2873 : 279722 : const frame_region *frame0 = get_frame_at_index (0);
2874 : 279722 : gcc_assert (frame0);
2875 : 279722 : return id_equal (DECL_NAME (frame0->get_function ().decl), "main");
2876 : : }
2877 : :
2878 : : /* Subroutine of region_model::get_store_value for when REG is (or is within)
2879 : : a global variable that hasn't been touched since the start of this path
2880 : : (or was implicitly touched due to a call to an unknown function). */
2881 : :
2882 : : const svalue *
2883 : 296296 : region_model::get_initial_value_for_global (const region *reg) const
2884 : : {
2885 : : /* Get the decl that REG is for (or is within). */
2886 : 296296 : const decl_region *base_reg
2887 : 296296 : = reg->get_base_region ()->dyn_cast_decl_region ();
2888 : 296296 : gcc_assert (base_reg);
2889 : 296296 : tree decl = base_reg->get_decl ();
2890 : :
2891 : : /* Special-case: to avoid having to explicitly update all previously
2892 : : untracked globals when calling an unknown fn, they implicitly have
2893 : : an unknown value if an unknown call has occurred, unless this is
2894 : : static to-this-TU and hasn't escaped. Globals that have escaped
2895 : : are explicitly tracked, so we shouldn't hit this case for them. */
2896 : 296296 : if (m_store.called_unknown_fn_p ()
2897 : 67729 : && TREE_PUBLIC (decl)
2898 : 306707 : && !TREE_READONLY (decl))
2899 : 10393 : return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
2900 : :
2901 : : /* If we are on a path from the entrypoint from "main" and we have a
2902 : : global decl defined in this TU that hasn't been touched yet, then
2903 : : the initial value of REG can be taken from the initialization value
2904 : : of the decl. */
2905 : 285903 : if (called_from_main_p () || TREE_READONLY (decl))
2906 : 7734 : return reg->get_initial_value_at_main (m_mgr);
2907 : :
2908 : : /* Otherwise, return INIT_VAL(REG). */
2909 : 278169 : return m_mgr->get_or_create_initial_value (reg);
2910 : : }
2911 : :
2912 : : /* Get a value for REG, looking it up in the store, or otherwise falling
2913 : : back to "initial" or "unknown" values.
2914 : : Use CTXT to report any warnings associated with reading from REG. */
2915 : :
2916 : : const svalue *
2917 : 3704188 : region_model::get_store_value (const region *reg,
2918 : : region_model_context *ctxt) const
2919 : : {
2920 : : /* Getting the value of an empty region gives an unknown_svalue. */
2921 : 3704188 : if (reg->empty_p ())
2922 : 44 : return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
2923 : :
2924 : 3704144 : bool check_poisoned = true;
2925 : 3704144 : if (check_region_for_read (reg, ctxt))
2926 : 396 : check_poisoned = false;
2927 : :
2928 : : /* Special-case: handle var_decls in the constant pool. */
2929 : 3704144 : if (const decl_region *decl_reg = reg->dyn_cast_decl_region ())
2930 : 2956397 : if (const svalue *sval = decl_reg->maybe_get_constant_value (m_mgr))
2931 : : return sval;
2932 : :
2933 : 3704140 : const svalue *sval
2934 : 3704140 : = m_store.get_any_binding (m_mgr->get_store_manager (), reg);
2935 : 3704140 : if (sval)
2936 : : {
2937 : 1102980 : if (reg->get_type ())
2938 : 1100936 : sval = m_mgr->get_or_create_cast (reg->get_type (), sval);
2939 : 1102980 : return sval;
2940 : : }
2941 : :
2942 : : /* Special-case: read at a constant index within a STRING_CST. */
2943 : 2601160 : if (const offset_region *offset_reg = reg->dyn_cast_offset_region ())
2944 : 172563 : if (tree byte_offset_cst
2945 : 172563 : = offset_reg->get_byte_offset ()->maybe_get_constant ())
2946 : 12617 : if (const string_region *str_reg
2947 : 12617 : = reg->get_parent_region ()->dyn_cast_string_region ())
2948 : : {
2949 : 189 : tree string_cst = str_reg->get_string_cst ();
2950 : 378 : if (const svalue *char_sval
2951 : 189 : = m_mgr->maybe_get_char_from_string_cst (string_cst,
2952 : : byte_offset_cst))
2953 : 183 : return m_mgr->get_or_create_cast (reg->get_type (), char_sval);
2954 : : }
2955 : :
2956 : : /* Special-case: read the initial char of a STRING_CST. */
2957 : 2600977 : if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
2958 : 6352 : if (const string_region *str_reg
2959 : 3176 : = cast_reg->get_parent_region ()->dyn_cast_string_region ())
2960 : : {
2961 : 204 : tree string_cst = str_reg->get_string_cst ();
2962 : 204 : tree byte_offset_cst = integer_zero_node;
2963 : 408 : if (const svalue *char_sval
2964 : 204 : = m_mgr->maybe_get_char_from_string_cst (string_cst,
2965 : : byte_offset_cst))
2966 : 204 : return m_mgr->get_or_create_cast (reg->get_type (), char_sval);
2967 : : }
2968 : :
2969 : : /* Otherwise we implicitly have the initial value of the region
2970 : : (if the cluster had been touched, binding_cluster::get_any_binding,
2971 : : would have returned UNKNOWN, and we would already have returned
2972 : : that above). */
2973 : :
2974 : : /* Handle globals. */
2975 : 2600773 : if (reg->get_base_region ()->get_parent_region ()->get_kind ()
2976 : : == RK_GLOBALS)
2977 : 296296 : return get_initial_value_for_global (reg);
2978 : :
2979 : 2304477 : return m_mgr->get_or_create_initial_value (reg, check_poisoned);
2980 : : }
2981 : :
2982 : : /* Return false if REG does not exist, true if it may do.
2983 : : This is for detecting regions within the stack that don't exist anymore
2984 : : after frames are popped. */
2985 : :
2986 : : bool
2987 : 2363559 : region_model::region_exists_p (const region *reg) const
2988 : : {
2989 : : /* If within a stack frame, check that the stack frame is live. */
2990 : 2363559 : if (const frame_region *enclosing_frame = reg->maybe_get_frame_region ())
2991 : : {
2992 : : /* Check that the current frame is the enclosing frame, or is called
2993 : : by it. */
2994 : 2333865 : for (const frame_region *iter_frame = get_current_frame (); iter_frame;
2995 : 774305 : iter_frame = iter_frame->get_calling_frame ())
2996 : 2320964 : if (iter_frame == enclosing_frame)
2997 : : return true;
2998 : : return false;
2999 : : }
3000 : :
3001 : : return true;
3002 : : }
3003 : :
3004 : : /* Get a region for referencing PTR_SVAL, creating a region if need be, and
3005 : : potentially generating warnings via CTXT.
3006 : : PTR_SVAL must be of pointer type.
3007 : : PTR_TREE if non-NULL can be used when emitting diagnostics. */
3008 : :
3009 : : const region *
3010 : 126306 : region_model::deref_rvalue (const svalue *ptr_sval, tree ptr_tree,
3011 : : region_model_context *ctxt,
3012 : : bool add_nonnull_constraint) const
3013 : : {
3014 : 126306 : gcc_assert (ptr_sval);
3015 : 126306 : gcc_assert (POINTER_TYPE_P (ptr_sval->get_type ()));
3016 : :
3017 : : /* If we're dereferencing PTR_SVAL, assume that it is non-NULL; add this
3018 : : as a constraint. This suppresses false positives from
3019 : : -Wanalyzer-null-dereference for the case where we later have an
3020 : : if (PTR_SVAL) that would occur if we considered the false branch
3021 : : and transitioned the malloc state machine from start->null. */
3022 : 126306 : if (add_nonnull_constraint)
3023 : : {
3024 : 120567 : tree null_ptr_cst = build_int_cst (ptr_sval->get_type (), 0);
3025 : 120567 : const svalue *null_ptr
3026 : 120567 : = m_mgr->get_or_create_constant_svalue (null_ptr_cst);
3027 : 120567 : m_constraints->add_constraint (ptr_sval, NE_EXPR, null_ptr);
3028 : : }
3029 : :
3030 : 126306 : switch (ptr_sval->get_kind ())
3031 : : {
3032 : : default:
3033 : : break;
3034 : :
3035 : 42557 : case SK_REGION:
3036 : 42557 : {
3037 : 42557 : const region_svalue *region_sval
3038 : 42557 : = as_a <const region_svalue *> (ptr_sval);
3039 : 42557 : return region_sval->get_pointee ();
3040 : : }
3041 : :
3042 : 16616 : case SK_BINOP:
3043 : 16616 : {
3044 : 16616 : const binop_svalue *binop_sval
3045 : 16616 : = as_a <const binop_svalue *> (ptr_sval);
3046 : 16616 : switch (binop_sval->get_op ())
3047 : : {
3048 : 16616 : case POINTER_PLUS_EXPR:
3049 : 16616 : {
3050 : : /* If we have a symbolic value expressing pointer arithmentic,
3051 : : try to convert it to a suitable region. */
3052 : 16616 : const region *parent_region
3053 : 16616 : = deref_rvalue (binop_sval->get_arg0 (), NULL_TREE, ctxt);
3054 : 16616 : const svalue *offset = binop_sval->get_arg1 ();
3055 : 16616 : tree type= TREE_TYPE (ptr_sval->get_type ());
3056 : 16616 : return m_mgr->get_offset_region (parent_region, type, offset);
3057 : : }
3058 : : default:
3059 : : break;
3060 : : }
3061 : : }
3062 : : break;
3063 : :
3064 : 3580 : case SK_POISONED:
3065 : 3580 : {
3066 : 3580 : if (ctxt)
3067 : : {
3068 : 798 : tree ptr = get_representative_tree (ptr_sval);
3069 : : /* If we can't get a representative tree for PTR_SVAL
3070 : : (e.g. if it hasn't been bound into the store), then
3071 : : fall back on PTR_TREE, if non-NULL. */
3072 : 798 : if (!ptr)
3073 : 786 : ptr = ptr_tree;
3074 : 798 : if (ptr)
3075 : : {
3076 : 36 : const poisoned_svalue *poisoned_sval
3077 : 36 : = as_a <const poisoned_svalue *> (ptr_sval);
3078 : 36 : enum poison_kind pkind = poisoned_sval->get_poison_kind ();
3079 : 36 : ctxt->warn (::make_unique<poisoned_value_diagnostic>
3080 : 72 : (ptr, pkind, nullptr, nullptr));
3081 : : }
3082 : : }
3083 : : }
3084 : : break;
3085 : : }
3086 : :
3087 : 67133 : return m_mgr->get_symbolic_region (ptr_sval);
3088 : : }
3089 : :
3090 : : /* Attempt to get BITS within any value of REG, as TYPE.
3091 : : In particular, extract values from compound_svalues for the case
3092 : : where there's a concrete binding at BITS.
3093 : : Return an unknown svalue if we can't handle the given case.
3094 : : Use CTXT to report any warnings associated with reading from REG. */
3095 : :
3096 : : const svalue *
3097 : 138 : region_model::get_rvalue_for_bits (tree type,
3098 : : const region *reg,
3099 : : const bit_range &bits,
3100 : : region_model_context *ctxt) const
3101 : : {
3102 : 138 : const svalue *sval = get_store_value (reg, ctxt);
3103 : 138 : return m_mgr->get_or_create_bits_within (type, bits, sval);
3104 : : }
3105 : :
3106 : : /* A subclass of pending_diagnostic for complaining about writes to
3107 : : constant regions of memory. */
3108 : :
3109 : : class write_to_const_diagnostic
3110 : : : public pending_diagnostic_subclass<write_to_const_diagnostic>
3111 : : {
3112 : : public:
3113 : 33 : write_to_const_diagnostic (const region *reg, tree decl)
3114 : 33 : : m_reg (reg), m_decl (decl)
3115 : : {}
3116 : :
3117 : 148 : const char *get_kind () const final override
3118 : : {
3119 : 148 : return "write_to_const_diagnostic";
3120 : : }
3121 : :
3122 : 33 : bool operator== (const write_to_const_diagnostic &other) const
3123 : : {
3124 : 33 : return (m_reg == other.m_reg
3125 : 33 : && m_decl == other.m_decl);
3126 : : }
3127 : :
3128 : 66 : int get_controlling_option () const final override
3129 : : {
3130 : 66 : return OPT_Wanalyzer_write_to_const;
3131 : : }
3132 : :
3133 : 33 : bool emit (diagnostic_emission_context &ctxt) final override
3134 : : {
3135 : 33 : auto_diagnostic_group d;
3136 : 33 : bool warned;
3137 : 33 : switch (m_reg->get_kind ())
3138 : : {
3139 : 20 : default:
3140 : 20 : warned = ctxt.warn ("write to %<const%> object %qE", m_decl);
3141 : 20 : break;
3142 : 9 : case RK_FUNCTION:
3143 : 9 : warned = ctxt.warn ("write to function %qE", m_decl);
3144 : 9 : break;
3145 : 4 : case RK_LABEL:
3146 : 4 : warned = ctxt.warn ("write to label %qE", m_decl);
3147 : 4 : break;
3148 : : }
3149 : 33 : if (warned)
3150 : 33 : inform (DECL_SOURCE_LOCATION (m_decl), "declared here");
3151 : 66 : return warned;
3152 : 33 : }
3153 : :
3154 : : bool
3155 : 66 : describe_final_event (pretty_printer &pp,
3156 : : const evdesc::final_event &) final override
3157 : : {
3158 : 66 : switch (m_reg->get_kind ())
3159 : : {
3160 : 40 : default:
3161 : 40 : {
3162 : 40 : pp_printf (&pp,
3163 : : "write to %<const%> object %qE here", m_decl);
3164 : 40 : return true;
3165 : : }
3166 : 18 : case RK_FUNCTION:
3167 : 18 : {
3168 : 18 : pp_printf (&pp,
3169 : : "write to function %qE here", m_decl);
3170 : 18 : return true;
3171 : : }
3172 : 8 : case RK_LABEL:
3173 : 8 : {
3174 : 8 : pp_printf (&pp,
3175 : : "write to label %qE here", m_decl);
3176 : 8 : return true;
3177 : : }
3178 : : }
3179 : : }
3180 : :
3181 : : private:
3182 : : const region *m_reg;
3183 : : tree m_decl;
3184 : : };
3185 : :
3186 : : /* A subclass of pending_diagnostic for complaining about writes to
3187 : : string literals. */
3188 : :
3189 : : class write_to_string_literal_diagnostic
3190 : : : public pending_diagnostic_subclass<write_to_string_literal_diagnostic>
3191 : : {
3192 : : public:
3193 : 51 : write_to_string_literal_diagnostic (const region *reg)
3194 : 51 : : m_reg (reg)
3195 : : {}
3196 : :
3197 : 200 : const char *get_kind () const final override
3198 : : {
3199 : 200 : return "write_to_string_literal_diagnostic";
3200 : : }
3201 : :
3202 : 47 : bool operator== (const write_to_string_literal_diagnostic &other) const
3203 : : {
3204 : 47 : return m_reg == other.m_reg;
3205 : : }
3206 : :
3207 : 94 : int get_controlling_option () const final override
3208 : : {
3209 : 94 : return OPT_Wanalyzer_write_to_string_literal;
3210 : : }
3211 : :
3212 : 43 : bool emit (diagnostic_emission_context &ctxt) final override
3213 : : {
3214 : 43 : return ctxt.warn ("write to string literal");
3215 : : /* Ideally we would show the location of the STRING_CST as well,
3216 : : but it is not available at this point. */
3217 : : }
3218 : :
3219 : : bool
3220 : 86 : describe_final_event (pretty_printer &pp,
3221 : : const evdesc::final_event &) final override
3222 : : {
3223 : 86 : pp_string (&pp, "write to string literal here");
3224 : 86 : return true;
3225 : : }
3226 : :
3227 : : private:
3228 : : const region *m_reg;
3229 : : };
3230 : :
3231 : : /* Use CTXT to warn If DEST_REG is a region that shouldn't be written to. */
3232 : :
3233 : : void
3234 : 195566 : region_model::check_for_writable_region (const region* dest_reg,
3235 : : region_model_context *ctxt) const
3236 : : {
3237 : : /* Fail gracefully if CTXT is NULL. */
3238 : 195566 : if (!ctxt)
3239 : : return;
3240 : :
3241 : 195566 : const region *base_reg = dest_reg->get_base_region ();
3242 : 195566 : switch (base_reg->get_kind ())
3243 : : {
3244 : : default:
3245 : : break;
3246 : 9 : case RK_FUNCTION:
3247 : 9 : {
3248 : 9 : const function_region *func_reg = as_a <const function_region *> (base_reg);
3249 : 9 : tree fndecl = func_reg->get_fndecl ();
3250 : 9 : ctxt->warn (make_unique<write_to_const_diagnostic>
3251 : 18 : (func_reg, fndecl));
3252 : : }
3253 : 9 : break;
3254 : 4 : case RK_LABEL:
3255 : 4 : {
3256 : 4 : const label_region *label_reg = as_a <const label_region *> (base_reg);
3257 : 4 : tree label = label_reg->get_label ();
3258 : 4 : ctxt->warn (make_unique<write_to_const_diagnostic>
3259 : 8 : (label_reg, label));
3260 : : }
3261 : 4 : break;
3262 : 183358 : case RK_DECL:
3263 : 183358 : {
3264 : 183358 : const decl_region *decl_reg = as_a <const decl_region *> (base_reg);
3265 : 183358 : tree decl = decl_reg->get_decl ();
3266 : : /* Warn about writes to const globals.
3267 : : Don't warn for writes to const locals, and params in particular,
3268 : : since we would warn in push_frame when setting them up (e.g the
3269 : : "this" param is "T* const"). */
3270 : 183358 : if (TREE_READONLY (decl)
3271 : 183358 : && is_global_var (decl))
3272 : 20 : ctxt->warn (make_unique<write_to_const_diagnostic> (dest_reg, decl));
3273 : : }
3274 : 183358 : break;
3275 : 51 : case RK_STRING:
3276 : 51 : ctxt->warn (make_unique<write_to_string_literal_diagnostic> (dest_reg));
3277 : 51 : break;
3278 : : }
3279 : : }
3280 : :
3281 : : /* Get the capacity of REG in bytes. */
3282 : :
3283 : : const svalue *
3284 : 690105 : region_model::get_capacity (const region *reg) const
3285 : : {
3286 : 690137 : switch (reg->get_kind ())
3287 : : {
3288 : : default:
3289 : : break;
3290 : 630458 : case RK_DECL:
3291 : 630458 : {
3292 : 630458 : const decl_region *decl_reg = as_a <const decl_region *> (reg);
3293 : 630458 : tree decl = decl_reg->get_decl ();
3294 : 630458 : if (TREE_CODE (decl) == SSA_NAME)
3295 : : {
3296 : 555832 : tree type = TREE_TYPE (decl);
3297 : 555832 : tree size = TYPE_SIZE (type);
3298 : 555832 : return get_rvalue (size, NULL);
3299 : : }
3300 : : else
3301 : : {
3302 : 74626 : tree size = decl_init_size (decl, false);
3303 : 74626 : if (size)
3304 : 74457 : return get_rvalue (size, NULL);
3305 : : }
3306 : : }
3307 : : break;
3308 : 32 : case RK_SIZED:
3309 : : /* Look through sized regions to get at the capacity
3310 : : of the underlying regions. */
3311 : 32 : return get_capacity (reg->get_parent_region ());
3312 : 456 : case RK_STRING:
3313 : 456 : {
3314 : : /* "Capacity" here means "size". */
3315 : 456 : const string_region *string_reg = as_a <const string_region *> (reg);
3316 : 456 : tree string_cst = string_reg->get_string_cst ();
3317 : 456 : return m_mgr->get_or_create_int_cst (size_type_node,
3318 : 456 : TREE_STRING_LENGTH (string_cst));
3319 : : }
3320 : 59360 : break;
3321 : : }
3322 : :
3323 : 59360 : if (const svalue *recorded = get_dynamic_extents (reg))
3324 : : return recorded;
3325 : :
3326 : 46857 : return m_mgr->get_or_create_unknown_svalue (sizetype);
3327 : : }
3328 : :
3329 : : /* If CTXT is non-NULL, use it to warn about any problems accessing REG,
3330 : : using DIR to determine if this access is a read or write.
3331 : : Return TRUE if an OOB access was detected.
3332 : : If SVAL_HINT is non-NULL, use it as a hint in diagnostics
3333 : : about the value that would be written to REG. */
3334 : :
3335 : : bool
3336 : 4021280 : region_model::check_region_access (const region *reg,
3337 : : enum access_direction dir,
3338 : : const svalue *sval_hint,
3339 : : region_model_context *ctxt) const
3340 : : {
3341 : : /* Fail gracefully if CTXT is NULL. */
3342 : 4021280 : if (!ctxt)
3343 : : return false;
3344 : :
3345 : 681924 : bool oob_access_detected = false;
3346 : 681924 : check_region_for_taint (reg, dir, ctxt);
3347 : 681924 : if (!check_region_bounds (reg, dir, sval_hint, ctxt))
3348 : 743 : oob_access_detected = true;
3349 : :
3350 : 681924 : switch (dir)
3351 : : {
3352 : 0 : default:
3353 : 0 : gcc_unreachable ();
3354 : : case DIR_READ:
3355 : : /* Currently a no-op. */
3356 : : break;
3357 : 195566 : case DIR_WRITE:
3358 : 195566 : check_for_writable_region (reg, ctxt);
3359 : 195566 : break;
3360 : : }
3361 : : return oob_access_detected;
3362 : : }
3363 : :
3364 : : /* If CTXT is non-NULL, use it to warn about any problems writing to REG. */
3365 : :
3366 : : void
3367 : 317136 : region_model::check_region_for_write (const region *dest_reg,
3368 : : const svalue *sval_hint,
3369 : : region_model_context *ctxt) const
3370 : : {
3371 : 317136 : check_region_access (dest_reg, DIR_WRITE, sval_hint, ctxt);
3372 : 317136 : }
3373 : :
3374 : : /* If CTXT is non-NULL, use it to warn about any problems reading from REG.
3375 : : Returns TRUE if an OOB read was detected. */
3376 : :
3377 : : bool
3378 : 3704144 : region_model::check_region_for_read (const region *src_reg,
3379 : : region_model_context *ctxt) const
3380 : : {
3381 : 3704144 : return check_region_access (src_reg, DIR_READ, NULL, ctxt);
3382 : : }
3383 : :
3384 : : /* Concrete subclass for casts of pointers that lead to trailing bytes. */
3385 : :
3386 : : class dubious_allocation_size
3387 : : : public pending_diagnostic_subclass<dubious_allocation_size>
3388 : : {
3389 : : public:
3390 : 134 : dubious_allocation_size (const region *lhs, const region *rhs,
3391 : : const svalue *capacity_sval, tree expr,
3392 : : const gimple *stmt)
3393 : 134 : : m_lhs (lhs), m_rhs (rhs),
3394 : 134 : m_capacity_sval (capacity_sval), m_expr (expr),
3395 : 134 : m_stmt (stmt),
3396 : 134 : m_has_allocation_event (false)
3397 : : {
3398 : 134 : gcc_assert (m_capacity_sval);
3399 : : }
3400 : :
3401 : 537 : const char *get_kind () const final override
3402 : : {
3403 : 537 : return "dubious_allocation_size";
3404 : : }
3405 : :
3406 : 134 : bool operator== (const dubious_allocation_size &other) const
3407 : : {
3408 : 134 : return (m_stmt == other.m_stmt
3409 : 134 : && pending_diagnostic::same_tree_p (m_expr, other.m_expr));
3410 : : }
3411 : :
3412 : 236 : int get_controlling_option () const final override
3413 : : {
3414 : 236 : return OPT_Wanalyzer_allocation_size;
3415 : : }
3416 : :
3417 : 114 : bool emit (diagnostic_emission_context &ctxt) final override
3418 : : {
3419 : 114 : ctxt.add_cwe (131);
3420 : :
3421 : 114 : return ctxt.warn ("allocated buffer size is not a multiple"
3422 : 114 : " of the pointee's size");
3423 : : }
3424 : :
3425 : : bool
3426 : 228 : describe_final_event (pretty_printer &pp,
3427 : : const evdesc::final_event &) final override
3428 : : {
3429 : 228 : tree pointee_type = TREE_TYPE (m_lhs->get_type ());
3430 : 228 : if (m_has_allocation_event)
3431 : : {
3432 : 188 : pp_printf (&pp,
3433 : : "assigned to %qT here;"
3434 : : " %<sizeof (%T)%> is %qE",
3435 : 188 : m_lhs->get_type (), pointee_type,
3436 : : size_in_bytes (pointee_type));
3437 : 188 : return true;
3438 : : }
3439 : : /* Fallback: Typically, we should always see an allocation_event
3440 : : before. */
3441 : 40 : if (m_expr)
3442 : : {
3443 : 40 : if (TREE_CODE (m_expr) == INTEGER_CST)
3444 : : {
3445 : 8 : pp_printf (&pp,
3446 : : "allocated %E bytes and assigned to"
3447 : : " %qT here; %<sizeof (%T)%> is %qE",
3448 : 8 : m_expr, m_lhs->get_type (), pointee_type,
3449 : : size_in_bytes (pointee_type));
3450 : 8 : return true;
3451 : : }
3452 : : else
3453 : : {
3454 : 32 : pp_printf (&pp,
3455 : : "allocated %qE bytes and assigned to"
3456 : : " %qT here; %<sizeof (%T)%> is %qE",
3457 : 32 : m_expr, m_lhs->get_type (), pointee_type,
3458 : : size_in_bytes (pointee_type));
3459 : 32 : return true;
3460 : : }
3461 : : }
3462 : :
3463 : 0 : pp_printf (&pp,
3464 : : "allocated and assigned to %qT here;"
3465 : : " %<sizeof (%T)%> is %qE",
3466 : 0 : m_lhs->get_type (), pointee_type,
3467 : : size_in_bytes (pointee_type));
3468 : 0 : return true;
3469 : : }
3470 : :
3471 : : void
3472 : 94 : add_region_creation_events (const region *,
3473 : : tree capacity,
3474 : : const event_loc_info &loc_info,
3475 : : checker_path &emission_path) final override
3476 : : {
3477 : 94 : emission_path.add_event
3478 : 94 : (make_unique<region_creation_event_allocation_size> (capacity, loc_info));
3479 : :
3480 : 94 : m_has_allocation_event = true;
3481 : 94 : }
3482 : :
3483 : 114 : void mark_interesting_stuff (interesting_t *interest) final override
3484 : : {
3485 : 114 : interest->add_region_creation (m_rhs);
3486 : 114 : }
3487 : :
3488 : 0 : void maybe_add_sarif_properties (sarif_object &result_obj)
3489 : : const final override
3490 : : {
3491 : 0 : sarif_property_bag &props = result_obj.get_or_create_properties ();
3492 : : #define PROPERTY_PREFIX "gcc/analyzer/dubious_allocation_size/"
3493 : 0 : props.set (PROPERTY_PREFIX "lhs", m_lhs->to_json ());
3494 : 0 : props.set (PROPERTY_PREFIX "rhs", m_rhs->to_json ());
3495 : 0 : props.set (PROPERTY_PREFIX "capacity_sval", m_capacity_sval->to_json ());
3496 : : #undef PROPERTY_PREFIX
3497 : 0 : }
3498 : :
3499 : : private:
3500 : : const region *m_lhs;
3501 : : const region *m_rhs;
3502 : : const svalue *m_capacity_sval;
3503 : : const tree m_expr;
3504 : : const gimple *m_stmt;
3505 : : bool m_has_allocation_event;
3506 : : };
3507 : :
3508 : : /* Return true on dubious allocation sizes for constant sizes. */
3509 : :
3510 : : static bool
3511 : 2301 : capacity_compatible_with_type (tree cst, tree pointee_size_tree,
3512 : : bool is_struct)
3513 : : {
3514 : 2301 : gcc_assert (TREE_CODE (cst) == INTEGER_CST);
3515 : 2301 : gcc_assert (TREE_CODE (pointee_size_tree) == INTEGER_CST);
3516 : :
3517 : 2301 : unsigned HOST_WIDE_INT pointee_size = TREE_INT_CST_LOW (pointee_size_tree);
3518 : 2301 : unsigned HOST_WIDE_INT alloc_size = TREE_INT_CST_LOW (cst);
3519 : :
3520 : 2301 : if (is_struct)
3521 : 822 : return alloc_size == 0 || alloc_size >= pointee_size;
3522 : 1479 : return alloc_size % pointee_size == 0;
3523 : : }
3524 : :
3525 : : static bool
3526 : 628 : capacity_compatible_with_type (tree cst, tree pointee_size_tree)
3527 : : {
3528 : 0 : return capacity_compatible_with_type (cst, pointee_size_tree, false);
3529 : : }
3530 : :
3531 : : /* Checks whether SVAL could be a multiple of SIZE_CST.
3532 : :
3533 : : It works by visiting all svalues inside SVAL until it reaches
3534 : : atomic nodes. From those, it goes back up again and adds each
3535 : : node that is not a multiple of SIZE_CST to the RESULT_SET. */
3536 : :
3537 : 2136 : class size_visitor : public visitor
3538 : : {
3539 : : public:
3540 : 1068 : size_visitor (tree size_cst, const svalue *root_sval, constraint_manager *cm)
3541 : 1068 : : m_size_cst (size_cst), m_root_sval (root_sval), m_cm (cm)
3542 : : {
3543 : 1068 : m_root_sval->accept (this);
3544 : 1068 : }
3545 : :
3546 : 1068 : bool is_dubious_capacity ()
3547 : : {
3548 : 1068 : return result_set.contains (m_root_sval);
3549 : : }
3550 : :
3551 : 668 : void visit_constant_svalue (const constant_svalue *sval) final override
3552 : : {
3553 : 668 : check_constant (sval->get_constant (), sval);
3554 : 668 : }
3555 : :
3556 : 421 : void visit_unaryop_svalue (const unaryop_svalue *sval) final override
3557 : : {
3558 : 421 : if (CONVERT_EXPR_CODE_P (sval->get_op ())
3559 : 495 : && result_set.contains (sval->get_arg ()))
3560 : 141 : result_set.add (sval);
3561 : 421 : }
3562 : :
3563 : 684 : void visit_binop_svalue (const binop_svalue *sval) final override
3564 : : {
3565 : 684 : const svalue *arg0 = sval->get_arg0 ();
3566 : 684 : const svalue *arg1 = sval->get_arg1 ();
3567 : :
3568 : 684 : switch (sval->get_op ())
3569 : : {
3570 : 501 : case MULT_EXPR:
3571 : 501 : if (result_set.contains (arg0) && result_set.contains (arg1))
3572 : 28 : result_set.add (sval);
3573 : : break;
3574 : 127 : case PLUS_EXPR:
3575 : 127 : case MINUS_EXPR:
3576 : 127 : if (result_set.contains (arg0) || result_set.contains (arg1))
3577 : 51 : result_set.add (sval);
3578 : : break;
3579 : : default:
3580 : : break;
3581 : : }
3582 : 684 : }
3583 : :
3584 : 0 : void visit_unmergeable_svalue (const unmergeable_svalue *sval) final override
3585 : : {
3586 : 0 : if (result_set.contains (sval->get_arg ()))
3587 : 0 : result_set.add (sval);
3588 : 0 : }
3589 : :
3590 : 12 : void visit_widening_svalue (const widening_svalue *sval) final override
3591 : : {
3592 : 12 : const svalue *base = sval->get_base_svalue ();
3593 : 12 : const svalue *iter = sval->get_iter_svalue ();
3594 : :
3595 : 12 : if (result_set.contains (base) || result_set.contains (iter))
3596 : 8 : result_set.add (sval);
3597 : 12 : }
3598 : :
3599 : 511 : void visit_initial_svalue (const initial_svalue *sval) final override
3600 : : {
3601 : 511 : equiv_class_id id = equiv_class_id::null ();
3602 : 511 : if (m_cm->get_equiv_class_by_svalue (sval, &id))
3603 : : {
3604 : 176 : if (tree cst = id.get_obj (*m_cm).get_any_constant ())
3605 : 0 : check_constant (cst, sval);
3606 : : }
3607 : 335 : else if (!m_cm->sval_constrained_p (sval))
3608 : : {
3609 : 267 : result_set.add (sval);
3610 : : }
3611 : 511 : }
3612 : :
3613 : 36 : void visit_conjured_svalue (const conjured_svalue *sval) final override
3614 : : {
3615 : 36 : equiv_class_id id = equiv_class_id::null ();
3616 : 36 : if (m_cm->get_equiv_class_by_svalue (sval, &id))
3617 : 14 : if (tree cst = id.get_obj (*m_cm).get_any_constant ())
3618 : 8 : check_constant (cst, sval);
3619 : 36 : }
3620 : :
3621 : : private:
3622 : 676 : void check_constant (tree cst, const svalue *sval)
3623 : : {
3624 : 676 : switch (TREE_CODE (cst))
3625 : : {
3626 : : default:
3627 : : /* Assume all unhandled operands are compatible. */
3628 : : break;
3629 : 628 : case INTEGER_CST:
3630 : 628 : if (!capacity_compatible_with_type (cst, m_size_cst))
3631 : 111 : result_set.add (sval);
3632 : : break;
3633 : : }
3634 : 676 : }
3635 : :
3636 : : tree m_size_cst;
3637 : : const svalue *m_root_sval;
3638 : : constraint_manager *m_cm;
3639 : : svalue_set result_set; /* Used as a mapping of svalue*->bool. */
3640 : : };
3641 : :
3642 : : /* Return true if SIZE_CST is a power of 2, and we have
3643 : : CAPACITY_SVAL == ((X | (Y - 1) ) + 1), since it is then a multiple
3644 : : of SIZE_CST, as used by Linux kernel's round_up macro. */
3645 : :
3646 : : static bool
3647 : 1076 : is_round_up (tree size_cst,
3648 : : const svalue *capacity_sval)
3649 : : {
3650 : 1076 : if (!integer_pow2p (size_cst))
3651 : : return false;
3652 : 1076 : const binop_svalue *binop_sval = capacity_sval->dyn_cast_binop_svalue ();
3653 : 1076 : if (!binop_sval)
3654 : : return false;
3655 : 449 : if (binop_sval->get_op () != PLUS_EXPR)
3656 : : return false;
3657 : 100 : tree rhs_cst = binop_sval->get_arg1 ()->maybe_get_constant ();
3658 : 100 : if (!rhs_cst)
3659 : : return false;
3660 : 100 : if (!integer_onep (rhs_cst))
3661 : : return false;
3662 : :
3663 : : /* We have CAPACITY_SVAL == (LHS + 1) for some LHS expression. */
3664 : :
3665 : 8 : const binop_svalue *lhs_binop_sval
3666 : 8 : = binop_sval->get_arg0 ()->dyn_cast_binop_svalue ();
3667 : 8 : if (!lhs_binop_sval)
3668 : : return false;
3669 : 8 : if (lhs_binop_sval->get_op () != BIT_IOR_EXPR)
3670 : : return false;
3671 : :
3672 : 8 : tree inner_rhs_cst = lhs_binop_sval->get_arg1 ()->maybe_get_constant ();
3673 : 8 : if (!inner_rhs_cst)
3674 : : return false;
3675 : :
3676 : 8 : if (wi::to_widest (inner_rhs_cst) + 1 != wi::to_widest (size_cst))
3677 : : return false;
3678 : : return true;
3679 : : }
3680 : :
3681 : : /* Return true if CAPACITY_SVAL is known to be a multiple of SIZE_CST. */
3682 : :
3683 : : static bool
3684 : 1076 : is_multiple_p (tree size_cst,
3685 : : const svalue *capacity_sval)
3686 : : {
3687 : 1140 : if (const svalue *sval = capacity_sval->maybe_undo_cast ())
3688 : : return is_multiple_p (size_cst, sval);
3689 : :
3690 : 1076 : if (is_round_up (size_cst, capacity_sval))
3691 : : return true;
3692 : :
3693 : : return false;
3694 : : }
3695 : :
3696 : : /* Return true if we should emit a dubious_allocation_size warning
3697 : : on assigning a region of capacity CAPACITY_SVAL bytes to a pointer
3698 : : of type with size SIZE_CST, where CM expresses known constraints. */
3699 : :
3700 : : static bool
3701 : 1076 : is_dubious_capacity (tree size_cst,
3702 : : const svalue *capacity_sval,
3703 : : constraint_manager *cm)
3704 : : {
3705 : 1076 : if (is_multiple_p (size_cst, capacity_sval))
3706 : : return false;
3707 : 1068 : size_visitor v (size_cst, capacity_sval, cm);
3708 : 1068 : return v.is_dubious_capacity ();
3709 : 1068 : }
3710 : :
3711 : :
3712 : : /* Return true if a struct or union either uses the inheritance pattern,
3713 : : where the first field is a base struct, or the flexible array member
3714 : : pattern, where the last field is an array without a specified size. */
3715 : :
3716 : : static bool
3717 : 3988 : struct_or_union_with_inheritance_p (tree struc)
3718 : : {
3719 : 3988 : tree iter = TYPE_FIELDS (struc);
3720 : 3988 : if (iter == NULL_TREE)
3721 : : return false;
3722 : 3979 : if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (iter)))
3723 : : return true;
3724 : :
3725 : : tree last_field;
3726 : 39099 : while (iter != NULL_TREE)
3727 : : {
3728 : 35371 : last_field = iter;
3729 : 35371 : iter = DECL_CHAIN (iter);
3730 : : }
3731 : :
3732 : 3728 : if (last_field != NULL_TREE
3733 : 3728 : && TREE_CODE (TREE_TYPE (last_field)) == ARRAY_TYPE)
3734 : : return true;
3735 : :
3736 : : return false;
3737 : : }
3738 : :
3739 : : /* Return true if the lhs and rhs of an assignment have different types. */
3740 : :
3741 : : static bool
3742 : 163233 : is_any_cast_p (const gimple *stmt)
3743 : : {
3744 : 163233 : if (const gassign *assign = dyn_cast <const gassign *> (stmt))
3745 : 120087 : return gimple_assign_cast_p (assign)
3746 : 226093 : || !pending_diagnostic::same_tree_p (
3747 : 106006 : TREE_TYPE (gimple_assign_lhs (assign)),
3748 : 106006 : TREE_TYPE (gimple_assign_rhs1 (assign)));
3749 : 43146 : else if (const gcall *call = dyn_cast <const gcall *> (stmt))
3750 : : {
3751 : 34953 : tree lhs = gimple_call_lhs (call);
3752 : 64781 : return lhs != NULL_TREE && !pending_diagnostic::same_tree_p (
3753 : 29828 : TREE_TYPE (gimple_call_lhs (call)),
3754 : : gimple_call_return_type (call));
3755 : : }
3756 : :
3757 : : return false;
3758 : : }
3759 : :
3760 : : /* On pointer assignments, check whether the buffer size of
3761 : : RHS_SVAL is compatible with the type of the LHS_REG.
3762 : : Use a non-null CTXT to report allocation size warnings. */
3763 : :
3764 : : void
3765 : 315537 : region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval,
3766 : : region_model_context *ctxt) const
3767 : : {
3768 : 315537 : if (!ctxt || ctxt->get_stmt () == NULL)
3769 : 309993 : return;
3770 : : /* Only report warnings on assignments that actually change the type. */
3771 : 163233 : if (!is_any_cast_p (ctxt->get_stmt ()))
3772 : : return;
3773 : :
3774 : 41862 : tree pointer_type = lhs_reg->get_type ();
3775 : 41862 : if (pointer_type == NULL_TREE || !POINTER_TYPE_P (pointer_type))
3776 : : return;
3777 : :
3778 : 9304 : tree pointee_type = TREE_TYPE (pointer_type);
3779 : : /* Make sure that the type on the left-hand size actually has a size. */
3780 : 9304 : if (pointee_type == NULL_TREE || VOID_TYPE_P (pointee_type)
3781 : 18217 : || TYPE_SIZE_UNIT (pointee_type) == NULL_TREE)
3782 : : return;
3783 : :
3784 : : /* Bail out early on function pointers. */
3785 : 8801 : if (TREE_CODE (pointee_type) == FUNCTION_TYPE)
3786 : : return;
3787 : :
3788 : : /* Bail out early on pointers to structs where we can
3789 : : not deduce whether the buffer size is compatible. */
3790 : 8500 : bool is_struct = RECORD_OR_UNION_TYPE_P (pointee_type);
3791 : 8500 : if (is_struct && struct_or_union_with_inheritance_p (pointee_type))
3792 : : return;
3793 : :
3794 : 8206 : tree pointee_size_tree = size_in_bytes (pointee_type);
3795 : : /* We give up if the type size is not known at compile-time or the
3796 : : type size is always compatible regardless of the buffer size. */
3797 : 8206 : if (TREE_CODE (pointee_size_tree) != INTEGER_CST
3798 : 8048 : || integer_zerop (pointee_size_tree)
3799 : 16229 : || integer_onep (pointee_size_tree))
3800 : 2662 : return;
3801 : :
3802 : 5544 : const region *rhs_reg = deref_rvalue (rhs_sval, NULL_TREE, ctxt, false);
3803 : 5544 : const svalue *capacity = get_capacity (rhs_reg);
3804 : 5544 : switch (capacity->get_kind ())
3805 : : {
3806 : 1673 : case svalue_kind::SK_CONSTANT:
3807 : 1673 : {
3808 : 1673 : const constant_svalue *cst_cap_sval
3809 : 1673 : = as_a <const constant_svalue *> (capacity);
3810 : 1673 : tree cst_cap = cst_cap_sval->get_constant ();
3811 : 1673 : if (TREE_CODE (cst_cap) == INTEGER_CST
3812 : 1673 : && !capacity_compatible_with_type (cst_cap, pointee_size_tree,
3813 : : is_struct))
3814 : 70 : ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg, rhs_reg,
3815 : : capacity, cst_cap,
3816 : 140 : ctxt->get_stmt ()));
3817 : : }
3818 : 1673 : break;
3819 : 3871 : default:
3820 : 3871 : {
3821 : 3871 : if (!is_struct)
3822 : : {
3823 : 1076 : if (is_dubious_capacity (pointee_size_tree,
3824 : : capacity,
3825 : 1076 : m_constraints))
3826 : : {
3827 : 64 : tree expr = get_representative_tree (capacity);
3828 : 64 : ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg,
3829 : : rhs_reg,
3830 : : capacity, expr,
3831 : 128 : ctxt->get_stmt ()));
3832 : : }
3833 : : }
3834 : : break;
3835 : : }
3836 : : }
3837 : : }
3838 : :
3839 : : /* Set the value of the region given by LHS_REG to the value given
3840 : : by RHS_SVAL.
3841 : : Use CTXT to report any warnings associated with writing to LHS_REG. */
3842 : :
3843 : : void
3844 : 315557 : region_model::set_value (const region *lhs_reg, const svalue *rhs_sval,
3845 : : region_model_context *ctxt)
3846 : : {
3847 : 315557 : gcc_assert (lhs_reg);
3848 : 315557 : gcc_assert (rhs_sval);
3849 : :
3850 : : /* Setting the value of an empty region is a no-op. */
3851 : 315557 : if (lhs_reg->empty_p ())
3852 : : return;
3853 : :
3854 : 315537 : check_region_size (lhs_reg, rhs_sval, ctxt);
3855 : :
3856 : 315537 : check_region_for_write (lhs_reg, rhs_sval, ctxt);
3857 : :
3858 : 510082 : m_store.set_value (m_mgr->get_store_manager(), lhs_reg, rhs_sval,
3859 : 194545 : ctxt ? ctxt->get_uncertainty () : NULL);
3860 : : }
3861 : :
3862 : : /* Set the value of the region given by LHS to the value given by RHS. */
3863 : :
3864 : : void
3865 : 84 : region_model::set_value (tree lhs, tree rhs, region_model_context *ctxt)
3866 : : {
3867 : 84 : const region *lhs_reg = get_lvalue (lhs, ctxt);
3868 : 84 : const svalue *rhs_sval = get_rvalue (rhs, ctxt);
3869 : 84 : gcc_assert (lhs_reg);
3870 : 84 : gcc_assert (rhs_sval);
3871 : 84 : set_value (lhs_reg, rhs_sval, ctxt);
3872 : 84 : }
3873 : :
3874 : : /* Issue a note specifying that a particular function parameter is expected
3875 : : to be a valid null-terminated string. */
3876 : :
3877 : : static void
3878 : 146 : inform_about_expected_null_terminated_string_arg (const call_arg_details &ad)
3879 : : {
3880 : : // TODO: ideally we'd underline the param here
3881 : 146 : inform (DECL_SOURCE_LOCATION (ad.m_called_fndecl),
3882 : : "argument %d of %qD must be a pointer to a null-terminated string",
3883 : 146 : ad.m_arg_idx + 1, ad.m_called_fndecl);
3884 : 146 : }
3885 : :
3886 : : /* A binding of a specific svalue at a concrete byte range. */
3887 : :
3888 : : struct fragment
3889 : : {
3890 : 3855 : fragment ()
3891 : 3855 : : m_byte_range (0, 0), m_sval (nullptr)
3892 : : {
3893 : 3855 : }
3894 : :
3895 : 683 : fragment (const byte_range &bytes, const svalue *sval)
3896 : 683 : : m_byte_range (bytes), m_sval (sval)
3897 : : {
3898 : : }
3899 : :
3900 : 571 : static int cmp_ptrs (const void *p1, const void *p2)
3901 : : {
3902 : 571 : const fragment *f1 = (const fragment *)p1;
3903 : 571 : const fragment *f2 = (const fragment *)p2;
3904 : 571 : return byte_range::cmp (f1->m_byte_range, f2->m_byte_range);
3905 : : }
3906 : :
3907 : : void
3908 : 0 : dump_to_pp (pretty_printer *pp) const
3909 : : {
3910 : 0 : pp_string (pp, "fragment(");
3911 : 0 : m_byte_range.dump_to_pp (pp);
3912 : 0 : pp_string (pp, ", sval: ");
3913 : 0 : if (m_sval)
3914 : 0 : m_sval->dump_to_pp (pp, true);
3915 : : else
3916 : 0 : pp_string (pp, "nullptr");
3917 : 0 : pp_string (pp, ")");
3918 : 0 : }
3919 : :
3920 : : byte_range m_byte_range;
3921 : : const svalue *m_sval;
3922 : : };
3923 : :
3924 : : /* Determine if there is a zero terminator somewhere in the
3925 : : part of STRING_CST covered by BYTES (where BYTES is relative to the
3926 : : start of the constant).
3927 : :
3928 : : Return a tristate:
3929 : : - true if there definitely is a zero byte, writing to *OUT_BYTES_READ
3930 : : the number of bytes from that would be read, including the zero byte.
3931 : : - false if there definitely isn't a zero byte
3932 : : - unknown if we don't know. */
3933 : :
3934 : : static tristate
3935 : 287 : string_cst_has_null_terminator (tree string_cst,
3936 : : const byte_range &bytes,
3937 : : byte_offset_t *out_bytes_read)
3938 : : {
3939 : 287 : gcc_assert (bytes.m_start_byte_offset >= 0);
3940 : :
3941 : : /* If we're beyond the string_cst, reads are unsuccessful. */
3942 : 287 : if (tree cst_size = get_string_cst_size (string_cst))
3943 : 287 : if (TREE_CODE (cst_size) == INTEGER_CST)
3944 : 287 : if (bytes.m_start_byte_offset >= TREE_INT_CST_LOW (cst_size))
3945 : 0 : return tristate::unknown ();
3946 : :
3947 : : /* Assume all bytes after TREE_STRING_LENGTH are zero. This handles
3948 : : the case where an array is initialized with a string_cst that isn't
3949 : : as long as the array, where the remaining elements are
3950 : : empty-initialized and thus zeroed. */
3951 : 287 : if (bytes.m_start_byte_offset >= TREE_STRING_LENGTH (string_cst))
3952 : : {
3953 : 2 : *out_bytes_read = 1;
3954 : 2 : return tristate (true);
3955 : : }
3956 : :
3957 : : /* Look for the first 0 byte within STRING_CST
3958 : : from START_READ_OFFSET onwards. */
3959 : 285 : const byte_offset_t num_bytes_to_search
3960 : 570 : = std::min<byte_offset_t> ((TREE_STRING_LENGTH (string_cst)
3961 : 285 : - bytes.m_start_byte_offset),
3962 : 285 : bytes.m_size_in_bytes);
3963 : 285 : const char *start = (TREE_STRING_POINTER (string_cst)
3964 : 285 : + bytes.m_start_byte_offset.slow ());
3965 : 285 : if (num_bytes_to_search >= 0)
3966 : 285 : if (const void *p = memchr (start, 0, bytes.m_size_in_bytes.slow ()))
3967 : : {
3968 : 142 : *out_bytes_read = (const char *)p - start + 1;
3969 : 142 : return tristate (true);
3970 : : }
3971 : :
3972 : 143 : *out_bytes_read = bytes.m_size_in_bytes;
3973 : 143 : return tristate (false);
3974 : : }
3975 : :
3976 : : static tristate
3977 : : svalue_byte_range_has_null_terminator (const svalue *sval,
3978 : : const byte_range &bytes,
3979 : : byte_offset_t *out_bytes_read,
3980 : : logger *logger);
3981 : :
3982 : : /* Determine if there is a zero terminator somewhere in the
3983 : : part of SVAL covered by BYTES (where BYTES is relative to the svalue).
3984 : :
3985 : : Return a tristate:
3986 : : - true if there definitely is a zero byte, writing to *OUT_BYTES_READ
3987 : : the number of bytes from that would be read, including the zero byte.
3988 : : - false if there definitely isn't a zero byte
3989 : : - unknown if we don't know.
3990 : :
3991 : : Use LOGGER (if non-null) for any logging. */
3992 : :
3993 : : static tristate
3994 : 632 : svalue_byte_range_has_null_terminator_1 (const svalue *sval,
3995 : : const byte_range &bytes,
3996 : : byte_offset_t *out_bytes_read,
3997 : : logger *logger)
3998 : : {
3999 : 632 : if (bytes.m_start_byte_offset == 0
4000 : 632 : && sval->all_zeroes_p ())
4001 : : {
4002 : : /* The initial byte of an all-zeroes SVAL is a zero byte. */
4003 : 22 : *out_bytes_read = 1;
4004 : 22 : return tristate (true);
4005 : : }
4006 : :
4007 : 610 : switch (sval->get_kind ())
4008 : : {
4009 : 203 : case SK_CONSTANT:
4010 : 203 : {
4011 : 203 : tree cst
4012 : 203 : = as_a <const constant_svalue *> (sval)->get_constant ();
4013 : 203 : switch (TREE_CODE (cst))
4014 : : {
4015 : 184 : case STRING_CST:
4016 : 184 : return string_cst_has_null_terminator (cst, bytes, out_bytes_read);
4017 : 19 : case INTEGER_CST:
4018 : 19 : if (bytes.m_start_byte_offset == 0
4019 : 19 : && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (cst))))
4020 : : {
4021 : : /* Model accesses to the initial byte of a 1-byte
4022 : : INTEGER_CST. */
4023 : 17 : *out_bytes_read = 1;
4024 : 17 : if (zerop (cst))
4025 : 0 : return tristate (true);
4026 : : else
4027 : 17 : return tristate (false);
4028 : : }
4029 : : /* Treat any other access to an INTEGER_CST as unknown. */
4030 : 2 : return tristate::TS_UNKNOWN;
4031 : :
4032 : : default:
4033 : : break;
4034 : : }
4035 : : }
4036 : : break;
4037 : :
4038 : 112 : case SK_INITIAL:
4039 : 112 : {
4040 : 112 : const initial_svalue *initial_sval = (const initial_svalue *)sval;
4041 : 112 : const region *reg = initial_sval->get_region ();
4042 : 112 : if (const string_region *string_reg = reg->dyn_cast_string_region ())
4043 : : {
4044 : 103 : tree string_cst = string_reg->get_string_cst ();
4045 : 103 : return string_cst_has_null_terminator (string_cst,
4046 : : bytes,
4047 : 103 : out_bytes_read);
4048 : : }
4049 : 9 : return tristate::TS_UNKNOWN;
4050 : : }
4051 : 44 : break;
4052 : :
4053 : 44 : case SK_BITS_WITHIN:
4054 : 44 : {
4055 : 44 : const bits_within_svalue *bits_within_sval
4056 : : = (const bits_within_svalue *)sval;
4057 : 44 : byte_range bytes_within_inner (0, 0);
4058 : 44 : if (bits_within_sval->get_bits ().as_byte_range (&bytes_within_inner))
4059 : : {
4060 : : /* Consider e.g. looking for null terminator of
4061 : : bytes 2-4 of BITS_WITHIN(bytes 10-15 of inner_sval)
4062 : :
4063 : : This is equivalent to looking within bytes 12-14 of
4064 : : inner_sval. */
4065 : 44 : const byte_offset_t start_byte_relative_to_inner
4066 : 44 : = (bytes.m_start_byte_offset
4067 : 44 : + bytes_within_inner.m_start_byte_offset);
4068 : 44 : const byte_offset_t next_byte_relative_to_inner
4069 : 44 : = (bytes.get_next_byte_offset ()
4070 : 44 : + bytes_within_inner.m_start_byte_offset);
4071 : 44 : if (next_byte_relative_to_inner > start_byte_relative_to_inner)
4072 : : {
4073 : 44 : const byte_range relative_to_inner
4074 : : (start_byte_relative_to_inner,
4075 : 44 : next_byte_relative_to_inner - start_byte_relative_to_inner);
4076 : 44 : const svalue *inner_sval
4077 : 44 : = bits_within_sval->get_inner_svalue ();
4078 : 44 : return svalue_byte_range_has_null_terminator (inner_sval,
4079 : : relative_to_inner,
4080 : : out_bytes_read,
4081 : : logger);
4082 : : }
4083 : : }
4084 : : }
4085 : 0 : break;
4086 : :
4087 : : default:
4088 : : // TODO: it may be possible to handle other cases here.
4089 : : break;
4090 : : }
4091 : 251 : return tristate::TS_UNKNOWN;
4092 : : }
4093 : :
4094 : : /* Like svalue_byte_range_has_null_terminator_1, but add logging. */
4095 : :
4096 : : static tristate
4097 : 632 : svalue_byte_range_has_null_terminator (const svalue *sval,
4098 : : const byte_range &bytes,
4099 : : byte_offset_t *out_bytes_read,
4100 : : logger *logger)
4101 : : {
4102 : 632 : LOG_SCOPE (logger);
4103 : 632 : if (logger)
4104 : : {
4105 : 0 : pretty_printer *pp = logger->get_printer ();
4106 : 0 : logger->start_log_line ();
4107 : 0 : bytes.dump_to_pp (pp);
4108 : 0 : logger->log_partial (" of sval: ");
4109 : 0 : sval->dump_to_pp (pp, true);
4110 : 0 : logger->end_log_line ();
4111 : : }
4112 : 632 : tristate ts
4113 : 632 : = svalue_byte_range_has_null_terminator_1 (sval, bytes,
4114 : : out_bytes_read, logger);
4115 : 632 : if (logger)
4116 : : {
4117 : 0 : pretty_printer *pp = logger->get_printer ();
4118 : 0 : logger->start_log_line ();
4119 : 0 : pp_printf (pp, "has null terminator: %s", ts.as_string ());
4120 : 0 : if (ts.is_true ())
4121 : : {
4122 : 0 : pp_string (pp, "; bytes read: ");
4123 : 0 : pp_wide_int (pp, *out_bytes_read, SIGNED);
4124 : : }
4125 : 0 : logger->end_log_line ();
4126 : : }
4127 : 1264 : return ts;
4128 : 632 : }
4129 : :
4130 : : /* A frozen copy of a single base region's binding_cluster within a store,
4131 : : optimized for traversal of the concrete parts in byte order.
4132 : : This only captures concrete bindings, and is an implementation detail
4133 : : of region_model::scan_for_null_terminator. */
4134 : :
4135 : 3695 : class iterable_cluster
4136 : : {
4137 : : public:
4138 : 3695 : iterable_cluster (const binding_cluster *cluster)
4139 : 3695 : {
4140 : 3695 : if (!cluster)
4141 : : return;
4142 : 3662 : for (auto iter : *cluster)
4143 : : {
4144 : 875 : const binding_key *key = iter.first;
4145 : 875 : const svalue *sval = iter.second;
4146 : :
4147 : 1750 : if (const concrete_binding *concrete_key
4148 : 875 : = key->dyn_cast_concrete_binding ())
4149 : : {
4150 : 683 : byte_range fragment_bytes (0, 0);
4151 : 683 : if (concrete_key->get_byte_range (&fragment_bytes))
4152 : 683 : m_fragments.safe_push (fragment (fragment_bytes, sval));
4153 : : }
4154 : : else
4155 : 192 : m_symbolic_bindings.safe_push (key);
4156 : : }
4157 : 1912 : m_fragments.qsort (fragment::cmp_ptrs);
4158 : : }
4159 : :
4160 : : bool
4161 : 3855 : get_fragment_for_byte (byte_offset_t byte, fragment *out_frag) const
4162 : : {
4163 : : /* TODO: binary search rather than linear. */
4164 : 3855 : unsigned iter_idx;
4165 : 4068 : for (iter_idx = 0; iter_idx < m_fragments.length (); iter_idx++)
4166 : : {
4167 : 801 : if (m_fragments[iter_idx].m_byte_range.contains_p (byte))
4168 : : {
4169 : 588 : *out_frag = m_fragments[iter_idx];
4170 : 588 : return true;
4171 : : }
4172 : : }
4173 : : return false;
4174 : : }
4175 : :
4176 : 3267 : bool has_symbolic_bindings_p () const
4177 : : {
4178 : 6534 : return !m_symbolic_bindings.is_empty ();
4179 : : }
4180 : :
4181 : 0 : void dump_to_pp (pretty_printer *pp) const
4182 : : {
4183 : 0 : pp_string (pp, "iterable_cluster (fragments: [");
4184 : 0 : for (auto const &iter : &m_fragments)
4185 : : {
4186 : 0 : if (&iter != m_fragments.begin ())
4187 : 0 : pp_string (pp, ", ");
4188 : 0 : iter.dump_to_pp (pp);
4189 : : }
4190 : 0 : pp_printf (pp, "], symbolic bindings: [");
4191 : 0 : for (auto const &iter : m_symbolic_bindings)
4192 : : {
4193 : 0 : if (&iter != m_symbolic_bindings.begin ())
4194 : 0 : pp_string (pp, ", ");
4195 : 0 : (*iter).dump_to_pp (pp, true);
4196 : : }
4197 : 0 : pp_string (pp, "])");
4198 : 0 : }
4199 : :
4200 : : private:
4201 : : auto_vec<fragment> m_fragments;
4202 : : auto_vec<const binding_key *> m_symbolic_bindings;
4203 : : };
4204 : :
4205 : : /* Simulate reading the bytes at BYTES from BASE_REG.
4206 : : Complain to CTXT about any issues with the read e.g. out-of-bounds. */
4207 : :
4208 : : const svalue *
4209 : 7611 : region_model::get_store_bytes (const region *base_reg,
4210 : : const byte_range &bytes,
4211 : : region_model_context *ctxt) const
4212 : : {
4213 : : /* Shortcut reading all of a string_region. */
4214 : 7611 : if (bytes.get_start_byte_offset () == 0)
4215 : 7395 : if (const string_region *string_reg = base_reg->dyn_cast_string_region ())
4216 : 4208 : if (bytes.m_size_in_bytes
4217 : 4208 : == TREE_STRING_LENGTH (string_reg->get_string_cst ()))
4218 : 4208 : return m_mgr->get_or_create_initial_value (base_reg);
4219 : :
4220 : 3403 : const svalue *index_sval
4221 : 3403 : = m_mgr->get_or_create_int_cst (size_type_node,
4222 : 3403 : bytes.get_start_byte_offset ());
4223 : 3403 : const region *offset_reg = m_mgr->get_offset_region (base_reg,
4224 : : NULL_TREE,
4225 : : index_sval);
4226 : 3403 : const svalue *byte_size_sval
4227 : 3403 : = m_mgr->get_or_create_int_cst (size_type_node, bytes.m_size_in_bytes);
4228 : 3403 : const region *read_reg = m_mgr->get_sized_region (offset_reg,
4229 : : NULL_TREE,
4230 : : byte_size_sval);
4231 : :
4232 : : /* Simulate reading those bytes from the store. */
4233 : 3403 : const svalue *sval = get_store_value (read_reg, ctxt);
4234 : 3403 : return sval;
4235 : : }
4236 : :
4237 : : static tree
4238 : 2955 : get_tree_for_byte_offset (tree ptr_expr, byte_offset_t byte_offset)
4239 : : {
4240 : 2955 : gcc_assert (ptr_expr);
4241 : 2955 : tree ptype = build_pointer_type_for_mode (char_type_node, ptr_mode, true);
4242 : 2955 : return fold_build2 (MEM_REF,
4243 : : char_type_node,
4244 : : ptr_expr, wide_int_to_tree (ptype, byte_offset));
4245 : : }
4246 : :
4247 : : /* Simulate a series of reads of REG until we find a 0 byte
4248 : : (equivalent to calling strlen).
4249 : :
4250 : : Complain to CTXT and return NULL if:
4251 : : - the buffer pointed to isn't null-terminated
4252 : : - the buffer pointed to has any uninitialized bytes before any 0-terminator
4253 : : - any of the reads aren't within the bounds of the underlying base region
4254 : :
4255 : : Otherwise, return a svalue for the number of bytes read (strlen + 1),
4256 : : and, if OUT_SVAL is non-NULL, write to *OUT_SVAL with an svalue
4257 : : representing the content of REG up to and including the terminator.
4258 : :
4259 : : Algorithm
4260 : : =========
4261 : :
4262 : : Get offset for first byte to read.
4263 : : Find the binding (if any) that contains it.
4264 : : Find the size in bits of that binding.
4265 : : Round to the nearest byte (which way???)
4266 : : Or maybe give up if we have a partial binding there.
4267 : : Get the svalue from the binding.
4268 : : Determine the strlen (if any) of that svalue.
4269 : : Does it have a 0-terminator within it?
4270 : : If so, we have a partial read up to and including that terminator
4271 : : Read those bytes from the store; add to the result in the correct place.
4272 : : Finish
4273 : : If not, we have a full read of that svalue
4274 : : Read those bytes from the store; add to the result in the correct place.
4275 : : Update read/write offsets
4276 : : Continue
4277 : : If unknown:
4278 : : Result is unknown
4279 : : Finish
4280 : : */
4281 : :
4282 : : const svalue *
4283 : 8006 : region_model::scan_for_null_terminator_1 (const region *reg,
4284 : : tree expr,
4285 : : const svalue **out_sval,
4286 : : region_model_context *ctxt) const
4287 : : {
4288 : 8006 : logger *logger = ctxt ? ctxt->get_logger () : nullptr;
4289 : 8006 : store_manager *store_mgr = m_mgr->get_store_manager ();
4290 : :
4291 : 8006 : region_offset offset = reg->get_offset (m_mgr);
4292 : 8006 : if (offset.symbolic_p ())
4293 : : {
4294 : 101 : if (out_sval)
4295 : 0 : *out_sval = get_store_value (reg, nullptr);
4296 : 101 : if (logger)
4297 : 0 : logger->log ("offset is symbolic");
4298 : 101 : return m_mgr->get_or_create_unknown_svalue (size_type_node);
4299 : : }
4300 : 7905 : byte_offset_t src_byte_offset;
4301 : 7905 : if (!offset.get_concrete_byte_offset (&src_byte_offset))
4302 : : {
4303 : 0 : if (out_sval)
4304 : 0 : *out_sval = get_store_value (reg, nullptr);
4305 : 0 : if (logger)
4306 : 0 : logger->log ("can't get concrete byte offset");
4307 : 0 : return m_mgr->get_or_create_unknown_svalue (size_type_node);
4308 : : }
4309 : 7905 : const byte_offset_t initial_src_byte_offset = src_byte_offset;
4310 : 7905 : byte_offset_t dst_byte_offset = 0;
4311 : :
4312 : 7905 : const region *base_reg = reg->get_base_region ();
4313 : :
4314 : 7905 : if (const string_region *str_reg = base_reg->dyn_cast_string_region ())
4315 : : {
4316 : 4210 : tree string_cst = str_reg->get_string_cst ();
4317 : 4210 : if (const void *p = memchr (TREE_STRING_POINTER (string_cst),
4318 : : 0,
4319 : 4210 : TREE_STRING_LENGTH (string_cst)))
4320 : : {
4321 : 4210 : size_t num_bytes_read
4322 : 4210 : = (const char *)p - TREE_STRING_POINTER (string_cst) + 1;
4323 : : /* Simulate the read. */
4324 : 4210 : byte_range bytes_to_read (0, num_bytes_read);
4325 : 4210 : const svalue *sval = get_store_bytes (reg, bytes_to_read, ctxt);
4326 : 4210 : if (out_sval)
4327 : 516 : *out_sval = sval;
4328 : 4210 : if (logger)
4329 : 0 : logger->log ("using string_cst");
4330 : 4210 : return m_mgr->get_or_create_int_cst (size_type_node,
4331 : : num_bytes_read);
4332 : : }
4333 : : }
4334 : :
4335 : 3695 : const binding_cluster *cluster = m_store.get_cluster (base_reg);
4336 : 3695 : iterable_cluster c (cluster);
4337 : 3695 : if (logger)
4338 : : {
4339 : 0 : pretty_printer *pp = logger->get_printer ();
4340 : 0 : logger->start_log_line ();
4341 : 0 : c.dump_to_pp (pp);
4342 : 0 : logger->end_log_line ();
4343 : : }
4344 : :
4345 : 3695 : binding_map result;
4346 : :
4347 : 160 : while (1)
4348 : : {
4349 : 3855 : fragment f;
4350 : 3855 : if (c.get_fragment_for_byte (src_byte_offset, &f))
4351 : : {
4352 : 588 : if (logger)
4353 : : {
4354 : 0 : logger->start_log_line ();
4355 : 0 : pretty_printer *pp = logger->get_printer ();
4356 : 0 : pp_printf (pp, "src_byte_offset: ");
4357 : 0 : pp_wide_int (pp, src_byte_offset, SIGNED);
4358 : 0 : pp_string (pp, ": ");
4359 : 0 : f.dump_to_pp (pp);
4360 : 0 : logger->end_log_line ();
4361 : : }
4362 : 588 : gcc_assert (f.m_byte_range.contains_p (src_byte_offset));
4363 : : /* src_byte_offset and f.m_byte_range are both expressed relative to
4364 : : the base region.
4365 : : Convert to a byte_range relative to the svalue. */
4366 : 588 : const byte_range bytes_relative_to_svalue
4367 : 588 : (src_byte_offset - f.m_byte_range.get_start_byte_offset (),
4368 : 588 : f.m_byte_range.get_next_byte_offset () - src_byte_offset);
4369 : 588 : byte_offset_t fragment_bytes_read;
4370 : 588 : tristate is_terminated
4371 : 588 : = svalue_byte_range_has_null_terminator (f.m_sval,
4372 : : bytes_relative_to_svalue,
4373 : : &fragment_bytes_read,
4374 : : logger);
4375 : 588 : if (is_terminated.is_unknown ())
4376 : : {
4377 : 262 : if (out_sval)
4378 : 2 : *out_sval = get_store_value (reg, nullptr);
4379 : 428 : return m_mgr->get_or_create_unknown_svalue (size_type_node);
4380 : : }
4381 : :
4382 : : /* Simulate reading those bytes from the store. */
4383 : 326 : byte_range bytes_to_read (src_byte_offset, fragment_bytes_read);
4384 : 326 : const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
4385 : 326 : check_for_poison (sval, expr, nullptr, ctxt);
4386 : :
4387 : 326 : if (out_sval)
4388 : : {
4389 : 8 : byte_range bytes_to_write (dst_byte_offset, fragment_bytes_read);
4390 : 8 : const binding_key *key
4391 : 8 : = store_mgr->get_concrete_binding (bytes_to_write);
4392 : 8 : result.put (key, sval);
4393 : : }
4394 : :
4395 : 326 : src_byte_offset += fragment_bytes_read;
4396 : 326 : dst_byte_offset += fragment_bytes_read;
4397 : :
4398 : 326 : if (is_terminated.is_true ())
4399 : : {
4400 : 166 : if (out_sval)
4401 : 5 : *out_sval = m_mgr->get_or_create_compound_svalue (NULL_TREE,
4402 : : result);
4403 : 166 : if (logger)
4404 : 0 : logger->log ("got terminator");
4405 : 166 : return m_mgr->get_or_create_int_cst (size_type_node,
4406 : : dst_byte_offset);
4407 : : }
4408 : : }
4409 : : else
4410 : : break;
4411 : : }
4412 : :
4413 : : /* No binding for this base_region, or no binding at src_byte_offset
4414 : : (or a symbolic binding). */
4415 : :
4416 : 3267 : if (c.has_symbolic_bindings_p ())
4417 : : {
4418 : 192 : if (out_sval)
4419 : 75 : *out_sval = get_store_value (reg, nullptr);
4420 : 192 : if (logger)
4421 : 0 : logger->log ("got symbolic binding");
4422 : 192 : return m_mgr->get_or_create_unknown_svalue (size_type_node);
4423 : : }
4424 : :
4425 : : /* TODO: the various special-cases seen in
4426 : : region_model::get_store_value. */
4427 : :
4428 : : /* Simulate reading from this byte, then give up. */
4429 : 3075 : byte_range bytes_to_read (src_byte_offset, 1);
4430 : 3075 : const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
4431 : 3075 : tree byte_expr
4432 : : = (expr
4433 : 6030 : ? get_tree_for_byte_offset (expr,
4434 : : src_byte_offset - initial_src_byte_offset)
4435 : 3075 : : NULL_TREE);
4436 : 3075 : check_for_poison (sval, byte_expr, nullptr, ctxt);
4437 : 3075 : if (base_reg->can_have_initial_svalue_p ())
4438 : : {
4439 : 2840 : if (out_sval)
4440 : 300 : *out_sval = get_store_value (reg, nullptr);
4441 : 2840 : return m_mgr->get_or_create_unknown_svalue (size_type_node);
4442 : : }
4443 : : else
4444 : : return nullptr;
4445 : 7390 : }
4446 : :
4447 : : /* Like region_model::scan_for_null_terminator_1, but add logging. */
4448 : :
4449 : : const svalue *
4450 : 8006 : region_model::scan_for_null_terminator (const region *reg,
4451 : : tree expr,
4452 : : const svalue **out_sval,
4453 : : region_model_context *ctxt) const
4454 : : {
4455 : 8006 : logger *logger = ctxt ? ctxt->get_logger () : nullptr;
4456 : 8006 : LOG_SCOPE (logger);
4457 : 8006 : if (logger)
4458 : : {
4459 : 0 : pretty_printer *pp = logger->get_printer ();
4460 : 0 : logger->start_log_line ();
4461 : 0 : logger->log_partial ("region: ");
4462 : 0 : reg->dump_to_pp (pp, true);
4463 : 0 : logger->end_log_line ();
4464 : : }
4465 : 8006 : const svalue *sval = scan_for_null_terminator_1 (reg, expr, out_sval, ctxt);
4466 : 8006 : if (logger)
4467 : : {
4468 : 0 : pretty_printer *pp = logger->get_printer ();
4469 : 0 : logger->start_log_line ();
4470 : 0 : logger->log_partial ("length result: ");
4471 : 0 : if (sval)
4472 : 0 : sval->dump_to_pp (pp, true);
4473 : : else
4474 : 0 : pp_printf (pp, "NULL");
4475 : 0 : logger->end_log_line ();
4476 : 0 : if (out_sval)
4477 : : {
4478 : 0 : logger->start_log_line ();
4479 : 0 : logger->log_partial ("content result: ");
4480 : 0 : if (*out_sval)
4481 : 0 : (*out_sval)->dump_to_pp (pp, true);
4482 : : else
4483 : 0 : pp_printf (pp, "NULL");
4484 : 0 : logger->end_log_line ();
4485 : : }
4486 : : }
4487 : 16012 : return sval;
4488 : 8006 : }
4489 : :
4490 : : /* Check that argument ARG_IDX (0-based) to the call described by CD
4491 : : is a pointer to a valid null-terminated string.
4492 : :
4493 : : Simulate scanning through the buffer, reading until we find a 0 byte
4494 : : (equivalent to calling strlen).
4495 : :
4496 : : Complain and return NULL if:
4497 : : - the buffer pointed to isn't null-terminated
4498 : : - the buffer pointed to has any uninitalized bytes before any 0-terminator
4499 : : - any of the reads aren't within the bounds of the underlying base region
4500 : :
4501 : : Otherwise, return a svalue for strlen of the buffer (*not* including
4502 : : the null terminator).
4503 : :
4504 : : TODO: we should also complain if:
4505 : : - the pointer is NULL (or could be). */
4506 : :
4507 : : const svalue *
4508 : 196 : region_model::check_for_null_terminated_string_arg (const call_details &cd,
4509 : : unsigned arg_idx) const
4510 : : {
4511 : 196 : return check_for_null_terminated_string_arg (cd,
4512 : : arg_idx,
4513 : : false, /* include_terminator */
4514 : 196 : nullptr); // out_sval
4515 : : }
4516 : :
4517 : :
4518 : : /* Check that argument ARG_IDX (0-based) to the call described by CD
4519 : : is a pointer to a valid null-terminated string.
4520 : :
4521 : : Simulate scanning through the buffer, reading until we find a 0 byte
4522 : : (equivalent to calling strlen).
4523 : :
4524 : : Complain and return NULL if:
4525 : : - the buffer pointed to isn't null-terminated
4526 : : - the buffer pointed to has any uninitalized bytes before any 0-terminator
4527 : : - any of the reads aren't within the bounds of the underlying base region
4528 : :
4529 : : Otherwise, return a svalue. This will be the number of bytes read
4530 : : (including the null terminator) if INCLUDE_TERMINATOR is true, or strlen
4531 : : of the buffer (not including the null terminator) if it is false.
4532 : :
4533 : : Also, when returning an svalue, if OUT_SVAL is non-NULL, write to
4534 : : *OUT_SVAL with an svalue representing the content of the buffer up to
4535 : : and including the terminator.
4536 : :
4537 : : TODO: we should also complain if:
4538 : : - the pointer is NULL (or could be). */
4539 : :
4540 : : const svalue *
4541 : 7459 : region_model::check_for_null_terminated_string_arg (const call_details &cd,
4542 : : unsigned arg_idx,
4543 : : bool include_terminator,
4544 : : const svalue **out_sval) const
4545 : : {
4546 : 0 : class null_terminator_check_event : public custom_event
4547 : : {
4548 : : public:
4549 : 170 : null_terminator_check_event (const event_loc_info &loc_info,
4550 : : const call_arg_details &arg_details)
4551 : 170 : : custom_event (loc_info),
4552 : 170 : m_arg_details (arg_details)
4553 : : {
4554 : : }
4555 : :
4556 : 292 : void print_desc (pretty_printer &pp) const final override
4557 : : {
4558 : 292 : if (m_arg_details.m_arg_expr)
4559 : 292 : pp_printf (&pp,
4560 : : "while looking for null terminator"
4561 : : " for argument %i (%qE) of %qD...",
4562 : 292 : m_arg_details.m_arg_idx + 1,
4563 : : m_arg_details.m_arg_expr,
4564 : 292 : m_arg_details.m_called_fndecl);
4565 : : else
4566 : 0 : pp_printf (&pp,
4567 : : "while looking for null terminator"
4568 : : " for argument %i of %qD...",
4569 : 0 : m_arg_details.m_arg_idx + 1,
4570 : 0 : m_arg_details.m_called_fndecl);
4571 : 292 : }
4572 : :
4573 : : private:
4574 : : const call_arg_details m_arg_details;
4575 : : };
4576 : :
4577 : 0 : class null_terminator_check_decl_note
4578 : : : public pending_note_subclass<null_terminator_check_decl_note>
4579 : : {
4580 : : public:
4581 : 170 : null_terminator_check_decl_note (const call_arg_details &arg_details)
4582 : 170 : : m_arg_details (arg_details)
4583 : : {
4584 : : }
4585 : :
4586 : 1496 : const char *get_kind () const final override
4587 : : {
4588 : 1496 : return "null_terminator_check_decl_note";
4589 : : }
4590 : :
4591 : 146 : void emit () const final override
4592 : : {
4593 : 146 : inform_about_expected_null_terminated_string_arg (m_arg_details);
4594 : 146 : }
4595 : :
4596 : 748 : bool operator== (const null_terminator_check_decl_note &other) const
4597 : : {
4598 : 748 : return m_arg_details == other.m_arg_details;
4599 : : }
4600 : :
4601 : : private:
4602 : : const call_arg_details m_arg_details;
4603 : : };
4604 : :
4605 : : /* Subclass of decorated_region_model_context that
4606 : : adds the above event and note to any saved diagnostics. */
4607 : 7459 : class annotating_ctxt : public annotating_context
4608 : : {
4609 : : public:
4610 : 7459 : annotating_ctxt (const call_details &cd,
4611 : : unsigned arg_idx)
4612 : 7459 : : annotating_context (cd.get_ctxt ()),
4613 : 7459 : m_cd (cd),
4614 : 7459 : m_arg_idx (arg_idx)
4615 : : {
4616 : : }
4617 : 170 : void add_annotations () final override
4618 : : {
4619 : 170 : call_arg_details arg_details (m_cd, m_arg_idx);
4620 : 340 : event_loc_info loc_info (m_cd.get_location (),
4621 : 170 : m_cd.get_model ()->get_current_function ()->decl,
4622 : 340 : m_cd.get_model ()->get_stack_depth ());
4623 : :
4624 : 170 : add_event (make_unique<null_terminator_check_event> (loc_info,
4625 : : arg_details));
4626 : 170 : add_note (make_unique <null_terminator_check_decl_note> (arg_details));
4627 : 170 : }
4628 : : private:
4629 : : const call_details &m_cd;
4630 : : unsigned m_arg_idx;
4631 : : };
4632 : :
4633 : : /* Use this ctxt below so that any diagnostics that get added
4634 : : get annotated. */
4635 : 7459 : annotating_ctxt my_ctxt (cd, arg_idx);
4636 : :
4637 : 7459 : const svalue *arg_sval = cd.get_arg_svalue (arg_idx);
4638 : 7459 : const region *buf_reg
4639 : 7459 : = deref_rvalue (arg_sval, cd.get_arg_tree (arg_idx), &my_ctxt);
4640 : :
4641 : 14918 : if (const svalue *num_bytes_read_sval
4642 : 7459 : = scan_for_null_terminator (buf_reg,
4643 : : cd.get_arg_tree (arg_idx),
4644 : : out_sval,
4645 : : &my_ctxt))
4646 : : {
4647 : 7281 : if (include_terminator)
4648 : : return num_bytes_read_sval;
4649 : : else
4650 : : {
4651 : : /* strlen is (bytes_read - 1). */
4652 : 6383 : const svalue *one = m_mgr->get_or_create_int_cst (size_type_node, 1);
4653 : 6383 : return m_mgr->get_or_create_binop (size_type_node,
4654 : : MINUS_EXPR,
4655 : : num_bytes_read_sval,
4656 : 6383 : one);
4657 : : }
4658 : : }
4659 : : else
4660 : : return nullptr;
4661 : : }
4662 : :
4663 : : /* Remove all bindings overlapping REG within the store. */
4664 : :
4665 : : void
4666 : 6152 : region_model::clobber_region (const region *reg)
4667 : : {
4668 : 6152 : m_store.clobber_region (m_mgr->get_store_manager(), reg);
4669 : 6152 : }
4670 : :
4671 : : /* Remove any bindings for REG within the store. */
4672 : :
4673 : : void
4674 : 178736 : region_model::purge_region (const region *reg)
4675 : : {
4676 : 178736 : m_store.purge_region (m_mgr->get_store_manager(), reg);
4677 : 178736 : }
4678 : :
4679 : : /* Fill REG with SVAL.
4680 : : Use CTXT to report any warnings associated with the write
4681 : : (e.g. out-of-bounds). */
4682 : :
4683 : : void
4684 : 663 : region_model::fill_region (const region *reg,
4685 : : const svalue *sval,
4686 : : region_model_context *ctxt)
4687 : : {
4688 : 663 : check_region_for_write (reg, nullptr, ctxt);
4689 : 663 : m_store.fill_region (m_mgr->get_store_manager(), reg, sval);
4690 : 663 : }
4691 : :
4692 : : /* Zero-fill REG.
4693 : : Use CTXT to report any warnings associated with the write
4694 : : (e.g. out-of-bounds). */
4695 : :
4696 : : void
4697 : 777 : region_model::zero_fill_region (const region *reg,
4698 : : region_model_context *ctxt)
4699 : : {
4700 : 777 : check_region_for_write (reg, nullptr, ctxt);
4701 : 777 : m_store.zero_fill_region (m_mgr->get_store_manager(), reg);
4702 : 777 : }
4703 : :
4704 : : /* Copy NUM_BYTES_SVAL of SVAL to DEST_REG.
4705 : : Use CTXT to report any warnings associated with the copy
4706 : : (e.g. out-of-bounds writes). */
4707 : :
4708 : : void
4709 : 1799 : region_model::write_bytes (const region *dest_reg,
4710 : : const svalue *num_bytes_sval,
4711 : : const svalue *sval,
4712 : : region_model_context *ctxt)
4713 : : {
4714 : 1799 : const region *sized_dest_reg
4715 : 1799 : = m_mgr->get_sized_region (dest_reg, NULL_TREE, num_bytes_sval);
4716 : 1799 : set_value (sized_dest_reg, sval, ctxt);
4717 : 1799 : }
4718 : :
4719 : : /* Read NUM_BYTES_SVAL from SRC_REG.
4720 : : Use CTXT to report any warnings associated with the copy
4721 : : (e.g. out-of-bounds reads, copying of uninitialized values, etc). */
4722 : :
4723 : : const svalue *
4724 : 1013 : region_model::read_bytes (const region *src_reg,
4725 : : tree src_ptr_expr,
4726 : : const svalue *num_bytes_sval,
4727 : : region_model_context *ctxt) const
4728 : : {
4729 : 1013 : if (num_bytes_sval->get_kind () == SK_UNKNOWN)
4730 : 179 : return m_mgr->get_or_create_unknown_svalue (NULL_TREE);
4731 : 834 : const region *sized_src_reg
4732 : 834 : = m_mgr->get_sized_region (src_reg, NULL_TREE, num_bytes_sval);
4733 : 834 : const svalue *src_contents_sval = get_store_value (sized_src_reg, ctxt);
4734 : 834 : check_for_poison (src_contents_sval, src_ptr_expr,
4735 : : sized_src_reg, ctxt);
4736 : 834 : return src_contents_sval;
4737 : : }
4738 : :
4739 : : /* Copy NUM_BYTES_SVAL bytes from SRC_REG to DEST_REG.
4740 : : Use CTXT to report any warnings associated with the copy
4741 : : (e.g. out-of-bounds reads/writes, copying of uninitialized values,
4742 : : etc). */
4743 : :
4744 : : void
4745 : 459 : region_model::copy_bytes (const region *dest_reg,
4746 : : const region *src_reg,
4747 : : tree src_ptr_expr,
4748 : : const svalue *num_bytes_sval,
4749 : : region_model_context *ctxt)
4750 : : {
4751 : 459 : const svalue *data_sval
4752 : 459 : = read_bytes (src_reg, src_ptr_expr, num_bytes_sval, ctxt);
4753 : 459 : write_bytes (dest_reg, num_bytes_sval, data_sval, ctxt);
4754 : 459 : }
4755 : :
4756 : : /* Mark REG as having unknown content. */
4757 : :
4758 : : void
4759 : 289 : region_model::mark_region_as_unknown (const region *reg,
4760 : : uncertainty_t *uncertainty)
4761 : : {
4762 : 289 : svalue_set maybe_live_values;
4763 : 289 : m_store.mark_region_as_unknown (m_mgr->get_store_manager(), reg,
4764 : : uncertainty, &maybe_live_values);
4765 : 289 : m_store.on_maybe_live_values (maybe_live_values);
4766 : 289 : }
4767 : :
4768 : : /* Determine what is known about the condition "LHS_SVAL OP RHS_SVAL" within
4769 : : this model. */
4770 : :
4771 : : tristate
4772 : 193006 : region_model::eval_condition (const svalue *lhs,
4773 : : enum tree_code op,
4774 : : const svalue *rhs) const
4775 : : {
4776 : 193006 : gcc_assert (lhs);
4777 : 193006 : gcc_assert (rhs);
4778 : :
4779 : : /* For now, make no attempt to capture constraints on floating-point
4780 : : values. */
4781 : 193006 : if ((lhs->get_type () && FLOAT_TYPE_P (lhs->get_type ()))
4782 : 329905 : || (rhs->get_type () && FLOAT_TYPE_P (rhs->get_type ())))
4783 : 72 : return tristate::unknown ();
4784 : :
4785 : : /* See what we know based on the values. */
4786 : :
4787 : : /* Unwrap any unmergeable values. */
4788 : 192934 : lhs = lhs->unwrap_any_unmergeable ();
4789 : 192934 : rhs = rhs->unwrap_any_unmergeable ();
4790 : :
4791 : 192934 : if (lhs == rhs)
4792 : : {
4793 : : /* If we have the same svalue, then we have equality
4794 : : (apart from NaN-handling).
4795 : : TODO: should this definitely be the case for poisoned values? */
4796 : : /* Poisoned and unknown values are "unknowable". */
4797 : 14651 : if (lhs->get_kind () == SK_POISONED
4798 : 14651 : || lhs->get_kind () == SK_UNKNOWN)
4799 : 3578 : return tristate::TS_UNKNOWN;
4800 : :
4801 : 11073 : switch (op)
4802 : : {
4803 : 8134 : case EQ_EXPR:
4804 : 8134 : case GE_EXPR:
4805 : 8134 : case LE_EXPR:
4806 : 8134 : return tristate::TS_TRUE;
4807 : :
4808 : 2939 : case NE_EXPR:
4809 : 2939 : case GT_EXPR:
4810 : 2939 : case LT_EXPR:
4811 : 2939 : return tristate::TS_FALSE;
4812 : :
4813 : : default:
4814 : : /* For other ops, use the logic below. */
4815 : : break;
4816 : : }
4817 : : }
4818 : :
4819 : : /* If we have a pair of region_svalues, compare them. */
4820 : 178283 : if (const region_svalue *lhs_ptr = lhs->dyn_cast_region_svalue ())
4821 : 13004 : if (const region_svalue *rhs_ptr = rhs->dyn_cast_region_svalue ())
4822 : : {
4823 : 349 : tristate res = region_svalue::eval_condition (lhs_ptr, op, rhs_ptr);
4824 : 349 : if (res.is_known ())
4825 : 341 : return res;
4826 : : /* Otherwise, only known through constraints. */
4827 : : }
4828 : :
4829 : 177942 : if (const constant_svalue *cst_lhs = lhs->dyn_cast_constant_svalue ())
4830 : : {
4831 : : /* If we have a pair of constants, compare them. */
4832 : 47604 : if (const constant_svalue *cst_rhs = rhs->dyn_cast_constant_svalue ())
4833 : 10523 : return constant_svalue::eval_condition (cst_lhs, op, cst_rhs);
4834 : : else
4835 : : {
4836 : : /* When we have one constant, put it on the RHS. */
4837 : 37081 : std::swap (lhs, rhs);
4838 : 37081 : op = swap_tree_comparison (op);
4839 : : }
4840 : : }
4841 : 167419 : gcc_assert (lhs->get_kind () != SK_CONSTANT);
4842 : :
4843 : : /* Handle comparison against zero. */
4844 : 167419 : if (const constant_svalue *cst_rhs = rhs->dyn_cast_constant_svalue ())
4845 : 138523 : if (zerop (cst_rhs->get_constant ()))
4846 : : {
4847 : 82726 : if (const region_svalue *ptr = lhs->dyn_cast_region_svalue ())
4848 : : {
4849 : : /* A region_svalue is a non-NULL pointer, except in certain
4850 : : special cases (see the comment for region::non_null_p). */
4851 : 12433 : const region *pointee = ptr->get_pointee ();
4852 : 12433 : if (pointee->non_null_p ())
4853 : : {
4854 : 3471 : switch (op)
4855 : : {
4856 : 0 : default:
4857 : 0 : gcc_unreachable ();
4858 : :
4859 : 200 : case EQ_EXPR:
4860 : 200 : case GE_EXPR:
4861 : 200 : case LE_EXPR:
4862 : 200 : return tristate::TS_FALSE;
4863 : :
4864 : 3271 : case NE_EXPR:
4865 : 3271 : case GT_EXPR:
4866 : 3271 : case LT_EXPR:
4867 : 3271 : return tristate::TS_TRUE;
4868 : : }
4869 : : }
4870 : : }
4871 : 70293 : else if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4872 : : {
4873 : : /* Treat offsets from a non-NULL pointer as being non-NULL. This
4874 : : isn't strictly true, in that eventually ptr++ will wrap
4875 : : around and be NULL, but it won't occur in practise and thus
4876 : : can be used to suppress effectively false positives that we
4877 : : shouldn't warn for. */
4878 : 12639 : if (binop->get_op () == POINTER_PLUS_EXPR)
4879 : : {
4880 : 6473 : tristate lhs_ts = eval_condition (binop->get_arg0 (), op, rhs);
4881 : 6473 : if (lhs_ts.is_known ())
4882 : 5180 : return lhs_ts;
4883 : : }
4884 : : }
4885 : 115308 : else if (const unaryop_svalue *unaryop
4886 : 57654 : = lhs->dyn_cast_unaryop_svalue ())
4887 : : {
4888 : 1974 : if (unaryop->get_op () == NEGATE_EXPR)
4889 : : {
4890 : : /* e.g. "-X <= 0" is equivalent to X >= 0". */
4891 : 17 : tristate lhs_ts = eval_condition (unaryop->get_arg (),
4892 : : swap_tree_comparison (op),
4893 : : rhs);
4894 : 17 : if (lhs_ts.is_known ())
4895 : 16 : return lhs_ts;
4896 : : }
4897 : : }
4898 : : }
4899 : :
4900 : : /* Handle rejection of equality for comparisons of the initial values of
4901 : : "external" values (such as params) with the address of locals. */
4902 : 158752 : if (const initial_svalue *init_lhs = lhs->dyn_cast_initial_svalue ())
4903 : 41746 : if (const region_svalue *rhs_ptr = rhs->dyn_cast_region_svalue ())
4904 : : {
4905 : 65 : tristate res = compare_initial_and_pointer (init_lhs, rhs_ptr);
4906 : 65 : if (res.is_known ())
4907 : 0 : return res;
4908 : : }
4909 : 158752 : if (const initial_svalue *init_rhs = rhs->dyn_cast_initial_svalue ())
4910 : 5238 : if (const region_svalue *lhs_ptr = lhs->dyn_cast_region_svalue ())
4911 : : {
4912 : 215 : tristate res = compare_initial_and_pointer (init_rhs, lhs_ptr);
4913 : 215 : if (res.is_known ())
4914 : 32 : return res;
4915 : : }
4916 : :
4917 : 158720 : if (const widening_svalue *widen_lhs = lhs->dyn_cast_widening_svalue ())
4918 : 5244 : if (tree rhs_cst = rhs->maybe_get_constant ())
4919 : : {
4920 : 2966 : tristate res = widen_lhs->eval_condition_without_cm (op, rhs_cst);
4921 : 2966 : if (res.is_known ())
4922 : 105 : return res;
4923 : : }
4924 : :
4925 : : /* Handle comparisons between two svalues with more than one operand. */
4926 : 158615 : if (const binop_svalue *binop = lhs->dyn_cast_binop_svalue ())
4927 : : {
4928 : 26260 : switch (op)
4929 : : {
4930 : : default:
4931 : : break;
4932 : 2705 : case EQ_EXPR:
4933 : 2705 : {
4934 : : /* TODO: binops can be equal even if they are not structurally
4935 : : equal in case of commutative operators. */
4936 : 2705 : tristate res = structural_equality (lhs, rhs);
4937 : 2705 : if (res.is_true ())
4938 : 44 : return res;
4939 : : }
4940 : 2661 : break;
4941 : 892 : case LE_EXPR:
4942 : 892 : {
4943 : 892 : tristate res = structural_equality (lhs, rhs);
4944 : 892 : if (res.is_true ())
4945 : 0 : return res;
4946 : : }
4947 : 892 : break;
4948 : 7810 : case GE_EXPR:
4949 : 7810 : {
4950 : 7810 : tristate res = structural_equality (lhs, rhs);
4951 : 7810 : if (res.is_true ())
4952 : 30 : return res;
4953 : 7780 : res = symbolic_greater_than (binop, rhs);
4954 : 7780 : if (res.is_true ())
4955 : 36 : return res;
4956 : : }
4957 : : break;
4958 : 9209 : case GT_EXPR:
4959 : 9209 : {
4960 : 9209 : tristate res = symbolic_greater_than (binop, rhs);
4961 : 9209 : if (res.is_true ())
4962 : 150 : return res;
4963 : : }
4964 : 9059 : break;
4965 : : }
4966 : : }
4967 : :
4968 : : /* Attempt to unwrap cast if there is one, and the types match. */
4969 : 158355 : tree lhs_type = lhs->get_type ();
4970 : 158355 : tree rhs_type = rhs->get_type ();
4971 : 158355 : if (lhs_type && rhs_type)
4972 : : {
4973 : 100285 : const unaryop_svalue *lhs_un_op = dyn_cast <const unaryop_svalue *> (lhs);
4974 : 100285 : const unaryop_svalue *rhs_un_op = dyn_cast <const unaryop_svalue *> (rhs);
4975 : 2575 : if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
4976 : 2492 : && rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
4977 : 100349 : && lhs_type == rhs_type)
4978 : : {
4979 : 64 : tristate res = eval_condition (lhs_un_op->get_arg (),
4980 : : op,
4981 : : rhs_un_op->get_arg ());
4982 : 64 : if (res.is_known ())
4983 : 0 : return res;
4984 : : }
4985 : 2511 : else if (lhs_un_op && CONVERT_EXPR_CODE_P (lhs_un_op->get_op ())
4986 : 102649 : && lhs_type == rhs_type)
4987 : : {
4988 : 2028 : tristate res = eval_condition (lhs_un_op->get_arg (), op, rhs);
4989 : 2028 : if (res.is_known ())
4990 : 19 : return res;
4991 : : }
4992 : 721 : else if (rhs_un_op && CONVERT_EXPR_CODE_P (rhs_un_op->get_op ())
4993 : 98914 : && lhs_type == rhs_type)
4994 : : {
4995 : 520 : tristate res = eval_condition (lhs, op, rhs_un_op->get_arg ());
4996 : 520 : if (res.is_known ())
4997 : 0 : return res;
4998 : : }
4999 : : }
5000 : :
5001 : : /* Otherwise, try constraints.
5002 : : Cast to const to ensure we don't change the constraint_manager as we
5003 : : do this (e.g. by creating equivalence classes). */
5004 : 158336 : const constraint_manager *constraints = m_constraints;
5005 : 158336 : return constraints->eval_condition (lhs, op, rhs);
5006 : : }
5007 : :
5008 : : /* Subroutine of region_model::eval_condition, for rejecting
5009 : : equality of INIT_VAL(PARM) with &LOCAL. */
5010 : :
5011 : : tristate
5012 : 280 : region_model::compare_initial_and_pointer (const initial_svalue *init,
5013 : : const region_svalue *ptr) const
5014 : : {
5015 : 280 : const region *pointee = ptr->get_pointee ();
5016 : :
5017 : : /* If we have a pointer to something within a stack frame, it can't be the
5018 : : initial value of a param. */
5019 : 280 : if (pointee->maybe_get_frame_region ())
5020 : 32 : if (init->initial_value_of_param_p ())
5021 : 32 : return tristate::TS_FALSE;
5022 : :
5023 : 248 : return tristate::TS_UNKNOWN;
5024 : : }
5025 : :
5026 : : /* Return true if SVAL is definitely positive. */
5027 : :
5028 : : static bool
5029 : 16198 : is_positive_svalue (const svalue *sval)
5030 : : {
5031 : 16198 : if (tree cst = sval->maybe_get_constant ())
5032 : 15782 : return !zerop (cst) && get_range_pos_neg (cst) == 1;
5033 : 416 : tree type = sval->get_type ();
5034 : 416 : if (!type)
5035 : : return false;
5036 : : /* Consider a binary operation size_t + int. The analyzer wraps the int in
5037 : : an unaryop_svalue, converting it to a size_t, but in the dynamic execution
5038 : : the result is smaller than the first operand. Thus, we have to look if
5039 : : the argument of the unaryop_svalue is also positive. */
5040 : 329 : if (const unaryop_svalue *un_op = dyn_cast <const unaryop_svalue *> (sval))
5041 : 19 : return CONVERT_EXPR_CODE_P (un_op->get_op ()) && TYPE_UNSIGNED (type)
5042 : 27 : && is_positive_svalue (un_op->get_arg ());
5043 : 310 : return TYPE_UNSIGNED (type);
5044 : : }
5045 : :
5046 : : /* Return true if A is definitely larger than B.
5047 : :
5048 : : Limitation: does not account for integer overflows and does not try to
5049 : : return false, so it can not be used negated. */
5050 : :
5051 : : tristate
5052 : 16989 : region_model::symbolic_greater_than (const binop_svalue *bin_a,
5053 : : const svalue *b) const
5054 : : {
5055 : 16989 : if (bin_a->get_op () == PLUS_EXPR || bin_a->get_op () == MULT_EXPR)
5056 : : {
5057 : : /* Eliminate the right-hand side of both svalues. */
5058 : 16230 : if (const binop_svalue *bin_b = dyn_cast <const binop_svalue *> (b))
5059 : 3126 : if (bin_a->get_op () == bin_b->get_op ()
5060 : 1699 : && eval_condition (bin_a->get_arg1 (),
5061 : : GT_EXPR,
5062 : 1699 : bin_b->get_arg1 ()).is_true ()
5063 : 4825 : && eval_condition (bin_a->get_arg0 (),
5064 : : GE_EXPR,
5065 : 46 : bin_b->get_arg0 ()).is_true ())
5066 : 40 : return tristate (tristate::TS_TRUE);
5067 : :
5068 : : /* Otherwise, try to remove a positive offset or factor from BIN_A. */
5069 : 16190 : if (is_positive_svalue (bin_a->get_arg1 ())
5070 : 16190 : && eval_condition (bin_a->get_arg0 (),
5071 : 15381 : GE_EXPR, b).is_true ())
5072 : 146 : return tristate (tristate::TS_TRUE);
5073 : : }
5074 : 16803 : return tristate::unknown ();
5075 : : }
5076 : :
5077 : : /* Return true if A and B are equal structurally.
5078 : :
5079 : : Structural equality means that A and B are equal if the svalues A and B have
5080 : : the same nodes at the same positions in the tree and the leafs are equal.
5081 : : Equality for conjured_svalues and initial_svalues is determined by comparing
5082 : : the pointers while constants are compared by value. That behavior is useful
5083 : : to check for binaryop_svlaues that evaluate to the same concrete value but
5084 : : might use one operand with a different type but the same constant value.
5085 : :
5086 : : For example,
5087 : : binop_svalue (mult_expr,
5088 : : initial_svalue (‘size_t’, decl_region (..., 'some_var')),
5089 : : constant_svalue (‘size_t’, 4))
5090 : : and
5091 : : binop_svalue (mult_expr,
5092 : : initial_svalue (‘size_t’, decl_region (..., 'some_var'),
5093 : : constant_svalue (‘sizetype’, 4))
5094 : : are structurally equal. A concrete C code example, where this occurs, can
5095 : : be found in test7 of out-of-bounds-5.c. */
5096 : :
5097 : : tristate
5098 : 14525 : region_model::structural_equality (const svalue *a, const svalue *b) const
5099 : : {
5100 : : /* If A and B are referentially equal, they are also structurally equal. */
5101 : 14525 : if (a == b)
5102 : 393 : return tristate (tristate::TS_TRUE);
5103 : :
5104 : 14132 : switch (a->get_kind ())
5105 : : {
5106 : 1442 : default:
5107 : 1442 : return tristate::unknown ();
5108 : : /* SK_CONJURED and SK_INITIAL are already handled
5109 : : by the referential equality above. */
5110 : 1195 : case SK_CONSTANT:
5111 : 1195 : {
5112 : 1195 : tree a_cst = a->maybe_get_constant ();
5113 : 1195 : tree b_cst = b->maybe_get_constant ();
5114 : 1195 : if (a_cst && b_cst)
5115 : 2284 : return tristate (tree_int_cst_equal (a_cst, b_cst));
5116 : : }
5117 : 40 : return tristate (tristate::TS_FALSE);
5118 : 8 : case SK_UNARYOP:
5119 : 8 : {
5120 : 8 : const unaryop_svalue *un_a = as_a <const unaryop_svalue *> (a);
5121 : 8 : if (const unaryop_svalue *un_b = dyn_cast <const unaryop_svalue *> (b))
5122 : 8 : return tristate (pending_diagnostic::same_tree_p (un_a->get_type (),
5123 : : un_b->get_type ())
5124 : 8 : && un_a->get_op () == un_b->get_op ()
5125 : : && structural_equality (un_a->get_arg (),
5126 : 16 : un_b->get_arg ()));
5127 : : }
5128 : 0 : return tristate (tristate::TS_FALSE);
5129 : 11487 : case SK_BINOP:
5130 : 11487 : {
5131 : 11487 : const binop_svalue *bin_a = as_a <const binop_svalue *> (a);
5132 : 11487 : if (const binop_svalue *bin_b = dyn_cast <const binop_svalue *> (b))
5133 : 1555 : return tristate (bin_a->get_op () == bin_b->get_op ()
5134 : : && structural_equality (bin_a->get_arg0 (),
5135 : 4260 : bin_b->get_arg0 ())
5136 : : && structural_equality (bin_a->get_arg1 (),
5137 : 3110 : bin_b->get_arg1 ()));
5138 : : }
5139 : 9932 : return tristate (tristate::TS_FALSE);
5140 : : }
5141 : : }
5142 : :
5143 : : /* Handle various constraints of the form:
5144 : : LHS: ((bool)INNER_LHS INNER_OP INNER_RHS))
5145 : : OP : == or !=
5146 : : RHS: zero
5147 : : and (with a cast):
5148 : : LHS: CAST([long]int, ((bool)INNER_LHS INNER_OP INNER_RHS))
5149 : : OP : == or !=
5150 : : RHS: zero
5151 : : by adding constraints for INNER_LHS INNEROP INNER_RHS.
5152 : :
5153 : : Return true if this function can fully handle the constraint; if
5154 : : so, add the implied constraint(s) and write true to *OUT if they
5155 : : are consistent with existing constraints, or write false to *OUT
5156 : : if they contradicts existing constraints.
5157 : :
5158 : : Return false for cases that this function doeesn't know how to handle.
5159 : :
5160 : : For example, if we're checking a stored conditional, we'll have
5161 : : something like:
5162 : : LHS: CAST(long int, (&HEAP_ALLOCATED_REGION(8)!=(int *)0B))
5163 : : OP : NE_EXPR
5164 : : RHS: zero
5165 : : which this function can turn into an add_constraint of:
5166 : : (&HEAP_ALLOCATED_REGION(8) != (int *)0B)
5167 : :
5168 : : Similarly, optimized && and || conditionals lead to e.g.
5169 : : if (p && q)
5170 : : becoming gimple like this:
5171 : : _1 = p_6 == 0B;
5172 : : _2 = q_8 == 0B
5173 : : _3 = _1 | _2
5174 : : On the "_3 is false" branch we can have constraints of the form:
5175 : : ((&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
5176 : : | (&HEAP_ALLOCATED_REGION(10)!=(int *)0B))
5177 : : == 0
5178 : : which implies that both _1 and _2 are false,
5179 : : which this function can turn into a pair of add_constraints of
5180 : : (&HEAP_ALLOCATED_REGION(8)!=(int *)0B)
5181 : : and:
5182 : : (&HEAP_ALLOCATED_REGION(10)!=(int *)0B). */
5183 : :
5184 : : bool
5185 : 50669 : region_model::add_constraints_from_binop (const svalue *outer_lhs,
5186 : : enum tree_code outer_op,
5187 : : const svalue *outer_rhs,
5188 : : bool *out,
5189 : : region_model_context *ctxt)
5190 : : {
5191 : 52015 : while (const svalue *cast = outer_lhs->maybe_undo_cast ())
5192 : : outer_lhs = cast;
5193 : 50669 : const binop_svalue *binop_sval = outer_lhs->dyn_cast_binop_svalue ();
5194 : 50669 : if (!binop_sval)
5195 : : return false;
5196 : 6492 : if (!outer_rhs->all_zeroes_p ())
5197 : : return false;
5198 : :
5199 : 4661 : const svalue *inner_lhs = binop_sval->get_arg0 ();
5200 : 4661 : enum tree_code inner_op = binop_sval->get_op ();
5201 : 4661 : const svalue *inner_rhs = binop_sval->get_arg1 ();
5202 : :
5203 : 4661 : if (outer_op != NE_EXPR && outer_op != EQ_EXPR)
5204 : : return false;
5205 : :
5206 : : /* We have either
5207 : : - "OUTER_LHS != false" (i.e. OUTER is true), or
5208 : : - "OUTER_LHS == false" (i.e. OUTER is false). */
5209 : 4125 : bool is_true = outer_op == NE_EXPR;
5210 : :
5211 : 4125 : switch (inner_op)
5212 : : {
5213 : : default:
5214 : : return false;
5215 : :
5216 : 2563 : case EQ_EXPR:
5217 : 2563 : case NE_EXPR:
5218 : 2563 : case GE_EXPR:
5219 : 2563 : case GT_EXPR:
5220 : 2563 : case LE_EXPR:
5221 : 2563 : case LT_EXPR:
5222 : 2563 : {
5223 : : /* ...and "(inner_lhs OP inner_rhs) == 0"
5224 : : then (inner_lhs OP inner_rhs) must have the same
5225 : : logical value as LHS. */
5226 : 2563 : if (!is_true)
5227 : 1324 : inner_op = invert_tree_comparison (inner_op, false /* honor_nans */);
5228 : 2563 : *out = add_constraint (inner_lhs, inner_op, inner_rhs, ctxt);
5229 : 2563 : return true;
5230 : : }
5231 : 1013 : break;
5232 : :
5233 : 1013 : case BIT_AND_EXPR:
5234 : 1013 : if (is_true)
5235 : : {
5236 : : /* ...and "(inner_lhs & inner_rhs) != 0"
5237 : : then both inner_lhs and inner_rhs must be true. */
5238 : 497 : const svalue *false_sval
5239 : 497 : = m_mgr->get_or_create_constant_svalue (boolean_false_node);
5240 : 497 : bool sat1 = add_constraint (inner_lhs, NE_EXPR, false_sval, ctxt);
5241 : 497 : bool sat2 = add_constraint (inner_rhs, NE_EXPR, false_sval, ctxt);
5242 : 497 : *out = sat1 && sat2;
5243 : 497 : return true;
5244 : : }
5245 : : return false;
5246 : :
5247 : 117 : case BIT_IOR_EXPR:
5248 : 117 : if (!is_true)
5249 : : {
5250 : : /* ...and "(inner_lhs | inner_rhs) == 0"
5251 : : i.e. "(inner_lhs | inner_rhs)" is false
5252 : : then both inner_lhs and inner_rhs must be false. */
5253 : 64 : const svalue *false_sval
5254 : 64 : = m_mgr->get_or_create_constant_svalue (boolean_false_node);
5255 : 64 : bool sat1 = add_constraint (inner_lhs, EQ_EXPR, false_sval, ctxt);
5256 : 64 : bool sat2 = add_constraint (inner_rhs, EQ_EXPR, false_sval, ctxt);
5257 : 64 : *out = sat1 && sat2;
5258 : 64 : return true;
5259 : : }
5260 : : return false;
5261 : : }
5262 : : }
5263 : :
5264 : : /* Attempt to add the constraint "LHS OP RHS" to this region_model.
5265 : : If it is consistent with existing constraints, add it, and return true.
5266 : : Return false if it contradicts existing constraints.
5267 : : Use CTXT for reporting any diagnostics associated with the accesses. */
5268 : :
5269 : : bool
5270 : 64920 : region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
5271 : : region_model_context *ctxt)
5272 : : {
5273 : : /* For now, make no attempt to capture constraints on floating-point
5274 : : values. */
5275 : 64920 : if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
5276 : : return true;
5277 : :
5278 : 64554 : const svalue *lhs_sval = get_rvalue (lhs, ctxt);
5279 : 64554 : const svalue *rhs_sval = get_rvalue (rhs, ctxt);
5280 : :
5281 : 64554 : return add_constraint (lhs_sval, op, rhs_sval, ctxt);
5282 : : }
5283 : :
5284 : : static bool
5285 : 9501 : unusable_in_infinite_loop_constraint_p (const svalue *sval)
5286 : : {
5287 : 9501 : if (sval->get_kind () == SK_WIDENING)
5288 : 0 : return true;
5289 : : return false;
5290 : : }
5291 : :
5292 : : /* Attempt to add the constraint "LHS OP RHS" to this region_model.
5293 : : If it is consistent with existing constraints, add it, and return true.
5294 : : Return false if it contradicts existing constraints.
5295 : : Use CTXT for reporting any diagnostics associated with the accesses. */
5296 : :
5297 : : bool
5298 : 72610 : region_model::add_constraint (const svalue *lhs,
5299 : : enum tree_code op,
5300 : : const svalue *rhs,
5301 : : region_model_context *ctxt)
5302 : : {
5303 : 72610 : const bool checking_for_infinite_loop
5304 : 72610 : = ctxt ? ctxt->checking_for_infinite_loop_p () : false;
5305 : :
5306 : 4868 : if (checking_for_infinite_loop)
5307 : : {
5308 : 9501 : if (unusable_in_infinite_loop_constraint_p (lhs)
5309 : 72610 : || unusable_in_infinite_loop_constraint_p (rhs))
5310 : : {
5311 : 236 : gcc_assert (ctxt);
5312 : 236 : ctxt->on_unusable_in_infinite_loop ();
5313 : 236 : return false;
5314 : : }
5315 : : }
5316 : :
5317 : 72374 : tristate t_cond = eval_condition (lhs, op, rhs);
5318 : :
5319 : : /* If we already have the condition, do nothing. */
5320 : 72374 : if (t_cond.is_true ())
5321 : : return true;
5322 : :
5323 : : /* Reject a constraint that would contradict existing knowledge, as
5324 : : unsatisfiable. */
5325 : 61971 : if (t_cond.is_false ())
5326 : : return false;
5327 : :
5328 : 53709 : if (checking_for_infinite_loop)
5329 : : {
5330 : : /* Here, we don't have a definite true/false value, so bail out
5331 : : when checking for infinite loops. */
5332 : 3040 : gcc_assert (ctxt);
5333 : 3040 : ctxt->on_unusable_in_infinite_loop ();
5334 : 3040 : return false;
5335 : : }
5336 : :
5337 : 50669 : bool out;
5338 : 50669 : if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt))
5339 : 3124 : return out;
5340 : :
5341 : : /* Attempt to store the constraint. */
5342 : 47545 : if (!m_constraints->add_constraint (lhs, op, rhs))
5343 : : return false;
5344 : :
5345 : : /* Notify the context, if any. This exists so that the state machines
5346 : : in a program_state can be notified about the condition, and so can
5347 : : set sm-state for e.g. unchecked->checked, both for cfg-edges, and
5348 : : when synthesizing constraints as above. */
5349 : 47461 : if (ctxt)
5350 : 30160 : ctxt->on_condition (lhs, op, rhs);
5351 : :
5352 : : /* If we have ®ION == NULL, then drop dynamic extents for REGION (for
5353 : : the case where REGION is heap-allocated and thus could be NULL). */
5354 : 47461 : if (tree rhs_cst = rhs->maybe_get_constant ())
5355 : 39892 : if (op == EQ_EXPR && zerop (rhs_cst))
5356 : 12132 : if (const region_svalue *region_sval = lhs->dyn_cast_region_svalue ())
5357 : 1374 : unset_dynamic_extents (region_sval->get_pointee ());
5358 : :
5359 : : return true;
5360 : : }
5361 : :
5362 : : /* As above, but when returning false, if OUT is non-NULL, write a
5363 : : new rejected_constraint to *OUT. */
5364 : :
5365 : : bool
5366 : 63780 : region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
5367 : : region_model_context *ctxt,
5368 : : std::unique_ptr<rejected_constraint> *out)
5369 : : {
5370 : 63780 : bool sat = add_constraint (lhs, op, rhs, ctxt);
5371 : 63780 : if (!sat && out)
5372 : 1916 : *out = make_unique <rejected_op_constraint> (*this, lhs, op, rhs);
5373 : 63780 : return sat;
5374 : : }
5375 : :
5376 : : /* Determine what is known about the condition "LHS OP RHS" within
5377 : : this model.
5378 : : Use CTXT for reporting any diagnostics associated with the accesses. */
5379 : :
5380 : : tristate
5381 : 31732 : region_model::eval_condition (tree lhs,
5382 : : enum tree_code op,
5383 : : tree rhs,
5384 : : region_model_context *ctxt) const
5385 : : {
5386 : : /* For now, make no attempt to model constraints on floating-point
5387 : : values. */
5388 : 31732 : if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
5389 : 16 : return tristate::unknown ();
5390 : :
5391 : 31716 : return eval_condition (get_rvalue (lhs, ctxt), op, get_rvalue (rhs, ctxt));
5392 : : }
5393 : :
5394 : : /* Implementation of region_model::get_representative_path_var.
5395 : : Attempt to return a path_var that represents SVAL, or return NULL_TREE.
5396 : : Use VISITED to prevent infinite mutual recursion with the overload for
5397 : : regions. */
5398 : :
5399 : : path_var
5400 : 14625 : region_model::get_representative_path_var_1 (const svalue *sval,
5401 : : svalue_set *visited,
5402 : : logger *logger) const
5403 : : {
5404 : 14625 : gcc_assert (sval);
5405 : :
5406 : : /* Prevent infinite recursion. */
5407 : 14625 : if (visited->contains (sval))
5408 : : {
5409 : 22 : if (sval->get_kind () == SK_CONSTANT)
5410 : 22 : return path_var (sval->maybe_get_constant (), 0);
5411 : : else
5412 : 0 : return path_var (NULL_TREE, 0);
5413 : : }
5414 : 14603 : visited->add (sval);
5415 : :
5416 : : /* Handle casts by recursion into get_representative_path_var. */
5417 : 14603 : if (const svalue *cast_sval = sval->maybe_undo_cast ())
5418 : : {
5419 : 436 : path_var result = get_representative_path_var (cast_sval, visited,
5420 : : logger);
5421 : 436 : tree orig_type = sval->get_type ();
5422 : : /* If necessary, wrap the result in a cast. */
5423 : 436 : if (result.m_tree && orig_type)
5424 : 349 : result.m_tree = build1 (NOP_EXPR, orig_type, result.m_tree);
5425 : 436 : return result;
5426 : : }
5427 : :
5428 : 14167 : auto_vec<path_var> pvs;
5429 : 14167 : m_store.get_representative_path_vars (this, visited, sval, logger, &pvs);
5430 : :
5431 : 14167 : if (tree cst = sval->maybe_get_constant ())
5432 : 2052 : pvs.safe_push (path_var (cst, 0));
5433 : :
5434 : : /* Handle string literals and various other pointers. */
5435 : 14167 : if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
5436 : : {
5437 : 4760 : const region *reg = ptr_sval->get_pointee ();
5438 : 4760 : if (path_var pv = get_representative_path_var (reg, visited, logger))
5439 : 30 : return path_var (build1 (ADDR_EXPR,
5440 : : sval->get_type (),
5441 : : pv.m_tree),
5442 : 30 : pv.m_stack_depth);
5443 : : }
5444 : :
5445 : : /* If we have a sub_svalue, look for ways to represent the parent. */
5446 : 14137 : if (const sub_svalue *sub_sval = sval->dyn_cast_sub_svalue ())
5447 : : {
5448 : 647 : const svalue *parent_sval = sub_sval->get_parent ();
5449 : 647 : const region *subreg = sub_sval->get_subregion ();
5450 : 1294 : if (path_var parent_pv
5451 : 647 : = get_representative_path_var (parent_sval, visited, logger))
5452 : 214 : if (const field_region *field_reg = subreg->dyn_cast_field_region ())
5453 : 156 : return path_var (build3 (COMPONENT_REF,
5454 : : sval->get_type (),
5455 : : parent_pv.m_tree,
5456 : : field_reg->get_field (),
5457 : : NULL_TREE),
5458 : 156 : parent_pv.m_stack_depth);
5459 : : }
5460 : :
5461 : : /* Handle binops. */
5462 : 13981 : if (const binop_svalue *binop_sval = sval->dyn_cast_binop_svalue ())
5463 : 615 : if (path_var lhs_pv
5464 : 615 : = get_representative_path_var (binop_sval->get_arg0 (), visited,
5465 : 615 : logger))
5466 : 530 : if (path_var rhs_pv
5467 : 530 : = get_representative_path_var (binop_sval->get_arg1 (), visited,
5468 : 530 : logger))
5469 : 484 : return path_var (build2 (binop_sval->get_op (),
5470 : : sval->get_type (),
5471 : : lhs_pv.m_tree, rhs_pv.m_tree),
5472 : 484 : lhs_pv.m_stack_depth);
5473 : :
5474 : 13497 : if (pvs.length () < 1)
5475 : 2690 : return path_var (NULL_TREE, 0);
5476 : :
5477 : 10807 : pvs.qsort (readability_comparator);
5478 : 10807 : return pvs[0];
5479 : 14167 : }
5480 : :
5481 : : /* Attempt to return a path_var that represents SVAL, or return NULL_TREE.
5482 : : Use VISITED to prevent infinite mutual recursion with the overload for
5483 : : regions
5484 : :
5485 : : This function defers to get_representative_path_var_1 to do the work;
5486 : : it adds verification that get_representative_path_var_1 returned a tree
5487 : : of the correct type. */
5488 : :
5489 : : path_var
5490 : 20071 : region_model::get_representative_path_var (const svalue *sval,
5491 : : svalue_set *visited,
5492 : : logger *logger) const
5493 : : {
5494 : 20071 : if (sval == NULL)
5495 : 5446 : return path_var (NULL_TREE, 0);
5496 : :
5497 : 14625 : LOG_SCOPE (logger);
5498 : 14625 : if (logger)
5499 : : {
5500 : 0 : logger->start_log_line ();
5501 : 0 : logger->log_partial ("sval: ");
5502 : 0 : sval->dump_to_pp (logger->get_printer (), true);
5503 : 0 : logger->end_log_line ();
5504 : : }
5505 : :
5506 : 14625 : tree orig_type = sval->get_type ();
5507 : :
5508 : 14625 : path_var result = get_representative_path_var_1 (sval, visited, logger);
5509 : :
5510 : : /* Verify that the result has the same type as SVAL, if any. */
5511 : 14625 : if (result.m_tree && orig_type)
5512 : 11768 : gcc_assert (TREE_TYPE (result.m_tree) == orig_type);
5513 : :
5514 : 14625 : if (logger)
5515 : : {
5516 : 0 : logger->start_log_line ();
5517 : 0 : logger->log_partial ("sval: ");
5518 : 0 : sval->dump_to_pp (logger->get_printer (), true);
5519 : 0 : logger->end_log_line ();
5520 : :
5521 : 0 : if (result.m_tree)
5522 : 0 : logger->log ("tree: %qE", result.m_tree);
5523 : : else
5524 : 0 : logger->log ("tree: NULL");
5525 : : }
5526 : :
5527 : 14625 : return result;
5528 : 14625 : }
5529 : :
5530 : : /* Attempt to return a tree that represents SVAL, or return NULL_TREE.
5531 : :
5532 : : Strip off any top-level cast, to avoid messages like
5533 : : double-free of '(void *)ptr'
5534 : : from analyzer diagnostics. */
5535 : :
5536 : : tree
5537 : 15244 : region_model::get_representative_tree (const svalue *sval, logger *logger) const
5538 : : {
5539 : 15244 : svalue_set visited;
5540 : 15244 : tree expr = get_representative_path_var (sval, &visited, logger).m_tree;
5541 : :
5542 : : /* Strip off any top-level cast. */
5543 : 15244 : if (expr && TREE_CODE (expr) == NOP_EXPR)
5544 : 431 : expr = TREE_OPERAND (expr, 0);
5545 : :
5546 : 15244 : return fixup_tree_for_diagnostic (expr);
5547 : 15244 : }
5548 : :
5549 : : tree
5550 : 745 : region_model::get_representative_tree (const region *reg, logger *logger) const
5551 : : {
5552 : 745 : svalue_set visited;
5553 : 745 : tree expr = get_representative_path_var (reg, &visited, logger).m_tree;
5554 : :
5555 : : /* Strip off any top-level cast. */
5556 : 745 : if (expr && TREE_CODE (expr) == NOP_EXPR)
5557 : 0 : expr = TREE_OPERAND (expr, 0);
5558 : :
5559 : 745 : return fixup_tree_for_diagnostic (expr);
5560 : 745 : }
5561 : :
5562 : : /* Implementation of region_model::get_representative_path_var.
5563 : :
5564 : : Attempt to return a path_var that represents REG, or return
5565 : : the NULL path_var.
5566 : : For example, a region for a field of a local would be a path_var
5567 : : wrapping a COMPONENT_REF.
5568 : : Use VISITED to prevent infinite mutual recursion with the overload for
5569 : : svalues. */
5570 : :
5571 : : path_var
5572 : 17769 : region_model::get_representative_path_var_1 (const region *reg,
5573 : : svalue_set *visited,
5574 : : logger *logger) const
5575 : : {
5576 : 17769 : switch (reg->get_kind ())
5577 : : {
5578 : 0 : default:
5579 : 0 : gcc_unreachable ();
5580 : :
5581 : 0 : case RK_FRAME:
5582 : 0 : case RK_GLOBALS:
5583 : 0 : case RK_CODE:
5584 : 0 : case RK_HEAP:
5585 : 0 : case RK_STACK:
5586 : 0 : case RK_THREAD_LOCAL:
5587 : 0 : case RK_ROOT:
5588 : : /* Regions that represent memory spaces are not expressible as trees. */
5589 : 0 : return path_var (NULL_TREE, 0);
5590 : :
5591 : 1 : case RK_FUNCTION:
5592 : 1 : {
5593 : 1 : const function_region *function_reg
5594 : 1 : = as_a <const function_region *> (reg);
5595 : 1 : return path_var (function_reg->get_fndecl (), 0);
5596 : : }
5597 : 1 : case RK_LABEL:
5598 : 1 : {
5599 : 1 : const label_region *label_reg = as_a <const label_region *> (reg);
5600 : 1 : return path_var (label_reg->get_label (), 0);
5601 : : }
5602 : :
5603 : 400 : case RK_SYMBOLIC:
5604 : 400 : {
5605 : 400 : const symbolic_region *symbolic_reg
5606 : 400 : = as_a <const symbolic_region *> (reg);
5607 : 400 : const svalue *pointer = symbolic_reg->get_pointer ();
5608 : 400 : path_var pointer_pv = get_representative_path_var (pointer, visited,
5609 : : logger);
5610 : 400 : if (!pointer_pv)
5611 : 20 : return path_var (NULL_TREE, 0);
5612 : 380 : tree offset = build_int_cst (pointer->get_type (), 0);
5613 : 380 : return path_var (build2 (MEM_REF,
5614 : : reg->get_type (),
5615 : : pointer_pv.m_tree,
5616 : : offset),
5617 : 380 : pointer_pv.m_stack_depth);
5618 : : }
5619 : 11078 : case RK_DECL:
5620 : 11078 : {
5621 : 11078 : const decl_region *decl_reg = as_a <const decl_region *> (reg);
5622 : 11078 : return path_var (decl_reg->get_decl (), decl_reg->get_stack_depth ());
5623 : : }
5624 : 960 : case RK_FIELD:
5625 : 960 : {
5626 : 960 : const field_region *field_reg = as_a <const field_region *> (reg);
5627 : 960 : path_var parent_pv
5628 : 960 : = get_representative_path_var (reg->get_parent_region (), visited,
5629 : : logger);
5630 : 960 : if (!parent_pv)
5631 : 54 : return path_var (NULL_TREE, 0);
5632 : 906 : return path_var (build3 (COMPONENT_REF,
5633 : : reg->get_type (),
5634 : : parent_pv.m_tree,
5635 : : field_reg->get_field (),
5636 : : NULL_TREE),
5637 : 906 : parent_pv.m_stack_depth);
5638 : : }
5639 : :
5640 : 240 : case RK_ELEMENT:
5641 : 240 : {
5642 : 240 : const element_region *element_reg
5643 : 240 : = as_a <const element_region *> (reg);
5644 : 240 : path_var parent_pv
5645 : 240 : = get_representative_path_var (reg->get_parent_region (), visited,
5646 : : logger);
5647 : 240 : if (!parent_pv)
5648 : 0 : return path_var (NULL_TREE, 0);
5649 : 240 : path_var index_pv
5650 : 240 : = get_representative_path_var (element_reg->get_index (), visited,
5651 : : logger);
5652 : 240 : if (!index_pv)
5653 : 0 : return path_var (NULL_TREE, 0);
5654 : 240 : return path_var (build4 (ARRAY_REF,
5655 : : reg->get_type (),
5656 : : parent_pv.m_tree, index_pv.m_tree,
5657 : : NULL_TREE, NULL_TREE),
5658 : 240 : parent_pv.m_stack_depth);
5659 : : }
5660 : :
5661 : 109 : case RK_OFFSET:
5662 : 109 : {
5663 : 109 : const offset_region *offset_reg
5664 : 109 : = as_a <const offset_region *> (reg);
5665 : 109 : path_var parent_pv
5666 : 109 : = get_representative_path_var (reg->get_parent_region (), visited,
5667 : : logger);
5668 : 109 : if (!parent_pv)
5669 : 0 : return path_var (NULL_TREE, 0);
5670 : 109 : path_var offset_pv
5671 : 109 : = get_representative_path_var (offset_reg->get_byte_offset (),
5672 : : visited, logger);
5673 : 109 : if (!offset_pv || TREE_CODE (offset_pv.m_tree) != INTEGER_CST)
5674 : 66 : return path_var (NULL_TREE, 0);
5675 : 43 : tree addr_parent = build1 (ADDR_EXPR,
5676 : : build_pointer_type (reg->get_type ()),
5677 : : parent_pv.m_tree);
5678 : 43 : tree ptype = build_pointer_type_for_mode (char_type_node, ptr_mode,
5679 : : true);
5680 : 43 : return path_var (build2 (MEM_REF, reg->get_type (), addr_parent,
5681 : : fold_convert (ptype, offset_pv.m_tree)),
5682 : 43 : parent_pv.m_stack_depth);
5683 : : }
5684 : :
5685 : 56 : case RK_SIZED:
5686 : 56 : return path_var (NULL_TREE, 0);
5687 : :
5688 : 6 : case RK_CAST:
5689 : 6 : {
5690 : 6 : path_var parent_pv
5691 : 6 : = get_representative_path_var (reg->get_parent_region (), visited,
5692 : : logger);
5693 : 6 : if (!parent_pv)
5694 : 0 : return path_var (NULL_TREE, 0);
5695 : 6 : return path_var (build1 (NOP_EXPR,
5696 : : reg->get_type (),
5697 : : parent_pv.m_tree),
5698 : 6 : parent_pv.m_stack_depth);
5699 : : }
5700 : :
5701 : 4904 : case RK_HEAP_ALLOCATED:
5702 : 4904 : case RK_ALLOCA:
5703 : : /* No good way to express heap-allocated/alloca regions as trees. */
5704 : 4904 : return path_var (NULL_TREE, 0);
5705 : :
5706 : 10 : case RK_STRING:
5707 : 10 : {
5708 : 10 : const string_region *string_reg = as_a <const string_region *> (reg);
5709 : 10 : return path_var (string_reg->get_string_cst (), 0);
5710 : : }
5711 : :
5712 : 4 : case RK_VAR_ARG:
5713 : 4 : case RK_ERRNO:
5714 : 4 : case RK_UNKNOWN:
5715 : 4 : case RK_PRIVATE:
5716 : 4 : return path_var (NULL_TREE, 0);
5717 : : }
5718 : : }
5719 : :
5720 : : /* Attempt to return a path_var that represents REG, or return
5721 : : the NULL path_var.
5722 : : For example, a region for a field of a local would be a path_var
5723 : : wrapping a COMPONENT_REF.
5724 : : Use VISITED to prevent infinite mutual recursion with the overload for
5725 : : svalues.
5726 : :
5727 : : This function defers to get_representative_path_var_1 to do the work;
5728 : : it adds verification that get_representative_path_var_1 returned a tree
5729 : : of the correct type. */
5730 : :
5731 : : path_var
5732 : 17769 : region_model::get_representative_path_var (const region *reg,
5733 : : svalue_set *visited,
5734 : : logger *logger) const
5735 : : {
5736 : 17769 : LOG_SCOPE (logger);
5737 : 17769 : if (logger)
5738 : : {
5739 : 0 : logger->start_log_line ();
5740 : 0 : logger->log_partial ("reg: ");
5741 : 0 : reg->dump_to_pp (logger->get_printer (), true);
5742 : 0 : logger->end_log_line ();
5743 : : }
5744 : :
5745 : 17769 : path_var result = get_representative_path_var_1 (reg, visited, logger);
5746 : :
5747 : : /* Verify that the result has the same type as REG, if any. */
5748 : 17769 : if (result.m_tree && reg->get_type ())
5749 : 12664 : gcc_assert (TREE_TYPE (result.m_tree) == reg->get_type ());
5750 : :
5751 : 17769 : if (logger)
5752 : : {
5753 : 0 : logger->start_log_line ();
5754 : 0 : logger->log_partial ("reg: ");
5755 : 0 : reg->dump_to_pp (logger->get_printer (), true);
5756 : 0 : logger->end_log_line ();
5757 : :
5758 : 0 : if (result.m_tree)
5759 : 0 : logger->log ("tree: %qE", result.m_tree);
5760 : : else
5761 : 0 : logger->log ("tree: NULL");
5762 : : }
5763 : :
5764 : 35538 : return result;
5765 : 17769 : }
5766 : :
5767 : : /* Update this model for any phis in SNODE, assuming we came from
5768 : : LAST_CFG_SUPEREDGE. */
5769 : :
5770 : : void
5771 : 150389 : region_model::update_for_phis (const supernode *snode,
5772 : : const cfg_superedge *last_cfg_superedge,
5773 : : region_model_context *ctxt)
5774 : : {
5775 : 150389 : gcc_assert (last_cfg_superedge);
5776 : :
5777 : : /* Copy this state and pass it to handle_phi so that all of the phi stmts
5778 : : are effectively handled simultaneously. */
5779 : 150389 : const region_model old_state (*this);
5780 : :
5781 : 150389 : hash_set<const svalue *> svals_changing_meaning;
5782 : :
5783 : 150389 : for (gphi_iterator gpi = const_cast<supernode *>(snode)->start_phis ();
5784 : 227035 : !gsi_end_p (gpi); gsi_next (&gpi))
5785 : : {
5786 : 76646 : gphi *phi = gpi.phi ();
5787 : :
5788 : 76646 : tree src = last_cfg_superedge->get_phi_arg (phi);
5789 : 76646 : tree lhs = gimple_phi_result (phi);
5790 : :
5791 : : /* Update next_state based on phi and old_state. */
5792 : 76646 : handle_phi (phi, lhs, src, old_state, svals_changing_meaning, ctxt);
5793 : : }
5794 : :
5795 : 302438 : for (auto iter : svals_changing_meaning)
5796 : 1660 : m_constraints->purge_state_involving (iter);
5797 : 150389 : }
5798 : :
5799 : : /* Attempt to update this model for taking EDGE (where the last statement
5800 : : was LAST_STMT), returning true if the edge can be taken, false
5801 : : otherwise.
5802 : : When returning false, if OUT is non-NULL, write a new rejected_constraint
5803 : : to it.
5804 : :
5805 : : For CFG superedges where LAST_STMT is a conditional or a switch
5806 : : statement, attempt to add the relevant conditions for EDGE to this
5807 : : model, returning true if they are feasible, or false if they are
5808 : : impossible.
5809 : :
5810 : : For call superedges, push frame information and store arguments
5811 : : into parameters.
5812 : :
5813 : : For return superedges, pop frame information and store return
5814 : : values into any lhs.
5815 : :
5816 : : Rejection of call/return superedges happens elsewhere, in
5817 : : program_point::on_edge (i.e. based on program point, rather
5818 : : than program state). */
5819 : :
5820 : : bool
5821 : 180624 : region_model::maybe_update_for_edge (const superedge &edge,
5822 : : const gimple *last_stmt,
5823 : : region_model_context *ctxt,
5824 : : std::unique_ptr<rejected_constraint> *out)
5825 : : {
5826 : : /* Handle frame updates for interprocedural edges. */
5827 : 180624 : switch (edge.m_kind)
5828 : : {
5829 : : default:
5830 : : break;
5831 : :
5832 : 9350 : case SUPEREDGE_CALL:
5833 : 9350 : {
5834 : 9350 : const call_superedge *call_edge = as_a <const call_superedge *> (&edge);
5835 : 9350 : update_for_call_superedge (*call_edge, ctxt);
5836 : : }
5837 : 9350 : break;
5838 : :
5839 : 7094 : case SUPEREDGE_RETURN:
5840 : 7094 : {
5841 : 7094 : const return_superedge *return_edge
5842 : 7094 : = as_a <const return_superedge *> (&edge);
5843 : 7094 : update_for_return_superedge (*return_edge, ctxt);
5844 : : }
5845 : 7094 : break;
5846 : :
5847 : : case SUPEREDGE_INTRAPROCEDURAL_CALL:
5848 : : /* This is a no-op for call summaries; we should already
5849 : : have handled the effect of the call summary at the call stmt. */
5850 : : break;
5851 : : }
5852 : :
5853 : 180624 : if (last_stmt == NULL)
5854 : : return true;
5855 : :
5856 : : /* Apply any constraints for conditionals/switch/computed-goto statements. */
5857 : :
5858 : 143652 : if (const gcond *cond_stmt = dyn_cast <const gcond *> (last_stmt))
5859 : : {
5860 : 63768 : const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (&edge);
5861 : 63768 : return apply_constraints_for_gcond (*cfg_sedge, cond_stmt, ctxt, out);
5862 : : }
5863 : :
5864 : 79884 : if (const gswitch *switch_stmt = dyn_cast <const gswitch *> (last_stmt))
5865 : : {
5866 : 8062 : const switch_cfg_superedge *switch_sedge
5867 : 8062 : = as_a <const switch_cfg_superedge *> (&edge);
5868 : 8062 : return apply_constraints_for_gswitch (*switch_sedge, switch_stmt,
5869 : 8062 : ctxt, out);
5870 : : }
5871 : :
5872 : 71822 : if (const ggoto *goto_stmt = dyn_cast <const ggoto *> (last_stmt))
5873 : : {
5874 : 79 : const cfg_superedge *cfg_sedge = as_a <const cfg_superedge *> (&edge);
5875 : 79 : return apply_constraints_for_ggoto (*cfg_sedge, goto_stmt, ctxt);
5876 : : }
5877 : :
5878 : : /* Apply any constraints due to an exception being thrown. */
5879 : 71743 : if (const cfg_superedge *cfg_sedge = dyn_cast <const cfg_superedge *> (&edge))
5880 : 60840 : if (cfg_sedge->get_flags () & EDGE_EH)
5881 : 2497 : return apply_constraints_for_exception (last_stmt, ctxt, out);
5882 : :
5883 : : return true;
5884 : : }
5885 : :
5886 : : /* Push a new frame_region on to the stack region.
5887 : : Populate the frame_region with child regions for the function call's
5888 : : parameters, using values from the arguments at the callsite in the
5889 : : caller's frame. */
5890 : :
5891 : : void
5892 : 9590 : region_model::update_for_gcall (const gcall *call_stmt,
5893 : : region_model_context *ctxt,
5894 : : function *callee)
5895 : : {
5896 : : /* Build a vec of argument svalues, using the current top
5897 : : frame for resolving tree expressions. */
5898 : 9590 : auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt));
5899 : :
5900 : 20176 : for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
5901 : : {
5902 : 10586 : tree arg = gimple_call_arg (call_stmt, i);
5903 : 10586 : arg_svals.quick_push (get_rvalue (arg, ctxt));
5904 : : }
5905 : :
5906 : 9590 : if(!callee)
5907 : : {
5908 : : /* Get the function * from the gcall. */
5909 : 77 : tree fn_decl = get_fndecl_for_call (call_stmt,ctxt);
5910 : 77 : callee = DECL_STRUCT_FUNCTION (fn_decl);
5911 : : }
5912 : :
5913 : 77 : gcc_assert (callee);
5914 : 9590 : push_frame (*callee, &arg_svals, ctxt);
5915 : 9590 : }
5916 : :
5917 : : /* Pop the top-most frame_region from the stack, and copy the return
5918 : : region's values (if any) into the region for the lvalue of the LHS of
5919 : : the call (if any). */
5920 : :
5921 : : void
5922 : 7302 : region_model::update_for_return_gcall (const gcall *call_stmt,
5923 : : region_model_context *ctxt)
5924 : : {
5925 : : /* Get the lvalue for the result of the call, passing it to pop_frame,
5926 : : so that pop_frame can determine the region with respect to the
5927 : : *caller* frame. */
5928 : 7302 : tree lhs = gimple_call_lhs (call_stmt);
5929 : 7302 : pop_frame (lhs, NULL, ctxt, call_stmt);
5930 : 7302 : }
5931 : :
5932 : : /* Extract calling information from the superedge and update the model for the
5933 : : call */
5934 : :
5935 : : void
5936 : 9350 : region_model::update_for_call_superedge (const call_superedge &call_edge,
5937 : : region_model_context *ctxt)
5938 : : {
5939 : 9350 : const gcall *call_stmt = call_edge.get_call_stmt ();
5940 : 9350 : update_for_gcall (call_stmt, ctxt, call_edge.get_callee_function ());
5941 : 9350 : }
5942 : :
5943 : : /* Extract calling information from the return superedge and update the model
5944 : : for the returning call */
5945 : :
5946 : : void
5947 : 7094 : region_model::update_for_return_superedge (const return_superedge &return_edge,
5948 : : region_model_context *ctxt)
5949 : : {
5950 : 7094 : const gcall *call_stmt = return_edge.get_call_stmt ();
5951 : 7094 : update_for_return_gcall (call_stmt, ctxt);
5952 : 7094 : }
5953 : :
5954 : : /* Attempt to use R to replay SUMMARY into this object.
5955 : : Return true if it is possible. */
5956 : :
5957 : : bool
5958 : 1598 : region_model::replay_call_summary (call_summary_replay &r,
5959 : : const region_model &summary)
5960 : : {
5961 : 1598 : gcc_assert (summary.get_stack_depth () == 1);
5962 : :
5963 : 1598 : m_store.replay_call_summary (r, summary.m_store);
5964 : :
5965 : 1598 : if (r.get_ctxt ())
5966 : 1487 : r.get_ctxt ()->maybe_did_work ();
5967 : :
5968 : 1598 : if (!m_constraints->replay_call_summary (r, *summary.m_constraints))
5969 : : return false;
5970 : :
5971 : 6007 : for (auto kv : summary.m_dynamic_extents)
5972 : : {
5973 : 2247 : const region *summary_reg = kv.first;
5974 : 2247 : const region *caller_reg = r.convert_region_from_summary (summary_reg);
5975 : 2247 : if (!caller_reg)
5976 : 2 : continue;
5977 : 2245 : const svalue *summary_sval = kv.second;
5978 : 2245 : const svalue *caller_sval = r.convert_svalue_from_summary (summary_sval);
5979 : 2245 : if (!caller_sval)
5980 : 0 : continue;
5981 : 2245 : m_dynamic_extents.put (caller_reg, caller_sval);
5982 : : }
5983 : :
5984 : 1513 : return true;
5985 : : }
5986 : :
5987 : : /* Given a true or false edge guarded by conditional statement COND_STMT,
5988 : : determine appropriate constraints for the edge to be taken.
5989 : :
5990 : : If they are feasible, add the constraints and return true.
5991 : :
5992 : : Return false if the constraints contradict existing knowledge
5993 : : (and so the edge should not be taken).
5994 : : When returning false, if OUT is non-NULL, write a new rejected_constraint
5995 : : to it. */
5996 : :
5997 : : bool
5998 : 63768 : region_model::
5999 : : apply_constraints_for_gcond (const cfg_superedge &sedge,
6000 : : const gcond *cond_stmt,
6001 : : region_model_context *ctxt,
6002 : : std::unique_ptr<rejected_constraint> *out)
6003 : : {
6004 : 63768 : ::edge cfg_edge = sedge.get_cfg_edge ();
6005 : 63768 : gcc_assert (cfg_edge != NULL);
6006 : 63768 : gcc_assert (cfg_edge->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE));
6007 : :
6008 : 63768 : enum tree_code op = gimple_cond_code (cond_stmt);
6009 : 63768 : tree lhs = gimple_cond_lhs (cond_stmt);
6010 : 63768 : tree rhs = gimple_cond_rhs (cond_stmt);
6011 : 63768 : if (cfg_edge->flags & EDGE_FALSE_VALUE)
6012 : 30214 : op = invert_tree_comparison (op, false /* honor_nans */);
6013 : 63768 : return add_constraint (lhs, op, rhs, ctxt, out);
6014 : : }
6015 : :
6016 : : /* Return true iff SWITCH_STMT has a non-default label that contains
6017 : : INT_CST. */
6018 : :
6019 : : static bool
6020 : 144 : has_nondefault_case_for_value_p (const gswitch *switch_stmt, tree int_cst)
6021 : : {
6022 : : /* We expect the initial label to be the default; skip it. */
6023 : 144 : gcc_assert (CASE_LOW (gimple_switch_label (switch_stmt, 0)) == NULL);
6024 : 144 : unsigned min_idx = 1;
6025 : 144 : unsigned max_idx = gimple_switch_num_labels (switch_stmt) - 1;
6026 : :
6027 : : /* Binary search: try to find the label containing INT_CST.
6028 : : This requires the cases to be sorted by CASE_LOW (done by the
6029 : : gimplifier). */
6030 : 260 : while (max_idx >= min_idx)
6031 : : {
6032 : 250 : unsigned case_idx = (min_idx + max_idx) / 2;
6033 : 250 : tree label = gimple_switch_label (switch_stmt, case_idx);
6034 : 250 : tree low = CASE_LOW (label);
6035 : 250 : gcc_assert (low);
6036 : 250 : tree high = CASE_HIGH (label);
6037 : 250 : if (!high)
6038 : 198 : high = low;
6039 : 250 : if (tree_int_cst_compare (int_cst, low) < 0)
6040 : : {
6041 : : /* INT_CST is below the range of this label. */
6042 : 27 : gcc_assert (case_idx > 0);
6043 : 27 : max_idx = case_idx - 1;
6044 : : }
6045 : 223 : else if (tree_int_cst_compare (int_cst, high) > 0)
6046 : : {
6047 : : /* INT_CST is above the range of this case. */
6048 : 89 : min_idx = case_idx + 1;
6049 : : }
6050 : : else
6051 : : /* This case contains INT_CST. */
6052 : : return true;
6053 : : }
6054 : : /* Not found. */
6055 : : return false;
6056 : : }
6057 : :
6058 : : /* Return true iff SWITCH_STMT (which must be on an enum value)
6059 : : has nondefault cases handling all values in the enum. */
6060 : :
6061 : : static bool
6062 : 46 : has_nondefault_cases_for_all_enum_values_p (const gswitch *switch_stmt,
6063 : : tree type)
6064 : : {
6065 : 46 : gcc_assert (switch_stmt);
6066 : 46 : gcc_assert (TREE_CODE (type) == ENUMERAL_TYPE);
6067 : :
6068 : 46 : for (tree enum_val_iter = TYPE_VALUES (type);
6069 : 180 : enum_val_iter;
6070 : 134 : enum_val_iter = TREE_CHAIN (enum_val_iter))
6071 : : {
6072 : 144 : tree enum_val = TREE_VALUE (enum_val_iter);
6073 : 144 : gcc_assert (TREE_CODE (enum_val) == CONST_DECL);
6074 : 144 : gcc_assert (TREE_CODE (DECL_INITIAL (enum_val)) == INTEGER_CST);
6075 : 144 : if (!has_nondefault_case_for_value_p (switch_stmt,
6076 : 144 : DECL_INITIAL (enum_val)))
6077 : : return false;
6078 : : }
6079 : : return true;
6080 : : }
6081 : :
6082 : : /* Given an EDGE guarded by SWITCH_STMT, determine appropriate constraints
6083 : : for the edge to be taken.
6084 : :
6085 : : If they are feasible, add the constraints and return true.
6086 : :
6087 : : Return false if the constraints contradict existing knowledge
6088 : : (and so the edge should not be taken).
6089 : : When returning false, if OUT is non-NULL, write a new rejected_constraint
6090 : : to it. */
6091 : :
6092 : : bool
6093 : 8062 : region_model::
6094 : : apply_constraints_for_gswitch (const switch_cfg_superedge &edge,
6095 : : const gswitch *switch_stmt,
6096 : : region_model_context *ctxt,
6097 : : std::unique_ptr<rejected_constraint> *out)
6098 : : {
6099 : 8062 : tree index = gimple_switch_index (switch_stmt);
6100 : 8062 : const svalue *index_sval = get_rvalue (index, ctxt);
6101 : 8062 : bool check_index_type = true;
6102 : :
6103 : : /* With -fshort-enum, there may be a type cast. */
6104 : 7055 : if (ctxt && index_sval->get_kind () == SK_UNARYOP
6105 : 8635 : && TREE_CODE (index_sval->get_type ()) == INTEGER_TYPE)
6106 : : {
6107 : 555 : const unaryop_svalue *unaryop = as_a <const unaryop_svalue *> (index_sval);
6108 : 555 : if (unaryop->get_op () == NOP_EXPR
6109 : 555 : && is_a <const initial_svalue *> (unaryop->get_arg ()))
6110 : 543 : if (const initial_svalue *initvalop = (as_a <const initial_svalue *>
6111 : 543 : (unaryop->get_arg ())))
6112 : 543 : if (initvalop->get_type ()
6113 : 543 : && TREE_CODE (initvalop->get_type ()) == ENUMERAL_TYPE)
6114 : : {
6115 : : index_sval = initvalop;
6116 : : check_index_type = false;
6117 : : }
6118 : : }
6119 : :
6120 : : /* If we're switching based on an enum type, assume that the user is only
6121 : : working with values from the enum. Hence if this is an
6122 : : implicitly-created "default", assume it doesn't get followed.
6123 : : This fixes numerous "uninitialized" false positives where we otherwise
6124 : : consider jumping past the initialization cases. */
6125 : :
6126 : 8062 : if (/* Don't check during feasibility-checking (when ctxt is NULL). */
6127 : : ctxt
6128 : : /* Must be an enum value. */
6129 : 7055 : && index_sval->get_type ()
6130 : 7055 : && (!check_index_type
6131 : 6662 : || TREE_CODE (TREE_TYPE (index)) == ENUMERAL_TYPE)
6132 : 724 : && TREE_CODE (index_sval->get_type ()) == ENUMERAL_TYPE
6133 : : /* If we have a constant, then we can check it directly. */
6134 : 724 : && index_sval->get_kind () != SK_CONSTANT
6135 : 715 : && edge.implicitly_created_default_p ()
6136 : 46 : && has_nondefault_cases_for_all_enum_values_p (switch_stmt,
6137 : : index_sval->get_type ())
6138 : : /* Don't do this if there's a chance that the index is
6139 : : attacker-controlled. */
6140 : 8098 : && !ctxt->possibly_tainted_p (index_sval))
6141 : : {
6142 : 34 : if (out)
6143 : 0 : *out = make_unique <rejected_default_case> (*this);
6144 : 34 : return false;
6145 : : }
6146 : :
6147 : 8028 : bounded_ranges_manager *ranges_mgr = get_range_manager ();
6148 : 8028 : const bounded_ranges *all_cases_ranges
6149 : 8028 : = ranges_mgr->get_or_create_ranges_for_switch (&edge, switch_stmt);
6150 : 8028 : bool sat = m_constraints->add_bounded_ranges (index_sval, all_cases_ranges);
6151 : 8028 : if (!sat && out)
6152 : 98 : *out = make_unique <rejected_ranges_constraint> (*this, index, all_cases_ranges);
6153 : 8028 : if (sat && ctxt && !all_cases_ranges->empty_p ())
6154 : 6491 : ctxt->on_bounded_ranges (*index_sval, *all_cases_ranges);
6155 : : return sat;
6156 : : }
6157 : :
6158 : : /* Given an edge reached by GOTO_STMT, determine appropriate constraints
6159 : : for the edge to be taken.
6160 : :
6161 : : If they are feasible, add the constraints and return true.
6162 : :
6163 : : Return false if the constraints contradict existing knowledge
6164 : : (and so the edge should not be taken). */
6165 : :
6166 : : bool
6167 : 79 : region_model::apply_constraints_for_ggoto (const cfg_superedge &edge,
6168 : : const ggoto *goto_stmt,
6169 : : region_model_context *ctxt)
6170 : : {
6171 : 79 : tree dest = gimple_goto_dest (goto_stmt);
6172 : 79 : const svalue *dest_sval = get_rvalue (dest, ctxt);
6173 : :
6174 : : /* If we know we were jumping to a specific label. */
6175 : 79 : if (tree dst_label = edge.m_dest->get_label ())
6176 : : {
6177 : 79 : const label_region *dst_label_reg
6178 : 79 : = m_mgr->get_region_for_label (dst_label);
6179 : 79 : const svalue *dst_label_ptr
6180 : 79 : = m_mgr->get_ptr_svalue (ptr_type_node, dst_label_reg);
6181 : :
6182 : 79 : if (!add_constraint (dest_sval, EQ_EXPR, dst_label_ptr, ctxt))
6183 : : return false;
6184 : : }
6185 : :
6186 : : return true;
6187 : : }
6188 : :
6189 : : /* Apply any constraints due to an exception being thrown at LAST_STMT.
6190 : :
6191 : : If they are feasible, add the constraints and return true.
6192 : :
6193 : : Return false if the constraints contradict existing knowledge
6194 : : (and so the edge should not be taken).
6195 : : When returning false, if OUT is non-NULL, write a new rejected_constraint
6196 : : to it. */
6197 : :
6198 : : bool
6199 : 2497 : region_model::
6200 : : apply_constraints_for_exception (const gimple *last_stmt,
6201 : : region_model_context *ctxt,
6202 : : std::unique_ptr<rejected_constraint> *out)
6203 : : {
6204 : 2497 : gcc_assert (last_stmt);
6205 : 2497 : if (const gcall *call = dyn_cast <const gcall *> (last_stmt))
6206 : 2490 : if (tree callee_fndecl = get_fndecl_for_call (call, ctxt))
6207 : 2490 : if (is_named_call_p (callee_fndecl, "operator new", call, 1)
6208 : 2490 : || is_named_call_p (callee_fndecl, "operator new []", call, 1))
6209 : : {
6210 : : /* We have an exception thrown from operator new.
6211 : : Add a constraint that the result was NULL, to avoid a false
6212 : : leak report due to the result being lost when following
6213 : : the EH edge. */
6214 : 12 : if (tree lhs = gimple_call_lhs (call))
6215 : 12 : return add_constraint (lhs, EQ_EXPR, null_pointer_node, ctxt, out);
6216 : : return true;
6217 : : }
6218 : : return true;
6219 : : }
6220 : :
6221 : : /* For use with push_frame when handling a top-level call within the analysis.
6222 : : PARAM has a defined but unknown initial value.
6223 : : Anything it points to has escaped, since the calling context "knows"
6224 : : the pointer, and thus calls to unknown functions could read/write into
6225 : : the region.
6226 : : If NONNULL is true, then assume that PARAM must be non-NULL. */
6227 : :
6228 : : void
6229 : 18674 : region_model::on_top_level_param (tree param,
6230 : : bool nonnull,
6231 : : region_model_context *ctxt)
6232 : : {
6233 : 18674 : if (POINTER_TYPE_P (TREE_TYPE (param)))
6234 : : {
6235 : 8823 : const region *param_reg = get_lvalue (param, ctxt);
6236 : 8823 : const svalue *init_ptr_sval
6237 : 8823 : = m_mgr->get_or_create_initial_value (param_reg);
6238 : 8823 : const region *pointee_reg = m_mgr->get_symbolic_region (init_ptr_sval);
6239 : 8823 : m_store.mark_as_escaped (pointee_reg);
6240 : 8823 : if (nonnull)
6241 : : {
6242 : 356 : const svalue *null_ptr_sval
6243 : 356 : = m_mgr->get_or_create_null_ptr (TREE_TYPE (param));
6244 : 356 : add_constraint (init_ptr_sval, NE_EXPR, null_ptr_sval, ctxt);
6245 : : }
6246 : : }
6247 : 18674 : }
6248 : :
6249 : : /* Update this region_model to reflect pushing a frame onto the stack
6250 : : for a call to FUN.
6251 : :
6252 : : If ARG_SVALS is non-NULL, use it to populate the parameters
6253 : : in the new frame.
6254 : : Otherwise, the params have their initial_svalues.
6255 : :
6256 : : Return the frame_region for the new frame. */
6257 : :
6258 : : const region *
6259 : 28923 : region_model::push_frame (const function &fun,
6260 : : const vec<const svalue *> *arg_svals,
6261 : : region_model_context *ctxt)
6262 : : {
6263 : 28923 : m_current_frame = m_mgr->get_frame_region (m_current_frame, fun);
6264 : 28923 : if (arg_svals)
6265 : : {
6266 : : /* Arguments supplied from a caller frame. */
6267 : 9590 : tree fndecl = fun.decl;
6268 : 9590 : unsigned idx = 0;
6269 : 19774 : for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
6270 : 10184 : iter_parm = DECL_CHAIN (iter_parm), ++idx)
6271 : : {
6272 : : /* If there's a mismatching declaration, the call stmt might
6273 : : not have enough args. Handle this case by leaving the
6274 : : rest of the params as uninitialized. */
6275 : 10187 : if (idx >= arg_svals->length ())
6276 : : break;
6277 : 10184 : tree parm_lval = iter_parm;
6278 : 10184 : if (tree parm_default_ssa = get_ssa_default_def (fun, iter_parm))
6279 : 9191 : parm_lval = parm_default_ssa;
6280 : 10184 : const region *parm_reg = get_lvalue (parm_lval, ctxt);
6281 : 10184 : const svalue *arg_sval = (*arg_svals)[idx];
6282 : 10184 : set_value (parm_reg, arg_sval, ctxt);
6283 : : }
6284 : :
6285 : : /* Handle any variadic args. */
6286 : : unsigned va_arg_idx = 0;
6287 : 9992 : for (; idx < arg_svals->length (); idx++, va_arg_idx++)
6288 : : {
6289 : 402 : const svalue *arg_sval = (*arg_svals)[idx];
6290 : 402 : const region *var_arg_reg
6291 : 402 : = m_mgr->get_var_arg_region (m_current_frame,
6292 : : va_arg_idx);
6293 : 402 : set_value (var_arg_reg, arg_sval, ctxt);
6294 : : }
6295 : : }
6296 : : else
6297 : : {
6298 : : /* Otherwise we have a top-level call within the analysis. The params
6299 : : have defined but unknown initial values.
6300 : : Anything they point to has escaped. */
6301 : 19333 : tree fndecl = fun.decl;
6302 : :
6303 : : /* Handle "__attribute__((nonnull))". */
6304 : 19333 : tree fntype = TREE_TYPE (fndecl);
6305 : 19333 : bitmap nonnull_args = get_nonnull_args (fntype);
6306 : :
6307 : 19333 : unsigned parm_idx = 0;
6308 : 38007 : for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
6309 : 18674 : iter_parm = DECL_CHAIN (iter_parm))
6310 : : {
6311 : 18674 : bool non_null = (nonnull_args
6312 : 18674 : ? (bitmap_empty_p (nonnull_args)
6313 : 388 : || bitmap_bit_p (nonnull_args, parm_idx))
6314 : 18674 : : false);
6315 : 18674 : if (tree parm_default_ssa = get_ssa_default_def (fun, iter_parm))
6316 : 15651 : on_top_level_param (parm_default_ssa, non_null, ctxt);
6317 : : else
6318 : 3023 : on_top_level_param (iter_parm, non_null, ctxt);
6319 : 18674 : parm_idx++;
6320 : : }
6321 : :
6322 : 19333 : BITMAP_FREE (nonnull_args);
6323 : : }
6324 : :
6325 : 28923 : return m_current_frame;
6326 : : }
6327 : :
6328 : : /* Get the function of the top-most frame in this region_model's stack.
6329 : : There must be such a frame. */
6330 : :
6331 : : const function *
6332 : 19443 : region_model::get_current_function () const
6333 : : {
6334 : 19443 : const frame_region *frame = get_current_frame ();
6335 : 19443 : gcc_assert (frame);
6336 : 19443 : return &frame->get_function ();
6337 : : }
6338 : :
6339 : : /* Custom region_model_context for the assignment to the result
6340 : : at a call statement when popping a frame (PR analyzer/106203). */
6341 : :
6342 : : class caller_context : public region_model_context_decorator
6343 : : {
6344 : : public:
6345 : 3629 : caller_context (region_model_context *inner,
6346 : : const gcall *call_stmt,
6347 : : const frame_region &caller_frame)
6348 : 3629 : : region_model_context_decorator (inner),
6349 : 3629 : m_call_stmt (call_stmt),
6350 : 3629 : m_caller_frame (caller_frame)
6351 : : {}
6352 : 12 : bool warn (std::unique_ptr<pending_diagnostic> d,
6353 : : const stmt_finder *custom_finder) override
6354 : : {
6355 : 12 : if (m_inner && custom_finder == nullptr)
6356 : : {
6357 : : /* Custom stmt_finder to use m_call_stmt for the
6358 : : diagnostic. */
6359 : 0 : class my_finder : public stmt_finder
6360 : : {
6361 : : public:
6362 : 24 : my_finder (const gcall *call_stmt,
6363 : : const frame_region &caller_frame)
6364 : 24 : : m_call_stmt (call_stmt),
6365 : 12 : m_caller_frame (caller_frame)
6366 : : {}
6367 : 12 : std::unique_ptr<stmt_finder> clone () const override
6368 : : {
6369 : 12 : return ::make_unique<my_finder> (m_call_stmt, m_caller_frame);
6370 : : }
6371 : 12 : const gimple *find_stmt (const exploded_path &) override
6372 : : {
6373 : 12 : return m_call_stmt;
6374 : : }
6375 : 12 : void update_event_loc_info (event_loc_info &loc_info) final override
6376 : : {
6377 : 12 : loc_info.m_fndecl = m_caller_frame.get_fndecl ();
6378 : 12 : loc_info.m_depth = m_caller_frame.get_stack_depth ();
6379 : 12 : }
6380 : :
6381 : : private:
6382 : : const gcall *m_call_stmt;
6383 : : const frame_region &m_caller_frame;
6384 : : };
6385 : 12 : my_finder finder (m_call_stmt, m_caller_frame);
6386 : 12 : return m_inner->warn (std::move (d), &finder);
6387 : 12 : }
6388 : : else
6389 : 0 : return region_model_context_decorator::warn (std::move (d),
6390 : : custom_finder);
6391 : : }
6392 : 7270 : const gimple *get_stmt () const override
6393 : : {
6394 : 7270 : return m_call_stmt;
6395 : : };
6396 : :
6397 : : private:
6398 : : const gcall *m_call_stmt;
6399 : : const frame_region &m_caller_frame;
6400 : : };
6401 : :
6402 : :
6403 : : /* Pop the topmost frame_region from this region_model's stack;
6404 : :
6405 : : If RESULT_LVALUE is non-null, copy any return value from the frame
6406 : : into the corresponding region (evaluated with respect to the *caller*
6407 : : frame, rather than the called frame).
6408 : : If OUT_RESULT is non-null, copy any return value from the frame
6409 : : into *OUT_RESULT.
6410 : :
6411 : : If non-null, use CALL_STMT as the location when complaining about
6412 : : assignment of the return value to RESULT_LVALUE.
6413 : :
6414 : : If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
6415 : : This is for use when unwinding frames e.g. due to longjmp, to suppress
6416 : : erroneously reporting uninitialized return values.
6417 : :
6418 : : Purge the frame region and all its descendent regions.
6419 : : Convert any pointers that point into such regions into
6420 : : POISON_KIND_POPPED_STACK svalues. */
6421 : :
6422 : : void
6423 : 18098 : region_model::pop_frame (tree result_lvalue,
6424 : : const svalue **out_result,
6425 : : region_model_context *ctxt,
6426 : : const gcall *call_stmt,
6427 : : bool eval_return_svalue)
6428 : : {
6429 : 18098 : gcc_assert (m_current_frame);
6430 : :
6431 : 18098 : const region_model pre_popped_model = *this;
6432 : 18098 : const frame_region *frame_reg = m_current_frame;
6433 : :
6434 : : /* Notify state machines. */
6435 : 18098 : if (ctxt)
6436 : 16137 : ctxt->on_pop_frame (frame_reg);
6437 : :
6438 : : /* Evaluate the result, within the callee frame. */
6439 : 18098 : tree fndecl = m_current_frame->get_function ().decl;
6440 : 18098 : tree result = DECL_RESULT (fndecl);
6441 : 18098 : const svalue *retval = NULL;
6442 : 18098 : if (result
6443 : 18090 : && TREE_TYPE (result) != void_type_node
6444 : 26961 : && eval_return_svalue)
6445 : : {
6446 : 8855 : retval = get_rvalue (result, ctxt);
6447 : 8855 : if (out_result)
6448 : 4916 : *out_result = retval;
6449 : : }
6450 : :
6451 : : /* Pop the frame. */
6452 : 18098 : m_current_frame = m_current_frame->get_calling_frame ();
6453 : :
6454 : 18098 : if (result_lvalue && retval)
6455 : : {
6456 : 3629 : gcc_assert (eval_return_svalue);
6457 : :
6458 : : /* Compute result_dst_reg using RESULT_LVALUE *after* popping
6459 : : the frame, but before poisoning pointers into the old frame. */
6460 : 3629 : const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);
6461 : :
6462 : : /* Assign retval to result_dst_reg, using caller_context
6463 : : to set the call_stmt and the popped_frame for any diagnostics
6464 : : due to the assignment. */
6465 : 3629 : gcc_assert (m_current_frame);
6466 : 3629 : caller_context caller_ctxt (ctxt, call_stmt, *m_current_frame);
6467 : 3629 : set_value (result_dst_reg, retval, call_stmt ? &caller_ctxt : ctxt);
6468 : : }
6469 : :
6470 : 18098 : unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK);
6471 : 18098 : notify_on_pop_frame (this, &pre_popped_model, retval, ctxt);
6472 : 18098 : }
6473 : :
6474 : : /* Get the number of frames in this region_model's stack. */
6475 : :
6476 : : int
6477 : 5022445 : region_model::get_stack_depth () const
6478 : : {
6479 : 5022445 : const frame_region *frame = get_current_frame ();
6480 : 5022445 : if (frame)
6481 : 5005978 : return frame->get_stack_depth ();
6482 : : else
6483 : : return 0;
6484 : : }
6485 : :
6486 : : /* Get the frame_region with the given index within the stack.
6487 : : The frame_region must exist. */
6488 : :
6489 : : const frame_region *
6490 : 1566849 : region_model::get_frame_at_index (int index) const
6491 : : {
6492 : 1566849 : const frame_region *frame = get_current_frame ();
6493 : 1566849 : gcc_assert (frame);
6494 : 1566849 : gcc_assert (index >= 0);
6495 : 1566849 : gcc_assert (index <= frame->get_index ());
6496 : 1875735 : while (index != frame->get_index ())
6497 : : {
6498 : 308886 : frame = frame->get_calling_frame ();
6499 : 308886 : gcc_assert (frame);
6500 : : }
6501 : 1566849 : return frame;
6502 : : }
6503 : :
6504 : : /* Unbind svalues for any regions in REG and below.
6505 : : Find any pointers to such regions; convert them to
6506 : : poisoned values of kind PKIND.
6507 : : Also purge any dynamic extents. */
6508 : :
6509 : : void
6510 : 29064 : region_model::unbind_region_and_descendents (const region *reg,
6511 : : enum poison_kind pkind)
6512 : : {
6513 : : /* Gather a set of base regions to be unbound. */
6514 : 29064 : hash_set<const region *> base_regs;
6515 : 170385 : for (store::cluster_map_t::iterator iter = m_store.begin ();
6516 : 311706 : iter != m_store.end (); ++iter)
6517 : : {
6518 : 141321 : const region *iter_base_reg = (*iter).first;
6519 : 141321 : if (iter_base_reg->descendent_of_p (reg))
6520 : 32598 : base_regs.add (iter_base_reg);
6521 : : }
6522 : 61662 : for (hash_set<const region *>::iterator iter = base_regs.begin ();
6523 : 94260 : iter != base_regs.end (); ++iter)
6524 : 32598 : m_store.purge_cluster (*iter);
6525 : :
6526 : : /* Find any pointers to REG or its descendents; convert to poisoned. */
6527 : 29064 : poison_any_pointers_to_descendents (reg, pkind);
6528 : :
6529 : : /* Purge dynamic extents of any base regions in REG and below
6530 : : (e.g. VLAs and alloca stack regions). */
6531 : 92224 : for (auto iter : m_dynamic_extents)
6532 : : {
6533 : 17048 : const region *iter_reg = iter.first;
6534 : 17048 : if (iter_reg->descendent_of_p (reg))
6535 : 6339 : unset_dynamic_extents (iter_reg);
6536 : : }
6537 : 29064 : }
6538 : :
6539 : : /* Implementation of BindingVisitor.
6540 : : Update the bound svalues for regions below REG to use poisoned
6541 : : values instead. */
6542 : :
6543 : : struct bad_pointer_finder
6544 : : {
6545 : 29064 : bad_pointer_finder (const region *reg, enum poison_kind pkind,
6546 : : region_model_manager *mgr)
6547 : 29064 : : m_reg (reg), m_pkind (pkind), m_mgr (mgr), m_count (0)
6548 : : {}
6549 : :
6550 : 113050 : void on_binding (const binding_key *, const svalue *&sval)
6551 : : {
6552 : 113050 : if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
6553 : : {
6554 : 27371 : const region *ptr_dst = ptr_sval->get_pointee ();
6555 : : /* Poison ptrs to descendents of REG, but not to REG itself,
6556 : : otherwise double-free detection doesn't work (since sm-state
6557 : : for "free" is stored on the original ptr svalue). */
6558 : 27371 : if (ptr_dst->descendent_of_p (m_reg)
6559 : 27371 : && ptr_dst != m_reg)
6560 : : {
6561 : 151 : sval = m_mgr->get_or_create_poisoned_svalue (m_pkind,
6562 : : sval->get_type ());
6563 : 151 : ++m_count;
6564 : : }
6565 : : }
6566 : 113050 : }
6567 : :
6568 : : const region *m_reg;
6569 : : enum poison_kind m_pkind;
6570 : : region_model_manager *const m_mgr;
6571 : : int m_count;
6572 : : };
6573 : :
6574 : : /* Find any pointers to REG or its descendents; convert them to
6575 : : poisoned values of kind PKIND.
6576 : : Return the number of pointers that were poisoned. */
6577 : :
6578 : : int
6579 : 29064 : region_model::poison_any_pointers_to_descendents (const region *reg,
6580 : : enum poison_kind pkind)
6581 : : {
6582 : 29064 : bad_pointer_finder bv (reg, pkind, m_mgr);
6583 : 29064 : m_store.for_each_binding (bv);
6584 : 29064 : return bv.m_count;
6585 : : }
6586 : :
6587 : : /* Attempt to merge THIS with OTHER_MODEL, writing the result
6588 : : to OUT_MODEL. Use POINT to distinguish values created as a
6589 : : result of merging. */
6590 : :
6591 : : bool
6592 : 151668 : region_model::can_merge_with_p (const region_model &other_model,
6593 : : const program_point &point,
6594 : : region_model *out_model,
6595 : : const extrinsic_state *ext_state,
6596 : : const program_state *state_a,
6597 : : const program_state *state_b) const
6598 : : {
6599 : 151668 : gcc_assert (out_model);
6600 : 151668 : gcc_assert (m_mgr == other_model.m_mgr);
6601 : 151668 : gcc_assert (m_mgr == out_model->m_mgr);
6602 : :
6603 : 151668 : if (m_current_frame != other_model.m_current_frame)
6604 : : return false;
6605 : 151668 : out_model->m_current_frame = m_current_frame;
6606 : :
6607 : 151668 : model_merger m (this, &other_model, point, out_model,
6608 : 151668 : ext_state, state_a, state_b);
6609 : :
6610 : 151668 : if (!store::can_merge_p (&m_store, &other_model.m_store,
6611 : 151668 : &out_model->m_store, m_mgr->get_store_manager (),
6612 : : &m))
6613 : : return false;
6614 : :
6615 : 66551 : if (!m_dynamic_extents.can_merge_with_p (other_model.m_dynamic_extents,
6616 : : &out_model->m_dynamic_extents))
6617 : : return false;
6618 : :
6619 : : /* Merge constraints. */
6620 : 62336 : constraint_manager::merge (*m_constraints,
6621 : 62336 : *other_model.m_constraints,
6622 : : out_model->m_constraints);
6623 : :
6624 : 63114 : for (auto iter : m.m_svals_changing_meaning)
6625 : 778 : out_model->m_constraints->purge_state_involving (iter);
6626 : :
6627 : 62336 : return true;
6628 : 151668 : }
6629 : :
6630 : : /* Attempt to get the fndecl used at CALL, if known, or NULL_TREE
6631 : : otherwise. */
6632 : :
6633 : : tree
6634 : 884121 : region_model::get_fndecl_for_call (const gcall *call,
6635 : : region_model_context *ctxt)
6636 : : {
6637 : 884121 : tree fn_ptr = gimple_call_fn (call);
6638 : 884121 : if (fn_ptr == NULL_TREE)
6639 : : return NULL_TREE;
6640 : 870344 : const svalue *fn_ptr_sval = get_rvalue (fn_ptr, ctxt);
6641 : 1740688 : if (const region_svalue *fn_ptr_ptr
6642 : 870344 : = fn_ptr_sval->dyn_cast_region_svalue ())
6643 : : {
6644 : 864541 : const region *reg = fn_ptr_ptr->get_pointee ();
6645 : 864541 : if (const function_region *fn_reg = reg->dyn_cast_function_region ())
6646 : : {
6647 : 864493 : tree fn_decl = fn_reg->get_fndecl ();
6648 : 864493 : cgraph_node *node = cgraph_node::get (fn_decl);
6649 : 864493 : if (!node)
6650 : : return NULL_TREE;
6651 : 864493 : const cgraph_node *ultimate_node = node->ultimate_alias_target ();
6652 : 864493 : if (ultimate_node)
6653 : 864493 : return ultimate_node->decl;
6654 : : }
6655 : : }
6656 : :
6657 : : return NULL_TREE;
6658 : : }
6659 : :
6660 : : /* Would be much simpler to use a lambda here, if it were supported. */
6661 : :
6662 : : struct append_regions_cb_data
6663 : : {
6664 : : const region_model *model;
6665 : : auto_vec<const decl_region *> *out;
6666 : : };
6667 : :
6668 : : /* Populate *OUT with all decl_regions in the current
6669 : : frame that have clusters within the store. */
6670 : :
6671 : : void
6672 : 598270 : region_model::
6673 : : get_regions_for_current_frame (auto_vec<const decl_region *> *out) const
6674 : : {
6675 : 598270 : append_regions_cb_data data;
6676 : 598270 : data.model = this;
6677 : 598270 : data.out = out;
6678 : 598270 : m_store.for_each_cluster (append_regions_cb, &data);
6679 : 598270 : }
6680 : :
6681 : : /* Implementation detail of get_regions_for_current_frame. */
6682 : :
6683 : : void
6684 : 3576820 : region_model::append_regions_cb (const region *base_reg,
6685 : : append_regions_cb_data *cb_data)
6686 : : {
6687 : 3576820 : if (base_reg->get_parent_region () != cb_data->model->m_current_frame)
6688 : : return;
6689 : 1368368 : if (const decl_region *decl_reg = base_reg->dyn_cast_decl_region ())
6690 : 1332266 : cb_data->out->safe_push (decl_reg);
6691 : : }
6692 : :
6693 : :
6694 : : /* Abstract class for diagnostics related to the use of
6695 : : floating-point arithmetic where precision is needed. */
6696 : :
6697 : 46 : class imprecise_floating_point_arithmetic : public pending_diagnostic
6698 : : {
6699 : : public:
6700 : 71 : int get_controlling_option () const final override
6701 : : {
6702 : 71 : return OPT_Wanalyzer_imprecise_fp_arithmetic;
6703 : : }
6704 : : };
6705 : :
6706 : : /* Concrete diagnostic to complain about uses of floating-point arithmetic
6707 : : in the size argument of malloc etc. */
6708 : :
6709 : : class float_as_size_arg : public imprecise_floating_point_arithmetic
6710 : : {
6711 : : public:
6712 : 46 : float_as_size_arg (tree arg) : m_arg (arg)
6713 : : {}
6714 : :
6715 : 163 : const char *get_kind () const final override
6716 : : {
6717 : 163 : return "float_as_size_arg_diagnostic";
6718 : : }
6719 : :
6720 : 46 : bool subclass_equal_p (const pending_diagnostic &other) const final override
6721 : : {
6722 : 46 : return same_tree_p (m_arg, ((const float_as_size_arg &) other).m_arg);
6723 : : }
6724 : :
6725 : 25 : bool emit (diagnostic_emission_context &ctxt) final override
6726 : : {
6727 : 25 : bool warned = ctxt.warn ("use of floating-point arithmetic here might"
6728 : : " yield unexpected results");
6729 : 25 : if (warned)
6730 : 25 : inform (ctxt.get_location (),
6731 : : "only use operands of an integer type"
6732 : : " inside the size argument");
6733 : 25 : return warned;
6734 : : }
6735 : :
6736 : : bool
6737 : 50 : describe_final_event (pretty_printer &pp,
6738 : : const evdesc::final_event &) final override
6739 : : {
6740 : 50 : if (m_arg)
6741 : 50 : pp_printf (&pp,
6742 : : "operand %qE is of type %qT",
6743 : 50 : m_arg, TREE_TYPE (m_arg));
6744 : : else
6745 : 0 : pp_printf (&pp,
6746 : : "at least one operand of the size argument is"
6747 : : " of a floating-point type");
6748 : 50 : return true;
6749 : : }
6750 : :
6751 : : private:
6752 : : tree m_arg;
6753 : : };
6754 : :
6755 : : /* Visitor to find uses of floating-point variables/constants in an svalue. */
6756 : :
6757 : : class contains_floating_point_visitor : public visitor
6758 : : {
6759 : : public:
6760 : 8427 : contains_floating_point_visitor (const svalue *root_sval) : m_result (NULL)
6761 : : {
6762 : 8427 : root_sval->accept (this);
6763 : : }
6764 : :
6765 : 8427 : const svalue *get_svalue_to_report ()
6766 : : {
6767 : 8427 : return m_result;
6768 : : }
6769 : :
6770 : 7817 : void visit_constant_svalue (const constant_svalue *sval) final override
6771 : : {
6772 : : /* At the point the analyzer runs, constant integer operands in a floating
6773 : : point expression are already implictly converted to floating-points.
6774 : : Thus, we do prefer to report non-constants such that the diagnostic
6775 : : always reports a floating-point operand. */
6776 : 7817 : tree type = sval->get_type ();
6777 : 7817 : if (type && FLOAT_TYPE_P (type) && !m_result)
6778 : 18 : m_result = sval;
6779 : 7817 : }
6780 : :
6781 : 443 : void visit_conjured_svalue (const conjured_svalue *sval) final override
6782 : : {
6783 : 443 : tree type = sval->get_type ();
6784 : 443 : if (type && FLOAT_TYPE_P (type))
6785 : 0 : m_result = sval;
6786 : 443 : }
6787 : :
6788 : 1289 : void visit_initial_svalue (const initial_svalue *sval) final override
6789 : : {
6790 : 1289 : tree type = sval->get_type ();
6791 : 1289 : if (type && FLOAT_TYPE_P (type))
6792 : 28 : m_result = sval;
6793 : 1289 : }
6794 : :
6795 : : private:
6796 : : /* Non-null if at least one floating-point operand was found. */
6797 : : const svalue *m_result;
6798 : : };
6799 : :
6800 : : /* May complain about uses of floating-point operands in SIZE_IN_BYTES. */
6801 : :
6802 : : void
6803 : 8427 : region_model::check_dynamic_size_for_floats (const svalue *size_in_bytes,
6804 : : region_model_context *ctxt) const
6805 : : {
6806 : 8427 : gcc_assert (ctxt);
6807 : :
6808 : 8427 : contains_floating_point_visitor v (size_in_bytes);
6809 : 8427 : if (const svalue *float_sval = v.get_svalue_to_report ())
6810 : : {
6811 : 46 : tree diag_arg = get_representative_tree (float_sval);
6812 : 46 : ctxt->warn (make_unique<float_as_size_arg> (diag_arg));
6813 : : }
6814 : 8427 : }
6815 : :
6816 : : /* Return a region describing a heap-allocated block of memory.
6817 : : Use CTXT to complain about tainted sizes.
6818 : :
6819 : : Reuse an existing heap_allocated_region if it's not being referenced by
6820 : : this region_model; otherwise create a new one.
6821 : :
6822 : : Optionally (update_state_machine) transitions the pointer pointing to the
6823 : : heap_allocated_region from start to assumed non-null. */
6824 : :
6825 : : const region *
6826 : 12687 : region_model::get_or_create_region_for_heap_alloc (const svalue *size_in_bytes,
6827 : : region_model_context *ctxt,
6828 : : bool update_state_machine,
6829 : : const call_details *cd)
6830 : : {
6831 : : /* Determine which regions are referenced in this region_model, so that
6832 : : we can reuse an existing heap_allocated_region if it's not in use on
6833 : : this path. */
6834 : 12687 : auto_bitmap base_regs_in_use;
6835 : 12687 : get_referenced_base_regions (base_regs_in_use);
6836 : :
6837 : : /* Don't reuse regions that are marked as TOUCHED. */
6838 : 89729 : for (store::cluster_map_t::iterator iter = m_store.begin ();
6839 : 166771 : iter != m_store.end (); ++iter)
6840 : 77042 : if ((*iter).second->touched_p ())
6841 : : {
6842 : 9531 : const region *base_reg = (*iter).first;
6843 : 9531 : bitmap_set_bit (base_regs_in_use, base_reg->get_id ());
6844 : : }
6845 : :
6846 : 12687 : const region *reg
6847 : 12687 : = m_mgr->get_or_create_region_for_heap_alloc (base_regs_in_use);
6848 : 12687 : if (size_in_bytes)
6849 : 12661 : if (compat_types_p (size_in_bytes->get_type (), size_type_node))
6850 : 12661 : set_dynamic_extents (reg, size_in_bytes, ctxt);
6851 : :
6852 : 12687 : if (update_state_machine && cd)
6853 : : {
6854 : 0 : const svalue *ptr_sval
6855 : 0 : = m_mgr->get_ptr_svalue (cd->get_lhs_type (), reg);
6856 : 0 : transition_ptr_sval_non_null (ctxt, ptr_sval);
6857 : : }
6858 : :
6859 : 12687 : return reg;
6860 : 12687 : }
6861 : :
6862 : : /* Populate OUT_IDS with the set of IDs of those base regions which are
6863 : : reachable in this region_model. */
6864 : :
6865 : : void
6866 : 15708 : region_model::get_referenced_base_regions (auto_bitmap &out_ids) const
6867 : : {
6868 : 15708 : reachable_regions reachable_regs (const_cast<region_model *> (this));
6869 : 15708 : m_store.for_each_cluster (reachable_regions::init_cluster_cb,
6870 : : &reachable_regs);
6871 : : /* Get regions for locals that have explicitly bound values. */
6872 : 150792 : for (store::cluster_map_t::iterator iter = m_store.begin ();
6873 : 285876 : iter != m_store.end (); ++iter)
6874 : : {
6875 : 135084 : const region *base_reg = (*iter).first;
6876 : 135084 : if (const region *parent = base_reg->get_parent_region ())
6877 : 135084 : if (parent->get_kind () == RK_FRAME)
6878 : 72915 : reachable_regs.add (base_reg, false);
6879 : : }
6880 : :
6881 : 15708 : bitmap_clear (out_ids);
6882 : 153595 : for (auto iter_reg : reachable_regs)
6883 : 137887 : bitmap_set_bit (out_ids, iter_reg->get_id ());
6884 : 15708 : }
6885 : :
6886 : : /* Return a new region describing a block of memory allocated within the
6887 : : current frame.
6888 : : Use CTXT to complain about tainted sizes. */
6889 : :
6890 : : const region *
6891 : 538 : region_model::create_region_for_alloca (const svalue *size_in_bytes,
6892 : : region_model_context *ctxt)
6893 : : {
6894 : 538 : const region *reg = m_mgr->create_region_for_alloca (m_current_frame);
6895 : 538 : if (compat_types_p (size_in_bytes->get_type (), size_type_node))
6896 : 537 : set_dynamic_extents (reg, size_in_bytes, ctxt);
6897 : 538 : return reg;
6898 : : }
6899 : :
6900 : : /* Record that the size of REG is SIZE_IN_BYTES.
6901 : : Use CTXT to complain about tainted sizes. */
6902 : :
6903 : : void
6904 : 13785 : region_model::set_dynamic_extents (const region *reg,
6905 : : const svalue *size_in_bytes,
6906 : : region_model_context *ctxt)
6907 : : {
6908 : 13785 : assert_compat_types (size_in_bytes->get_type (), size_type_node);
6909 : 13785 : if (ctxt)
6910 : : {
6911 : 8427 : check_dynamic_size_for_taint (reg->get_memory_space (), size_in_bytes,
6912 : : ctxt);
6913 : 8427 : check_dynamic_size_for_floats (size_in_bytes, ctxt);
6914 : : }
6915 : 13785 : m_dynamic_extents.put (reg, size_in_bytes);
6916 : 13785 : }
6917 : :
6918 : : /* Get the recording of REG in bytes, or NULL if no dynamic size was
6919 : : recorded. */
6920 : :
6921 : : const svalue *
6922 : 60702 : region_model::get_dynamic_extents (const region *reg) const
6923 : : {
6924 : 60702 : if (const svalue * const *slot = m_dynamic_extents.get (reg))
6925 : 13138 : return *slot;
6926 : : return NULL;
6927 : : }
6928 : :
6929 : : /* Unset any recorded dynamic size of REG. */
6930 : :
6931 : : void
6932 : 57494 : region_model::unset_dynamic_extents (const region *reg)
6933 : : {
6934 : 57494 : m_dynamic_extents.remove (reg);
6935 : 57494 : }
6936 : :
6937 : : /* A subclass of pending_diagnostic for complaining about uninitialized data
6938 : : being copied across a trust boundary to an untrusted output
6939 : : (e.g. copy_to_user infoleaks in the Linux kernel). */
6940 : :
6941 : : class exposure_through_uninit_copy
6942 : : : public pending_diagnostic_subclass<exposure_through_uninit_copy>
6943 : : {
6944 : : public:
6945 : 47 : exposure_through_uninit_copy (const region *src_region,
6946 : : const region *dest_region,
6947 : : const svalue *copied_sval)
6948 : 47 : : m_src_region (src_region),
6949 : 47 : m_dest_region (dest_region),
6950 : 47 : m_copied_sval (copied_sval)
6951 : : {
6952 : 47 : gcc_assert (m_copied_sval->get_kind () == SK_POISONED
6953 : : || m_copied_sval->get_kind () == SK_COMPOUND);
6954 : 47 : }
6955 : :
6956 : 166 : const char *get_kind () const final override
6957 : : {
6958 : 166 : return "exposure_through_uninit_copy";
6959 : : }
6960 : :
6961 : 47 : bool operator== (const exposure_through_uninit_copy &other) const
6962 : : {
6963 : 47 : return (m_src_region == other.m_src_region
6964 : 47 : && m_dest_region == other.m_dest_region
6965 : 94 : && m_copied_sval == other.m_copied_sval);
6966 : : }
6967 : :
6968 : 72 : int get_controlling_option () const final override
6969 : : {
6970 : 72 : return OPT_Wanalyzer_exposure_through_uninit_copy;
6971 : : }
6972 : :
6973 : 25 : bool emit (diagnostic_emission_context &ctxt) final override
6974 : : {
6975 : : /* CWE-200: Exposure of Sensitive Information to an Unauthorized Actor. */
6976 : 25 : ctxt.add_cwe (200);
6977 : 50 : enum memory_space mem_space = get_src_memory_space ();
6978 : 25 : bool warned;
6979 : 25 : switch (mem_space)
6980 : : {
6981 : 0 : default:
6982 : 0 : warned = ctxt.warn ("potential exposure of sensitive information"
6983 : : " by copying uninitialized data"
6984 : : " across trust boundary");
6985 : 0 : break;
6986 : 25 : case MEMSPACE_STACK:
6987 : 25 : warned = ctxt.warn ("potential exposure of sensitive information"
6988 : : " by copying uninitialized data from stack"
6989 : : " across trust boundary");
6990 : 25 : break;
6991 : 0 : case MEMSPACE_HEAP:
6992 : 0 : warned = ctxt.warn ("potential exposure of sensitive information"
6993 : : " by copying uninitialized data from heap"
6994 : : " across trust boundary");
6995 : 0 : break;
6996 : : }
6997 : 25 : if (warned)
6998 : : {
6999 : 25 : const location_t loc = ctxt.get_location ();
7000 : 25 : inform_number_of_uninit_bits (loc);
7001 : 25 : complain_about_uninit_ranges (loc);
7002 : :
7003 : 25 : if (mem_space == MEMSPACE_STACK)
7004 : 25 : maybe_emit_fixit_hint ();
7005 : : }
7006 : 25 : return warned;
7007 : : }
7008 : :
7009 : : bool
7010 : 50 : describe_final_event (pretty_printer &pp,
7011 : : const evdesc::final_event &) final override
7012 : : {
7013 : 100 : enum memory_space mem_space = get_src_memory_space ();
7014 : 50 : switch (mem_space)
7015 : : {
7016 : 0 : default:
7017 : 0 : pp_string (&pp, "uninitialized data copied here");
7018 : 0 : return true;
7019 : :
7020 : 50 : case MEMSPACE_STACK:
7021 : 50 : pp_string (&pp, "uninitialized data copied from stack here");
7022 : 50 : return true;
7023 : :
7024 : 0 : case MEMSPACE_HEAP:
7025 : 0 : pp_string (&pp, "uninitialized data copied from heap here");
7026 : 0 : return true;
7027 : : }
7028 : : }
7029 : :
7030 : 25 : void mark_interesting_stuff (interesting_t *interest) final override
7031 : : {
7032 : 25 : if (m_src_region)
7033 : 25 : interest->add_region_creation (m_src_region);
7034 : 25 : }
7035 : :
7036 : : void
7037 : 0 : maybe_add_sarif_properties (sarif_object &result_obj) const final override
7038 : : {
7039 : 0 : sarif_property_bag &props = result_obj.get_or_create_properties ();
7040 : : #define PROPERTY_PREFIX "gcc/-Wanalyzer-exposure-through-uninit-copy/"
7041 : 0 : props.set (PROPERTY_PREFIX "src_region", m_src_region->to_json ());
7042 : 0 : props.set (PROPERTY_PREFIX "dest_region", m_dest_region->to_json ());
7043 : 0 : props.set (PROPERTY_PREFIX "copied_sval", m_copied_sval->to_json ());
7044 : : #undef PROPERTY_PREFIX
7045 : 0 : }
7046 : :
7047 : : private:
7048 : 75 : enum memory_space get_src_memory_space () const
7049 : : {
7050 : 75 : return m_src_region ? m_src_region->get_memory_space () : MEMSPACE_UNKNOWN;
7051 : : }
7052 : :
7053 : 25 : bit_size_t calc_num_uninit_bits () const
7054 : : {
7055 : 25 : switch (m_copied_sval->get_kind ())
7056 : : {
7057 : 0 : default:
7058 : 0 : gcc_unreachable ();
7059 : 4 : break;
7060 : 4 : case SK_POISONED:
7061 : 4 : {
7062 : 4 : const poisoned_svalue *poisoned_sval
7063 : 4 : = as_a <const poisoned_svalue *> (m_copied_sval);
7064 : 4 : gcc_assert (poisoned_sval->get_poison_kind () == POISON_KIND_UNINIT);
7065 : :
7066 : : /* Give up if don't have type information. */
7067 : 4 : if (m_copied_sval->get_type () == NULL_TREE)
7068 : 0 : return 0;
7069 : :
7070 : 4 : bit_size_t size_in_bits;
7071 : 4 : if (int_size_in_bits (m_copied_sval->get_type (), &size_in_bits))
7072 : 4 : return size_in_bits;
7073 : :
7074 : : /* Give up if we can't get the size of the type. */
7075 : 0 : return 0;
7076 : : }
7077 : 21 : break;
7078 : 21 : case SK_COMPOUND:
7079 : 21 : {
7080 : 21 : const compound_svalue *compound_sval
7081 : 21 : = as_a <const compound_svalue *> (m_copied_sval);
7082 : 21 : bit_size_t result = 0;
7083 : : /* Find keys for uninit svals. */
7084 : 143 : for (auto iter : *compound_sval)
7085 : : {
7086 : 61 : const svalue *sval = iter.second;
7087 : 122 : if (const poisoned_svalue *psval
7088 : 61 : = sval->dyn_cast_poisoned_svalue ())
7089 : 24 : if (psval->get_poison_kind () == POISON_KIND_UNINIT)
7090 : : {
7091 : 24 : const binding_key *key = iter.first;
7092 : 24 : const concrete_binding *ckey
7093 : 24 : = key->dyn_cast_concrete_binding ();
7094 : 24 : gcc_assert (ckey);
7095 : 24 : result += ckey->get_size_in_bits ();
7096 : : }
7097 : : }
7098 : 21 : return result;
7099 : : }
7100 : : }
7101 : : }
7102 : :
7103 : 25 : void inform_number_of_uninit_bits (location_t loc) const
7104 : : {
7105 : 25 : bit_size_t num_uninit_bits = calc_num_uninit_bits ();
7106 : 25 : if (num_uninit_bits <= 0)
7107 : 0 : return;
7108 : 25 : if (num_uninit_bits % BITS_PER_UNIT == 0)
7109 : : {
7110 : : /* Express in bytes. */
7111 : 25 : byte_size_t num_uninit_bytes = num_uninit_bits / BITS_PER_UNIT;
7112 : 25 : if (num_uninit_bytes == 1)
7113 : 3 : inform (loc, "1 byte is uninitialized");
7114 : : else
7115 : 22 : inform (loc,
7116 : : "%wu bytes are uninitialized", num_uninit_bytes.to_uhwi ());
7117 : : }
7118 : : else
7119 : : {
7120 : : /* Express in bits. */
7121 : 0 : if (num_uninit_bits == 1)
7122 : 0 : inform (loc, "1 bit is uninitialized");
7123 : : else
7124 : 0 : inform (loc,
7125 : : "%wu bits are uninitialized", num_uninit_bits.to_uhwi ());
7126 : : }
7127 : : }
7128 : :
7129 : 25 : void complain_about_uninit_ranges (location_t loc) const
7130 : : {
7131 : 50 : if (const compound_svalue *compound_sval
7132 : 25 : = m_copied_sval->dyn_cast_compound_svalue ())
7133 : : {
7134 : : /* Find keys for uninit svals. */
7135 : 21 : auto_vec<const concrete_binding *> uninit_keys;
7136 : 143 : for (auto iter : *compound_sval)
7137 : : {
7138 : 61 : const svalue *sval = iter.second;
7139 : 122 : if (const poisoned_svalue *psval
7140 : 61 : = sval->dyn_cast_poisoned_svalue ())
7141 : 24 : if (psval->get_poison_kind () == POISON_KIND_UNINIT)
7142 : : {
7143 : 24 : const binding_key *key = iter.first;
7144 : 24 : const concrete_binding *ckey
7145 : 24 : = key->dyn_cast_concrete_binding ();
7146 : 24 : gcc_assert (ckey);
7147 : 24 : uninit_keys.safe_push (ckey);
7148 : : }
7149 : : }
7150 : : /* Complain about them in sorted order. */
7151 : 21 : uninit_keys.qsort (concrete_binding::cmp_ptr_ptr);
7152 : :
7153 : 21 : std::unique_ptr<record_layout> layout;
7154 : :
7155 : 21 : tree type = m_copied_sval->get_type ();
7156 : 21 : if (type && TREE_CODE (type) == RECORD_TYPE)
7157 : : {
7158 : : // (std::make_unique is C++14)
7159 : 17 : layout = std::unique_ptr<record_layout> (new record_layout (type));
7160 : :
7161 : 17 : if (0)
7162 : : layout->dump ();
7163 : : }
7164 : :
7165 : : unsigned i;
7166 : : const concrete_binding *ckey;
7167 : 45 : FOR_EACH_VEC_ELT (uninit_keys, i, ckey)
7168 : : {
7169 : 24 : bit_offset_t start_bit = ckey->get_start_bit_offset ();
7170 : 24 : bit_offset_t next_bit = ckey->get_next_bit_offset ();
7171 : 24 : complain_about_uninit_range (loc, start_bit, next_bit,
7172 : 24 : layout.get ());
7173 : : }
7174 : 21 : }
7175 : 25 : }
7176 : :
7177 : 24 : void complain_about_uninit_range (location_t loc,
7178 : : bit_offset_t start_bit,
7179 : : bit_offset_t next_bit,
7180 : : const record_layout *layout) const
7181 : : {
7182 : 24 : if (layout)
7183 : : {
7184 : 75 : while (start_bit < next_bit)
7185 : : {
7186 : 165 : if (const record_layout::item *item
7187 : 55 : = layout->get_item_at (start_bit))
7188 : : {
7189 : 55 : gcc_assert (start_bit >= item->get_start_bit_offset ());
7190 : 55 : gcc_assert (start_bit < item->get_next_bit_offset ());
7191 : 55 : if (item->get_start_bit_offset () == start_bit
7192 : 108 : && item->get_next_bit_offset () <= next_bit)
7193 : 53 : complain_about_fully_uninit_item (*item);
7194 : : else
7195 : 2 : complain_about_partially_uninit_item (*item);
7196 : 55 : start_bit = item->get_next_bit_offset ();
7197 : 55 : continue;
7198 : : }
7199 : : else
7200 : : break;
7201 : : }
7202 : : }
7203 : :
7204 : 24 : if (start_bit >= next_bit)
7205 : : return;
7206 : :
7207 : 4 : if (start_bit % 8 == 0 && next_bit % 8 == 0)
7208 : : {
7209 : : /* Express in bytes. */
7210 : 4 : byte_offset_t start_byte = start_bit / 8;
7211 : 4 : byte_offset_t last_byte = (next_bit / 8) - 1;
7212 : 4 : if (last_byte == start_byte)
7213 : 0 : inform (loc,
7214 : : "byte %wu is uninitialized",
7215 : : start_byte.to_uhwi ());
7216 : : else
7217 : 4 : inform (loc,
7218 : : "bytes %wu - %wu are uninitialized",
7219 : : start_byte.to_uhwi (),
7220 : : last_byte.to_uhwi ());
7221 : : }
7222 : : else
7223 : : {
7224 : : /* Express in bits. */
7225 : 0 : bit_offset_t last_bit = next_bit - 1;
7226 : 0 : if (last_bit == start_bit)
7227 : 0 : inform (loc,
7228 : : "bit %wu is uninitialized",
7229 : : start_bit.to_uhwi ());
7230 : : else
7231 : 0 : inform (loc,
7232 : : "bits %wu - %wu are uninitialized",
7233 : : start_bit.to_uhwi (),
7234 : : last_bit.to_uhwi ());
7235 : : }
7236 : : }
7237 : :
7238 : : static void
7239 : 53 : complain_about_fully_uninit_item (const record_layout::item &item)
7240 : : {
7241 : 53 : tree field = item.m_field;
7242 : 53 : bit_size_t num_bits = item.m_bit_range.m_size_in_bits;
7243 : 53 : if (item.m_is_padding)
7244 : : {
7245 : 11 : if (num_bits % 8 == 0)
7246 : : {
7247 : : /* Express in bytes. */
7248 : 9 : byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
7249 : 9 : if (num_bytes == 1)
7250 : 2 : inform (DECL_SOURCE_LOCATION (field),
7251 : : "padding after field %qD is uninitialized (1 byte)",
7252 : : field);
7253 : : else
7254 : 7 : inform (DECL_SOURCE_LOCATION (field),
7255 : : "padding after field %qD is uninitialized (%wu bytes)",
7256 : : field, num_bytes.to_uhwi ());
7257 : : }
7258 : : else
7259 : : {
7260 : : /* Express in bits. */
7261 : 2 : if (num_bits == 1)
7262 : 0 : inform (DECL_SOURCE_LOCATION (field),
7263 : : "padding after field %qD is uninitialized (1 bit)",
7264 : : field);
7265 : : else
7266 : 2 : inform (DECL_SOURCE_LOCATION (field),
7267 : : "padding after field %qD is uninitialized (%wu bits)",
7268 : : field, num_bits.to_uhwi ());
7269 : : }
7270 : : }
7271 : : else
7272 : : {
7273 : 42 : if (num_bits % 8 == 0)
7274 : : {
7275 : : /* Express in bytes. */
7276 : 32 : byte_size_t num_bytes = num_bits / BITS_PER_UNIT;
7277 : 32 : if (num_bytes == 1)
7278 : 1 : inform (DECL_SOURCE_LOCATION (field),
7279 : : "field %qD is uninitialized (1 byte)", field);
7280 : : else
7281 : 31 : inform (DECL_SOURCE_LOCATION (field),
7282 : : "field %qD is uninitialized (%wu bytes)",
7283 : : field, num_bytes.to_uhwi ());
7284 : : }
7285 : : else
7286 : : {
7287 : : /* Express in bits. */
7288 : 10 : if (num_bits == 1)
7289 : 9 : inform (DECL_SOURCE_LOCATION (field),
7290 : : "field %qD is uninitialized (1 bit)", field);
7291 : : else
7292 : 1 : inform (DECL_SOURCE_LOCATION (field),
7293 : : "field %qD is uninitialized (%wu bits)",
7294 : : field, num_bits.to_uhwi ());
7295 : : }
7296 : : }
7297 : 53 : }
7298 : :
7299 : : static void
7300 : 2 : complain_about_partially_uninit_item (const record_layout::item &item)
7301 : : {
7302 : 2 : tree field = item.m_field;
7303 : 2 : if (item.m_is_padding)
7304 : 0 : inform (DECL_SOURCE_LOCATION (field),
7305 : : "padding after field %qD is partially uninitialized",
7306 : : field);
7307 : : else
7308 : 2 : inform (DECL_SOURCE_LOCATION (field),
7309 : : "field %qD is partially uninitialized",
7310 : : field);
7311 : : /* TODO: ideally we'd describe what parts are uninitialized. */
7312 : 2 : }
7313 : :
7314 : 25 : void maybe_emit_fixit_hint () const
7315 : : {
7316 : 25 : if (tree decl = m_src_region->maybe_get_decl ())
7317 : : {
7318 : 25 : gcc_rich_location hint_richloc (DECL_SOURCE_LOCATION (decl));
7319 : 25 : hint_richloc.add_fixit_insert_after (" = {0}");
7320 : 25 : inform (&hint_richloc,
7321 : : "suggest forcing zero-initialization by"
7322 : : " providing a %<{0}%> initializer");
7323 : 25 : }
7324 : 25 : }
7325 : :
7326 : : private:
7327 : : const region *m_src_region;
7328 : : const region *m_dest_region;
7329 : : const svalue *m_copied_sval;
7330 : : };
7331 : :
7332 : : /* Return true if any part of SVAL is uninitialized. */
7333 : :
7334 : : static bool
7335 : 152 : contains_uninit_p (const svalue *sval)
7336 : : {
7337 : 152 : switch (sval->get_kind ())
7338 : : {
7339 : : default:
7340 : : return false;
7341 : 5 : case SK_POISONED:
7342 : 5 : {
7343 : 5 : const poisoned_svalue *psval
7344 : 5 : = as_a <const poisoned_svalue *> (sval);
7345 : 5 : return psval->get_poison_kind () == POISON_KIND_UNINIT;
7346 : : }
7347 : 84 : case SK_COMPOUND:
7348 : 84 : {
7349 : 84 : const compound_svalue *compound_sval
7350 : 84 : = as_a <const compound_svalue *> (sval);
7351 : :
7352 : 402 : for (auto iter : *compound_sval)
7353 : : {
7354 : 201 : const svalue *sval = iter.second;
7355 : 402 : if (const poisoned_svalue *psval
7356 : 201 : = sval->dyn_cast_poisoned_svalue ())
7357 : 42 : if (psval->get_poison_kind () == POISON_KIND_UNINIT)
7358 : 42 : return true;
7359 : : }
7360 : :
7361 : 42 : return false;
7362 : : }
7363 : : }
7364 : : }
7365 : :
7366 : : /* Function for use by plugins when simulating writing data through a
7367 : : pointer to an "untrusted" region DST_REG (and thus crossing a security
7368 : : boundary), such as copying data to user space in an OS kernel.
7369 : :
7370 : : Check that COPIED_SVAL is fully initialized. If not, complain about
7371 : : an infoleak to CTXT.
7372 : :
7373 : : SRC_REG can be NULL; if non-NULL it is used as a hint in the diagnostic
7374 : : as to where COPIED_SVAL came from. */
7375 : :
7376 : : void
7377 : 152 : region_model::maybe_complain_about_infoleak (const region *dst_reg,
7378 : : const svalue *copied_sval,
7379 : : const region *src_reg,
7380 : : region_model_context *ctxt)
7381 : : {
7382 : : /* Check for exposure. */
7383 : 152 : if (contains_uninit_p (copied_sval))
7384 : 47 : ctxt->warn (make_unique<exposure_through_uninit_copy> (src_reg,
7385 : : dst_reg,
7386 : : copied_sval));
7387 : 152 : }
7388 : :
7389 : : /* Set errno to a positive symbolic int, as if some error has occurred. */
7390 : :
7391 : : void
7392 : 455 : region_model::set_errno (const call_details &cd)
7393 : : {
7394 : 455 : const region *errno_reg = m_mgr->get_errno_region ();
7395 : 455 : conjured_purge p (this, cd.get_ctxt ());
7396 : 455 : const svalue *new_errno_sval
7397 : 455 : = m_mgr->get_or_create_conjured_svalue (integer_type_node,
7398 : 455 : cd.get_call_stmt (),
7399 : : errno_reg, p);
7400 : 455 : const svalue *zero
7401 : 455 : = m_mgr->get_or_create_int_cst (integer_type_node, 0);
7402 : 455 : add_constraint (new_errno_sval, GT_EXPR, zero, cd.get_ctxt ());
7403 : 455 : set_value (errno_reg, new_errno_sval, cd.get_ctxt ());
7404 : 455 : }
7405 : :
7406 : : /* class noop_region_model_context : public region_model_context. */
7407 : :
7408 : : void
7409 : 0 : noop_region_model_context::add_note (std::unique_ptr<pending_note>)
7410 : : {
7411 : 0 : }
7412 : :
7413 : : void
7414 : 0 : noop_region_model_context::add_event (std::unique_ptr<checker_event>)
7415 : : {
7416 : 0 : }
7417 : :
7418 : : void
7419 : 0 : noop_region_model_context::bifurcate (std::unique_ptr<custom_edge_info>)
7420 : : {
7421 : 0 : }
7422 : :
7423 : : void
7424 : 0 : noop_region_model_context::terminate_path ()
7425 : : {
7426 : 0 : }
7427 : :
7428 : : /* class region_model_context_decorator : public region_model_context. */
7429 : :
7430 : : void
7431 : 179 : region_model_context_decorator::add_event (std::unique_ptr<checker_event> event)
7432 : : {
7433 : 179 : if (m_inner)
7434 : 179 : m_inner->add_event (std::move (event));
7435 : 179 : }
7436 : :
7437 : : /* struct model_merger. */
7438 : :
7439 : : /* Dump a multiline representation of this merger to PP. */
7440 : :
7441 : : void
7442 : 0 : model_merger::dump_to_pp (pretty_printer *pp, bool simple) const
7443 : : {
7444 : 0 : pp_string (pp, "model A:");
7445 : 0 : pp_newline (pp);
7446 : 0 : m_model_a->dump_to_pp (pp, simple, true);
7447 : 0 : pp_newline (pp);
7448 : :
7449 : 0 : pp_string (pp, "model B:");
7450 : 0 : pp_newline (pp);
7451 : 0 : m_model_b->dump_to_pp (pp, simple, true);
7452 : 0 : pp_newline (pp);
7453 : :
7454 : 0 : pp_string (pp, "merged model:");
7455 : 0 : pp_newline (pp);
7456 : 0 : m_merged_model->dump_to_pp (pp, simple, true);
7457 : 0 : pp_newline (pp);
7458 : 0 : }
7459 : :
7460 : : /* Dump a multiline representation of this merger to FILE. */
7461 : :
7462 : : void
7463 : 0 : model_merger::dump (FILE *fp, bool simple) const
7464 : : {
7465 : 0 : tree_dump_pretty_printer pp (fp);
7466 : 0 : dump_to_pp (&pp, simple);
7467 : 0 : }
7468 : :
7469 : : /* Dump a multiline representation of this merger to stderr. */
7470 : :
7471 : : DEBUG_FUNCTION void
7472 : 0 : model_merger::dump (bool simple) const
7473 : : {
7474 : 0 : dump (stderr, simple);
7475 : 0 : }
7476 : :
7477 : : /* Return true if it's OK to merge SVAL with other svalues. */
7478 : :
7479 : : bool
7480 : 377956 : model_merger::mergeable_svalue_p (const svalue *sval) const
7481 : : {
7482 : 377956 : if (m_ext_state)
7483 : : {
7484 : : /* Reject merging svalues that have non-purgable sm-state,
7485 : : to avoid falsely reporting memory leaks by merging them
7486 : : with something else. For example, given a local var "p",
7487 : : reject the merger of a:
7488 : : store_a mapping "p" to a malloc-ed ptr
7489 : : with:
7490 : : store_b mapping "p" to a NULL ptr. */
7491 : 377908 : if (m_state_a)
7492 : 377908 : if (!m_state_a->can_purge_p (*m_ext_state, sval))
|