analyzer: start adding support for errno
[platform/upstream/gcc.git] / gcc / analyzer / region-model-impl-calls.cc
1 /* Handling for the known behavior of various specific functions.
2    Copyright (C) 2020-2022 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_MEMORY
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "function.h"
27 #include "basic-block.h"
28 #include "gimple.h"
29 #include "gimple-iterator.h"
30 #include "diagnostic-core.h"
31 #include "graphviz.h"
32 #include "options.h"
33 #include "cgraph.h"
34 #include "tree-dfa.h"
35 #include "stringpool.h"
36 #include "convert.h"
37 #include "target.h"
38 #include "fold-const.h"
39 #include "tree-pretty-print.h"
40 #include "diagnostic-color.h"
41 #include "diagnostic-metadata.h"
42 #include "bitmap.h"
43 #include "analyzer/analyzer.h"
44 #include "analyzer/analyzer-logging.h"
45 #include "ordered-hash-map.h"
46 #include "options.h"
47 #include "analyzer/supergraph.h"
48 #include "sbitmap.h"
49 #include "analyzer/call-string.h"
50 #include "analyzer/program-point.h"
51 #include "analyzer/store.h"
52 #include "analyzer/region-model.h"
53 #include "analyzer/call-info.h"
54 #include "analyzer/sm.h"
55 #include "diagnostic-path.h"
56 #include "analyzer/pending-diagnostic.h"
57 #include "gimple-pretty-print.h"
58 #include "make-unique.h"
59
60 #if ENABLE_ANALYZER
61
62 namespace ana {
63
64 /* class call_details.  */
65
66 /* call_details's ctor.  */
67
68 call_details::call_details (const gcall *call, region_model *model,
69                             region_model_context *ctxt)
70 : m_call (call), m_model (model), m_ctxt (ctxt),
71   m_lhs_type (NULL_TREE), m_lhs_region (NULL)
72 {
73   m_lhs_type = NULL_TREE;
74   if (tree lhs = gimple_call_lhs (call))
75     {
76       m_lhs_region = model->get_lvalue (lhs, ctxt);
77       m_lhs_type = TREE_TYPE (lhs);
78     }
79 }
80
81 /* Get the manager from m_model.  */
82
83 region_model_manager *
84 call_details::get_manager () const
85 {
86   return m_model->get_manager ();
87 }
88
89 /* Get any logger associated with this object.  */
90
91 logger *
92 call_details::get_logger () const
93 {
94   if (m_ctxt)
95     return m_ctxt->get_logger ();
96   else
97     return NULL;
98 }
99
100 /* Get any uncertainty_t associated with the region_model_context.  */
101
102 uncertainty_t *
103 call_details::get_uncertainty () const
104 {
105   if (m_ctxt)
106     return m_ctxt->get_uncertainty ();
107   else
108     return NULL;
109 }
110
111 /* If the callsite has a left-hand-side region, set it to RESULT
112    and return true.
113    Otherwise do nothing and return false.  */
114
115 bool
116 call_details::maybe_set_lhs (const svalue *result) const
117 {
118   gcc_assert (result);
119   if (m_lhs_region)
120     {
121       m_model->set_value (m_lhs_region, result, m_ctxt);
122       return true;
123     }
124   else
125     return false;
126 }
127
128 /* Return the number of arguments used by the call statement.  */
129
130 unsigned
131 call_details::num_args () const
132 {
133   return gimple_call_num_args (m_call);
134 }
135
136 /* Get argument IDX at the callsite as a tree.  */
137
138 tree
139 call_details::get_arg_tree (unsigned idx) const
140 {
141   return gimple_call_arg (m_call, idx);
142 }
143
144 /* Get the type of argument IDX.  */
145
146 tree
147 call_details::get_arg_type (unsigned idx) const
148 {
149   return TREE_TYPE (gimple_call_arg (m_call, idx));
150 }
151
152 /* Get argument IDX at the callsite as an svalue.  */
153
154 const svalue *
155 call_details::get_arg_svalue (unsigned idx) const
156 {
157   tree arg = get_arg_tree (idx);
158   return m_model->get_rvalue (arg, m_ctxt);
159 }
160
161 /* Attempt to get the string literal for argument IDX, or return NULL
162    otherwise.
163    For use when implementing "__analyzer_*" functions that take
164    string literals.  */
165
166 const char *
167 call_details::get_arg_string_literal (unsigned idx) const
168 {
169   const svalue *str_arg = get_arg_svalue (idx);
170   if (const region *pointee = str_arg->maybe_get_region ())
171     if (const string_region *string_reg = pointee->dyn_cast_string_region ())
172       {
173         tree string_cst = string_reg->get_string_cst ();
174         return TREE_STRING_POINTER (string_cst);
175       }
176   return NULL;
177 }
178
179 /* Attempt to get the fndecl used at this call, if known, or NULL_TREE
180    otherwise.  */
181
182 tree
183 call_details::get_fndecl_for_call () const
184 {
185   return m_model->get_fndecl_for_call (m_call, m_ctxt);
186 }
187
188 /* Dump a multiline representation of this call to PP.  */
189
190 void
191 call_details::dump_to_pp (pretty_printer *pp, bool simple) const
192 {
193   pp_string (pp, "gcall: ");
194   pp_gimple_stmt_1 (pp, m_call, 0 /* spc */, TDF_NONE /* flags */);
195   pp_newline (pp);
196   pp_string (pp, "return region: ");
197   if (m_lhs_region)
198     m_lhs_region->dump_to_pp (pp, simple);
199   else
200     pp_string (pp, "NULL");
201   pp_newline (pp);
202   for (unsigned i = 0; i < gimple_call_num_args (m_call); i++)
203     {
204       const svalue *arg_sval = get_arg_svalue (i);
205       pp_printf (pp, "arg %i: ", i);
206       arg_sval->dump_to_pp (pp, simple);
207       pp_newline (pp);
208     }
209 }
210
211 /* Dump a multiline representation of this call to stderr.  */
212
213 DEBUG_FUNCTION void
214 call_details::dump (bool simple) const
215 {
216   pretty_printer pp;
217   pp_format_decoder (&pp) = default_tree_printer;
218   pp_show_color (&pp) = pp_show_color (global_dc->printer);
219   pp.buffer->stream = stderr;
220   dump_to_pp (&pp, simple);
221   pp_flush (&pp);
222 }
223
224 /* Get a conjured_svalue for this call for REG,
225    and purge any state already relating to that conjured_svalue.  */
226
227 const svalue *
228 call_details::get_or_create_conjured_svalue (const region *reg) const
229 {
230   region_model_manager *mgr = m_model->get_manager ();
231   return mgr->get_or_create_conjured_svalue (reg->get_type (), m_call, reg,
232                                              conjured_purge (m_model, m_ctxt));
233 }
234
235 /* Implementations of specific functions.  */
236
237 /* Handle the on_call_pre part of "alloca".  */
238
239 void
240 region_model::impl_call_alloca (const call_details &cd)
241 {
242   const svalue *size_sval = cd.get_arg_svalue (0);
243   const region *new_reg = create_region_for_alloca (size_sval, cd.get_ctxt ());
244   const svalue *ptr_sval
245     = m_mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
246   cd.maybe_set_lhs (ptr_sval);
247 }
248
249 /* Handle a call to "__analyzer_describe".
250
251    Emit a warning describing the 2nd argument (which can be of any
252    type), at the given verbosity level.  This is for use when
253    debugging, and may be of use in DejaGnu tests.  */
254
255 void
256 region_model::impl_call_analyzer_describe (const gcall *call,
257                                            region_model_context *ctxt)
258 {
259   tree t_verbosity = gimple_call_arg (call, 0);
260   tree t_val = gimple_call_arg (call, 1);
261   const svalue *sval = get_rvalue (t_val, ctxt);
262   bool simple = zerop (t_verbosity);
263   label_text desc = sval->get_desc (simple);
264   warning_at (call->location, 0, "svalue: %qs", desc.get ());
265 }
266
267 /* Handle a call to "__analyzer_dump_capacity".
268
269    Emit a warning describing the capacity of the base region of
270    the region pointed to by the 1st argument.
271    This is for use when debugging, and may be of use in DejaGnu tests.  */
272
273 void
274 region_model::impl_call_analyzer_dump_capacity (const gcall *call,
275                                                 region_model_context *ctxt)
276 {
277   tree t_ptr = gimple_call_arg (call, 0);
278   const svalue *sval_ptr = get_rvalue (t_ptr, ctxt);
279   const region *reg = deref_rvalue (sval_ptr, t_ptr, ctxt);
280   const region *base_reg = reg->get_base_region ();
281   const svalue *capacity = get_capacity (base_reg);
282   label_text desc = capacity->get_desc (true);
283   warning_at (call->location, 0, "capacity: %qs", desc.get ());
284 }
285
286 /* Compare D1 and D2 using their names, and then IDs to order them.  */
287
288 static int
289 cmp_decls (tree d1, tree d2)
290 {
291   gcc_assert (DECL_P (d1));
292   gcc_assert (DECL_P (d2));
293   if (DECL_NAME (d1) && DECL_NAME (d2))
294     if (int cmp = strcmp (IDENTIFIER_POINTER (DECL_NAME (d1)),
295                           IDENTIFIER_POINTER (DECL_NAME (d2))))
296       return cmp;
297   return (int)DECL_UID (d1) - (int)DECL_UID (d2);
298 }
299
300 /* Comparator for use by vec<tree>::qsort,
301    using their names, and then IDs to order them.  */
302
303 static int
304 cmp_decls_ptr_ptr (const void *p1, const void *p2)
305 {
306   tree const *d1 = (tree const *)p1;
307   tree const *d2 = (tree const *)p2;
308
309   return cmp_decls (*d1, *d2);
310 }
311
312 /* Handle a call to "__analyzer_dump_escaped".
313
314    Emit a warning giving the number of decls that have escaped, followed
315    by a comma-separated list of their names, in alphabetical order.
316
317    This is for use when debugging, and may be of use in DejaGnu tests.  */
318
319 void
320 region_model::impl_call_analyzer_dump_escaped (const gcall *call)
321 {
322   auto_vec<tree> escaped_decls;
323   for (auto iter : m_store)
324     {
325       const binding_cluster *c = iter.second;
326       if (!c->escaped_p ())
327         continue;
328       if (tree decl = c->get_base_region ()->maybe_get_decl ())
329         escaped_decls.safe_push (decl);
330     }
331
332   /* Sort them into deterministic order; alphabetical is
333      probably most user-friendly.  */
334   escaped_decls.qsort (cmp_decls_ptr_ptr);
335
336   pretty_printer pp;
337   pp_format_decoder (&pp) = default_tree_printer;
338   pp_show_color (&pp) = pp_show_color (global_dc->printer);
339   bool first = true;
340   for (auto iter : escaped_decls)
341     {
342       if (first)
343         first = false;
344       else
345         pp_string (&pp, ", ");
346       pp_printf (&pp, "%qD", iter);
347     }
348   /* Print the number to make it easier to write DejaGnu tests for
349      the "nothing has escaped" case.  */
350   warning_at (call->location, 0, "escaped: %i: %s",
351               escaped_decls.length (),
352               pp_formatted_text (&pp));
353 }
354
355 /* Handle a call to "__analyzer_eval" by evaluating the input
356    and dumping as a dummy warning, so that test cases can use
357    dg-warning to validate the result (and so unexpected warnings will
358    lead to DejaGnu failures).
359    Broken out as a subroutine to make it easier to put a breakpoint on it
360    - though typically this doesn't help, as we have an SSA name as the arg,
361    and what's more interesting is usually the def stmt for that name.  */
362
363 void
364 region_model::impl_call_analyzer_eval (const gcall *call,
365                                        region_model_context *ctxt)
366 {
367   tree t_arg = gimple_call_arg (call, 0);
368   tristate t = eval_condition (t_arg, NE_EXPR, integer_zero_node, ctxt);
369   warning_at (call->location, 0, "%s", t.as_string ());
370 }
371
372 /* Handle the on_call_pre part of "__analyzer_get_unknown_ptr".  */
373
374 void
375 region_model::impl_call_analyzer_get_unknown_ptr (const call_details &cd)
376 {
377   const svalue *ptr_sval
378     = m_mgr->get_or_create_unknown_svalue (cd.get_lhs_type ());
379   cd.maybe_set_lhs (ptr_sval);
380 }
381
382 /* Handle the on_call_pre part of "__builtin_expect" etc.  */
383
384 void
385 region_model::impl_call_builtin_expect (const call_details &cd)
386 {
387   /* __builtin_expect's return value is its initial argument.  */
388   const svalue *sval = cd.get_arg_svalue (0);
389   cd.maybe_set_lhs (sval);
390 }
391
392 /* Handle the on_call_pre part of "calloc".  */
393
394 void
395 region_model::impl_call_calloc (const call_details &cd)
396 {
397   const svalue *nmemb_sval = cd.get_arg_svalue (0);
398   const svalue *size_sval = cd.get_arg_svalue (1);
399   /* TODO: check for overflow here?  */
400   const svalue *prod_sval
401     = m_mgr->get_or_create_binop (size_type_node, MULT_EXPR,
402                                   nmemb_sval, size_sval);
403   const region *new_reg
404     = create_region_for_heap_alloc (prod_sval, cd.get_ctxt ());
405   const region *sized_reg
406     = m_mgr->get_sized_region (new_reg, NULL_TREE, prod_sval);
407   zero_fill_region (sized_reg);
408   if (cd.get_lhs_type ())
409     {
410       const svalue *ptr_sval
411         = m_mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
412       cd.maybe_set_lhs (ptr_sval);
413     }
414 }
415
416 /* Handle the on_call_pre part of "__errno_location".  */
417
418 void
419 region_model::impl_call_errno_location (const call_details &cd)
420 {
421   if (cd.get_lhs_region ())
422     {
423       const region *errno_reg = m_mgr->get_errno_region ();
424       const svalue *errno_ptr = m_mgr->get_ptr_svalue (cd.get_lhs_type (),
425                                                        errno_reg);
426       cd.maybe_set_lhs (errno_ptr);
427     }
428 }
429
430 /* Handle the on_call_pre part of "error" and "error_at_line" from
431    GNU's non-standard <error.h>.
432    MIN_ARGS identifies the minimum number of expected arguments
433    to be consistent with such a call (3 and 5 respectively).
434    Return true if handling it as one of these functions.
435    Write true to *OUT_TERMINATE_PATH if this execution path should be
436    terminated (e.g. the function call terminates the process).  */
437
438 bool
439 region_model::impl_call_error (const call_details &cd, unsigned min_args,
440                                bool *out_terminate_path)
441 {
442   /* Bail if not enough args.  */
443   if (cd.num_args () < min_args)
444     return false;
445
446   /* Initial argument ought to be of type "int".  */
447   if (cd.get_arg_type (0) != integer_type_node)
448     return false;
449
450   /* The process exits if status != 0, so it only continues
451      for the case where status == 0.
452      Add that constraint, or terminate this analysis path.  */
453   tree status = cd.get_arg_tree (0);
454   if (!add_constraint (status, EQ_EXPR, integer_zero_node, cd.get_ctxt ()))
455     *out_terminate_path = true;
456
457   return true;
458 }
459
460 /* Handle the on_call_pre part of "fgets" and "fgets_unlocked".  */
461
462 void
463 region_model::impl_call_fgets (const call_details &cd)
464 {
465   /* Ideally we would bifurcate state here between the
466      error vs no error cases.  */
467   const svalue *ptr_sval = cd.get_arg_svalue (0);
468   if (const region *reg = ptr_sval->maybe_get_region ())
469     {
470       const region *base_reg = reg->get_base_region ();
471       const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg);
472       set_value (base_reg, new_sval, cd.get_ctxt ());
473     }
474 }
475
476 /* Handle the on_call_pre part of "fread".  */
477
478 void
479 region_model::impl_call_fread (const call_details &cd)
480 {
481   const svalue *ptr_sval = cd.get_arg_svalue (0);
482   if (const region *reg = ptr_sval->maybe_get_region ())
483     {
484       const region *base_reg = reg->get_base_region ();
485       const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg);
486       set_value (base_reg, new_sval, cd.get_ctxt ());
487     }
488 }
489
490 /* Handle the on_call_post part of "free", after sm-handling.
491
492    If the ptr points to an underlying heap region, delete the region,
493    poisoning pointers to it and regions within it.
494
495    We delay this until after sm-state has been updated so that the
496    sm-handling can transition all of the various casts of the pointer
497    to a "freed" state *before* we delete the related region here.
498
499    This has to be done here so that the sm-handling can use the fact
500    that they point to the same region to establish that they are equal
501    (in region_model::eval_condition_without_cm), and thus transition
502    all pointers to the region to the "freed" state together, regardless
503    of casts.  */
504
505 void
506 region_model::impl_call_free (const call_details &cd)
507 {
508   const svalue *ptr_sval = cd.get_arg_svalue (0);
509   if (const region *freed_reg = ptr_sval->maybe_get_region ())
510     {
511       /* If the ptr points to an underlying heap region, delete it,
512          poisoning pointers.  */
513       unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
514       m_dynamic_extents.remove (freed_reg);
515     }
516 }
517
518 /* Handle the on_call_pre part of "malloc".  */
519
520 void
521 region_model::impl_call_malloc (const call_details &cd)
522 {
523   const svalue *size_sval = cd.get_arg_svalue (0);
524   const region *new_reg
525     = create_region_for_heap_alloc (size_sval, cd.get_ctxt ());
526   if (cd.get_lhs_type ())
527     {
528       const svalue *ptr_sval
529         = m_mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
530       cd.maybe_set_lhs (ptr_sval);
531     }
532 }
533
534 /* Handle the on_call_pre part of "memcpy" and "__builtin_memcpy".  */
535 // TODO: complain about overlapping src and dest.
536
537 void
538 region_model::impl_call_memcpy (const call_details &cd)
539 {
540   const svalue *dest_ptr_sval = cd.get_arg_svalue (0);
541   const svalue *src_ptr_sval = cd.get_arg_svalue (1);
542   const svalue *num_bytes_sval = cd.get_arg_svalue (2);
543
544   const region *dest_reg = deref_rvalue (dest_ptr_sval, cd.get_arg_tree (0),
545                                          cd.get_ctxt ());
546   const region *src_reg = deref_rvalue (src_ptr_sval, cd.get_arg_tree (1),
547                                         cd.get_ctxt ());
548
549   cd.maybe_set_lhs (dest_ptr_sval);
550
551   const region *sized_src_reg
552     = m_mgr->get_sized_region (src_reg, NULL_TREE, num_bytes_sval);
553   const region *sized_dest_reg
554     = m_mgr->get_sized_region (dest_reg, NULL_TREE, num_bytes_sval);
555   const svalue *src_contents_sval
556     = get_store_value (sized_src_reg, cd.get_ctxt ());
557   set_value (sized_dest_reg, src_contents_sval, cd.get_ctxt ());
558 }
559
560 /* Handle the on_call_pre part of "memset" and "__builtin_memset".  */
561
562 void
563 region_model::impl_call_memset (const call_details &cd)
564 {
565   const svalue *dest_sval = cd.get_arg_svalue (0);
566   const svalue *fill_value_sval = cd.get_arg_svalue (1);
567   const svalue *num_bytes_sval = cd.get_arg_svalue (2);
568
569   const region *dest_reg = deref_rvalue (dest_sval, cd.get_arg_tree (0),
570                                           cd.get_ctxt ());
571
572   const svalue *fill_value_u8
573     = m_mgr->get_or_create_cast (unsigned_char_type_node, fill_value_sval);
574
575   const region *sized_dest_reg = m_mgr->get_sized_region (dest_reg,
576                                                           NULL_TREE,
577                                                           num_bytes_sval);
578   check_region_for_write (sized_dest_reg, cd.get_ctxt ());
579   fill_region (sized_dest_reg, fill_value_u8);
580 }
581
582 /* Handle the on_call_post part of "pipe".  */
583
584 void
585 region_model::impl_call_pipe (const call_details &cd)
586 {
587   class failure : public failed_call_info
588   {
589   public:
590     failure (const call_details &cd) : failed_call_info (cd) {}
591
592     bool update_model (region_model *model,
593                        const exploded_edge *,
594                        region_model_context *ctxt) const final override
595     {
596       /* Return -1; everything else is unchanged.  */
597       const call_details cd (get_call_details (model, ctxt));
598       model->update_for_int_cst_return (cd, -1, true);
599       return true;
600     }
601   };
602
603   class success : public success_call_info
604   {
605   public:
606     success (const call_details &cd) : success_call_info (cd) {}
607
608     bool update_model (region_model *model,
609                        const exploded_edge *,
610                        region_model_context *ctxt) const final override
611     {
612       const call_details cd (get_call_details (model, ctxt));
613
614       /* Return 0.  */
615       model->update_for_zero_return (cd, true);
616
617       /* Update fd array.  */
618       region_model_manager *mgr = cd.get_manager ();
619       tree arr_tree = cd.get_arg_tree (0);
620       const svalue *arr_sval = cd.get_arg_svalue (0);
621       for (int idx = 0; idx < 2; idx++)
622         {
623           const region *arr_reg
624             = model->deref_rvalue (arr_sval, arr_tree, cd.get_ctxt ());
625           const svalue *idx_sval
626             = mgr->get_or_create_int_cst (integer_type_node, idx);
627           const region *element_reg
628             = mgr->get_element_region (arr_reg, integer_type_node, idx_sval);
629           conjured_purge p (model, cd.get_ctxt ());
630           const svalue *fd_sval
631             = mgr->get_or_create_conjured_svalue (integer_type_node,
632                                                   cd.get_call_stmt (),
633                                                   element_reg,
634                                                   p);
635           model->set_value (element_reg, fd_sval, cd.get_ctxt ());
636           model->mark_as_valid_fd (fd_sval, cd.get_ctxt ());
637
638         }
639       return true;
640     }
641   };
642
643   /* Body of region_model::impl_call_pipe.  */
644   if (cd.get_ctxt ())
645     {
646       cd.get_ctxt ()->bifurcate (make_unique<failure> (cd));
647       cd.get_ctxt ()->bifurcate (make_unique<success> (cd));
648       cd.get_ctxt ()->terminate_path ();
649     }
650 }
651
652 /* A subclass of pending_diagnostic for complaining about 'putenv'
653    called on an auto var.  */
654
655 class putenv_of_auto_var
656 : public pending_diagnostic_subclass<putenv_of_auto_var>
657 {
658 public:
659   putenv_of_auto_var (tree fndecl, const region *reg)
660   : m_fndecl (fndecl), m_reg (reg),
661     m_var_decl (reg->get_base_region ()->maybe_get_decl ())
662   {
663   }
664
665   const char *get_kind () const final override
666   {
667     return "putenv_of_auto_var";
668   }
669
670   bool operator== (const putenv_of_auto_var &other) const
671   {
672     return (m_fndecl == other.m_fndecl
673             && m_reg == other.m_reg
674             && same_tree_p (m_var_decl, other.m_var_decl));
675   }
676
677   int get_controlling_option () const final override
678   {
679     return OPT_Wanalyzer_putenv_of_auto_var;
680   }
681
682   bool emit (rich_location *rich_loc) final override
683   {
684     auto_diagnostic_group d;
685     diagnostic_metadata m;
686
687     /* SEI CERT C Coding Standard: "POS34-C. Do not call putenv() with a
688        pointer to an automatic variable as the argument".  */
689     diagnostic_metadata::precanned_rule
690       rule ("POS34-C", "https://wiki.sei.cmu.edu/confluence/x/6NYxBQ");
691     m.add_rule (rule);
692
693     bool warned;
694     if (m_var_decl)
695       warned = warning_meta (rich_loc, m, get_controlling_option (),
696                              "%qE on a pointer to automatic variable %qE",
697                              m_fndecl, m_var_decl);
698     else
699       warned = warning_meta (rich_loc, m, get_controlling_option (),
700                              "%qE on a pointer to an on-stack buffer",
701                              m_fndecl);
702     if (warned)
703       {
704         if (m_var_decl)
705           inform (DECL_SOURCE_LOCATION (m_var_decl),
706                   "%qE declared on stack here", m_var_decl);
707         inform (rich_loc->get_loc (), "perhaps use %qs rather than %qE",
708                 "setenv", m_fndecl);
709       }
710
711     return warned;
712   }
713
714   label_text describe_final_event (const evdesc::final_event &ev) final override
715   {
716     if (m_var_decl)
717       return ev.formatted_print ("%qE on a pointer to automatic variable %qE",
718                                  m_fndecl, m_var_decl);
719     else
720       return ev.formatted_print ("%qE on a pointer to an on-stack buffer",
721                                  m_fndecl);
722   }
723
724   void mark_interesting_stuff (interesting_t *interest) final override
725   {
726     if (!m_var_decl)
727       interest->add_region_creation (m_reg->get_base_region ());
728   }
729
730 private:
731   tree m_fndecl; // non-NULL
732   const region *m_reg; // non-NULL
733   tree m_var_decl; // could be NULL
734 };
735
736 /* Handle the on_call_pre part of "putenv".
737
738    In theory we could try to model the state of the environment variables
739    for the process; for now we merely complain about putenv of regions
740    on the stack.  */
741
742 void
743 region_model::impl_call_putenv (const call_details &cd)
744 {
745   tree fndecl = cd.get_fndecl_for_call ();
746   gcc_assert (fndecl);
747   region_model_context *ctxt = cd.get_ctxt ();
748   const svalue *ptr_sval = cd.get_arg_svalue (0);
749   const region *reg = deref_rvalue (ptr_sval, cd.get_arg_tree (0), ctxt);
750   m_store.mark_as_escaped (reg);
751   enum memory_space mem_space = reg->get_memory_space ();
752   switch (mem_space)
753     {
754     default:
755       gcc_unreachable ();
756     case MEMSPACE_UNKNOWN:
757     case MEMSPACE_CODE:
758     case MEMSPACE_GLOBALS:
759     case MEMSPACE_HEAP:
760     case MEMSPACE_READONLY_DATA:
761       break;
762     case MEMSPACE_STACK:
763       if (ctxt)
764         ctxt->warn (make_unique<putenv_of_auto_var> (fndecl, reg));
765       break;
766     }
767 }
768
769 /* Handle the on_call_pre part of "operator new".  */
770
771 void
772 region_model::impl_call_operator_new (const call_details &cd)
773 {
774   const svalue *size_sval = cd.get_arg_svalue (0);
775   const region *new_reg
776     = create_region_for_heap_alloc (size_sval, cd.get_ctxt ());
777   if (cd.get_lhs_type ())
778     {
779       const svalue *ptr_sval
780         = m_mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
781       cd.maybe_set_lhs (ptr_sval);
782     }
783 }
784
785 /* Handle the on_call_pre part of "operator delete", which comes in
786    both sized and unsized variants (2 arguments and 1 argument
787    respectively).  */
788
789 void
790 region_model::impl_call_operator_delete (const call_details &cd)
791 {
792   const svalue *ptr_sval = cd.get_arg_svalue (0);
793   if (const region *freed_reg = ptr_sval->maybe_get_region ())
794     {
795       /* If the ptr points to an underlying heap region, delete it,
796          poisoning pointers.  */
797       unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
798     }
799 }
800
801 /* Handle the on_call_post part of "realloc":
802
803      void *realloc(void *ptr, size_t size);
804
805    realloc(3) is awkward, since it has various different outcomes
806    that are best modelled as separate exploded nodes/edges.
807
808    We first check for sm-state, in
809    malloc_state_machine::on_realloc_call, so that we
810    can complain about issues such as realloc of a non-heap
811    pointer, and terminate the path for such cases (and issue
812    the complaints at the call's exploded node).
813
814    Assuming that these checks pass, we split the path here into
815    three special cases (and terminate the "standard" path):
816    (A) failure, returning NULL
817    (B) success, growing the buffer in-place without moving it
818    (C) success, allocating a new buffer, copying the content
819    of the old buffer to it, and freeing the old buffer.
820
821    Each of these has a custom_edge_info subclass, which updates
822    the region_model and sm-state of the destination state.  */
823
824 void
825 region_model::impl_call_realloc (const call_details &cd)
826 {
827   /* Three custom subclasses of custom_edge_info, for handling the various
828      outcomes of "realloc".  */
829
830   /* Concrete custom_edge_info: a realloc call that fails, returning NULL.  */
831   class failure : public failed_call_info
832   {
833   public:
834     failure (const call_details &cd)
835     : failed_call_info (cd)
836     {
837     }
838
839     bool update_model (region_model *model,
840                        const exploded_edge *,
841                        region_model_context *ctxt) const final override
842     {
843       /* Return NULL; everything else is unchanged.  */
844       const call_details cd (get_call_details (model, ctxt));
845       if (cd.get_lhs_type ())
846         {
847           const svalue *zero
848             = model->m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
849           model->set_value (cd.get_lhs_region (),
850                             zero,
851                             cd.get_ctxt ());
852         }
853       return true;
854     }
855   };
856
857   /* Concrete custom_edge_info: a realloc call that succeeds, growing
858      the existing buffer without moving it.  */
859   class success_no_move : public call_info
860   {
861   public:
862     success_no_move (const call_details &cd)
863     : call_info (cd)
864     {
865     }
866
867     label_text get_desc (bool can_colorize) const final override
868     {
869       return make_label_text (can_colorize,
870                               "when %qE succeeds, without moving buffer",
871                               get_fndecl ());
872     }
873
874     bool update_model (region_model *model,
875                        const exploded_edge *,
876                        region_model_context *ctxt) const final override
877     {
878       /* Update size of buffer and return the ptr unchanged.  */
879       const call_details cd (get_call_details (model, ctxt));
880       const svalue *ptr_sval = cd.get_arg_svalue (0);
881       const svalue *size_sval = cd.get_arg_svalue (1);
882
883       /* We can only grow in place with a non-NULL pointer.  */
884       {
885         const svalue *null_ptr
886           = model->m_mgr->get_or_create_int_cst (ptr_sval->get_type (), 0);
887         if (!model->add_constraint (ptr_sval, NE_EXPR, null_ptr,
888                                     cd.get_ctxt ()))
889           return false;
890       }
891
892       if (const region *buffer_reg = model->deref_rvalue (ptr_sval, NULL_TREE,
893                                                           ctxt))
894         if (compat_types_p (size_sval->get_type (), size_type_node))
895           model->set_dynamic_extents (buffer_reg, size_sval, ctxt);
896       if (cd.get_lhs_region ())
897         {
898           model->set_value (cd.get_lhs_region (), ptr_sval, cd.get_ctxt ());
899           const svalue *zero
900             = model->m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
901           return model->add_constraint (ptr_sval, NE_EXPR, zero, cd.get_ctxt ());
902         }
903       else
904         return true;
905     }
906   };
907
908   /* Concrete custom_edge_info: a realloc call that succeeds, freeing
909      the existing buffer and moving the content to a freshly allocated
910      buffer.  */
911   class success_with_move : public call_info
912   {
913   public:
914     success_with_move (const call_details &cd)
915     : call_info (cd)
916     {
917     }
918
919     label_text get_desc (bool can_colorize) const final override
920     {
921       return make_label_text (can_colorize,
922                               "when %qE succeeds, moving buffer",
923                               get_fndecl ());
924     }
925     bool update_model (region_model *model,
926                        const exploded_edge *,
927                        region_model_context *ctxt) const final override
928     {
929       const call_details cd (get_call_details (model, ctxt));
930       const svalue *old_ptr_sval = cd.get_arg_svalue (0);
931       const svalue *new_size_sval = cd.get_arg_svalue (1);
932
933       /* Create the new region.  */
934       const region *new_reg
935         = model->create_region_for_heap_alloc (new_size_sval, ctxt);
936       const svalue *new_ptr_sval
937         = model->m_mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
938       if (!model->add_constraint (new_ptr_sval, NE_EXPR, old_ptr_sval,
939                                   cd.get_ctxt ()))
940         return false;
941
942       if (cd.get_lhs_type ())
943         cd.maybe_set_lhs (new_ptr_sval);
944
945       if (const region *freed_reg = model->deref_rvalue (old_ptr_sval,
946                                                          NULL_TREE, ctxt))
947         {
948           /* Copy the data.  */
949           const svalue *old_size_sval = model->get_dynamic_extents (freed_reg);
950           if (old_size_sval)
951             {
952               const svalue *copied_size_sval
953                 = get_copied_size (model, old_size_sval, new_size_sval);
954               const region *copied_old_reg
955                 = model->m_mgr->get_sized_region (freed_reg, NULL,
956                                                   copied_size_sval);
957               const svalue *buffer_content_sval
958                 = model->get_store_value (copied_old_reg, cd.get_ctxt ());
959               const region *copied_new_reg
960                 = model->m_mgr->get_sized_region (new_reg, NULL,
961                                                   copied_size_sval);
962               model->set_value (copied_new_reg, buffer_content_sval,
963                                 cd.get_ctxt ());
964             }
965           else
966             {
967               /* We don't know how big the old region was;
968                  mark the new region as having been touched to avoid uninit
969                  issues.  */
970               model->mark_region_as_unknown (new_reg, cd.get_uncertainty ());
971             }
972
973           /* Free the old region, so that pointers to the old buffer become
974              invalid.  */
975
976           /* If the ptr points to an underlying heap region, delete it,
977              poisoning pointers.  */
978           model->unbind_region_and_descendents (freed_reg, POISON_KIND_FREED);
979           model->m_dynamic_extents.remove (freed_reg);
980         }
981
982       /* Update the sm-state: mark the old_ptr_sval as "freed",
983          and the new_ptr_sval as "nonnull".  */
984       model->on_realloc_with_move (cd, old_ptr_sval, new_ptr_sval);
985
986       if (cd.get_lhs_type ())
987         {
988           const svalue *zero
989             = model->m_mgr->get_or_create_int_cst (cd.get_lhs_type (), 0);
990           return model->add_constraint (new_ptr_sval, NE_EXPR, zero,
991                                         cd.get_ctxt ());
992         }
993       else
994         return true;
995     }
996
997   private:
998     /* Return the lesser of OLD_SIZE_SVAL and NEW_SIZE_SVAL.
999        If unknown, OLD_SIZE_SVAL is returned.  */
1000     const svalue *get_copied_size (region_model *model,
1001                                    const svalue *old_size_sval,
1002                                    const svalue *new_size_sval) const
1003     {
1004       tristate res
1005         = model->eval_condition (old_size_sval, GT_EXPR, new_size_sval);
1006       switch (res.get_value ())
1007         {
1008         case tristate::TS_TRUE:
1009           return new_size_sval;
1010         case tristate::TS_FALSE:
1011         case tristate::TS_UNKNOWN:
1012           return old_size_sval;
1013         default:
1014           gcc_unreachable ();
1015         }
1016     }
1017   };
1018
1019   /* Body of region_model::impl_call_realloc.  */
1020
1021   if (cd.get_ctxt ())
1022     {
1023       cd.get_ctxt ()->bifurcate (make_unique<failure> (cd));
1024       cd.get_ctxt ()->bifurcate (make_unique<success_no_move> (cd));
1025       cd.get_ctxt ()->bifurcate (make_unique<success_with_move> (cd));
1026       cd.get_ctxt ()->terminate_path ();
1027     }
1028 }
1029
1030 /* Handle the on_call_post part of "strchr" and "__builtin_strchr".  */
1031
1032 void
1033 region_model::impl_call_strchr (const call_details &cd)
1034 {
1035   class strchr_call_info : public call_info
1036   {
1037   public:
1038     strchr_call_info (const call_details &cd, bool found)
1039     : call_info (cd), m_found (found)
1040     {
1041     }
1042
1043     label_text get_desc (bool can_colorize) const final override
1044     {
1045       if (m_found)
1046         return make_label_text (can_colorize,
1047                                 "when %qE returns non-NULL",
1048                                 get_fndecl ());
1049       else
1050         return make_label_text (can_colorize,
1051                                 "when %qE returns NULL",
1052                                 get_fndecl ());
1053     }
1054
1055     bool update_model (region_model *model,
1056                        const exploded_edge *,
1057                        region_model_context *ctxt) const final override
1058     {
1059       const call_details cd (get_call_details (model, ctxt));
1060       if (tree lhs_type = cd.get_lhs_type ())
1061         {
1062           region_model_manager *mgr = model->get_manager ();
1063           const svalue *result;
1064           if (m_found)
1065             {
1066               const svalue *str_sval = cd.get_arg_svalue (0);
1067               const region *str_reg
1068                 = model->deref_rvalue (str_sval, cd.get_arg_tree (0),
1069                                        cd.get_ctxt ());
1070               /* We want str_sval + OFFSET for some unknown OFFSET.
1071                  Use a conjured_svalue to represent the offset,
1072                  using the str_reg as the id of the conjured_svalue.  */
1073               const svalue *offset
1074                 = mgr->get_or_create_conjured_svalue (size_type_node,
1075                                                       cd.get_call_stmt (),
1076                                                       str_reg,
1077                                                       conjured_purge (model,
1078                                                                       ctxt));
1079               result = mgr->get_or_create_binop (lhs_type, POINTER_PLUS_EXPR,
1080                                                  str_sval, offset);
1081             }
1082           else
1083             result = mgr->get_or_create_int_cst (lhs_type, 0);
1084           cd.maybe_set_lhs (result);
1085         }
1086       return true;
1087     }
1088   private:
1089     bool m_found;
1090   };
1091
1092   /* Body of region_model::impl_call_strchr.  */
1093   if (cd.get_ctxt ())
1094     {
1095       cd.get_ctxt ()->bifurcate (make_unique<strchr_call_info> (cd, false));
1096       cd.get_ctxt ()->bifurcate (make_unique<strchr_call_info> (cd, true));
1097       cd.get_ctxt ()->terminate_path ();
1098     }
1099 }
1100
1101 /* Handle the on_call_pre part of "strcpy" and "__builtin_strcpy_chk".  */
1102
1103 void
1104 region_model::impl_call_strcpy (const call_details &cd)
1105 {
1106   const svalue *dest_sval = cd.get_arg_svalue (0);
1107   const region *dest_reg = deref_rvalue (dest_sval, cd.get_arg_tree (0),
1108                                          cd.get_ctxt ());
1109   const svalue *src_sval = cd.get_arg_svalue (1);
1110   const region *src_reg = deref_rvalue (src_sval, cd.get_arg_tree (1),
1111                                         cd.get_ctxt ());
1112   const svalue *src_contents_sval = get_store_value (src_reg,
1113                                                      cd.get_ctxt ());
1114
1115   cd.maybe_set_lhs (dest_sval);
1116
1117   /* Try to get the string size if SRC_REG is a string_region.  */
1118   const svalue *copied_bytes_sval = get_string_size (src_reg);
1119   /* Otherwise, check if the contents of SRC_REG is a string.  */
1120   if (copied_bytes_sval->get_kind () == SK_UNKNOWN)
1121     copied_bytes_sval = get_string_size (src_contents_sval);
1122
1123   const region *sized_dest_reg
1124     = m_mgr->get_sized_region (dest_reg, NULL_TREE, copied_bytes_sval);
1125   set_value (sized_dest_reg, src_contents_sval, cd.get_ctxt ());
1126 }
1127
1128 /* Handle the on_call_pre part of "strlen".  */
1129
1130 void
1131 region_model::impl_call_strlen (const call_details &cd)
1132 {
1133   region_model_context *ctxt = cd.get_ctxt ();
1134   const svalue *arg_sval = cd.get_arg_svalue (0);
1135   const region *buf_reg = deref_rvalue (arg_sval, cd.get_arg_tree (0), ctxt);
1136   if (const string_region *str_reg
1137       = buf_reg->dyn_cast_string_region ())
1138     {
1139       tree str_cst = str_reg->get_string_cst ();
1140       /* TREE_STRING_LENGTH is sizeof, not strlen.  */
1141       int sizeof_cst = TREE_STRING_LENGTH (str_cst);
1142       int strlen_cst = sizeof_cst - 1;
1143       if (cd.get_lhs_type ())
1144         {
1145           tree t_cst = build_int_cst (cd.get_lhs_type (), strlen_cst);
1146           const svalue *result_sval
1147             = m_mgr->get_or_create_constant_svalue (t_cst);
1148           cd.maybe_set_lhs (result_sval);
1149           return;
1150         }
1151     }
1152   /* Otherwise a conjured value.  */
1153 }
1154
1155 /* Handle calls to functions referenced by
1156    __attribute__((malloc(FOO))).  */
1157
1158 void
1159 region_model::impl_deallocation_call (const call_details &cd)
1160 {
1161   impl_call_free (cd);
1162 }
1163
1164 } // namespace ana
1165
1166 #endif /* #if ENABLE_ANALYZER */