analyzer: eliminate region_model::on_ fns for sockets
[platform/upstream/gcc.git] / gcc / analyzer / sm-fd.cc
1 /* A state machine for detecting misuses of POSIX file descriptor APIs.
2    Copyright (C) 2019-2022 Free Software Foundation, Inc.
3    Contributed by Immad Mir <mir@sourceware.org>.
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 "make-unique.h"
26 #include "tree.h"
27 #include "function.h"
28 #include "basic-block.h"
29 #include "gimple.h"
30 #include "options.h"
31 #include "diagnostic-path.h"
32 #include "diagnostic-metadata.h"
33 #include "analyzer/analyzer.h"
34 #include "diagnostic-event-id.h"
35 #include "analyzer/analyzer-logging.h"
36 #include "analyzer/sm.h"
37 #include "analyzer/pending-diagnostic.h"
38 #include "analyzer/function-set.h"
39 #include "analyzer/analyzer-selftests.h"
40 #include "stringpool.h"
41 #include "attribs.h"
42 #include "analyzer/call-string.h"
43 #include "analyzer/program-point.h"
44 #include "analyzer/store.h"
45 #include "analyzer/region-model.h"
46 #include "bitmap.h"
47 #include "analyzer/program-state.h"
48 #include "analyzer/supergraph.h"
49 #include "analyzer/analyzer-language.h"
50 #include "analyzer/call-info.h"
51
52 #if ENABLE_ANALYZER
53
54 namespace ana {
55
56 namespace {
57
58 /* An enum for distinguishing between three different access modes.  */
59
60 enum access_mode
61 {
62   READ_WRITE,
63   READ_ONLY,
64   WRITE_ONLY
65 };
66
67 enum access_directions
68 {
69   DIRS_READ_WRITE,
70   DIRS_READ,
71   DIRS_WRITE
72 };
73
74 /* An enum for distinguishing between dup, dup2 and dup3.  */
75 enum dup
76 {
77   DUP_1,
78   DUP_2,
79   DUP_3
80 };
81
82 /* Enum for use by -Wanalyzer-fd-phase-mismatch.  */
83
84 enum expected_phase
85 {
86   EXPECTED_PHASE_CAN_TRANSFER, /* can "read"/"write".  */
87   EXPECTED_PHASE_CAN_BIND,
88   EXPECTED_PHASE_CAN_LISTEN,
89   EXPECTED_PHASE_CAN_ACCEPT,
90   EXPECTED_PHASE_CAN_CONNECT
91 };
92
93 class fd_state_machine : public state_machine
94 {
95 public:
96   fd_state_machine (logger *logger);
97
98   bool
99   inherited_state_p () const final override
100   {
101     return false;
102   }
103
104   state_machine::state_t
105   get_default_state (const svalue *sval) const final override
106   {
107     if (tree cst = sval->maybe_get_constant ())
108       {
109         if (TREE_CODE (cst) == INTEGER_CST)
110           {
111             int val = TREE_INT_CST_LOW (cst);
112             if (val >= 0)
113               return m_constant_fd;
114             else
115               return m_invalid;
116           }
117       }
118     return m_start;
119   }
120
121   bool on_stmt (sm_context *sm_ctxt, const supernode *node,
122                 const gimple *stmt) const final override;
123
124   void on_condition (sm_context *sm_ctxt, const supernode *node,
125                      const gimple *stmt, const svalue *lhs, const tree_code op,
126                      const svalue *rhs) const final override;
127
128   bool can_purge_p (state_t s) const final override;
129   std::unique_ptr<pending_diagnostic> on_leak (tree var) const final override;
130
131   bool is_unchecked_fd_p (state_t s) const;
132   bool is_valid_fd_p (state_t s) const;
133   bool is_socket_fd_p (state_t s) const;
134   bool is_datagram_socket_fd_p (state_t s) const;
135   bool is_stream_socket_fd_p (state_t s) const;
136   bool is_closed_fd_p (state_t s) const;
137   bool is_constant_fd_p (state_t s) const;
138   bool is_readonly_fd_p (state_t s) const;
139   bool is_writeonly_fd_p (state_t s) const;
140   enum access_mode get_access_mode_from_flag (int flag) const;
141   /* Function for one-to-one correspondence between valid
142      and unchecked states.  */
143   state_t valid_to_unchecked_state (state_t state) const;
144
145   void mark_as_valid_fd (region_model *model,
146                          sm_state_map *smap,
147                          const svalue *fd_sval,
148                          const extrinsic_state &ext_state) const;
149
150   bool on_socket (const call_details &cd,
151                   bool successful,
152                   sm_context *sm_ctxt,
153                   const extrinsic_state &ext_state) const;
154   bool on_bind (const call_details &cd,
155                 bool successful,
156                 sm_context *sm_ctxt,
157                 const extrinsic_state &ext_state) const;
158   bool on_listen (const call_details &cd,
159                   bool successful,
160                   sm_context *sm_ctxt,
161                   const extrinsic_state &ext_state) const;
162   bool on_accept (const call_details &cd,
163                   bool successful,
164                   sm_context *sm_ctxt,
165                   const extrinsic_state &ext_state) const;
166   bool on_connect (const call_details &cd,
167                    bool successful,
168                    sm_context *sm_ctxt,
169                    const extrinsic_state &ext_state) const;
170
171   /* State for a constant file descriptor (>= 0) */
172   state_t m_constant_fd;
173
174   /* States representing a file descriptor that hasn't yet been
175     checked for validity after opening, for three different
176     access modes.  */
177   state_t m_unchecked_read_write;
178
179   state_t m_unchecked_read_only;
180
181   state_t m_unchecked_write_only;
182
183   /* States for representing a file descriptor that is known to be valid (>=
184     0), for three different access modes.  */
185   state_t m_valid_read_write;
186
187   state_t m_valid_read_only;
188
189   state_t m_valid_write_only;
190
191   /* State for a file descriptor that is known to be invalid (< 0). */
192   state_t m_invalid;
193
194   /* State for a file descriptor that has been closed.  */
195   state_t m_closed;
196
197   /* States for FDs relating to socket APIs.  */
198
199   /* Result of successful "socket" with SOCK_DGRAM.  */
200   state_t m_new_datagram_socket;
201   /* Result of successful "socket" with SOCK_STREAM.  */
202   state_t m_new_stream_socket;
203   /* Result of successful "socket" with unknown type.  */
204   state_t m_new_unknown_socket;
205
206   /* The above after a successful call to "bind".  */
207   state_t m_bound_datagram_socket;
208   state_t m_bound_stream_socket;
209   state_t m_bound_unknown_socket;
210
211   /* A bound socket after a successful call to "listen" (stream or unknown).  */
212   state_t m_listening_stream_socket;
213
214   /* (i) the new FD as a result of a succesful call to "accept" on a
215      listening socket (via a passive open), or
216      (ii) an active socket after a successful call to "connect"
217      (via an active open).  */
218   state_t m_connected_stream_socket;
219
220   /* State for a file descriptor that we do not want to track anymore . */
221   state_t m_stop;
222
223   /* Stashed constant values from the frontend.  These could be NULL.  */
224   tree m_O_ACCMODE;
225   tree m_O_RDONLY;
226   tree m_O_WRONLY;
227   tree m_SOCK_STREAM;
228   tree m_SOCK_DGRAM;
229
230 private:
231   void on_open (sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
232                 const gcall *call) const;
233   void on_creat (sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
234                 const gcall *call) const;
235   void on_close (sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
236                  const gcall *call) const;
237   void on_read (sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
238                 const gcall *call, const tree callee_fndecl) const;
239   void on_write (sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
240                  const gcall *call, const tree callee_fndecl) const;
241   void check_for_open_fd (sm_context *sm_ctxt, const supernode *node,
242                           const gimple *stmt, const gcall *call,
243                           const tree callee_fndecl,
244                           enum access_directions access_fn) const;
245
246   void make_valid_transitions_on_condition (sm_context *sm_ctxt,
247                                             const supernode *node,
248                                             const gimple *stmt,
249                                             const svalue *lhs) const;
250   void make_invalid_transitions_on_condition (sm_context *sm_ctxt,
251                                               const supernode *node,
252                                               const gimple *stmt,
253                                               const svalue *lhs) const;
254   void check_for_fd_attrs (sm_context *sm_ctxt, const supernode *node,
255                            const gimple *stmt, const gcall *call,
256                            const tree callee_fndecl, const char *attr_name,
257                            access_directions fd_attr_access_dir) const;
258   void check_for_dup (sm_context *sm_ctxt, const supernode *node,
259        const gimple *stmt, const gcall *call, const tree callee_fndecl,
260        enum dup kind) const;
261
262   state_t get_state_for_socket_type (const svalue *socket_type_sval) const;
263
264   bool check_for_socket_fd (const call_details &cd,
265                             bool successful,
266                             sm_context *sm_ctxt,
267                             const svalue *fd_sval,
268                             const supernode *node,
269                             state_t old_state,
270                             bool *complained = NULL) const;
271   bool check_for_new_socket_fd (const call_details &cd,
272                                 bool successful,
273                                 sm_context *sm_ctxt,
274                                 const svalue *fd_sval,
275                                 const supernode *node,
276                                 state_t old_state,
277                                 enum expected_phase expected_phase) const;
278 };
279
280 /* Base diagnostic class relative to fd_state_machine.  */
281 class fd_diagnostic : public pending_diagnostic
282 {
283 public:
284   fd_diagnostic (const fd_state_machine &sm, tree arg) : m_sm (sm), m_arg (arg)
285   {
286   }
287
288   bool
289   subclass_equal_p (const pending_diagnostic &base_other) const override
290   {
291     return same_tree_p (m_arg, ((const fd_diagnostic &)base_other).m_arg);
292   }
293
294   label_text
295   describe_state_change (const evdesc::state_change &change) override
296   {
297     if (change.m_old_state == m_sm.get_start_state ())
298       {
299         if (change.m_new_state == m_sm.m_unchecked_read_write
300             || change.m_new_state == m_sm.m_valid_read_write)
301           return change.formatted_print ("opened here as read-write");
302
303         if (change.m_new_state == m_sm.m_unchecked_read_only
304             || change.m_new_state == m_sm.m_valid_read_only)
305           return change.formatted_print ("opened here as read-only");
306
307         if (change.m_new_state == m_sm.m_unchecked_write_only
308             || change.m_new_state == m_sm.m_valid_write_only)
309           return change.formatted_print ("opened here as write-only");
310
311         if (change.m_new_state == m_sm.m_new_datagram_socket)
312           return change.formatted_print ("datagram socket created here");
313
314         if (change.m_new_state == m_sm.m_new_stream_socket)
315           return change.formatted_print ("stream socket created here");
316
317         if (change.m_new_state == m_sm.m_new_unknown_socket
318             || change.m_new_state == m_sm.m_connected_stream_socket)
319           return change.formatted_print ("socket created here");
320       }
321
322     if (change.m_new_state == m_sm.m_bound_datagram_socket)
323       return change.formatted_print ("datagram socket bound here");
324
325     if (change.m_new_state == m_sm.m_bound_stream_socket)
326       return change.formatted_print ("stream socket bound here");
327
328     if (change.m_new_state == m_sm.m_bound_unknown_socket
329         || change.m_new_state == m_sm.m_connected_stream_socket)
330           return change.formatted_print ("socket bound here");
331
332     if (change.m_new_state == m_sm.m_listening_stream_socket)
333       return change.formatted_print
334         ("stream socket marked as passive here via %qs", "listen");
335
336     if (change.m_new_state == m_sm.m_closed)
337       return change.formatted_print ("closed here");
338
339     if (m_sm.is_unchecked_fd_p (change.m_old_state)
340         && m_sm.is_valid_fd_p (change.m_new_state))
341       {
342         if (change.m_expr)
343           return change.formatted_print (
344               "assuming %qE is a valid file descriptor (>= 0)", change.m_expr);
345         else
346           return change.formatted_print ("assuming a valid file descriptor");
347       }
348
349     if (m_sm.is_unchecked_fd_p (change.m_old_state)
350         && change.m_new_state == m_sm.m_invalid)
351       {
352         if (change.m_expr)
353           return change.formatted_print (
354               "assuming %qE is an invalid file descriptor (< 0)",
355               change.m_expr);
356         else
357           return change.formatted_print ("assuming an invalid file descriptor");
358       }
359
360     return label_text ();
361   }
362
363   diagnostic_event::meaning
364   get_meaning_for_state_change (
365       const evdesc::state_change &change) const final override
366   {
367     if (change.m_old_state == m_sm.get_start_state ()
368         && (m_sm.is_unchecked_fd_p (change.m_new_state)
369             || change.m_new_state == m_sm.m_new_datagram_socket
370             || change.m_new_state == m_sm.m_new_stream_socket
371             || change.m_new_state == m_sm.m_new_unknown_socket))
372       return diagnostic_event::meaning (diagnostic_event::VERB_acquire,
373                          diagnostic_event::NOUN_resource);
374     if (change.m_new_state == m_sm.m_closed)
375       return diagnostic_event::meaning (diagnostic_event::VERB_release,
376                          diagnostic_event::NOUN_resource);
377     return diagnostic_event::meaning ();
378   }
379
380 protected:
381   const fd_state_machine &m_sm;
382   tree m_arg;
383 };
384
385 class fd_param_diagnostic : public fd_diagnostic
386 {
387 public:
388   fd_param_diagnostic (const fd_state_machine &sm, tree arg, tree callee_fndecl,
389                        const char *attr_name, int arg_idx)
390       : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl),
391         m_attr_name (attr_name), m_arg_idx (arg_idx)
392   {
393   }
394
395   fd_param_diagnostic (const fd_state_machine &sm, tree arg, tree callee_fndecl)
396       : fd_diagnostic (sm, arg), m_callee_fndecl (callee_fndecl),
397         m_attr_name (NULL), m_arg_idx (-1)
398   {
399   }
400
401   bool
402   subclass_equal_p (const pending_diagnostic &base_other) const override
403   {
404     const fd_param_diagnostic &sub_other
405         = (const fd_param_diagnostic &)base_other;
406     return (same_tree_p (m_arg, sub_other.m_arg)
407             && same_tree_p (m_callee_fndecl, sub_other.m_callee_fndecl)
408             && m_arg_idx == sub_other.m_arg_idx
409             && ((m_attr_name)
410                     ? (strcmp (m_attr_name, sub_other.m_attr_name) == 0)
411                     : true));
412   }
413
414   void
415   inform_filedescriptor_attribute (access_directions fd_dir)
416   {
417
418     if (m_attr_name)
419       switch (fd_dir)
420         {
421         case DIRS_READ_WRITE:
422           inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
423                   "argument %d of %qD must be an open file descriptor, due to "
424                   "%<__attribute__((%s(%d)))%>",
425                   m_arg_idx + 1, m_callee_fndecl, m_attr_name, m_arg_idx + 1);
426           break;
427         case DIRS_WRITE:
428           inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
429                   "argument %d of %qD must be a readable file descriptor, due "
430                   "to %<__attribute__((%s(%d)))%>",
431                   m_arg_idx + 1, m_callee_fndecl, m_attr_name, m_arg_idx + 1);
432           break;
433         case DIRS_READ:
434           inform (DECL_SOURCE_LOCATION (m_callee_fndecl),
435                   "argument %d of %qD must be a writable file descriptor, due "
436                   "to %<__attribute__((%s(%d)))%>",
437                   m_arg_idx + 1, m_callee_fndecl, m_attr_name, m_arg_idx + 1);
438           break;
439         }
440   }
441
442 protected:
443   tree m_callee_fndecl;
444   const char *m_attr_name;
445   /* ARG_IDX is 0-based.  */
446   int m_arg_idx;
447 };
448
449 class fd_leak : public fd_diagnostic
450 {
451 public:
452   fd_leak (const fd_state_machine &sm, tree arg) : fd_diagnostic (sm, arg) {}
453
454   const char *
455   get_kind () const final override
456   {
457     return "fd_leak";
458   }
459
460   int
461   get_controlling_option () const final override
462   {
463     return OPT_Wanalyzer_fd_leak;
464   }
465
466   bool
467   emit (rich_location *rich_loc) final override
468   {
469     /*CWE-775: Missing Release of File Descriptor or Handle after Effective
470       Lifetime
471      */
472     diagnostic_metadata m;
473     m.add_cwe (775);
474     if (m_arg)
475       return warning_meta (rich_loc, m, get_controlling_option (),
476                            "leak of file descriptor %qE", m_arg);
477     else
478       return warning_meta (rich_loc, m, get_controlling_option (),
479                            "leak of file descriptor");
480   }
481
482   label_text
483   describe_state_change (const evdesc::state_change &change) final override
484   {
485     if (m_sm.is_unchecked_fd_p (change.m_new_state))
486       {
487         m_open_event = change.m_event_id;
488         return label_text::borrow ("opened here");
489       }
490
491     return fd_diagnostic::describe_state_change (change);
492   }
493
494   label_text
495   describe_final_event (const evdesc::final_event &ev) final override
496   {
497     if (m_open_event.known_p ())
498       {
499         if (ev.m_expr)
500           return ev.formatted_print ("%qE leaks here; was opened at %@",
501                                      ev.m_expr, &m_open_event);
502         else
503           return ev.formatted_print ("leaks here; was opened at %@",
504                                      &m_open_event);
505       }
506     else
507       {
508         if (ev.m_expr)
509           return ev.formatted_print ("%qE leaks here", ev.m_expr);
510         else
511           return ev.formatted_print ("leaks here");
512       }
513   }
514
515 private:
516   diagnostic_event_id_t m_open_event;
517 };
518
519 class fd_access_mode_mismatch : public fd_param_diagnostic
520 {
521 public:
522   fd_access_mode_mismatch (const fd_state_machine &sm, tree arg,
523                            enum access_directions fd_dir,
524                            const tree callee_fndecl, const char *attr_name,
525                            int arg_idx)
526       : fd_param_diagnostic (sm, arg, callee_fndecl, attr_name, arg_idx),
527         m_fd_dir (fd_dir)
528
529   {
530   }
531
532   fd_access_mode_mismatch (const fd_state_machine &sm, tree arg,
533                            enum access_directions fd_dir,
534                            const tree callee_fndecl)
535       : fd_param_diagnostic (sm, arg, callee_fndecl), m_fd_dir (fd_dir)
536   {
537   }
538
539   const char *
540   get_kind () const final override
541   {
542     return "fd_access_mode_mismatch";
543   }
544
545   int
546   get_controlling_option () const final override
547   {
548     return OPT_Wanalyzer_fd_access_mode_mismatch;
549   }
550
551   bool
552   emit (rich_location *rich_loc) final override
553   {
554     bool warned;
555     switch (m_fd_dir)
556       {
557       case DIRS_READ:
558         warned =  warning_at (rich_loc, get_controlling_option (),
559                            "%qE on read-only file descriptor %qE",
560                            m_callee_fndecl, m_arg);
561         break;
562       case DIRS_WRITE:
563         warned = warning_at (rich_loc, get_controlling_option (),
564                            "%qE on write-only file descriptor %qE",
565                            m_callee_fndecl, m_arg);
566         break;
567       default:
568         gcc_unreachable ();
569       }
570       if (warned)
571         inform_filedescriptor_attribute (m_fd_dir);
572       return warned;
573   }
574
575   label_text
576   describe_final_event (const evdesc::final_event &ev) final override
577   {
578     switch (m_fd_dir)
579       {
580       case DIRS_READ:
581         return ev.formatted_print ("%qE on read-only file descriptor %qE",
582                                    m_callee_fndecl, m_arg);
583       case DIRS_WRITE:
584         return ev.formatted_print ("%qE on write-only file descriptor %qE",
585                                    m_callee_fndecl, m_arg);
586       default:
587         gcc_unreachable ();
588       }
589   }
590
591 private:
592   enum access_directions m_fd_dir;
593 };
594
595 class fd_double_close : public fd_diagnostic
596 {
597 public:
598   fd_double_close (const fd_state_machine &sm, tree arg) : fd_diagnostic (sm, arg)
599   {
600   }
601
602   const char *
603   get_kind () const final override
604   {
605     return "fd_double_close";
606   }
607
608   int
609   get_controlling_option () const final override
610   {
611     return OPT_Wanalyzer_fd_double_close;
612   }
613   bool
614   emit (rich_location *rich_loc) final override
615   {
616     diagnostic_metadata m;
617     // CWE-1341: Multiple Releases of Same Resource or Handle
618     m.add_cwe (1341);
619     return warning_meta (rich_loc, m, get_controlling_option (),
620                          "double %<close%> of file descriptor %qE", m_arg);
621   }
622
623   label_text
624   describe_state_change (const evdesc::state_change &change) override
625   {
626     if (m_sm.is_unchecked_fd_p (change.m_new_state))
627       return label_text::borrow ("opened here");
628
629     if (change.m_new_state == m_sm.m_closed)
630       {
631         m_first_close_event = change.m_event_id;
632         return change.formatted_print ("first %qs here", "close");
633       }
634     return fd_diagnostic::describe_state_change (change);
635   }
636
637   label_text
638   describe_final_event (const evdesc::final_event &ev) final override
639   {
640     if (m_first_close_event.known_p ())
641       return ev.formatted_print ("second %qs here; first %qs was at %@",
642                                  "close", "close", &m_first_close_event);
643     return ev.formatted_print ("second %qs here", "close");
644   }
645
646 private:
647   diagnostic_event_id_t m_first_close_event;
648 };
649
650 class fd_use_after_close : public fd_param_diagnostic
651 {
652 public:
653   fd_use_after_close (const fd_state_machine &sm, tree arg,
654                       const tree callee_fndecl, const char *attr_name,
655                       int arg_idx)
656       : fd_param_diagnostic (sm, arg, callee_fndecl, attr_name, arg_idx)
657   {
658   }
659
660   fd_use_after_close (const fd_state_machine &sm, tree arg,
661                       const tree callee_fndecl)
662       : fd_param_diagnostic (sm, arg, callee_fndecl)
663   {
664   }
665
666   const char *
667   get_kind () const final override
668   {
669     return "fd_use_after_close";
670   }
671
672   int
673   get_controlling_option () const final override
674   {
675     return OPT_Wanalyzer_fd_use_after_close;
676   }
677
678   bool
679   emit (rich_location *rich_loc) final override
680   {
681     bool warned;
682     warned = warning_at (rich_loc, get_controlling_option (),
683                        "%qE on closed file descriptor %qE", m_callee_fndecl,
684                        m_arg);
685     if (warned)
686       inform_filedescriptor_attribute (DIRS_READ_WRITE);
687     return warned;
688   }
689
690   label_text
691   describe_state_change (const evdesc::state_change &change) override
692   {
693     if (m_sm.is_unchecked_fd_p (change.m_new_state))
694       return label_text::borrow ("opened here");
695
696     if (change.m_new_state == m_sm.m_closed)
697       {
698         m_first_close_event = change.m_event_id;
699         return change.formatted_print ("closed here");
700       }
701
702     return fd_diagnostic::describe_state_change (change);
703   }
704
705   label_text
706   describe_final_event (const evdesc::final_event &ev) final override
707   {
708     if (m_first_close_event.known_p ())
709         return ev.formatted_print (
710             "%qE on closed file descriptor %qE; %qs was at %@", m_callee_fndecl,
711             m_arg, "close", &m_first_close_event);
712       else
713         return ev.formatted_print ("%qE on closed file descriptor %qE",
714                                   m_callee_fndecl, m_arg);
715   }
716
717 private:
718   diagnostic_event_id_t m_first_close_event;
719 };
720
721 class fd_use_without_check : public fd_param_diagnostic
722 {
723 public:
724   fd_use_without_check (const fd_state_machine &sm, tree arg,
725                         const tree callee_fndecl, const char *attr_name,
726                         int arg_idx)
727       : fd_param_diagnostic (sm, arg, callee_fndecl, attr_name, arg_idx)
728   {
729   }
730
731   fd_use_without_check (const fd_state_machine &sm, tree arg,
732                         const tree callee_fndecl)
733       : fd_param_diagnostic (sm, arg, callee_fndecl)
734   {
735   }
736
737   const char *
738   get_kind () const final override
739   {
740     return "fd_use_without_check";
741   }
742
743   int
744   get_controlling_option () const final override
745   {
746     return OPT_Wanalyzer_fd_use_without_check;
747   }
748
749   bool
750   emit (rich_location *rich_loc) final override
751   {
752     bool warned;
753     warned = warning_at (rich_loc, get_controlling_option (),
754                         "%qE on possibly invalid file descriptor %qE",
755                         m_callee_fndecl, m_arg);
756     if (warned)
757      inform_filedescriptor_attribute (DIRS_READ_WRITE);
758     return warned;
759   }
760
761   label_text
762   describe_state_change (const evdesc::state_change &change) override
763   {
764     if (m_sm.is_unchecked_fd_p (change.m_new_state))
765       {
766         m_first_open_event = change.m_event_id;
767         return label_text::borrow ("opened here");
768       }
769
770     return fd_diagnostic::describe_state_change (change);
771   }
772
773   label_text
774   describe_final_event (const evdesc::final_event &ev) final override
775   {
776     if (m_first_open_event.known_p ())
777       return ev.formatted_print (
778           "%qE could be invalid: unchecked value from %@", m_arg,
779           &m_first_open_event);
780     else
781       return ev.formatted_print ("%qE could be invalid", m_arg);
782   }
783
784 private:
785   diagnostic_event_id_t m_first_open_event;
786 };
787
788 /* Concrete pending_diagnostic subclass for -Wanalyzer-fd-phase-mismatch.  */
789
790 class fd_phase_mismatch : public fd_param_diagnostic
791 {
792 public:
793   fd_phase_mismatch (const fd_state_machine &sm, tree arg,
794                      const tree callee_fndecl,
795                      state_machine::state_t actual_state,
796                      enum expected_phase expected_phase)
797   : fd_param_diagnostic (sm, arg, callee_fndecl),
798     m_actual_state (actual_state),
799     m_expected_phase (expected_phase)
800   {
801     gcc_assert (m_sm.is_socket_fd_p (actual_state));
802     switch (expected_phase)
803       {
804       case EXPECTED_PHASE_CAN_TRANSFER:
805         gcc_assert (actual_state == m_sm.m_new_stream_socket
806                     || actual_state == m_sm.m_bound_stream_socket
807                     || actual_state == m_sm.m_listening_stream_socket);
808         break;
809       case EXPECTED_PHASE_CAN_BIND:
810         gcc_assert (actual_state == m_sm.m_bound_datagram_socket
811                     || actual_state == m_sm.m_bound_stream_socket
812                     || actual_state == m_sm.m_bound_unknown_socket
813                     || actual_state == m_sm.m_connected_stream_socket
814                     || actual_state == m_sm.m_listening_stream_socket);
815         break;
816       case EXPECTED_PHASE_CAN_LISTEN:
817         gcc_assert (actual_state == m_sm.m_new_stream_socket
818                     || actual_state == m_sm.m_new_unknown_socket
819                     || actual_state == m_sm.m_connected_stream_socket);
820         break;
821       case EXPECTED_PHASE_CAN_ACCEPT:
822         gcc_assert (actual_state == m_sm.m_new_stream_socket
823                     || actual_state == m_sm.m_new_unknown_socket
824                     || actual_state == m_sm.m_bound_stream_socket
825                     || actual_state == m_sm.m_bound_unknown_socket
826                     || actual_state == m_sm.m_connected_stream_socket);
827         break;
828       case EXPECTED_PHASE_CAN_CONNECT:
829         gcc_assert (actual_state == m_sm.m_bound_datagram_socket
830                     || actual_state == m_sm.m_bound_stream_socket
831                     || actual_state == m_sm.m_bound_unknown_socket
832                     || actual_state == m_sm.m_listening_stream_socket
833                     || actual_state == m_sm.m_connected_stream_socket);
834         break;
835       }
836   }
837
838   const char *
839   get_kind () const final override
840   {
841     return "fd_phase_mismatch";
842   }
843
844   bool
845   subclass_equal_p (const pending_diagnostic &base_other) const final override
846   {
847     const fd_phase_mismatch &sub_other = (const fd_phase_mismatch &)base_other;
848     if (!fd_param_diagnostic ::subclass_equal_p (sub_other))
849       return false;
850     return (m_actual_state == sub_other.m_actual_state
851             && m_expected_phase == sub_other.m_expected_phase);
852   }
853
854   int
855   get_controlling_option () const final override
856   {
857     return OPT_Wanalyzer_fd_phase_mismatch;
858   }
859
860   bool
861   emit (rich_location *rich_loc) final override
862   {
863     /* CWE-666: Operation on Resource in Wrong Phase of Lifetime.  */
864     diagnostic_metadata m;
865     m.add_cwe (666);
866     return warning_at (rich_loc, get_controlling_option (),
867                        "%qE on file descriptor %qE in wrong phase",
868                        m_callee_fndecl, m_arg);
869   }
870
871   label_text
872   describe_final_event (const evdesc::final_event &ev) final override
873   {
874     switch (m_expected_phase)
875       {
876       case EXPECTED_PHASE_CAN_TRANSFER:
877         {
878           if (m_actual_state == m_sm.m_new_stream_socket)
879             return ev.formatted_print
880               ("%qE expects a stream socket to be connected via %qs"
881                " but %qE has not yet been bound",
882                m_callee_fndecl, "accept", m_arg);
883           if (m_actual_state == m_sm.m_bound_stream_socket)
884             return ev.formatted_print
885               ("%qE expects a stream socket to be connected via %qs"
886                " but %qE is not yet listening",
887                m_callee_fndecl, "accept", m_arg);
888           if (m_actual_state == m_sm.m_listening_stream_socket)
889             return ev.formatted_print
890               ("%qE expects a stream socket to be connected via"
891                " the return value of %qs"
892                " but %qE is listening; wrong file descriptor?",
893                m_callee_fndecl, "accept", m_arg);
894         }
895         break;
896       case EXPECTED_PHASE_CAN_BIND:
897         {
898           if (m_actual_state == m_sm.m_bound_datagram_socket
899               || m_actual_state == m_sm.m_bound_stream_socket
900               || m_actual_state == m_sm.m_bound_unknown_socket)
901             return ev.formatted_print
902               ("%qE expects a new socket file descriptor"
903                " but %qE has already been bound",
904                m_callee_fndecl, m_arg);
905           if (m_actual_state == m_sm.m_connected_stream_socket)
906             return ev.formatted_print
907               ("%qE expects a new socket file descriptor"
908                " but %qE is already connected",
909                m_callee_fndecl, m_arg);
910           if (m_actual_state == m_sm.m_listening_stream_socket)
911             return ev.formatted_print
912               ("%qE expects a new socket file descriptor"
913                " but %qE is already listening",
914                m_callee_fndecl, m_arg);
915         }
916         break;
917       case EXPECTED_PHASE_CAN_LISTEN:
918         {
919           if (m_actual_state == m_sm.m_new_stream_socket
920               || m_actual_state == m_sm.m_new_unknown_socket)
921             return ev.formatted_print
922               ("%qE expects a bound stream socket file descriptor"
923                " but %qE has not yet been bound",
924                m_callee_fndecl, m_arg);
925           if (m_actual_state == m_sm.m_connected_stream_socket)
926             return ev.formatted_print
927               ("%qE expects a bound stream socket file descriptor"
928                " but %qE is connected",
929                m_callee_fndecl, m_arg);
930         }
931         break;
932       case EXPECTED_PHASE_CAN_ACCEPT:
933         {
934           if (m_actual_state == m_sm.m_new_stream_socket
935               || m_actual_state == m_sm.m_new_unknown_socket)
936             return ev.formatted_print
937               ("%qE expects a listening stream socket file descriptor"
938                " but %qE has not yet been bound",
939                m_callee_fndecl, m_arg);
940           if (m_actual_state == m_sm.m_bound_stream_socket
941               || m_actual_state == m_sm.m_bound_unknown_socket)
942             return ev.formatted_print
943               ("%qE expects a listening stream socket file descriptor"
944                " whereas %qE is bound but not yet listening",
945                m_callee_fndecl, m_arg);
946           if (m_actual_state == m_sm.m_connected_stream_socket)
947             return ev.formatted_print
948               ("%qE expects a listening stream socket file descriptor"
949                " but %qE is connected",
950                m_callee_fndecl, m_arg);
951         }
952         break;
953       case EXPECTED_PHASE_CAN_CONNECT:
954         {
955           if (m_actual_state == m_sm.m_bound_datagram_socket
956               || m_actual_state == m_sm.m_bound_stream_socket
957               || m_actual_state == m_sm.m_bound_unknown_socket)
958             return ev.formatted_print
959               ("%qE expects a new socket file descriptor but %qE is bound",
960                m_callee_fndecl, m_arg);
961           else
962             return ev.formatted_print
963               ("%qE expects a new socket file descriptor", m_callee_fndecl);
964         }
965         break;
966       }
967     gcc_unreachable ();
968   }
969
970 private:
971   state_machine::state_t m_actual_state;
972   enum expected_phase m_expected_phase;
973 };
974
975 /* Enum for use by -Wanalyzer-fd-type-mismatch.  */
976
977 enum expected_type
978 {
979  EXPECTED_TYPE_SOCKET,
980  EXPECTED_TYPE_STREAM_SOCKET
981 };
982
983 /* Concrete pending_diagnostic subclass for -Wanalyzer-fd-type-mismatch.  */
984
985 class fd_type_mismatch : public fd_param_diagnostic
986 {
987 public:
988   fd_type_mismatch (const fd_state_machine &sm, tree arg,
989                     const tree callee_fndecl,
990                     state_machine::state_t actual_state,
991                     enum expected_type expected_type)
992   : fd_param_diagnostic (sm, arg, callee_fndecl),
993     m_actual_state (actual_state),
994     m_expected_type (expected_type)
995   {
996   }
997
998   const char *
999   get_kind () const final override
1000   {
1001     return "fd_type_mismatch";
1002   }
1003
1004   bool
1005   subclass_equal_p (const pending_diagnostic &base_other) const final override
1006   {
1007     const fd_type_mismatch &sub_other = (const fd_type_mismatch &)base_other;
1008     if (!fd_param_diagnostic ::subclass_equal_p (sub_other))
1009       return false;
1010     return (m_actual_state == sub_other.m_actual_state
1011             && m_expected_type == sub_other.m_expected_type);
1012   }
1013
1014   int
1015   get_controlling_option () const final override
1016   {
1017     return OPT_Wanalyzer_fd_type_mismatch;
1018   }
1019
1020   bool
1021   emit (rich_location *rich_loc) final override
1022   {
1023     switch (m_expected_type)
1024       {
1025       default:
1026         gcc_unreachable ();
1027       case EXPECTED_TYPE_SOCKET:
1028         return warning_at (rich_loc, get_controlling_option (),
1029                            "%qE on non-socket file descriptor %qE",
1030                            m_callee_fndecl, m_arg);
1031       case EXPECTED_TYPE_STREAM_SOCKET:
1032         if (m_sm.is_datagram_socket_fd_p (m_actual_state))
1033           return warning_at (rich_loc, get_controlling_option (),
1034                              "%qE on datagram socket file descriptor %qE",
1035                              m_callee_fndecl, m_arg);
1036         else
1037           return warning_at (rich_loc, get_controlling_option (),
1038                              "%qE on non-stream-socket file descriptor %qE",
1039                              m_callee_fndecl, m_arg);
1040       }
1041   }
1042
1043   label_text
1044   describe_final_event (const evdesc::final_event &ev) final override
1045   {
1046     switch (m_expected_type)
1047       {
1048       default:
1049         break;
1050         gcc_unreachable ();
1051       case EXPECTED_TYPE_SOCKET:
1052       case EXPECTED_TYPE_STREAM_SOCKET:
1053         if (!m_sm.is_socket_fd_p (m_actual_state))
1054           return ev.formatted_print ("%qE expects a socket file descriptor"
1055                                      " but %qE is not a socket",
1056                                      m_callee_fndecl, m_arg);
1057       }
1058     gcc_assert (m_expected_type == EXPECTED_TYPE_STREAM_SOCKET);
1059     gcc_assert (m_sm.is_datagram_socket_fd_p (m_actual_state));
1060     return ev.formatted_print
1061       ("%qE expects a stream socket file descriptor"
1062        " but %qE is a datagram socket",
1063        m_callee_fndecl, m_arg);
1064   }
1065
1066 private:
1067   state_machine::state_t m_actual_state;
1068   enum expected_type m_expected_type;
1069 };
1070
1071 fd_state_machine::fd_state_machine (logger *logger)
1072     : state_machine ("file-descriptor", logger),
1073       m_constant_fd (add_state ("fd-constant")),
1074       m_unchecked_read_write (add_state ("fd-unchecked-read-write")),
1075       m_unchecked_read_only (add_state ("fd-unchecked-read-only")),
1076       m_unchecked_write_only (add_state ("fd-unchecked-write-only")),
1077       m_valid_read_write (add_state ("fd-valid-read-write")),
1078       m_valid_read_only (add_state ("fd-valid-read-only")),
1079       m_valid_write_only (add_state ("fd-valid-write-only")),
1080       m_invalid (add_state ("fd-invalid")),
1081       m_closed (add_state ("fd-closed")),
1082       m_new_datagram_socket (add_state ("fd-new-datagram-socket")),
1083       m_new_stream_socket (add_state ("fd-new-stream-socket")),
1084       m_new_unknown_socket (add_state ("fd-new-unknown-socket")),
1085       m_bound_datagram_socket (add_state ("fd-bound-datagram-socket")),
1086       m_bound_stream_socket (add_state ("fd-bound-stream-socket")),
1087       m_bound_unknown_socket (add_state ("fd-bound-unknown-socket")),
1088       m_listening_stream_socket (add_state ("fd-listening-stream-socket")),
1089       m_connected_stream_socket (add_state ("fd-connected-stream-socket")),
1090       m_stop (add_state ("fd-stop")),
1091       m_O_ACCMODE (get_stashed_constant_by_name ("O_ACCMODE")),
1092       m_O_RDONLY (get_stashed_constant_by_name ("O_RDONLY")),
1093       m_O_WRONLY (get_stashed_constant_by_name ("O_WRONLY")),
1094       m_SOCK_STREAM (get_stashed_constant_by_name ("SOCK_STREAM")),
1095       m_SOCK_DGRAM (get_stashed_constant_by_name ("SOCK_DGRAM"))
1096 {
1097 }
1098
1099 bool
1100 fd_state_machine::is_unchecked_fd_p (state_t s) const
1101 {
1102   return (s == m_unchecked_read_write
1103        || s == m_unchecked_read_only
1104        || s == m_unchecked_write_only);
1105 }
1106
1107 bool
1108 fd_state_machine::is_valid_fd_p (state_t s) const
1109 {
1110   return (s == m_valid_read_write
1111        || s == m_valid_read_only
1112        || s == m_valid_write_only);
1113 }
1114
1115 bool
1116 fd_state_machine::is_socket_fd_p (state_t s) const
1117 {
1118   return (s == m_new_datagram_socket
1119           || s == m_new_stream_socket
1120           || s == m_new_unknown_socket
1121           || s == m_bound_datagram_socket
1122           || s == m_bound_stream_socket
1123           || s == m_bound_unknown_socket
1124           || s == m_listening_stream_socket
1125           || s == m_connected_stream_socket);
1126 }
1127
1128 bool
1129 fd_state_machine::is_datagram_socket_fd_p (state_t s) const
1130 {
1131   return (s == m_new_datagram_socket
1132           || s == m_new_unknown_socket
1133           || s == m_bound_datagram_socket
1134           || s == m_bound_unknown_socket);
1135 }
1136
1137 bool
1138 fd_state_machine::is_stream_socket_fd_p (state_t s) const
1139 {
1140   return (s == m_new_stream_socket
1141           || s == m_new_unknown_socket
1142           || s == m_bound_stream_socket
1143           || s == m_bound_unknown_socket
1144           || s == m_listening_stream_socket
1145           || s == m_connected_stream_socket);
1146 }
1147
1148 enum access_mode
1149 fd_state_machine::get_access_mode_from_flag (int flag) const
1150 {
1151   if (m_O_ACCMODE && TREE_CODE (m_O_ACCMODE) == INTEGER_CST)
1152     {
1153       const unsigned HOST_WIDE_INT mask_val = TREE_INT_CST_LOW (m_O_ACCMODE);
1154       const unsigned HOST_WIDE_INT masked_flag = flag & mask_val;
1155
1156       if (m_O_RDONLY && TREE_CODE (m_O_RDONLY) == INTEGER_CST)
1157         if (masked_flag == TREE_INT_CST_LOW (m_O_RDONLY))
1158           return READ_ONLY;
1159
1160       if (m_O_WRONLY && TREE_CODE (m_O_WRONLY) == INTEGER_CST)
1161         if (masked_flag == TREE_INT_CST_LOW (m_O_WRONLY))
1162           return WRITE_ONLY;
1163     }
1164   return READ_WRITE;
1165 }
1166
1167 bool
1168 fd_state_machine::is_readonly_fd_p (state_t state) const
1169 {
1170   return (state == m_unchecked_read_only || state == m_valid_read_only);
1171 }
1172
1173 bool
1174 fd_state_machine::is_writeonly_fd_p (state_t state) const
1175 {
1176   return (state == m_unchecked_write_only || state == m_valid_write_only);
1177 }
1178
1179 bool
1180 fd_state_machine::is_closed_fd_p (state_t state) const
1181 {
1182   return (state == m_closed);
1183 }
1184
1185 bool
1186 fd_state_machine::is_constant_fd_p (state_t state) const
1187 {
1188   return (state == m_constant_fd);
1189 }
1190
1191 fd_state_machine::state_t
1192 fd_state_machine::valid_to_unchecked_state (state_t state) const
1193 {
1194   if (state == m_valid_read_write)
1195     return m_unchecked_read_write;
1196   else if (state == m_valid_write_only)
1197     return m_unchecked_write_only;
1198   else if (state == m_valid_read_only)
1199     return m_unchecked_read_only;
1200   else
1201     gcc_unreachable ();
1202   return NULL;
1203 }
1204
1205 void
1206 fd_state_machine::mark_as_valid_fd (region_model *model,
1207                                     sm_state_map *smap,
1208                                     const svalue *fd_sval,
1209                                     const extrinsic_state &ext_state) const
1210 {
1211   smap->set_state (model, fd_sval, m_valid_read_write, NULL, ext_state);
1212 }
1213
1214 bool
1215 fd_state_machine::on_stmt (sm_context *sm_ctxt, const supernode *node,
1216                            const gimple *stmt) const
1217 {
1218   if (const gcall *call = dyn_cast<const gcall *> (stmt))
1219     if (tree callee_fndecl = sm_ctxt->get_fndecl_for_call (call))
1220       {
1221         if (is_named_call_p (callee_fndecl, "open", call, 2))
1222           {
1223             on_open (sm_ctxt, node, stmt, call);
1224             return true;
1225           } //  "open"
1226
1227         if (is_named_call_p (callee_fndecl, "creat", call, 2))
1228           {
1229             on_creat (sm_ctxt, node, stmt, call);
1230             return true;
1231           } // "creat"
1232
1233         if (is_named_call_p (callee_fndecl, "close", call, 1))
1234           {
1235             on_close (sm_ctxt, node, stmt, call);
1236             return true;
1237           } //  "close"
1238
1239         if (is_named_call_p (callee_fndecl, "write", call, 3))
1240           {
1241             on_write (sm_ctxt, node, stmt, call, callee_fndecl);
1242             return true;
1243           } // "write"
1244
1245         if (is_named_call_p (callee_fndecl, "read", call, 3))
1246           {
1247             on_read (sm_ctxt, node, stmt, call, callee_fndecl);
1248             return true;
1249           } // "read"
1250
1251         if (is_named_call_p (callee_fndecl, "dup", call, 1))
1252           {
1253             check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_1);
1254             return true;
1255           }
1256
1257         if (is_named_call_p (callee_fndecl, "dup2", call, 2))
1258           {
1259             check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_2);
1260             return true;
1261           }
1262
1263         if (is_named_call_p (callee_fndecl, "dup3", call, 3))
1264           {
1265             check_for_dup (sm_ctxt, node, stmt, call, callee_fndecl, DUP_3);
1266             return true;
1267           }
1268
1269         {
1270           // Handle __attribute__((fd_arg))
1271
1272           check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
1273                               "fd_arg", DIRS_READ_WRITE);
1274
1275           // Handle __attribute__((fd_arg_read))
1276
1277           check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
1278                               "fd_arg_read", DIRS_READ);
1279
1280           // Handle __attribute__((fd_arg_write))
1281
1282           check_for_fd_attrs (sm_ctxt, node, stmt, call, callee_fndecl,
1283                               "fd_arg_write", DIRS_WRITE);
1284         }
1285       }
1286
1287   return false;
1288 }
1289
1290 void
1291 fd_state_machine::check_for_fd_attrs (
1292     sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
1293     const gcall *call, const tree callee_fndecl, const char *attr_name,
1294     access_directions fd_attr_access_dir) const
1295 {
1296
1297   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee_fndecl));
1298   attrs = lookup_attribute (attr_name, attrs);
1299   if (!attrs)
1300     return;
1301
1302   if (!TREE_VALUE (attrs))
1303     return;
1304
1305   auto_bitmap argmap;
1306
1307   for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
1308     {
1309       unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
1310       bitmap_set_bit (argmap, val);
1311     }
1312   if (bitmap_empty_p (argmap))
1313     return;
1314
1315   for (unsigned arg_idx = 0; arg_idx < gimple_call_num_args (call); arg_idx++)
1316     {
1317       tree arg = gimple_call_arg (call, arg_idx);
1318       tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
1319       state_t state = sm_ctxt->get_state (stmt, arg);
1320       bool bit_set = bitmap_bit_p (argmap, arg_idx);
1321       if (TREE_CODE (TREE_TYPE (arg)) != INTEGER_TYPE)
1322         continue;
1323       if (bit_set) // Check if arg_idx is marked by any of the file descriptor
1324                    // attributes
1325         {
1326
1327           if (is_closed_fd_p (state))
1328             {
1329
1330               sm_ctxt->warn (node, stmt, arg,
1331                              make_unique<fd_use_after_close>
1332                                (*this, diag_arg,
1333                                 callee_fndecl, attr_name,
1334                                 arg_idx));
1335               continue;
1336             }
1337
1338           if (!(is_valid_fd_p (state) || (state == m_stop)))
1339             {
1340               if (!is_constant_fd_p (state))
1341                 sm_ctxt->warn (node, stmt, arg,
1342                                make_unique<fd_use_without_check>
1343                                  (*this, diag_arg,
1344                                   callee_fndecl, attr_name,
1345                                   arg_idx));
1346             }
1347
1348           switch (fd_attr_access_dir)
1349             {
1350             case DIRS_READ_WRITE:
1351               break;
1352             case DIRS_READ:
1353
1354               if (is_writeonly_fd_p (state))
1355                 {
1356                   sm_ctxt->warn (
1357                       node, stmt, arg,
1358                       make_unique<fd_access_mode_mismatch> (*this, diag_arg,
1359                                                             DIRS_WRITE,
1360                                                             callee_fndecl,
1361                                                             attr_name,
1362                                                             arg_idx));
1363                 }
1364
1365               break;
1366             case DIRS_WRITE:
1367
1368               if (is_readonly_fd_p (state))
1369                 {
1370                   sm_ctxt->warn (
1371                       node, stmt, arg,
1372                       make_unique<fd_access_mode_mismatch> (*this, diag_arg,
1373                                                             DIRS_READ,
1374                                                             callee_fndecl,
1375                                                             attr_name,
1376                                                             arg_idx));
1377                 }
1378
1379               break;
1380             }
1381         }
1382     }
1383 }
1384
1385
1386 void
1387 fd_state_machine::on_open (sm_context *sm_ctxt, const supernode *node,
1388                            const gimple *stmt, const gcall *call) const
1389 {
1390   tree lhs = gimple_call_lhs (call);
1391   if (lhs)
1392     {
1393       tree arg = gimple_call_arg (call, 1);
1394       enum access_mode mode = READ_WRITE;
1395       if (TREE_CODE (arg) == INTEGER_CST)
1396         {
1397           int flag = TREE_INT_CST_LOW (arg);
1398           mode = get_access_mode_from_flag (flag);
1399         }
1400       switch (mode)
1401         {
1402         case READ_ONLY:
1403           sm_ctxt->on_transition (node, stmt, lhs, m_start,
1404                                   m_unchecked_read_only);
1405           break;
1406         case WRITE_ONLY:
1407           sm_ctxt->on_transition (node, stmt, lhs, m_start,
1408                                   m_unchecked_write_only);
1409           break;
1410         default:
1411           sm_ctxt->on_transition (node, stmt, lhs, m_start,
1412                                   m_unchecked_read_write);
1413         }
1414     }
1415   else
1416     {
1417       sm_ctxt->warn (node, stmt, NULL_TREE,
1418                      make_unique<fd_leak> (*this, NULL_TREE));
1419     }
1420 }
1421
1422 void
1423 fd_state_machine::on_creat (sm_context *sm_ctxt, const supernode *node,
1424                             const gimple *stmt, const gcall *call) const
1425 {
1426   tree lhs = gimple_call_lhs (call);
1427   if (lhs)
1428     sm_ctxt->on_transition (node, stmt, lhs, m_start, m_unchecked_write_only);
1429   else
1430     sm_ctxt->warn (node, stmt, NULL_TREE,
1431                    make_unique<fd_leak> (*this, NULL_TREE));
1432 }
1433
1434 void
1435 fd_state_machine::check_for_dup (sm_context *sm_ctxt, const supernode *node,
1436                                  const gimple *stmt, const gcall *call,
1437                                  const tree callee_fndecl, enum dup kind) const
1438 {
1439   tree lhs = gimple_call_lhs (call);
1440   tree arg_1 = gimple_call_arg (call, 0);
1441   state_t state_arg_1 = sm_ctxt->get_state (stmt, arg_1);
1442   if (state_arg_1 == m_stop)
1443     return;
1444   if (!(is_constant_fd_p (state_arg_1) || is_valid_fd_p (state_arg_1)
1445         || state_arg_1 == m_start))
1446     {
1447       check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl,
1448                          DIRS_READ_WRITE);
1449       return;
1450     }
1451   switch (kind)
1452     {
1453     case DUP_1:
1454       if (lhs)
1455         {
1456           if (is_constant_fd_p (state_arg_1) || state_arg_1 == m_start)
1457             sm_ctxt->set_next_state (stmt, lhs, m_unchecked_read_write);
1458           else
1459             sm_ctxt->set_next_state (stmt, lhs,
1460                                      valid_to_unchecked_state (state_arg_1));
1461         }
1462       break;
1463
1464     case DUP_2:
1465     case DUP_3:
1466       tree arg_2 = gimple_call_arg (call, 1);
1467       state_t state_arg_2 = sm_ctxt->get_state (stmt, arg_2);
1468       tree diag_arg_2 = sm_ctxt->get_diagnostic_tree (arg_2);
1469       if (state_arg_2 == m_stop)
1470         return;
1471       /* Check if -1 was passed as second argument to dup2.  */
1472       if (!(is_constant_fd_p (state_arg_2) || is_valid_fd_p (state_arg_2)
1473             || state_arg_2 == m_start))
1474         {
1475           sm_ctxt->warn (
1476               node, stmt, arg_2,
1477               make_unique<fd_use_without_check> (*this, diag_arg_2,
1478                                                  callee_fndecl));
1479           return;
1480         }
1481       /* dup2 returns value of its second argument on success.But, the
1482       access mode of the returned file descriptor depends on the duplicated
1483       file descriptor i.e the first argument.  */
1484       if (lhs)
1485         {
1486           if (is_constant_fd_p (state_arg_1) || state_arg_1 == m_start)
1487             sm_ctxt->set_next_state (stmt, lhs, m_unchecked_read_write);
1488           else
1489             sm_ctxt->set_next_state (stmt, lhs,
1490                                      valid_to_unchecked_state (state_arg_1));
1491         }
1492
1493       break;
1494     }
1495 }
1496
1497 void
1498 fd_state_machine::on_close (sm_context *sm_ctxt, const supernode *node,
1499                             const gimple *stmt, const gcall *call) const
1500 {
1501   tree arg = gimple_call_arg (call, 0);
1502   state_t state = sm_ctxt->get_state (stmt, arg);
1503   tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
1504
1505   sm_ctxt->on_transition (node, stmt, arg, m_start, m_closed);
1506   sm_ctxt->on_transition (node, stmt, arg, m_unchecked_read_write, m_closed);
1507   sm_ctxt->on_transition (node, stmt, arg, m_unchecked_read_only, m_closed);
1508   sm_ctxt->on_transition (node, stmt, arg, m_unchecked_write_only, m_closed);
1509   sm_ctxt->on_transition (node, stmt, arg, m_valid_read_write, m_closed);
1510   sm_ctxt->on_transition (node, stmt, arg, m_valid_read_only, m_closed);
1511   sm_ctxt->on_transition (node, stmt, arg, m_valid_write_only, m_closed);
1512   sm_ctxt->on_transition (node, stmt, arg, m_constant_fd, m_closed);
1513   sm_ctxt->on_transition (node, stmt, arg, m_new_datagram_socket, m_closed);
1514   sm_ctxt->on_transition (node, stmt, arg, m_new_stream_socket, m_closed);
1515   sm_ctxt->on_transition (node, stmt, arg, m_new_unknown_socket, m_closed);
1516   sm_ctxt->on_transition (node, stmt, arg, m_bound_datagram_socket, m_closed);
1517   sm_ctxt->on_transition (node, stmt, arg, m_bound_stream_socket, m_closed);
1518   sm_ctxt->on_transition (node, stmt, arg, m_bound_unknown_socket, m_closed);
1519   sm_ctxt->on_transition (node, stmt, arg, m_listening_stream_socket, m_closed);
1520   sm_ctxt->on_transition (node, stmt, arg, m_connected_stream_socket, m_closed);
1521
1522   if (is_closed_fd_p (state))
1523     {
1524       sm_ctxt->warn (node, stmt, arg,
1525                      make_unique<fd_double_close> (*this, diag_arg));
1526       sm_ctxt->set_next_state (stmt, arg, m_stop);
1527     }
1528 }
1529 void
1530 fd_state_machine::on_read (sm_context *sm_ctxt, const supernode *node,
1531                            const gimple *stmt, const gcall *call,
1532                            const tree callee_fndecl) const
1533 {
1534   check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIRS_READ);
1535 }
1536 void
1537 fd_state_machine::on_write (sm_context *sm_ctxt, const supernode *node,
1538                             const gimple *stmt, const gcall *call,
1539                             const tree callee_fndecl) const
1540 {
1541   check_for_open_fd (sm_ctxt, node, stmt, call, callee_fndecl, DIRS_WRITE);
1542 }
1543
1544 void
1545 fd_state_machine::check_for_open_fd (
1546     sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
1547     const gcall *call, const tree callee_fndecl,
1548     enum access_directions callee_fndecl_dir) const
1549 {
1550   tree arg = gimple_call_arg (call, 0);
1551   tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
1552   state_t state = sm_ctxt->get_state (stmt, arg);
1553
1554   if (is_closed_fd_p (state))
1555     {
1556       sm_ctxt->warn (node, stmt, arg,
1557                      make_unique<fd_use_after_close> (*this, diag_arg,
1558                                                       callee_fndecl));
1559     }
1560
1561   else
1562     {
1563       if (state == m_new_stream_socket
1564           || state == m_bound_stream_socket
1565           || state == m_listening_stream_socket)
1566         /* Complain about fncall on socket in wrong phase.  */
1567         sm_ctxt->warn
1568           (node, stmt, arg,
1569            make_unique<fd_phase_mismatch> (*this, diag_arg,
1570                                            callee_fndecl,
1571                                            state,
1572                                            EXPECTED_PHASE_CAN_TRANSFER));
1573       else if (!(is_valid_fd_p (state)
1574                  || state == m_new_datagram_socket
1575                  || state == m_bound_unknown_socket
1576                  || state == m_connected_stream_socket
1577                  || state == m_start
1578                  || state == m_stop))
1579         {
1580           if (!is_constant_fd_p (state))
1581             sm_ctxt->warn (
1582                 node, stmt, arg,
1583                 make_unique<fd_use_without_check> (*this, diag_arg,
1584                                                    callee_fndecl));
1585         }
1586       switch (callee_fndecl_dir)
1587         {
1588         case DIRS_READ_WRITE:
1589           break;
1590         case DIRS_READ:
1591           if (is_writeonly_fd_p (state))
1592             {
1593               tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
1594               sm_ctxt->warn (node, stmt, arg,
1595                              make_unique<fd_access_mode_mismatch> (
1596                                  *this, diag_arg, DIRS_WRITE, callee_fndecl));
1597             }
1598
1599           break;
1600         case DIRS_WRITE:
1601
1602           if (is_readonly_fd_p (state))
1603             {
1604               tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
1605               sm_ctxt->warn (node, stmt, arg,
1606                              make_unique<fd_access_mode_mismatch> (
1607                                  *this, diag_arg, DIRS_READ, callee_fndecl));
1608             }
1609           break;
1610         }
1611     }
1612 }
1613
1614 static bool
1615 add_constraint_ge_zero (region_model *model,
1616                         const svalue *fd_sval,
1617                         region_model_context *ctxt)
1618 {
1619   const svalue *zero
1620     = model->get_manager ()->get_or_create_int_cst (integer_type_node, 0);
1621   return model->add_constraint (fd_sval, GE_EXPR, zero, ctxt);
1622 }
1623
1624 /* Get the state for a new socket type based on SOCKET_TYPE_SVAL,
1625    a SOCK_* value.  */
1626
1627 state_machine::state_t
1628 fd_state_machine::
1629 get_state_for_socket_type (const svalue *socket_type_sval) const
1630 {
1631   if (tree socket_type_cst = socket_type_sval->maybe_get_constant ())
1632     {
1633       /* Attempt to use SOCK_* constants stashed from the frontend.  */
1634       if (tree_int_cst_equal (socket_type_cst, m_SOCK_STREAM))
1635         return m_new_stream_socket;
1636       if (tree_int_cst_equal (socket_type_cst, m_SOCK_DGRAM))
1637         return m_new_datagram_socket;
1638     }
1639
1640   /* Unrecognized constant, or a symbolic "type" value.  */
1641   return m_new_unknown_socket;
1642 }
1643
1644 /* Update the model and fd state for an outcome of a call to "socket",
1645    where SUCCESSFUL indicate which of the two outcomes.
1646    Return true if the outcome is feasible, or false to reject it.  */
1647
1648 bool
1649 fd_state_machine::on_socket (const call_details &cd,
1650                              bool successful,
1651                              sm_context *sm_ctxt,
1652                              const extrinsic_state &ext_state) const
1653 {
1654   const gcall *stmt = cd.get_call_stmt ();
1655   engine *eng = ext_state.get_engine ();
1656   const supergraph *sg = eng->get_supergraph ();
1657   const supernode *node = sg->get_supernode_for_stmt (stmt);
1658   region_model *model = cd.get_model ();
1659
1660   if (successful)
1661     {
1662       if (gimple_call_lhs (stmt))
1663         {
1664           conjured_purge p (model, cd.get_ctxt ());
1665           region_model_manager *mgr = model->get_manager ();
1666           const svalue *new_fd
1667             = mgr->get_or_create_conjured_svalue (integer_type_node,
1668                                                   stmt,
1669                                                   cd.get_lhs_region (),
1670                                                   p);
1671           if (!add_constraint_ge_zero (model, new_fd, cd.get_ctxt ()))
1672             return false;
1673
1674           const svalue *socket_type_sval = cd.get_arg_svalue (1);
1675           state_machine::state_t new_state
1676             = get_state_for_socket_type (socket_type_sval);
1677           sm_ctxt->on_transition (node, stmt, new_fd, m_start, new_state);
1678           model->set_value (cd.get_lhs_region (), new_fd, cd.get_ctxt ());
1679         }
1680       else
1681         sm_ctxt->warn (node, stmt, NULL_TREE,
1682                        make_unique<fd_leak> (*this, NULL_TREE));
1683     }
1684   else
1685     {
1686       /* Return -1; set errno.  */
1687       model->update_for_int_cst_return (cd, -1, true);
1688       model->set_errno (cd);
1689     }
1690
1691   return true;
1692 }
1693
1694 /* Check that FD_SVAL is usable by socket APIs.
1695    Complain if it has been closed, if it is a non-socket,
1696    or is invalid.
1697    If COMPLAINED is non-NULL and a problem is found,
1698    write *COMPLAINED = true.
1699
1700    If SUCCESSFUL is true, attempt to add the constraint that FD_SVAL >= 0.
1701    Return true if this outcome is feasible.  */
1702
1703 bool
1704 fd_state_machine::check_for_socket_fd (const call_details &cd,
1705                                        bool successful,
1706                                        sm_context *sm_ctxt,
1707                                        const svalue *fd_sval,
1708                                        const supernode *node,
1709                                        state_t old_state,
1710                                        bool *complained) const
1711 {
1712   const gcall *stmt = cd.get_call_stmt ();
1713
1714   if (is_closed_fd_p (old_state))
1715     {
1716       tree diag_arg = sm_ctxt->get_diagnostic_tree (fd_sval);
1717       sm_ctxt->warn
1718         (node, stmt, fd_sval,
1719          make_unique<fd_use_after_close> (*this, diag_arg,
1720                                           cd.get_fndecl_for_call ()));
1721       if (complained)
1722         *complained = true;
1723       if (successful)
1724         return false;
1725     }
1726   else if (is_unchecked_fd_p (old_state) || is_valid_fd_p (old_state))
1727     {
1728       /* Complain about non-socket.  */
1729       tree diag_arg = sm_ctxt->get_diagnostic_tree (fd_sval);
1730       sm_ctxt->warn
1731         (node, stmt, fd_sval,
1732          make_unique<fd_type_mismatch> (*this, diag_arg,
1733                                         cd.get_fndecl_for_call (),
1734                                         old_state,
1735                                         EXPECTED_TYPE_SOCKET));
1736       if (complained)
1737         *complained = true;
1738       if (successful)
1739         return false;
1740     }
1741   else if (old_state == m_invalid)
1742     {
1743       tree diag_arg = sm_ctxt->get_diagnostic_tree (fd_sval);
1744       sm_ctxt->warn
1745         (node, stmt, fd_sval,
1746          make_unique<fd_use_without_check> (*this, diag_arg,
1747                                             cd.get_fndecl_for_call ()));
1748       if (complained)
1749         *complained = true;
1750       if (successful)
1751         return false;
1752     }
1753
1754   if (successful)
1755     if (!add_constraint_ge_zero (cd.get_model (), fd_sval, cd.get_ctxt ()))
1756       return false;
1757
1758   return true;
1759 }
1760
1761 /* For use by "bind" and "connect".
1762    As per fd_state_machine::check_for_socket_fd above,
1763    but also complain if we don't have a new socket, and check that
1764    we can read up to the size bytes from the address.  */
1765
1766 bool
1767 fd_state_machine::check_for_new_socket_fd (const call_details &cd,
1768                                            bool successful,
1769                                            sm_context *sm_ctxt,
1770                                            const svalue *fd_sval,
1771                                            const supernode *node,
1772                                            state_t old_state,
1773                                            enum expected_phase expected_phase)
1774   const
1775 {
1776   bool complained = false;
1777
1778   /* Check address and len.  */
1779   const svalue *address_sval = cd.get_arg_svalue (1);
1780   const svalue *len_sval = cd.get_arg_svalue (2);
1781
1782   /* Check that we can read the given number of bytes from the
1783      address.  */
1784   region_model *model = cd.get_model ();
1785   const region *address_reg
1786     = model->deref_rvalue (address_sval, cd.get_arg_tree (1),
1787                            cd.get_ctxt ());
1788   const region *sized_address_reg
1789     = model->get_manager ()->get_sized_region (address_reg,
1790                                                NULL_TREE,
1791                                                len_sval);
1792   model->get_store_value (sized_address_reg, cd.get_ctxt ());
1793
1794   if (!check_for_socket_fd (cd, successful, sm_ctxt,
1795                             fd_sval, node, old_state, &complained))
1796     return false;
1797   else if (!complained
1798            && !(old_state == m_new_stream_socket
1799                 || old_state == m_new_datagram_socket
1800                 || old_state == m_new_unknown_socket
1801                 || old_state == m_start
1802                 || old_state == m_stop
1803                 || old_state == m_constant_fd))
1804     {
1805       /* Complain about "bind" or "connect" in wrong phase.  */
1806       tree diag_arg = sm_ctxt->get_diagnostic_tree (fd_sval);
1807       sm_ctxt->warn
1808         (node, cd.get_call_stmt (), fd_sval,
1809          make_unique<fd_phase_mismatch> (*this, diag_arg,
1810                                          cd.get_fndecl_for_call (),
1811                                          old_state,
1812                                          expected_phase));
1813       if (successful)
1814         return false;
1815     }
1816   else if (!successful)
1817     {
1818       /* If we were in the start state, assume we had a new socket.  */
1819       if (old_state == m_start)
1820         sm_ctxt->set_next_state (cd.get_call_stmt (), fd_sval,
1821                                  m_new_unknown_socket);
1822     }
1823
1824   /* Passing NULL as the address will lead to failure.  */
1825   if (successful)
1826     if (address_sval->all_zeroes_p ())
1827       return false;
1828
1829   return true;
1830 }
1831
1832 /* Update the model and fd state for an outcome of a call to "bind",
1833    where SUCCESSFUL indicate which of the two outcomes.
1834    Return true if the outcome is feasible, or false to reject it.  */
1835
1836 bool
1837 fd_state_machine::on_bind (const call_details &cd,
1838                            bool successful,
1839                            sm_context *sm_ctxt,
1840                            const extrinsic_state &ext_state) const
1841 {
1842   const gcall *stmt = cd.get_call_stmt ();
1843   engine *eng = ext_state.get_engine ();
1844   const supergraph *sg = eng->get_supergraph ();
1845   const supernode *node = sg->get_supernode_for_stmt (stmt);
1846   const svalue *fd_sval = cd.get_arg_svalue (0);
1847   region_model *model = cd.get_model ();
1848   state_t old_state = sm_ctxt->get_state (stmt, fd_sval);
1849
1850   if (!check_for_new_socket_fd (cd, successful, sm_ctxt,
1851                                 fd_sval, node, old_state,
1852                                 EXPECTED_PHASE_CAN_BIND))
1853     return false;
1854
1855   if (successful)
1856     {
1857       state_t next_state = NULL;
1858       if (old_state == m_new_stream_socket)
1859         next_state = m_bound_stream_socket;
1860       else if (old_state == m_new_datagram_socket)
1861         next_state = m_bound_datagram_socket;
1862       else if (old_state == m_new_unknown_socket)
1863         next_state = m_bound_unknown_socket;
1864       else if (old_state == m_start)
1865         next_state = m_bound_unknown_socket;
1866       else if (old_state == m_stop)
1867         next_state = m_stop;
1868       else
1869         gcc_unreachable ();
1870       sm_ctxt->set_next_state (cd.get_call_stmt (), fd_sval, next_state);
1871       model->update_for_zero_return (cd, true);
1872     }
1873   else
1874     {
1875       /* Return -1; set errno.  */
1876       model->update_for_int_cst_return (cd, -1, true);
1877       model->set_errno (cd);
1878     }
1879
1880   return true;
1881 }
1882
1883 /* Update the model and fd state for an outcome of a call to "listen",
1884    where SUCCESSFUL indicate which of the two outcomes.
1885    Return true if the outcome is feasible, or false to reject it.  */
1886
1887 bool
1888 fd_state_machine::on_listen (const call_details &cd,
1889                              bool successful,
1890                              sm_context *sm_ctxt,
1891                              const extrinsic_state &ext_state) const
1892 {
1893   const gcall *stmt = cd.get_call_stmt ();
1894   engine *eng = ext_state.get_engine ();
1895   const supergraph *sg = eng->get_supergraph ();
1896   const supernode *node = sg->get_supernode_for_stmt (cd.get_call_stmt ());
1897   const svalue *fd_sval = cd.get_arg_svalue (0);
1898   region_model *model = cd.get_model ();
1899   state_t old_state = sm_ctxt->get_state (stmt, fd_sval);
1900
1901   /* We expect a stream socket that's had "bind" called on it.  */
1902   if (!check_for_socket_fd (cd, successful, sm_ctxt, fd_sval, node, old_state))
1903     return false;
1904   if (!(old_state == m_start
1905         || old_state == m_constant_fd
1906         || old_state == m_stop
1907         || old_state == m_bound_stream_socket
1908         || old_state == m_bound_unknown_socket
1909         /* Assume it's OK to call "listen" more than once.  */
1910         || old_state == m_listening_stream_socket))
1911     {
1912       /* Complain about fncall on wrong type or in wrong phase.  */
1913       tree diag_arg = sm_ctxt->get_diagnostic_tree (fd_sval);
1914       if (is_stream_socket_fd_p (old_state))
1915         sm_ctxt->warn
1916           (node, stmt, fd_sval,
1917            make_unique<fd_phase_mismatch> (*this, diag_arg,
1918                                            cd.get_fndecl_for_call (),
1919                                            old_state,
1920                                            EXPECTED_PHASE_CAN_LISTEN));
1921       else
1922         sm_ctxt->warn
1923           (node, stmt, fd_sval,
1924            make_unique<fd_type_mismatch> (*this, diag_arg,
1925                                           cd.get_fndecl_for_call (),
1926                                           old_state,
1927                                           EXPECTED_TYPE_STREAM_SOCKET));
1928       if (successful)
1929         return false;
1930     }
1931
1932   if (successful)
1933     {
1934       model->update_for_zero_return (cd, true);
1935       sm_ctxt->set_next_state (cd.get_call_stmt (), fd_sval,
1936                                m_listening_stream_socket);
1937     }
1938   else
1939     {
1940       /* Return -1; set errno.  */
1941       model->update_for_int_cst_return (cd, -1, true);
1942       model->set_errno (cd);
1943       if (old_state == m_start)
1944         sm_ctxt->set_next_state (cd.get_call_stmt (), fd_sval,
1945                                  m_bound_stream_socket);
1946     }
1947
1948   return true;
1949 }
1950
1951 /* Update the model and fd state for an outcome of a call to "accept",
1952    where SUCCESSFUL indicate which of the two outcomes.
1953    Return true if the outcome is feasible, or false to reject it.  */
1954
1955 bool
1956 fd_state_machine::on_accept (const call_details &cd,
1957                              bool successful,
1958                              sm_context *sm_ctxt,
1959                              const extrinsic_state &ext_state) const
1960 {
1961   const gcall *stmt = cd.get_call_stmt ();
1962   engine *eng = ext_state.get_engine ();
1963   const supergraph *sg = eng->get_supergraph ();
1964   const supernode *node = sg->get_supernode_for_stmt (stmt);
1965   const svalue *fd_sval = cd.get_arg_svalue (0);
1966   const svalue *address_sval = cd.get_arg_svalue (1);
1967   const svalue *len_ptr_sval = cd.get_arg_svalue (2);
1968   region_model *model = cd.get_model ();
1969   state_t old_state = sm_ctxt->get_state (stmt, fd_sval);
1970
1971   if (!address_sval->all_zeroes_p ())
1972     {
1973       region_model_manager *mgr = model->get_manager ();
1974
1975       /* We might have a union of various pointer types, rather than a
1976          pointer type; cast to (void *) before dereferencing.  */
1977       address_sval = mgr->get_or_create_cast (ptr_type_node, address_sval);
1978
1979       const region *address_reg
1980         = model->deref_rvalue (address_sval, cd.get_arg_tree (1),
1981                                cd.get_ctxt ());
1982       const region *len_reg
1983         = model->deref_rvalue (len_ptr_sval, cd.get_arg_tree (2),
1984                                cd.get_ctxt ());
1985       const svalue *old_len_sval
1986         = model->get_store_value (len_reg, cd.get_ctxt ());
1987       tree len_ptr = cd.get_arg_tree (2);
1988       tree star_len_ptr = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (len_ptr)),
1989                                   len_ptr,
1990                                   build_int_cst (TREE_TYPE (len_ptr), 0));
1991       old_len_sval = model->check_for_poison (old_len_sval,
1992                                               star_len_ptr,
1993                                               cd.get_ctxt ());
1994       if (successful)
1995         {
1996           conjured_purge p (model, cd.get_ctxt ());
1997           const region *old_sized_address_reg
1998             = mgr->get_sized_region (address_reg,
1999                                      NULL_TREE,
2000                                      old_len_sval);
2001           const svalue *new_addr_sval
2002             = mgr->get_or_create_conjured_svalue (NULL_TREE,
2003                                                   stmt,
2004                                                   old_sized_address_reg,
2005                                                   p);
2006           model->set_value (old_sized_address_reg, new_addr_sval,
2007                             cd.get_ctxt ());
2008           const svalue *new_addr_len
2009             = mgr->get_or_create_conjured_svalue (NULL_TREE,
2010                                                   stmt,
2011                                                   len_reg,
2012                                                   p);
2013           model->set_value (len_reg, new_addr_len, cd.get_ctxt ());
2014         }
2015     }
2016
2017   /* We expect a stream socket in the "listening" state.  */
2018   if (!check_for_socket_fd (cd, successful, sm_ctxt, fd_sval, node, old_state))
2019     return false;
2020
2021   if (old_state == m_start || old_state == m_constant_fd)
2022     /* If we were in the start state (or a constant), assume we had the
2023        expected state.  */
2024     sm_ctxt->set_next_state (cd.get_call_stmt (), fd_sval,
2025                              m_listening_stream_socket);
2026   else if (old_state == m_stop)
2027     {
2028       /* No further complaints.  */
2029     }
2030   else if (old_state != m_listening_stream_socket)
2031     {
2032       /* Complain about fncall on wrong type or in wrong phase.  */
2033       tree diag_arg = sm_ctxt->get_diagnostic_tree (fd_sval);
2034       if (is_stream_socket_fd_p (old_state))
2035         sm_ctxt->warn
2036           (node, stmt, fd_sval,
2037            make_unique<fd_phase_mismatch> (*this, diag_arg,
2038                                            cd.get_fndecl_for_call (),
2039                                            old_state,
2040                                            EXPECTED_PHASE_CAN_ACCEPT));
2041       else
2042         sm_ctxt->warn
2043           (node, stmt, fd_sval,
2044            make_unique<fd_type_mismatch> (*this, diag_arg,
2045                                           cd.get_fndecl_for_call (),
2046                                           old_state,
2047                                           EXPECTED_TYPE_STREAM_SOCKET));
2048       if (successful)
2049         return false;
2050     }
2051
2052   if (successful)
2053     {
2054       /* Return new conjured FD in "connected" state.  */
2055       if (gimple_call_lhs (stmt))
2056         {
2057           conjured_purge p (model, cd.get_ctxt ());
2058           region_model_manager *mgr = model->get_manager ();
2059           const svalue *new_fd
2060             = mgr->get_or_create_conjured_svalue (integer_type_node,
2061                                                   stmt,
2062                                                   cd.get_lhs_region (),
2063                                                   p);
2064           if (!add_constraint_ge_zero (model, new_fd, cd.get_ctxt ()))
2065             return false;
2066           sm_ctxt->on_transition (node, stmt, new_fd,
2067                                   m_start, m_connected_stream_socket);
2068           model->set_value (cd.get_lhs_region (), new_fd, cd.get_ctxt ());
2069         }
2070       else
2071         sm_ctxt->warn (node, stmt, NULL_TREE,
2072                        make_unique<fd_leak> (*this, NULL_TREE));
2073     }
2074   else
2075     {
2076       /* Return -1; set errno.  */
2077       model->update_for_int_cst_return (cd, -1, true);
2078       model->set_errno (cd);
2079     }
2080
2081   return true;
2082 }
2083
2084 /* Update the model and fd state for an outcome of a call to "connect",
2085    where SUCCESSFUL indicate which of the two outcomes.
2086    Return true if the outcome is feasible, or false to reject it.  */
2087
2088 bool
2089 fd_state_machine::on_connect (const call_details &cd,
2090                               bool successful,
2091                               sm_context *sm_ctxt,
2092                               const extrinsic_state &ext_state) const
2093 {
2094   const gcall *stmt = cd.get_call_stmt ();
2095   engine *eng = ext_state.get_engine ();
2096   const supergraph *sg = eng->get_supergraph ();
2097   const supernode *node = sg->get_supernode_for_stmt (stmt);
2098   const svalue *fd_sval = cd.get_arg_svalue (0);
2099   region_model *model = cd.get_model ();
2100   state_t old_state = sm_ctxt->get_state (stmt, fd_sval);
2101
2102   if (!check_for_new_socket_fd (cd, successful, sm_ctxt,
2103                                 fd_sval, node, old_state,
2104                                 EXPECTED_PHASE_CAN_CONNECT))
2105     return false;
2106
2107   if (successful)
2108     {
2109       model->update_for_zero_return (cd, true);
2110       state_t next_state = NULL;
2111       if (old_state == m_new_stream_socket)
2112         next_state = m_connected_stream_socket;
2113       else if (old_state == m_new_datagram_socket)
2114         /* It's legal to call connect on a datagram socket, potentially
2115            more than once.  We don't transition states for this.  */
2116         next_state = m_new_datagram_socket;
2117       else if (old_state == m_new_unknown_socket)
2118         next_state = m_stop;
2119       else if (old_state == m_start)
2120         next_state = m_stop;
2121       else if (old_state == m_stop)
2122         next_state = m_stop;
2123       else
2124         gcc_unreachable ();
2125       sm_ctxt->set_next_state (cd.get_call_stmt (), fd_sval, next_state);
2126     }
2127   else
2128     {
2129       /* Return -1; set errno.  */
2130       model->update_for_int_cst_return (cd, -1, true);
2131       model->set_errno (cd);
2132       /* TODO: perhaps transition to a failed state, since the
2133          portable way to handle a failed "connect" is to close
2134          the socket and try again with a new socket.  */
2135     }
2136
2137   return true;
2138 }
2139
2140 void
2141 fd_state_machine::on_condition (sm_context *sm_ctxt, const supernode *node,
2142                                 const gimple *stmt, const svalue *lhs,
2143                                 enum tree_code op, const svalue *rhs) const
2144 {
2145   if (tree cst = rhs->maybe_get_constant ())
2146     {
2147       if (TREE_CODE (cst) == INTEGER_CST)
2148         {
2149           int val = TREE_INT_CST_LOW (cst);
2150           if (val == -1)
2151             {
2152               if (op == NE_EXPR)
2153                 make_valid_transitions_on_condition (sm_ctxt, node, stmt, lhs);
2154
2155               else if (op == EQ_EXPR)
2156                 make_invalid_transitions_on_condition (sm_ctxt, node, stmt,
2157                                                        lhs);
2158             }
2159         }
2160     }
2161
2162   if (rhs->all_zeroes_p ())
2163     {
2164       if (op == GE_EXPR)
2165         make_valid_transitions_on_condition (sm_ctxt, node, stmt, lhs);
2166       else if (op == LT_EXPR)
2167         make_invalid_transitions_on_condition (sm_ctxt, node, stmt, lhs);
2168     }
2169 }
2170
2171 void
2172 fd_state_machine::make_valid_transitions_on_condition (sm_context *sm_ctxt,
2173                                                        const supernode *node,
2174                                                        const gimple *stmt,
2175                                                        const svalue *lhs) const
2176 {
2177   sm_ctxt->on_transition (node, stmt, lhs, m_unchecked_read_write,
2178                           m_valid_read_write);
2179   sm_ctxt->on_transition (node, stmt, lhs, m_unchecked_read_only,
2180                           m_valid_read_only);
2181   sm_ctxt->on_transition (node, stmt, lhs, m_unchecked_write_only,
2182                           m_valid_write_only);
2183 }
2184
2185 void
2186 fd_state_machine::make_invalid_transitions_on_condition (
2187     sm_context *sm_ctxt, const supernode *node, const gimple *stmt,
2188     const svalue *lhs) const
2189 {
2190   sm_ctxt->on_transition (node, stmt, lhs, m_unchecked_read_write, m_invalid);
2191   sm_ctxt->on_transition (node, stmt, lhs, m_unchecked_read_only, m_invalid);
2192   sm_ctxt->on_transition (node, stmt, lhs, m_unchecked_write_only, m_invalid);
2193 }
2194
2195 bool
2196 fd_state_machine::can_purge_p (state_t s) const
2197 {
2198   if (is_unchecked_fd_p (s)
2199       || is_valid_fd_p (s)
2200       || is_socket_fd_p (s))
2201     return false;
2202   else
2203     return true;
2204 }
2205
2206 std::unique_ptr<pending_diagnostic>
2207 fd_state_machine::on_leak (tree var) const
2208 {
2209   return make_unique<fd_leak> (*this, var);
2210 }
2211 } // namespace
2212
2213 state_machine *
2214 make_fd_state_machine (logger *logger)
2215 {
2216   return new fd_state_machine (logger);
2217 }
2218
2219 static bool
2220 get_fd_state (region_model_context *ctxt,
2221               sm_state_map **out_smap,
2222               const fd_state_machine **out_sm,
2223               unsigned *out_sm_idx,
2224               std::unique_ptr<sm_context> *out_sm_context)
2225 {
2226   if (!ctxt)
2227     return false;
2228
2229   const state_machine *sm;
2230   if (!ctxt->get_fd_map (out_smap, &sm, out_sm_idx, out_sm_context))
2231     return false;
2232
2233   gcc_assert (sm);
2234
2235   *out_sm = (const fd_state_machine *)sm;
2236   return true;
2237 }
2238
2239 /* Specialcase hook for handling pipe, for use by
2240    kf_pipe::success::update_model.  */
2241
2242 void
2243 region_model::mark_as_valid_fd (const svalue *sval, region_model_context *ctxt)
2244 {
2245   sm_state_map *smap;
2246   const fd_state_machine *fd_sm;
2247   if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, NULL))
2248     return;
2249   const extrinsic_state *ext_state = ctxt->get_ext_state ();
2250   if (!ext_state)
2251     return;
2252   fd_sm->mark_as_valid_fd (this, smap, sval, *ext_state);
2253 }
2254
2255 /* Handle calls to "socket".
2256    See e.g. https://man7.org/linux/man-pages/man3/socket.3p.html  */
2257
2258 class kf_socket : public known_function
2259 {
2260 public:
2261   class outcome_of_socket : public succeed_or_fail_call_info
2262   {
2263   public:
2264     outcome_of_socket (const call_details &cd, bool success)
2265     : succeed_or_fail_call_info (cd, success)
2266     {}
2267
2268     bool update_model (region_model *model,
2269                        const exploded_edge *,
2270                        region_model_context *ctxt) const final override
2271     {
2272       const call_details cd (get_call_details (model, ctxt));
2273       sm_state_map *smap;
2274       const fd_state_machine *fd_sm;
2275       std::unique_ptr<sm_context> sm_ctxt;
2276       if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
2277         return true;
2278       const extrinsic_state *ext_state = ctxt->get_ext_state ();
2279       if (!ext_state)
2280         return true;
2281
2282       return fd_sm->on_socket (cd, m_success, sm_ctxt.get (), *ext_state);
2283     }
2284   };
2285
2286   bool matches_call_types_p (const call_details &cd) const final override
2287   {
2288     return cd.num_args () == 3;
2289   }
2290
2291   void impl_call_post (const call_details &cd) const final override
2292   {
2293     if (cd.get_ctxt ())
2294       {
2295         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_socket> (cd, false));
2296         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_socket> (cd, true));
2297         cd.get_ctxt ()->terminate_path ();
2298       }
2299   }
2300 };
2301
2302 /* Handle calls to "bind".
2303    See e.g. https://man7.org/linux/man-pages/man3/bind.3p.html  */
2304
2305 class kf_bind : public known_function
2306 {
2307 public:
2308   class outcome_of_bind : public succeed_or_fail_call_info
2309   {
2310   public:
2311     outcome_of_bind (const call_details &cd, bool success)
2312     : succeed_or_fail_call_info (cd, success)
2313     {}
2314
2315     bool update_model (region_model *model,
2316                        const exploded_edge *,
2317                        region_model_context *ctxt) const final override
2318     {
2319       const call_details cd (get_call_details (model, ctxt));
2320       sm_state_map *smap;
2321       const fd_state_machine *fd_sm;
2322       std::unique_ptr<sm_context> sm_ctxt;
2323       if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
2324         return true;
2325       const extrinsic_state *ext_state = ctxt->get_ext_state ();
2326       if (!ext_state)
2327         return true;
2328       return fd_sm->on_bind (cd, m_success, sm_ctxt.get (), *ext_state);
2329     }
2330   };
2331
2332   bool matches_call_types_p (const call_details &cd) const final override
2333   {
2334     return (cd.num_args () == 3 && cd.arg_is_pointer_p (1));
2335   }
2336
2337   void impl_call_post (const call_details &cd) const final override
2338   {
2339     if (cd.get_ctxt ())
2340       {
2341         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_bind> (cd, false));
2342         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_bind> (cd, true));
2343         cd.get_ctxt ()->terminate_path ();
2344       }
2345   }
2346 };
2347
2348 /* Handle calls to "listen".
2349    See e.g. https://man7.org/linux/man-pages/man3/listen.3p.html  */
2350
2351 class kf_listen : public known_function
2352 {
2353   class outcome_of_listen : public succeed_or_fail_call_info
2354   {
2355   public:
2356     outcome_of_listen (const call_details &cd, bool success)
2357     : succeed_or_fail_call_info (cd, success)
2358     {}
2359
2360     bool update_model (region_model *model,
2361                        const exploded_edge *,
2362                        region_model_context *ctxt) const final override
2363     {
2364       const call_details cd (get_call_details (model, ctxt));
2365       sm_state_map *smap;
2366       const fd_state_machine *fd_sm;
2367       std::unique_ptr<sm_context> sm_ctxt;
2368       if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
2369         return true;
2370       const extrinsic_state *ext_state = ctxt->get_ext_state ();
2371       if (!ext_state)
2372         return true;
2373
2374       return fd_sm->on_listen (cd, m_success, sm_ctxt.get (), *ext_state);
2375     }
2376   };
2377
2378   bool matches_call_types_p (const call_details &cd) const final override
2379   {
2380     return cd.num_args () == 2;
2381   }
2382
2383   void impl_call_post (const call_details &cd) const final override
2384   {
2385     if (cd.get_ctxt ())
2386       {
2387         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_listen> (cd, false));
2388         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_listen> (cd, true));
2389         cd.get_ctxt ()->terminate_path ();
2390       }
2391   }
2392 };
2393
2394 /* Handle calls to "accept".
2395    See e.g. https://man7.org/linux/man-pages/man3/accept.3p.html  */
2396
2397 class kf_accept : public known_function
2398 {
2399   class outcome_of_accept : public succeed_or_fail_call_info
2400   {
2401   public:
2402     outcome_of_accept (const call_details &cd, bool success)
2403     : succeed_or_fail_call_info (cd, success)
2404     {}
2405
2406     bool update_model (region_model *model,
2407                        const exploded_edge *,
2408                        region_model_context *ctxt) const final override
2409     {
2410       const call_details cd (get_call_details (model, ctxt));
2411       sm_state_map *smap;
2412       const fd_state_machine *fd_sm;
2413       std::unique_ptr<sm_context> sm_ctxt;
2414       if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
2415         return true;
2416       const extrinsic_state *ext_state = ctxt->get_ext_state ();
2417       if (!ext_state)
2418         return true;
2419
2420       return fd_sm->on_accept (cd, m_success, sm_ctxt.get (), *ext_state);
2421     }
2422   };
2423
2424   bool matches_call_types_p (const call_details &cd) const final override
2425   {
2426     return (cd.num_args () == 3
2427             && cd.arg_is_pointer_p (1)
2428             && cd.arg_is_pointer_p (2));
2429   }
2430
2431   void impl_call_post (const call_details &cd) const final override
2432   {
2433     if (cd.get_ctxt ())
2434       {
2435         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_accept> (cd, false));
2436         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_accept> (cd, true));
2437         cd.get_ctxt ()->terminate_path ();
2438       }
2439   }
2440 };
2441
2442 /* Handle calls to "connect".
2443    See e.g. https://man7.org/linux/man-pages/man3/connect.3p.html  */
2444
2445 class kf_connect : public known_function
2446 {
2447 public:
2448   class outcome_of_connect : public succeed_or_fail_call_info
2449   {
2450   public:
2451     outcome_of_connect (const call_details &cd, bool success)
2452     : succeed_or_fail_call_info (cd, success)
2453     {}
2454
2455     bool update_model (region_model *model,
2456                        const exploded_edge *,
2457                        region_model_context *ctxt) const final override
2458     {
2459       const call_details cd (get_call_details (model, ctxt));
2460       sm_state_map *smap;
2461       const fd_state_machine *fd_sm;
2462       std::unique_ptr<sm_context> sm_ctxt;
2463       if (!get_fd_state (ctxt, &smap, &fd_sm, NULL, &sm_ctxt))
2464         return true;
2465       const extrinsic_state *ext_state = ctxt->get_ext_state ();
2466       if (!ext_state)
2467         return true;
2468
2469       return fd_sm->on_connect (cd, m_success, sm_ctxt.get (), *ext_state);
2470     }
2471   };
2472
2473   bool matches_call_types_p (const call_details &cd) const final override
2474   {
2475     return (cd.num_args () == 3
2476             && cd.arg_is_pointer_p (1));
2477   }
2478
2479   void impl_call_post (const call_details &cd) const final override
2480   {
2481     if (cd.get_ctxt ())
2482       {
2483         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_connect> (cd, false));
2484         cd.get_ctxt ()->bifurcate (make_unique<outcome_of_connect> (cd, true));
2485         cd.get_ctxt ()->terminate_path ();
2486       }
2487   }
2488 };
2489
2490 /* Handler for calls to "pipe" and "pipe2".
2491    See e.g. https://www.man7.org/linux/man-pages/man2/pipe.2.html  */
2492
2493 class kf_pipe : public known_function
2494 {
2495   class failure : public failed_call_info
2496   {
2497   public:
2498     failure (const call_details &cd) : failed_call_info (cd) {}
2499
2500     bool update_model (region_model *model,
2501                        const exploded_edge *,
2502                        region_model_context *ctxt) const final override
2503     {
2504       /* Return -1; everything else is unchanged.  */
2505       const call_details cd (get_call_details (model, ctxt));
2506       model->update_for_int_cst_return (cd, -1, true);
2507       return true;
2508     }
2509   };
2510
2511   class success : public success_call_info
2512   {
2513   public:
2514     success (const call_details &cd) : success_call_info (cd) {}
2515
2516     bool update_model (region_model *model,
2517                        const exploded_edge *,
2518                        region_model_context *ctxt) const final override
2519     {
2520       const call_details cd (get_call_details (model, ctxt));
2521
2522       /* Return 0.  */
2523       model->update_for_zero_return (cd, true);
2524
2525       /* Update fd array.  */
2526       region_model_manager *mgr = cd.get_manager ();
2527       tree arr_tree = cd.get_arg_tree (0);
2528       const svalue *arr_sval = cd.get_arg_svalue (0);
2529       for (int idx = 0; idx < 2; idx++)
2530         {
2531           const region *arr_reg
2532             = model->deref_rvalue (arr_sval, arr_tree, cd.get_ctxt ());
2533           const svalue *idx_sval
2534             = mgr->get_or_create_int_cst (integer_type_node, idx);
2535           const region *element_reg
2536             = mgr->get_element_region (arr_reg, integer_type_node, idx_sval);
2537           conjured_purge p (model, cd.get_ctxt ());
2538           const svalue *fd_sval
2539             = mgr->get_or_create_conjured_svalue (integer_type_node,
2540                                                   cd.get_call_stmt (),
2541                                                   element_reg,
2542                                                   p);
2543           model->set_value (element_reg, fd_sval, cd.get_ctxt ());
2544           model->mark_as_valid_fd (fd_sval, cd.get_ctxt ());
2545         }
2546       return true;
2547     }
2548   };
2549
2550 public:
2551   kf_pipe (unsigned num_args)
2552   : m_num_args (num_args)
2553   {
2554     gcc_assert (num_args > 0);
2555   }
2556
2557   bool matches_call_types_p (const call_details &cd) const final override
2558   {
2559     return (cd.num_args () == m_num_args && cd.arg_is_pointer_p (0));
2560   }
2561
2562   void impl_call_post (const call_details &cd) const final override
2563   {
2564     if (cd.get_ctxt ())
2565       {
2566         cd.get_ctxt ()->bifurcate (make_unique<failure> (cd));
2567         cd.get_ctxt ()->bifurcate (make_unique<success> (cd));
2568         cd.get_ctxt ()->terminate_path ();
2569       }
2570   }
2571
2572 private:
2573   unsigned m_num_args;
2574 };
2575
2576 /* Populate KFM with instances of known functions relating to
2577    file descriptors.  */
2578
2579 void
2580 register_known_fd_functions (known_function_manager &kfm)
2581 {
2582   kfm.add ("accept", make_unique<kf_accept> ());
2583   kfm.add ("bind", make_unique<kf_bind> ());
2584   kfm.add ("connect", make_unique<kf_connect> ());
2585   kfm.add ("listen", make_unique<kf_listen> ());
2586   kfm.add ("pipe", make_unique<kf_pipe> (1));
2587   kfm.add ("pipe2", make_unique<kf_pipe> (2));
2588   kfm.add ("socket", make_unique<kf_socket> ());
2589 }
2590
2591 } // namespace ana
2592
2593 #endif // ENABLE_ANALYZER