1 /* Classes for modeling the state of memory.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef GCC_ANALYZER_REGION_MODEL_H
22 #define GCC_ANALYZER_REGION_MODEL_H
24 /* Implementation of the region-based ternary model described in:
25 "A Memory Model for Static Analysis of C Programs"
26 (Zhongxing Xu, Ted Kremenek, and Jian Zhang)
27 http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf */
29 #include "analyzer/svalue.h"
30 #include "analyzer/region.h"
36 extern void add_path_var (path_var pv
, hash
&hstate
);
37 } // namespace inchash
45 one_way_id_map (int num_ids
);
46 void put (T src
, T dst
);
47 T
get_dst_for_src (T src
) const;
48 void dump_to_pp (pretty_printer
*pp
) const;
50 void update (T
*) const;
53 auto_vec
<T
> m_src_to_dst
;
56 /* class one_way_id_map. */
58 /* one_way_id_map's ctor, which populates the map with dummy null values. */
61 inline one_way_id_map
<T
>::one_way_id_map (int num_svalues
)
62 : m_src_to_dst (num_svalues
)
64 for (int i
= 0; i
< num_svalues
; i
++)
65 m_src_to_dst
.quick_push (T::null ());
68 /* Record that SRC is to be mapped to DST. */
72 one_way_id_map
<T
>::put (T src
, T dst
)
74 m_src_to_dst
[src
.as_int ()] = dst
;
77 /* Get the new value for SRC within the map. */
81 one_way_id_map
<T
>::get_dst_for_src (T src
) const
85 return m_src_to_dst
[src
.as_int ()];
88 /* Dump this map to PP. */
92 one_way_id_map
<T
>::dump_to_pp (pretty_printer
*pp
) const
94 pp_string (pp
, "src to dst: {");
97 FOR_EACH_VEC_ELT (m_src_to_dst
, i
, dst
)
100 pp_string (pp
, ", ");
101 T
src (T::from_int (i
));
103 pp_string (pp
, " -> ");
110 /* Dump this map to stderr. */
112 template <typename T
>
113 DEBUG_FUNCTION
inline void
114 one_way_id_map
<T
>::dump () const
117 pp
.buffer
->stream
= stderr
;
122 /* Update *ID from the old value to its new value in this map. */
124 template <typename T
>
126 one_way_id_map
<T
>::update (T
*id
) const
128 *id
= get_dst_for_src (*id
);
131 /* A mapping from region to svalue for use when tracking state. */
133 class region_to_value_map
136 typedef hash_map
<const region
*, const svalue
*> hash_map_t
;
137 typedef hash_map_t::iterator iterator
;
139 region_to_value_map () : m_hash_map () {}
140 region_to_value_map (const region_to_value_map
&other
)
141 : m_hash_map (other
.m_hash_map
) {}
142 region_to_value_map
&operator= (const region_to_value_map
&other
);
144 bool operator== (const region_to_value_map
&other
) const;
145 bool operator!= (const region_to_value_map
&other
) const
147 return !(*this == other
);
150 iterator
begin () const { return m_hash_map
.begin (); }
151 iterator
end () const { return m_hash_map
.end (); }
153 const svalue
* const *get (const region
*reg
) const
155 return const_cast <hash_map_t
&> (m_hash_map
).get (reg
);
157 void put (const region
*reg
, const svalue
*sval
)
159 m_hash_map
.put (reg
, sval
);
161 void remove (const region
*reg
)
163 m_hash_map
.remove (reg
);
166 bool is_empty () const { return m_hash_map
.is_empty (); }
168 void dump_to_pp (pretty_printer
*pp
, bool simple
, bool multiline
) const;
169 void dump (bool simple
) const;
171 bool can_merge_with_p (const region_to_value_map
&other
,
172 region_to_value_map
*out
) const;
174 void purge_state_involving (const svalue
*sval
);
177 hash_map_t m_hash_map
;
180 /* Various operations delete information from a region_model.
182 This struct tracks how many of each kind of entity were purged (e.g.
183 for selftests, and for debugging). */
190 m_num_equiv_classes (0),
191 m_num_constraints (0),
192 m_num_bounded_ranges_constraints (0),
193 m_num_client_items (0)
198 int m_num_equiv_classes
;
199 int m_num_constraints
;
200 int m_num_bounded_ranges_constraints
;
201 int m_num_client_items
;
204 /* A base class for visiting regions and svalues, with do-nothing
205 base implementations of the per-subclass vfuncs. */
210 virtual void visit_region_svalue (const region_svalue
*) {}
211 virtual void visit_constant_svalue (const constant_svalue
*) {}
212 virtual void visit_unknown_svalue (const unknown_svalue
*) {}
213 virtual void visit_poisoned_svalue (const poisoned_svalue
*) {}
214 virtual void visit_setjmp_svalue (const setjmp_svalue
*) {}
215 virtual void visit_initial_svalue (const initial_svalue
*) {}
216 virtual void visit_unaryop_svalue (const unaryop_svalue
*) {}
217 virtual void visit_binop_svalue (const binop_svalue
*) {}
218 virtual void visit_sub_svalue (const sub_svalue
*) {}
219 virtual void visit_repeated_svalue (const repeated_svalue
*) {}
220 virtual void visit_bits_within_svalue (const bits_within_svalue
*) {}
221 virtual void visit_unmergeable_svalue (const unmergeable_svalue
*) {}
222 virtual void visit_placeholder_svalue (const placeholder_svalue
*) {}
223 virtual void visit_widening_svalue (const widening_svalue
*) {}
224 virtual void visit_compound_svalue (const compound_svalue
*) {}
225 virtual void visit_conjured_svalue (const conjured_svalue
*) {}
226 virtual void visit_asm_output_svalue (const asm_output_svalue
*) {}
228 virtual void visit_region (const region
*) {}
235 /* A class responsible for owning and consolidating region and svalue
237 region and svalue instances are immutable as far as clients are
238 concerned, so they are provided as "const" ptrs. */
240 class region_model_manager
243 region_model_manager (logger
*logger
= NULL
);
244 ~region_model_manager ();
246 /* svalue consolidation. */
247 const svalue
*get_or_create_constant_svalue (tree cst_expr
);
248 const svalue
*get_or_create_int_cst (tree type
, poly_int64
);
249 const svalue
*get_or_create_unknown_svalue (tree type
);
250 const svalue
*get_or_create_setjmp_svalue (const setjmp_record
&r
,
252 const svalue
*get_or_create_poisoned_svalue (enum poison_kind kind
,
254 const svalue
*get_or_create_initial_value (const region
*reg
);
255 const svalue
*get_ptr_svalue (tree ptr_type
, const region
*pointee
);
256 const svalue
*get_or_create_unaryop (tree type
, enum tree_code op
,
258 const svalue
*get_or_create_cast (tree type
, const svalue
*arg
);
259 const svalue
*get_or_create_binop (tree type
,
261 const svalue
*arg0
, const svalue
*arg1
);
262 const svalue
*get_or_create_sub_svalue (tree type
,
263 const svalue
*parent_svalue
,
264 const region
*subregion
);
265 const svalue
*get_or_create_repeated_svalue (tree type
,
266 const svalue
*outer_size
,
267 const svalue
*inner_svalue
);
268 const svalue
*get_or_create_bits_within (tree type
,
269 const bit_range
&bits
,
270 const svalue
*inner_svalue
);
271 const svalue
*get_or_create_unmergeable (const svalue
*arg
);
272 const svalue
*get_or_create_widening_svalue (tree type
,
273 const program_point
&point
,
274 const svalue
*base_svalue
,
275 const svalue
*iter_svalue
);
276 const svalue
*get_or_create_compound_svalue (tree type
,
277 const binding_map
&map
);
278 const svalue
*get_or_create_conjured_svalue (tree type
, const gimple
*stmt
,
279 const region
*id_reg
);
281 get_or_create_asm_output_svalue (tree type
,
282 const gasm
*asm_stmt
,
284 const vec
<const svalue
*> &inputs
);
286 const svalue
*maybe_get_char_from_string_cst (tree string_cst
,
287 tree byte_offset_cst
);
289 /* region consolidation. */
290 const stack_region
* get_stack_region () const { return &m_stack_region
; }
291 const heap_region
*get_heap_region () const { return &m_heap_region
; }
292 const code_region
*get_code_region () const { return &m_code_region
; }
293 const globals_region
*get_globals_region () const
295 return &m_globals_region
;
297 const function_region
*get_region_for_fndecl (tree fndecl
);
298 const label_region
*get_region_for_label (tree label
);
299 const decl_region
*get_region_for_global (tree expr
);
300 const region
*get_field_region (const region
*parent
, tree field
);
301 const region
*get_element_region (const region
*parent
,
303 const svalue
*index
);
304 const region
*get_offset_region (const region
*parent
,
306 const svalue
*byte_offset
);
307 const region
*get_sized_region (const region
*parent
,
309 const svalue
*byte_size_sval
);
310 const region
*get_cast_region (const region
*original_region
,
312 const frame_region
*get_frame_region (const frame_region
*calling_frame
,
314 const region
*get_symbolic_region (const svalue
*sval
);
315 const string_region
*get_region_for_string (tree string_cst
);
318 get_region_for_unexpected_tree_code (region_model_context
*ctxt
,
320 const dump_location_t
&loc
);
322 unsigned alloc_region_id () { return m_next_region_id
++; }
324 store_manager
*get_store_manager () { return &m_store_mgr
; }
325 bounded_ranges_manager
*get_range_manager () const { return m_range_mgr
; }
327 /* Dynamically-allocated region instances.
328 The number of these within the analysis can grow arbitrarily.
329 They are still owned by the manager. */
330 const region
*create_region_for_heap_alloc ();
331 const region
*create_region_for_alloca (const frame_region
*frame
);
333 void log_stats (logger
*logger
, bool show_objs
) const;
335 void enable_complexity_check (void) { m_check_complexity
= true; }
336 void disable_complexity_check (void) { m_check_complexity
= false; }
338 logger
*get_logger () const { return m_logger
; }
341 bool too_complex_p (const complexity
&c
) const;
342 bool reject_if_too_complex (svalue
*sval
);
344 const svalue
*maybe_fold_unaryop (tree type
, enum tree_code op
,
346 const svalue
*maybe_fold_binop (tree type
, enum tree_code op
,
347 const svalue
*arg0
, const svalue
*arg1
);
348 const svalue
*maybe_fold_sub_svalue (tree type
,
349 const svalue
*parent_svalue
,
350 const region
*subregion
);
351 const svalue
*maybe_fold_repeated_svalue (tree type
,
352 const svalue
*outer_size
,
353 const svalue
*inner_svalue
);
354 const svalue
*maybe_fold_bits_within_svalue (tree type
,
355 const bit_range
&bits
,
356 const svalue
*inner_svalue
);
357 const svalue
*maybe_undo_optimize_bit_field_compare (tree type
,
358 const compound_svalue
*compound_sval
,
359 tree cst
, const svalue
*arg1
);
360 const svalue
*maybe_fold_asm_output_svalue (tree type
,
361 const vec
<const svalue
*> &inputs
);
365 unsigned m_next_region_id
;
366 root_region m_root_region
;
367 stack_region m_stack_region
;
368 heap_region m_heap_region
;
370 /* svalue consolidation. */
371 typedef hash_map
<tree
, constant_svalue
*> constants_map_t
;
372 constants_map_t m_constants_map
;
374 typedef hash_map
<tree
, unknown_svalue
*> unknowns_map_t
;
375 unknowns_map_t m_unknowns_map
;
376 const unknown_svalue
*m_unknown_NULL
;
378 typedef hash_map
<poisoned_svalue::key_t
,
379 poisoned_svalue
*> poisoned_values_map_t
;
380 poisoned_values_map_t m_poisoned_values_map
;
382 typedef hash_map
<setjmp_svalue::key_t
,
383 setjmp_svalue
*> setjmp_values_map_t
;
384 setjmp_values_map_t m_setjmp_values_map
;
386 typedef hash_map
<const region
*, initial_svalue
*> initial_values_map_t
;
387 initial_values_map_t m_initial_values_map
;
389 typedef hash_map
<region_svalue::key_t
, region_svalue
*> pointer_values_map_t
;
390 pointer_values_map_t m_pointer_values_map
;
392 typedef hash_map
<unaryop_svalue::key_t
,
393 unaryop_svalue
*> unaryop_values_map_t
;
394 unaryop_values_map_t m_unaryop_values_map
;
396 typedef hash_map
<binop_svalue::key_t
, binop_svalue
*> binop_values_map_t
;
397 binop_values_map_t m_binop_values_map
;
399 typedef hash_map
<sub_svalue::key_t
, sub_svalue
*> sub_values_map_t
;
400 sub_values_map_t m_sub_values_map
;
402 typedef hash_map
<repeated_svalue::key_t
,
403 repeated_svalue
*> repeated_values_map_t
;
404 repeated_values_map_t m_repeated_values_map
;
406 typedef hash_map
<bits_within_svalue::key_t
,
407 bits_within_svalue
*> bits_within_values_map_t
;
408 bits_within_values_map_t m_bits_within_values_map
;
410 typedef hash_map
<const svalue
*,
411 unmergeable_svalue
*> unmergeable_values_map_t
;
412 unmergeable_values_map_t m_unmergeable_values_map
;
414 typedef hash_map
<widening_svalue::key_t
,
416 widening_svalue::key_t::hash_map_traits*/
>
417 widening_values_map_t
;
418 widening_values_map_t m_widening_values_map
;
420 typedef hash_map
<compound_svalue::key_t
,
421 compound_svalue
*> compound_values_map_t
;
422 compound_values_map_t m_compound_values_map
;
424 typedef hash_map
<conjured_svalue::key_t
,
425 conjured_svalue
*> conjured_values_map_t
;
426 conjured_values_map_t m_conjured_values_map
;
428 typedef hash_map
<asm_output_svalue::key_t
,
429 asm_output_svalue
*> asm_output_values_map_t
;
430 asm_output_values_map_t m_asm_output_values_map
;
432 bool m_check_complexity
;
434 /* Maximum complexity of svalues that weren't rejected. */
435 complexity m_max_complexity
;
437 /* region consolidation. */
439 code_region m_code_region
;
440 typedef hash_map
<tree
, function_region
*> fndecls_map_t
;
441 typedef fndecls_map_t::iterator fndecls_iterator_t
;
442 fndecls_map_t m_fndecls_map
;
444 typedef hash_map
<tree
, label_region
*> labels_map_t
;
445 typedef labels_map_t::iterator labels_iterator_t
;
446 labels_map_t m_labels_map
;
448 globals_region m_globals_region
;
449 typedef hash_map
<tree
, decl_region
*> globals_map_t
;
450 typedef globals_map_t::iterator globals_iterator_t
;
451 globals_map_t m_globals_map
;
453 consolidation_map
<field_region
> m_field_regions
;
454 consolidation_map
<element_region
> m_element_regions
;
455 consolidation_map
<offset_region
> m_offset_regions
;
456 consolidation_map
<sized_region
> m_sized_regions
;
457 consolidation_map
<cast_region
> m_cast_regions
;
458 consolidation_map
<frame_region
> m_frame_regions
;
459 consolidation_map
<symbolic_region
> m_symbolic_regions
;
461 typedef hash_map
<tree
, string_region
*> string_map_t
;
462 string_map_t m_string_map
;
464 store_manager m_store_mgr
;
466 bounded_ranges_manager
*m_range_mgr
;
468 /* "Dynamically-allocated" region instances.
469 The number of these within the analysis can grow arbitrarily.
470 They are still owned by the manager. */
471 auto_delete_vec
<region
> m_managed_dynamic_regions
;
474 struct append_ssa_names_cb_data
;
476 /* Helper class for handling calls to functions with known behavior.
477 Implemented in region-model-impl-calls.c. */
482 call_details (const gcall
*call
, region_model
*model
,
483 region_model_context
*ctxt
);
485 region_model_context
*get_ctxt () const { return m_ctxt
; }
486 uncertainty_t
*get_uncertainty () const;
487 tree
get_lhs_type () const { return m_lhs_type
; }
488 const region
*get_lhs_region () const { return m_lhs_region
; }
490 bool maybe_set_lhs (const svalue
*result
) const;
492 unsigned num_args () const;
494 const gcall
*get_call_stmt () const { return m_call
; }
496 tree
get_arg_tree (unsigned idx
) const;
497 tree
get_arg_type (unsigned idx
) const;
498 const svalue
*get_arg_svalue (unsigned idx
) const;
499 const char *get_arg_string_literal (unsigned idx
) const;
501 tree
get_fndecl_for_call () const;
503 void dump_to_pp (pretty_printer
*pp
, bool simple
) const;
504 void dump (bool simple
) const;
506 const svalue
*get_or_create_conjured_svalue (const region
*) const;
510 region_model
*m_model
;
511 region_model_context
*m_ctxt
;
513 const region
*m_lhs_region
;
516 /* A region_model encapsulates a representation of the state of memory, with
517 a tree of regions, along with their associated values.
518 The representation is graph-like because values can be pointers to
521 - a constraint_manager, capturing relationships between the values, and
522 - dynamic extents, mapping dynamically-allocated regions to svalues (their
528 typedef region_to_value_map dynamic_extents_t
;
530 region_model (region_model_manager
*mgr
);
531 region_model (const region_model
&other
);
533 region_model
&operator= (const region_model
&other
);
535 bool operator== (const region_model
&other
) const;
536 bool operator!= (const region_model
&other
) const
538 return !(*this == other
);
541 hashval_t
hash () const;
543 void print (pretty_printer
*pp
) const;
545 void dump_to_pp (pretty_printer
*pp
, bool simple
, bool multiline
) const;
546 void dump (FILE *fp
, bool simple
, bool multiline
) const;
547 void dump (bool simple
) const;
551 void validate () const;
553 void canonicalize ();
554 bool canonicalized_p () const;
557 on_stmt_pre (const gimple
*stmt
,
558 bool *out_terminate_path
,
559 bool *out_unknown_side_effects
,
560 region_model_context
*ctxt
);
562 void on_assignment (const gassign
*stmt
, region_model_context
*ctxt
);
563 const svalue
*get_gassign_result (const gassign
*assign
,
564 region_model_context
*ctxt
);
565 void on_asm_stmt (const gasm
*asm_stmt
, region_model_context
*ctxt
);
566 bool on_call_pre (const gcall
*stmt
, region_model_context
*ctxt
,
567 bool *out_terminate_path
);
568 void on_call_post (const gcall
*stmt
,
569 bool unknown_side_effects
,
570 region_model_context
*ctxt
);
572 void purge_state_involving (const svalue
*sval
, region_model_context
*ctxt
);
574 /* Specific handling for on_call_pre. */
575 void impl_call_alloca (const call_details
&cd
);
576 void impl_call_analyzer_describe (const gcall
*call
,
577 region_model_context
*ctxt
);
578 void impl_call_analyzer_dump_capacity (const gcall
*call
,
579 region_model_context
*ctxt
);
580 void impl_call_analyzer_dump_escaped (const gcall
*call
);
581 void impl_call_analyzer_eval (const gcall
*call
,
582 region_model_context
*ctxt
);
583 void impl_call_builtin_expect (const call_details
&cd
);
584 void impl_call_calloc (const call_details
&cd
);
585 bool impl_call_error (const call_details
&cd
, unsigned min_args
,
586 bool *out_terminate_path
);
587 void impl_call_fgets (const call_details
&cd
);
588 void impl_call_fread (const call_details
&cd
);
589 void impl_call_free (const call_details
&cd
);
590 void impl_call_malloc (const call_details
&cd
);
591 void impl_call_memcpy (const call_details
&cd
);
592 void impl_call_memset (const call_details
&cd
);
593 void impl_call_realloc (const call_details
&cd
);
594 void impl_call_strchr (const call_details
&cd
);
595 void impl_call_strcpy (const call_details
&cd
);
596 void impl_call_strlen (const call_details
&cd
);
597 void impl_call_operator_new (const call_details
&cd
);
598 void impl_call_operator_delete (const call_details
&cd
);
599 void impl_deallocation_call (const call_details
&cd
);
601 void handle_unrecognized_call (const gcall
*call
,
602 region_model_context
*ctxt
);
603 void get_reachable_svalues (svalue_set
*out
,
604 const svalue
*extra_sval
,
605 const uncertainty_t
*uncertainty
);
607 void on_return (const greturn
*stmt
, region_model_context
*ctxt
);
608 void on_setjmp (const gcall
*stmt
, const exploded_node
*enode
,
609 region_model_context
*ctxt
);
610 void on_longjmp (const gcall
*longjmp_call
, const gcall
*setjmp_call
,
611 int setjmp_stack_depth
, region_model_context
*ctxt
);
613 void update_for_phis (const supernode
*snode
,
614 const cfg_superedge
*last_cfg_superedge
,
615 region_model_context
*ctxt
);
617 void handle_phi (const gphi
*phi
, tree lhs
, tree rhs
,
618 const region_model
&old_state
,
619 region_model_context
*ctxt
);
621 bool maybe_update_for_edge (const superedge
&edge
,
622 const gimple
*last_stmt
,
623 region_model_context
*ctxt
,
624 rejected_constraint
**out
);
626 void update_for_gcall (const gcall
*call_stmt
,
627 region_model_context
*ctxt
,
628 function
*callee
= NULL
);
630 void update_for_return_gcall (const gcall
*call_stmt
,
631 region_model_context
*ctxt
);
633 const region
*push_frame (function
*fun
, const vec
<const svalue
*> *arg_sids
,
634 region_model_context
*ctxt
);
635 const frame_region
*get_current_frame () const { return m_current_frame
; }
636 function
* get_current_function () const;
637 void pop_frame (const region
*result_dst
,
638 const svalue
**out_result
,
639 region_model_context
*ctxt
);
640 int get_stack_depth () const;
641 const frame_region
*get_frame_at_index (int index
) const;
643 const region
*get_lvalue (path_var pv
, region_model_context
*ctxt
) const;
644 const region
*get_lvalue (tree expr
, region_model_context
*ctxt
) const;
645 const svalue
*get_rvalue (path_var pv
, region_model_context
*ctxt
) const;
646 const svalue
*get_rvalue (tree expr
, region_model_context
*ctxt
) const;
648 const region
*deref_rvalue (const svalue
*ptr_sval
, tree ptr_tree
,
649 region_model_context
*ctxt
) const;
651 const svalue
*get_rvalue_for_bits (tree type
,
653 const bit_range
&bits
,
654 region_model_context
*ctxt
) const;
656 void set_value (const region
*lhs_reg
, const svalue
*rhs_sval
,
657 region_model_context
*ctxt
);
658 void set_value (tree lhs
, tree rhs
, region_model_context
*ctxt
);
659 void clobber_region (const region
*reg
);
660 void purge_region (const region
*reg
);
661 void fill_region (const region
*reg
, const svalue
*sval
);
662 void zero_fill_region (const region
*reg
);
663 void mark_region_as_unknown (const region
*reg
, uncertainty_t
*uncertainty
);
665 void copy_region (const region
*dst_reg
, const region
*src_reg
,
666 region_model_context
*ctxt
);
667 tristate
eval_condition (const svalue
*lhs
,
669 const svalue
*rhs
) const;
670 tristate
eval_condition_without_cm (const svalue
*lhs
,
672 const svalue
*rhs
) const;
673 tristate
compare_initial_and_pointer (const initial_svalue
*init
,
674 const region_svalue
*ptr
) const;
675 tristate
eval_condition (tree lhs
,
678 region_model_context
*ctxt
);
679 bool add_constraint (tree lhs
, enum tree_code op
, tree rhs
,
680 region_model_context
*ctxt
);
681 bool add_constraint (tree lhs
, enum tree_code op
, tree rhs
,
682 region_model_context
*ctxt
,
683 rejected_constraint
**out
);
685 const region
*create_region_for_heap_alloc (const svalue
*size_in_bytes
,
686 region_model_context
*ctxt
);
687 const region
*create_region_for_alloca (const svalue
*size_in_bytes
,
688 region_model_context
*ctxt
);
690 tree
get_representative_tree (const svalue
*sval
) const;
692 get_representative_path_var (const svalue
*sval
,
693 svalue_set
*visited
) const;
695 get_representative_path_var (const region
*reg
,
696 svalue_set
*visited
) const;
699 constraint_manager
*get_constraints ()
701 return m_constraints
;
704 store
*get_store () { return &m_store
; }
705 const store
*get_store () const { return &m_store
; }
707 const dynamic_extents_t
&
708 get_dynamic_extents () const
710 return m_dynamic_extents
;
712 const svalue
*get_dynamic_extents (const region
*reg
) const;
713 void set_dynamic_extents (const region
*reg
,
714 const svalue
*size_in_bytes
,
715 region_model_context
*ctxt
);
716 void unset_dynamic_extents (const region
*reg
);
718 region_model_manager
*get_manager () const { return m_mgr
; }
719 bounded_ranges_manager
*get_range_manager () const
721 return m_mgr
->get_range_manager ();
724 void unbind_region_and_descendents (const region
*reg
,
725 enum poison_kind pkind
);
727 bool can_merge_with_p (const region_model
&other_model
,
728 const program_point
&point
,
729 region_model
*out_model
,
730 const extrinsic_state
*ext_state
= NULL
,
731 const program_state
*state_a
= NULL
,
732 const program_state
*state_b
= NULL
) const;
734 tree
get_fndecl_for_call (const gcall
*call
,
735 region_model_context
*ctxt
);
737 void get_ssa_name_regions_for_current_frame
738 (auto_vec
<const decl_region
*> *out
) const;
739 static void append_ssa_names_cb (const region
*base_reg
,
740 struct append_ssa_names_cb_data
*data
);
742 const svalue
*get_store_value (const region
*reg
,
743 region_model_context
*ctxt
) const;
745 bool region_exists_p (const region
*reg
) const;
747 void loop_replay_fixup (const region_model
*dst_state
);
749 const svalue
*get_capacity (const region
*reg
) const;
751 /* Implemented in sm-malloc.cc */
752 void on_realloc_with_move (const call_details
&cd
,
753 const svalue
*old_ptr_sval
,
754 const svalue
*new_ptr_sval
);
757 const region
*get_lvalue_1 (path_var pv
, region_model_context
*ctxt
) const;
758 const svalue
*get_rvalue_1 (path_var pv
, region_model_context
*ctxt
) const;
761 get_representative_path_var_1 (const svalue
*sval
,
762 svalue_set
*visited
) const;
764 get_representative_path_var_1 (const region
*reg
,
765 svalue_set
*visited
) const;
767 bool add_constraint (const svalue
*lhs
,
770 region_model_context
*ctxt
);
771 bool add_constraints_from_binop (const svalue
*outer_lhs
,
772 enum tree_code outer_op
,
773 const svalue
*outer_rhs
,
775 region_model_context
*ctxt
);
777 void update_for_call_superedge (const call_superedge
&call_edge
,
778 region_model_context
*ctxt
);
779 void update_for_return_superedge (const return_superedge
&return_edge
,
780 region_model_context
*ctxt
);
781 void update_for_call_summary (const callgraph_superedge
&cg_sedge
,
782 region_model_context
*ctxt
);
783 bool apply_constraints_for_gcond (const cfg_superedge
&edge
,
784 const gcond
*cond_stmt
,
785 region_model_context
*ctxt
,
786 rejected_constraint
**out
);
787 bool apply_constraints_for_gswitch (const switch_cfg_superedge
&edge
,
788 const gswitch
*switch_stmt
,
789 region_model_context
*ctxt
,
790 rejected_constraint
**out
);
791 bool apply_constraints_for_exception (const gimple
*last_stmt
,
792 region_model_context
*ctxt
,
793 rejected_constraint
**out
);
795 int poison_any_pointers_to_descendents (const region
*reg
,
796 enum poison_kind pkind
);
798 void on_top_level_param (tree param
, region_model_context
*ctxt
);
800 bool called_from_main_p () const;
801 const svalue
*get_initial_value_for_global (const region
*reg
) const;
803 const svalue
*check_for_poison (const svalue
*sval
,
805 region_model_context
*ctxt
) const;
807 void check_dynamic_size_for_taint (enum memory_space mem_space
,
808 const svalue
*size_in_bytes
,
809 region_model_context
*ctxt
) const;
811 void check_region_for_taint (const region
*reg
,
812 enum access_direction dir
,
813 region_model_context
*ctxt
) const;
815 void check_for_writable_region (const region
* dest_reg
,
816 region_model_context
*ctxt
) const;
817 void check_region_access (const region
*reg
,
818 enum access_direction dir
,
819 region_model_context
*ctxt
) const;
820 void check_region_for_write (const region
*dest_reg
,
821 region_model_context
*ctxt
) const;
822 void check_region_for_read (const region
*src_reg
,
823 region_model_context
*ctxt
) const;
825 /* Storing this here to avoid passing it around everywhere. */
826 region_model_manager
*const m_mgr
;
830 constraint_manager
*m_constraints
; // TODO: embed, rather than dynalloc?
832 const frame_region
*m_current_frame
;
834 /* Map from base region to size in bytes, for tracking the sizes of
835 dynamically-allocated regions.
836 This is part of the region_model rather than the region to allow for
837 memory regions to be resized (e.g. by realloc). */
838 dynamic_extents_t m_dynamic_extents
;
841 /* Some region_model activity could lead to warnings (e.g. attempts to use an
842 uninitialized value). This abstract base class encapsulates an interface
843 for the region model to use when emitting such warnings.
845 Having this as an abstract base class allows us to support the various
846 operations needed by program_state in the analyzer within region_model,
847 whilst keeping them somewhat modularized. */
849 class region_model_context
852 /* Hook for clients to store pending diagnostics.
853 Return true if the diagnostic was stored, or false if it was deleted. */
854 virtual bool warn (pending_diagnostic
*d
) = 0;
856 /* Hook for clients to be notified when an SVAL that was reachable
857 in a previous state is no longer live, so that clients can emit warnings
859 virtual void on_svalue_leak (const svalue
*sval
) = 0;
861 /* Hook for clients to be notified when the set of explicitly live
862 svalues changes, so that they can purge state relating to dead
864 virtual void on_liveness_change (const svalue_set
&live_svalues
,
865 const region_model
*model
) = 0;
867 virtual logger
*get_logger () = 0;
869 /* Hook for clients to be notified when the condition
870 "LHS OP RHS" is added to the region model.
871 This exists so that state machines can detect tests on edges,
872 and use them to trigger sm-state transitions (e.g. transitions due
873 to ptrs becoming known to be NULL or non-NULL, rather than just
875 virtual void on_condition (const svalue
*lhs
,
877 const svalue
*rhs
) = 0;
879 /* Hooks for clients to be notified when an unknown change happens
880 to SVAL (in response to a call to an unknown function). */
881 virtual void on_unknown_change (const svalue
*sval
, bool is_mutable
) = 0;
883 /* Hooks for clients to be notified when a phi node is handled,
884 where RHS is the pertinent argument. */
885 virtual void on_phi (const gphi
*phi
, tree rhs
) = 0;
887 /* Hooks for clients to be notified when the region model doesn't
888 know how to handle the tree code of T at LOC. */
889 virtual void on_unexpected_tree_code (tree t
,
890 const dump_location_t
&loc
) = 0;
892 /* Hook for clients to be notified when a function_decl escapes. */
893 virtual void on_escaped_function (tree fndecl
) = 0;
895 virtual uncertainty_t
*get_uncertainty () = 0;
897 /* Hook for clients to purge state involving SVAL. */
898 virtual void purge_state_involving (const svalue
*sval
) = 0;
900 /* Hook for clients to split state with a non-standard path.
901 Take ownership of INFO. */
902 virtual void bifurcate (custom_edge_info
*info
) = 0;
904 /* Hook for clients to terminate the standard path. */
905 virtual void terminate_path () = 0;
907 virtual const extrinsic_state
*get_ext_state () const = 0;
909 /* Hook for clients to access the "malloc" state machine in
910 any underlying program_state. */
911 virtual bool get_malloc_map (sm_state_map
**out_smap
,
912 const state_machine
**out_sm
,
913 unsigned *out_sm_idx
) = 0;
914 /* Likewise for the "taint" state machine. */
915 virtual bool get_taint_map (sm_state_map
**out_smap
,
916 const state_machine
**out_sm
,
917 unsigned *out_sm_idx
) = 0;
920 /* A "do nothing" subclass of region_model_context. */
922 class noop_region_model_context
: public region_model_context
925 bool warn (pending_diagnostic
*) OVERRIDE
{ return false; }
926 void on_svalue_leak (const svalue
*) OVERRIDE
{}
927 void on_liveness_change (const svalue_set
&,
928 const region_model
*) OVERRIDE
{}
929 logger
*get_logger () OVERRIDE
{ return NULL
; }
930 void on_condition (const svalue
*lhs ATTRIBUTE_UNUSED
,
931 enum tree_code op ATTRIBUTE_UNUSED
,
932 const svalue
*rhs ATTRIBUTE_UNUSED
) OVERRIDE
935 void on_unknown_change (const svalue
*sval ATTRIBUTE_UNUSED
,
936 bool is_mutable ATTRIBUTE_UNUSED
) OVERRIDE
939 void on_phi (const gphi
*phi ATTRIBUTE_UNUSED
,
940 tree rhs ATTRIBUTE_UNUSED
) OVERRIDE
943 void on_unexpected_tree_code (tree
, const dump_location_t
&) OVERRIDE
{}
945 void on_escaped_function (tree
) OVERRIDE
{}
947 uncertainty_t
*get_uncertainty () OVERRIDE
{ return NULL
; }
949 void purge_state_involving (const svalue
*sval ATTRIBUTE_UNUSED
) OVERRIDE
{}
951 void bifurcate (custom_edge_info
*info
) OVERRIDE
;
952 void terminate_path () OVERRIDE
;
954 const extrinsic_state
*get_ext_state () const OVERRIDE
{ return NULL
; }
956 bool get_malloc_map (sm_state_map
**,
957 const state_machine
**,
962 bool get_taint_map (sm_state_map
**,
963 const state_machine
**,
970 /* A subclass of region_model_context for determining if operations fail
971 e.g. "can we generate a region for the lvalue of EXPR?". */
973 class tentative_region_model_context
: public noop_region_model_context
976 tentative_region_model_context () : m_num_unexpected_codes (0) {}
978 void on_unexpected_tree_code (tree
, const dump_location_t
&)
981 m_num_unexpected_codes
++;
984 bool had_errors_p () const { return m_num_unexpected_codes
> 0; }
987 int m_num_unexpected_codes
;
990 /* A bundle of data for use when attempting to merge two region_model
991 instances to make a third. */
995 model_merger (const region_model
*model_a
,
996 const region_model
*model_b
,
997 const program_point
&point
,
998 region_model
*merged_model
,
999 const extrinsic_state
*ext_state
,
1000 const program_state
*state_a
,
1001 const program_state
*state_b
)
1002 : m_model_a (model_a
), m_model_b (model_b
),
1004 m_merged_model (merged_model
),
1005 m_ext_state (ext_state
),
1006 m_state_a (state_a
), m_state_b (state_b
)
1010 void dump_to_pp (pretty_printer
*pp
, bool simple
) const;
1011 void dump (FILE *fp
, bool simple
) const;
1012 void dump (bool simple
) const;
1014 region_model_manager
*get_manager () const
1016 return m_model_a
->get_manager ();
1019 bool mergeable_svalue_p (const svalue
*) const;
1021 const region_model
*m_model_a
;
1022 const region_model
*m_model_b
;
1023 const program_point
&m_point
;
1024 region_model
*m_merged_model
;
1026 const extrinsic_state
*m_ext_state
;
1027 const program_state
*m_state_a
;
1028 const program_state
*m_state_b
;
1031 /* A record that can (optionally) be written out when
1032 region_model::add_constraint fails. */
1034 class rejected_constraint
1037 virtual ~rejected_constraint () {}
1038 virtual void dump_to_pp (pretty_printer
*pp
) const = 0;
1040 const region_model
&get_model () const { return m_model
; }
1043 rejected_constraint (const region_model
&model
)
1047 region_model m_model
;
1050 class rejected_op_constraint
: public rejected_constraint
1053 rejected_op_constraint (const region_model
&model
,
1054 tree lhs
, enum tree_code op
, tree rhs
)
1055 : rejected_constraint (model
),
1056 m_lhs (lhs
), m_op (op
), m_rhs (rhs
)
1059 void dump_to_pp (pretty_printer
*pp
) const FINAL OVERRIDE
;
1062 enum tree_code m_op
;
1066 class rejected_ranges_constraint
: public rejected_constraint
1069 rejected_ranges_constraint (const region_model
&model
,
1070 tree expr
, const bounded_ranges
*ranges
)
1071 : rejected_constraint (model
),
1072 m_expr (expr
), m_ranges (ranges
)
1075 void dump_to_pp (pretty_printer
*pp
) const FINAL OVERRIDE
;
1079 const bounded_ranges
*m_ranges
;
1082 /* A bundle of state. */
1087 engine (logger
*logger
= NULL
);
1088 region_model_manager
*get_model_manager () { return &m_mgr
; }
1090 void log_stats (logger
*logger
) const;
1093 region_model_manager m_mgr
;
1099 extern void debug (const region_model
&rmodel
);
1105 namespace selftest
{
1107 using namespace ::selftest
;
1109 /* An implementation of region_model_context for use in selftests, which
1110 stores any pending_diagnostic instances passed to it. */
1112 class test_region_model_context
: public noop_region_model_context
1115 bool warn (pending_diagnostic
*d
) FINAL OVERRIDE
1117 m_diagnostics
.safe_push (d
);
1121 unsigned get_num_diagnostics () const { return m_diagnostics
.length (); }
1123 void on_unexpected_tree_code (tree t
, const dump_location_t
&)
1126 internal_error ("unhandled tree code: %qs",
1127 get_tree_code_name (TREE_CODE (t
)));
1131 /* Implicitly delete any diagnostics in the dtor. */
1132 auto_delete_vec
<pending_diagnostic
> m_diagnostics
;
1135 /* Attempt to add the constraint (LHS OP RHS) to MODEL.
1136 Verify that MODEL remains satisfiable. */
1138 #define ADD_SAT_CONSTRAINT(MODEL, LHS, OP, RHS) \
1139 SELFTEST_BEGIN_STMT \
1140 bool sat = (MODEL).add_constraint (LHS, OP, RHS, NULL); \
1141 ASSERT_TRUE (sat); \
1144 /* Attempt to add the constraint (LHS OP RHS) to MODEL.
1145 Verify that the result is not satisfiable. */
1147 #define ADD_UNSAT_CONSTRAINT(MODEL, LHS, OP, RHS) \
1148 SELFTEST_BEGIN_STMT \
1149 bool sat = (MODEL).add_constraint (LHS, OP, RHS, NULL); \
1150 ASSERT_FALSE (sat); \
1153 /* Implementation detail of the ASSERT_CONDITION_* macros. */
1155 void assert_condition (const location
&loc
,
1156 region_model
&model
,
1157 const svalue
*lhs
, tree_code op
, const svalue
*rhs
,
1160 void assert_condition (const location
&loc
,
1161 region_model
&model
,
1162 tree lhs
, tree_code op
, tree rhs
,
1165 /* Assert that REGION_MODEL evaluates the condition "LHS OP RHS"
1168 #define ASSERT_CONDITION_TRUE(REGION_MODEL, LHS, OP, RHS) \
1169 SELFTEST_BEGIN_STMT \
1170 assert_condition (SELFTEST_LOCATION, REGION_MODEL, LHS, OP, RHS, \
1171 tristate (tristate::TS_TRUE)); \
1174 /* Assert that REGION_MODEL evaluates the condition "LHS OP RHS"
1177 #define ASSERT_CONDITION_FALSE(REGION_MODEL, LHS, OP, RHS) \
1178 SELFTEST_BEGIN_STMT \
1179 assert_condition (SELFTEST_LOCATION, REGION_MODEL, LHS, OP, RHS, \
1180 tristate (tristate::TS_FALSE)); \
1183 /* Assert that REGION_MODEL evaluates the condition "LHS OP RHS"
1186 #define ASSERT_CONDITION_UNKNOWN(REGION_MODEL, LHS, OP, RHS) \
1187 SELFTEST_BEGIN_STMT \
1188 assert_condition (SELFTEST_LOCATION, REGION_MODEL, LHS, OP, RHS, \
1189 tristate (tristate::TS_UNKNOWN)); \
1192 } /* end of namespace selftest. */
1194 #endif /* #if CHECKING_P */
1198 #endif /* GCC_ANALYZER_REGION_MODEL_H */