Bug Summary

File:obj-scan-build/libftpconn/../../libftpconn/open.c
Location:line 93, column 8
Description:Memory is never released; potential leak of memory pointed to by 'pass'

Annotated Source Code

1/* Connection initiation
2
3 Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
4
5 Written by Miles Bader <miles@gnu.ai.mit.edu>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program 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 this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21#include <unistd.h>
22#include <errno(*__errno_location ()).h>
23#include <string.h>
24#include <ctype.h>
25#include <pwd.h>
26#include <netdb.h>
27#include <netinet/in.h>
28
29#include <ftpconn.h>
30#include "priv.h"
31
32static error_t
33ftp_conn_login (struct ftp_conn *conn)
34{
35 int reply;
36 error_t err = 0;
37 const struct ftp_conn_params *p = conn->params;
38
39 err = ftp_conn_cmd (conn, "user", p->user ?: "anonymous", &reply, 0);
12
'?' condition is false
40
41 if (!err && reply == REPLY_NEED_ACCT332)
13
Assuming 'err' is 0
14
Assuming 'reply' is not equal to 332
15
Taking false branch
42 {
43 char *acct = p->acct;
44 if (!acct && conn->hooks && conn->hooks->get_login_param)
45 err = (* conn->hooks->get_login_param) (conn,
46 FTP_CONN_GET_LOGIN_PARAM_ACCT3,
47 &acct);
48 if (! err)
49 err = acct ? ftp_conn_cmd (conn, "acct", acct, &reply, 0) : EACCES((0x10 << 26) | ((13) & 0x3fff));
50 if (acct && !p->acct)
51 free (acct);
52 }
53
54 if (!err && reply == REPLY_NEED_PASS331)
16
Assuming 'reply' is equal to 331
17
Taking true branch
55 {
56 char *pass = p->pass;
57 if (!pass && conn->hooks && conn->hooks->get_login_param)
18
Assuming 'pass' is null
58 err = (* conn->hooks->get_login_param) (conn,
59 FTP_CONN_GET_LOGIN_PARAM_PASS2,
60 &pass);
61 if (! err)
19
Taking true branch
62 {
63 if (pass)
20
Taking false branch
64 err = ftp_conn_cmd (conn, "pass", pass, &reply, 0);
65 else
66 {
67 pass = getenv ("USER");
68 if (! pass)
21
Assuming 'pass' is non-null
22
Taking false branch
69 pass = getenv ("LOGNAME");
70 if (! pass)
23
Taking false branch
71 {
72 struct passwd *pe = getpwuid (getuid ());
73 pass = pe ? pe->pw_name : "?";
74 }
75
76 /* Append a '@' */
77 pass = strdup (pass);
24
Memory is allocated
78 if (pass)
25
Assuming 'pass' is non-null
26
Taking true branch
79 pass = realloc (pass, strlen (pass) + 1);
27
Attempt to reallocate memory
80 if (pass)
28
Assuming 'pass' is null
29
Reallocation failed
30
Taking false branch
81 {
82 strcat (pass, "@");
83 err = ftp_conn_cmd (conn, "pass", pass, &reply, 0);
84 }
85 else
86 err = ENOMEM((0x10 << 26) | ((12) & 0x3fff));
87 }
88 }
89 if (pass && !p->pass)
90 free (pass);
91 }
92
93 if (!err && reply != REPLY_LOGIN_OK230)
31
Memory is never released; potential leak of memory pointed to by 'pass'
94 {
95 if (REPLY_IS_FAILURE (reply)((reply) >= 500 && (reply) < 600))
96 err = EACCES((0x10 << 26) | ((13) & 0x3fff));
97 else
98 err = unexpected_reply (conn, reply, 0, 0);
99 }
100
101 return err;
102}
103
104static error_t
105ftp_conn_hello (struct ftp_conn *conn)
106{
107 int reply;
108 error_t err;
109
110 do
111 err = ftp_conn_get_reply (conn, &reply, 0);
112 while (!err && reply == REPLY_DELAY120);
113
114 if (err)
115 return err;
116
117 if (reply == REPLY_CLOSED421)
118 return ECONNREFUSED((0x10 << 26) | ((61) & 0x3fff));
119 if (reply != REPLY_HELLO220)
120 return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff));
121
122 return 0;
123}
124
125/* Sets CONN's syshooks to a copy of SYSHOOKS. */
126void
127ftp_conn_set_syshooks (struct ftp_conn *conn, struct ftp_conn_syshooks *syshooks)
128{
129 conn->syshooks = *syshooks;
130}
131
132void
133ftp_conn_choose_syshooks (struct ftp_conn *conn, const char *syst)
134{
135 if (!syst || (strncasecmp (syst, "UNIX", 4) == 0 && !isalnum (syst[4])((*__ctype_b_loc ())[(int) ((syst[4]))] & (unsigned short
int) _ISalnum)
))
136 ftp_conn_set_syshooks (conn, &ftp_conn_unix_syshooks);
137}
138
139/* Sets CONN's syshooks by querying the remote system to see what type it is. */
140static error_t
141ftp_conn_sysify (struct ftp_conn *conn)
142{
143 int reply;
144 const char *txt;
145 error_t err = ftp_conn_cmd (conn, "syst", 0, &reply, &txt);
146
147 if (! err)
148 {
149 if (reply == REPLY_SYSTYPE215 ||
150 reply == REPLY_BAD_CMD500 || reply == REPLY_UNIMP_CMD502 || REPLY_NO_LOGIN530)
151 {
152 if (reply == REPLY_BAD_CMD500 || reply == REPLY_UNIMP_CMD502
153 || reply == REPLY_NO_LOGIN530)
154 txt = 0;
155 if (conn->hooks && conn->hooks->choose_syshooks)
156 (*conn->hooks->choose_syshooks) (conn, txt);
157 else
158 ftp_conn_choose_syshooks (conn, txt);
159 conn->syshooks_valid = 1;
160 }
161 else
162 err = unexpected_reply (conn, reply, txt, 0);
163 }
164
165 return err;
166}
167
168error_t
169ftp_conn_open (struct ftp_conn *conn)
170{
171 static int ftp_port = 0;
172 int csock;
173 error_t err;
174 struct sockaddr_in ftp_addr;
175
176 if (conn->params->addr_type != AF_INET2)
1
Taking false branch
177 return EAFNOSUPPORT((0x10 << 26) | ((47) & 0x3fff));
178
179 if (! ftp_port)
2
Taking true branch
180 {
181 struct servent *se = getservbyname ("ftp", "tcp");
182 if (! se)
3
Assuming 'se' is non-null
4
Taking false branch
183 return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff));
184 ftp_port = se->s_port;
185 }
186
187 if (conn->control >= 0)
5
Taking false branch
188 {
189 close (conn->control);
190 conn->control = -1;
191 }
192 bzero (&conn->syshooks, sizeof conn->syshooks);
193
194 csock = socket (PF_INET2, SOCK_STREAMSOCK_STREAM, 0);
195 if (csock < 0)
6
Assuming 'csock' is >= 0
7
Taking false branch
196 return errno(*__errno_location ());
197
198 ftp_addr.sin_len = sizeof ftp_addr;
199 ftp_addr.sin_family = conn->params->addr_type;
200 ftp_addr.sin_addr = *(struct in_addr *)conn->params->addr;
201 ftp_addr.sin_port = ftp_port;
202
203 if (connect (csock, (struct sockaddr *)&ftp_addr, sizeof ftp_addr) < 0)
8
Taking false branch
204 {
205 err = errno(*__errno_location ());
206 close (csock);
207 return err;
208 }
209
210 conn->control = csock;
211
212 err = ftp_conn_hello (conn);
213
214 if (!err && conn->hooks && conn->hooks->opened)
215 (* conn->hooks->opened) (conn);
216
217 if (! err)
9
Taking true branch
218 /* Make any machine-dependent customizations. */
219 ftp_conn_sysify (conn);
220
221 if (! err)
10
Taking true branch
222 /* login */
223 err = ftp_conn_login (conn);
11
Calling 'ftp_conn_login'
224
225 if (!err && !conn->syshooks_valid)
226 /* Try again now. */
227 err = ftp_conn_sysify (conn);
228
229 if (!err && conn->type)
230 /* Set the connection type. */
231 {
232 int reply;
233 err = ftp_conn_cmd (conn, "type", conn->type, &reply, 0);
234 if (!err && reply != REPLY_OK200)
235 err = unexpected_reply (conn, reply, 0, 0);
236 }
237
238 if (err)
239 ftp_conn_close (conn);
240
241 return err;
242}
243
244void
245ftp_conn_close (struct ftp_conn *conn)
246{
247 if (conn->control >= 0)
248 close (conn->control);
249 conn->control = -1;
250 if (conn->hooks && conn->hooks->closed)
251 (* conn->hooks->closed) (conn);
252}