1 /* An overview of the state machine from sm-fd.cc.
2 Copyright (C) 2022-2023 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* Keep this in-sync with sm-fd.cc */
30 /* State for a constant file descriptor (>= 0). */
33 /* States representing a file descriptor that hasn't yet been
34 checked for validity after opening, for three different
40 /* States for representing a file descriptor that is known to be valid (>=
41 0), for three different access modes. */
46 /* State for a file descriptor that is known to be invalid (< 0). */
49 /* State for a file descriptor that has been closed. */
52 /* States for FDs relating to socket APIs. */
54 /* Result of successful "socket" with SOCK_DGRAM. */
56 /* Result of successful "socket" with SOCK_STREAM. */
58 /* Result of successful "socket" with unknown type. */
61 /* The above after a successful call to "bind". */
62 bound_datagram_socket
;
66 /* A bound socket after a successful call to "listen" (stream or unknown). */
67 listening_stream_socket
;
69 /* (i) the new FD as a result of a succesful call to "accept" on a
70 listening socket (via a passive open), or
71 (ii) an active socket after a successful call to "connect"
72 (via an active open). */
73 connected_stream_socket
;
75 /* State for a file descriptor that we do not want to track anymore . */
81 start
-> unchecked_read_only [
label=
"on 'X = open(..., O_RDONLY);'"]
;
82 start
-> unchecked_write_only [
label=
"on 'X = open(..., O_WRONLY);'"]
;
83 start
-> unchecked_read_write [
label=
"on 'X = open(..., ...);'"]
;
86 start
-> unchecked_write_only [
label=
"on 'X = create(...);'"]
;
89 start
-> closed [
label=
"on 'close(X);'"]
;
90 unchecked_read_write
-> closed [
label=
"on 'close(X);'"]
;
91 unchecked_read_only
-> closed [
label=
"on 'close(X);'"]
;
92 unchecked_write_only
-> closed [
label=
"on 'close(X);'"]
;
93 valid_read_write
-> closed [
label=
"on 'close(X);'"]
;
94 valid_read_only
-> closed [
label=
"on 'close(X);'"]
;
95 valid_write_only
-> closed [
label=
"on 'close(X);'"]
;
96 constant_fd
-> closed [
label=
"on 'close(X);'"]
;
97 new_datagram_socket
-> closed [
label=
"on 'close(X);'"]
;
98 new_stream_socket
-> closed [
label=
"on 'close(X);'"]
;
99 new_unknown_socket
-> closed [
label=
"on 'close(X);'"]
;
100 bound_datagram_socket
-> closed [
label=
"on 'close(X);'"]
;
101 bound_stream_socket
-> closed [
label=
"on 'close(X);'"]
;
102 bound_unknown_socket
-> closed [
label=
"on 'close(X);'"]
;
103 listening_stream_socket
-> closed [
label=
"on 'close(X);'"]
;
104 connected_stream_socket
-> closed [
label=
"on 'close(X);'"]
;
105 closed
-> stop [
label=
"on 'close(X);':\nWarn('double close')"]
;
108 closed
-> closed [
label=
"on 'read(X);':\nWarn('use after close')"]
;
109 unchecked_read_write
-> unchecked_read_write [
label=
"on 'read(X);:\nWarn('use without check')'"]
;
110 unchecked_read_only
-> unchecked_read_only [
label=
"on 'read(X);:\nWarn('use without check')'"]
;
111 unchecked_write_only
-> unchecked_write_only [
label=
"on 'read(X);:\nWarn('use without check')'"]
;
112 valid_write_only
-> valid_write_only [
label=
"on 'read(X);:\nWarn('access mode mismatch')'"]
;
115 closed
-> closed [
label=
"on 'write(X);':\nWarn('use after close')"]
;
116 unchecked_read_write
-> unchecked_read_write [
label=
"on 'write(X);:\nWarn('use without check')'"]
;
117 unchecked_read_only
-> unchecked_read_only [
label=
"on 'write(X);:\nWarn('use without check')'"]
;
118 unchecked_write_only
-> unchecked_write_only [
label=
"on 'write(X);:\nWarn('use without check')'"]
;
119 valid_read_only
-> valid_read_only [
label=
"on 'write(X);:\nWarn('access mode mismatch')'"]
;
122 closed
-> closed [
label=
"on 'dup(X);':\nWarn('use after close')"]
;
123 /* plus stuff for the new fd. */
126 start
-> valid_read_write [
label=
"when 'pipe()' succeeds"]
;
129 start
-> new_datagram_socket [
label=
"when 'socket(..., SOCK_DGRAM, ...)' succeeds"]
;
130 start
-> new_stream_socket [
label=
"when 'socket(..., SOCK_STREAM, ...)' succeeds"]
;
131 start
-> new_unknown_socket [
label=
"when 'socket(..., ..., ...)' succeeds"]
;
134 start
-> bound_unknown_socket [
label=
"when 'bind(X, ...)' succeeds"]
;
135 constant_fd
-> bound_unknown_socket [
label=
"when 'bind(X, ...)' succeeds"]
;
136 new_stream_socket
-> bound_stream_socket [
label=
"when 'bind(X, ...)' succeeds"]
;
137 new_datagram_socket
-> bound_datagram_socket [
label=
"when 'bind(X, ...)' succeeds"]
;
138 new_unknown_socket
-> bound_unknown_socket [
label=
"when 'bind(X, ...)' succeeds"]
;
141 start
-> listening_stream_socket [
label=
"when 'listen(X, ...)' succeeds"]
;
142 bound_stream_socket
-> listening_stream_socket [
label=
"when 'listen(X, ...)' succeeds"]
;
143 bound_unknown_socket
-> listening_stream_socket [
label=
"when 'listen(X, ...)' succeeds"]
;
146 start
-> connected_stream_socket [
label=
"when 'accept(OTHER, ...)' succeeds on a listening_stream_socket"]
;
147 constant_fd
-> connected_stream_socket [
label=
"when 'accept(OTHER, ...)' succeeds on a listening_stream_socket"]
;
150 new_stream_socket
-> connected_stream_socket [
label=
"when 'connect(X, ...)' succeeds"]
;
151 new_datagram_socket
-> new_datagram_socket [
label=
"when 'connect(X, ...)' succeeds"]
;
152 new_unknown_socket
-> stop [
label=
"when 'connect(X, ...)' succeeds"]
;
153 start
-> stop [
label=
"when 'connect(X, ...)' succeeds"]
;
154 constant_fd
-> stop [
label=
"when 'connect(X, ...)' succeeds"]
;
157 unchecked_read_write
-> valid_read_write [
label=
"on 'X >= 0'"]
;
158 unchecked_read_only
-> valid_read_only [
label=
"on 'X >= 0'"]
;
159 unchecked_write_only
-> valid_write_only [
label=
"on 'X >= 0'"]
;
160 unchecked_read_write
-> invalid [
label=
"on 'X < 0'"]
;
161 unchecked_read_only
-> invalid [
label=
"on 'X < 0'"]
;
162 unchecked_write_only
-> invalid [
label=
"on 'X < 0'"]
;
165 unchecked_read_write
-> stop [
label=
"on leak:\nWarn('leak')"]
;
166 unchecked_read_only
-> stop [
label=
"on leak:\nWarn('leak')"]
;
167 unchecked_write_only
-> stop [
label=
"on leak:\nWarn('leak')"]
;
168 valid_read_write
-> stop [
label=
"on leak:\nWarn('leak')"]
;
169 valid_read_only
-> stop [
label=
"on leak:\nWarn('leak')"]
;
170 valid_write_only
-> stop [
label=
"on leak:\nWarn('leak')"]
;
171 new_datagram_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
172 new_stream_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
173 new_unknown_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
174 bound_datagram_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
175 bound_stream_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
176 bound_unknown_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
177 listening_stream_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;
178 connected_stream_socket
-> stop [
label=
"on leak:\nWarn('leak')"]
;