Bug Summary

File:obj-scan-build/libftpconn/../../libftpconn/reply.c
Location:line 235, column 18
Description:The left operand of '==' is a garbage value

Annotated Source Code

1/* Parse ftp server replies
2
3 Copyright (C) 1997 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
26#include <ftpconn.h>
27#include "priv.h"
28
29/* Add STR (of size LEN) to CONN's reply_txt buffer, at offset *OFFS,
30 updating *OFFS. */
31static inline error_t
32ftp_conn_add_reply_txt (struct ftp_conn *conn, size_t *offs,
33 const char *str, size_t len)
34{
35 if (*offs + len + 1 > conn->reply_txt_sz)
36 {
37 size_t new_sz = *offs + len + 50;
38 char *new = realloc (conn->reply_txt, new_sz);
39 if (! new)
40 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
41 conn->reply_txt = new;
42 conn->reply_txt_sz = new_sz;
43 }
44
45 bcopy (str, conn->reply_txt + *offs, len);
46 conn->reply_txt[*offs + len] = '\0'; /* Make sure nul terminated. */
47
48 *offs += len;
49
50 return 0;
51}
52
53/* Return a new line read from CONN's control connection in LINE & LINE_LEN;
54 LINE points into storage allocated in CONN, and is only valid until the
55 next call to this function, or return an error code. (we used to just use
56 the stdio getline function, and keep a stdio stream for the control
57 connection, but interleaved I/O didn't work correctly.) */
58static inline error_t
59ftp_conn_getline (struct ftp_conn *conn, const char **line, size_t *line_len)
60{
61 char *l = conn->line;
62 size_t offs = conn->line_offs, len = conn->line_len, sz = conn->line_sz;
63 int (*icheck) (struct ftp_conn *conn) = conn->hooks->interrupt_check;
64
65 for (;;)
66 {
67 int rd;
68
69 if (offs < len)
70 /* See if there's a newline in the active part of the line buffer. */
71 {
72 char *nl = memchr (l + offs, '\n', len - offs);
73 if (nl)
74 /* There is! Consume and return the whole line we found. */
75 {
76 *line = l + offs;
77
78 offs = nl + 1 - l; /* Consume the line */
79
80 /* Null terminate the result by overwriting the newline; if
81 there's a CR preceding it, get rid of that too. */
82 if (nl > *line && nl[-1] == '\r')
83 nl--;
84 *nl = '\0';
85
86 *line_len = nl - *line;
87
88 if (offs == len)
89 conn->line_offs = conn->line_len = 0;
90 else
91 conn->line_offs = offs;
92
93 return 0;
94 }
95 }
96
97 /* No newline yet, so read some more! */
98
99 if (offs > (len << 2) && offs < len)
100 /* Relocate the current contents of the buffer to the beginning. */
101 {
102 len -= offs;
103 bcopy (l + offs, l, len - offs);
104 offs = conn->line_offs = 0;
105 conn->line_len = len;
106 }
107 if (len == sz)
108 /* Grow the line buffer; there's no space left. */
109 {
110 sz = sz + len ?: 50;
111 l = realloc (l, sz);
112 if (! l)
113 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
114 conn->line = l;
115 conn->line_sz = sz;
116 }
117
118 /* Actually read something. */
119 rd = read (conn->control, l + len, sz - len);
120 if (rd < 0)
121 return errno(*__errno_location ());
122 else if (rd == 0)
123 {
124 *line = l + offs;
125 *line_len = 0;
126 return 0;
127 }
128
129 len += rd;
130 conn->line_len = len;
131
132 if (icheck && (*icheck) (conn))
133 return EINTR((0x10 << 26) | ((4) & 0x3fff));
134 }
135}
136
137/* Get the next reply from CONN's ftp server, returning the reply code in
138 REPLY, if REPLY is non-zero, and the text of the reply (not including the
139 reply code) in REPLY_TXT (if it isn't zero), or return an error code. If
140 the reply is multiple lines, all of them are included in REPLY_TXT,
141 separated by newlines. */
142inline error_t
143ftp_conn_get_raw_reply (struct ftp_conn *conn, int *reply,
144 const char **reply_txt)
145{
146 size_t reply_txt_offs = 0; /* End of a multi-line reply in accum buf. */
147 int multi = 0; /* If a multi-line reply, the reply code. */
148
149 if (!reply && !reply_txt)
150 return 0; /* nop */
151
152 do
10
Loop condition is false. Exiting loop
153 {
154 const char *l;
155 size_t len;
156 error_t err = ftp_conn_getline (conn, &l, &len);
157
158 if (err)
3
Assuming 'err' is 0
4
Taking false branch
159 return err;
160 if (!multi && len == 0)
5
Assuming 'len' is not equal to 0
6
Taking false branch
161 return EPIPE((0x10 << 26) | ((32) & 0x3fff));
162
163#define ACCUM(txt, len)do { if (reply_txt) { error_t err = ftp_conn_add_reply_txt (conn
, &reply_txt_offs, txt, len); if (err) return err; } } while
(0)
\
164 do { \
165 if (reply_txt) /* Only accumulate if wanted. */ \
166 { \
167 error_t err = \
168 ftp_conn_add_reply_txt (conn, &reply_txt_offs, txt, len); \
169 if (err) \
170 return err; \
171 } \
172 } while (0)
173
174 if (conn->hooks && conn->hooks->cntl_debug)
175 (*conn->hooks->cntl_debug) (conn, FTP_CONN_CNTL_DEBUG_REPLY2, l);
176
177 if (isdigit (l[0])((*__ctype_b_loc ())[(int) ((l[0]))] & (unsigned short int
) _ISdigit)
&& isdigit (l[1])((*__ctype_b_loc ())[(int) ((l[1]))] & (unsigned short int
) _ISdigit)
&& isdigit (l[2])((*__ctype_b_loc ())[(int) ((l[2]))] & (unsigned short int
) _ISdigit)
)
7
Taking true branch
178 /* A reply code. */
179 {
180 int code = (l[0] - '0')*100 + (l[1] - '0')*10 + (l[2] - '0');
181
182 if (multi && code != multi)
183 /* Two codes in a multi-line reply don't match. */
184 return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff));
185
186 if (l[3] == '-')
8
Taking true branch
187 /* The non-terminal line of a multi-line reply. RFC959 actually
188 claims there shouldn't be more than one multi-line code (other
189 lines in between the two shouldn't have a numeric code at
190 all), but real ftp servers don't obey this rule. */
191 multi = code;
192 else if (l[3] != ' ')
193 /* Some syntax error. */
194 return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff));
195 else
196 /* The end of the reply (and perhaps the only line). */
197 {
198 multi = 0;
199 if (reply)
200 *reply = code;
201 }
202
203 ACCUM (l + 4, len - 4)do { if (reply_txt) { error_t err = ftp_conn_add_reply_txt (conn
, &reply_txt_offs, l + 4, len - 4); if (err) return err; }
} while (0)
;
9
Within the expansion of the macro 'ACCUM':
a
Assuming 'reply_txt' is null
204 }
205 else if (multi)
206 /* The lines between the first and last in a multi-line reply may be
207 anything as long as they don't start with a digit. */
208 ACCUM (l, len)do { if (reply_txt) { error_t err = ftp_conn_add_reply_txt (conn
, &reply_txt_offs, l, len); if (err) return err; } } while
(0)
;
209 else
210 return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff));
211 }
212 while (multi);
213
214 if (reply_txt)
11
Taking false branch
215 *reply_txt = conn->reply_txt;
216
217 return 0;
218}
219
220/* Get the next reply from CONN's ftp server, returning the reply code in
221 REPLY, if REPLY is non-zero, and the text of the reply (not including the
222 reply code) in REPLY_TXT (if it isn't zero), or return an error code. If
223 the reply is multiple lines, all of them are included in REPLY_TXT,
224 separated by newlines. This differs from ftp_conn_get_raw_reply in that
225 it eats REPLY_ABORT_OK replies on the assumption that they're junk left
226 over from the last abort command. */
227error_t
228ftp_conn_get_reply (struct ftp_conn *conn, int *reply, const char **reply_txt)
229{
230 int code;
1
Variable 'code' declared without an initial value
231 error_t err;
232
233 do
234 err = ftp_conn_get_raw_reply (conn, &code, reply_txt);
2
Calling 'ftp_conn_get_raw_reply'
12
Returning from 'ftp_conn_get_raw_reply'
235 while (!err && code == REPLY_ABORT_OK225);
13
The left operand of '==' is a garbage value
236
237 if (!err && reply)
238 *reply = code;
239
240 return err;
241}