Bug Summary

File:os/unix/ngx_readv_chain.c
Location:line 71, column 26
Description:Access to field 'iov_len' results in a dereference of a null pointer (loaded from variable 'iov')

Annotated Source Code

1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_event.h>
11
12
13#define NGX_IOVS16 16
14
15
16#if (NGX_HAVE_KQUEUE1)
17
18ssize_t
19ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
20{
21 u_char *prev;
22 ssize_t n, size;
23 ngx_err_t err;
24 ngx_array_t vec;
25 ngx_event_t *rev;
26 struct iovec *iov, iovs[NGX_IOVS16];
27
28 rev = c->read;
29
30 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
1
Taking false branch
31 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
32 "readv: eof:%d, avail:%d, err:%d",
33 rev->pending_eof, rev->available, rev->kq_errno);
34
35 if (rev->available == 0) {
36 if (rev->pending_eof) {
37 rev->ready = 0;
38 rev->eof = 1;
39
40 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,if ((c->log)->log_level >= 7) ngx_log_error_core(7, c
->log, rev->kq_errno, "kevent() reported about an closed connection"
)
41 "kevent() reported about an closed connection")if ((c->log)->log_level >= 7) ngx_log_error_core(7, c
->log, rev->kq_errno, "kevent() reported about an closed connection"
)
;
42
43 if (rev->kq_errno) {
44 rev->error = 1;
45 ngx_set_socket_errno(rev->kq_errno)(*__error()) = rev->kq_errno;
46 return NGX_ERROR-1;
47 }
48
49 return 0;
50
51 } else {
52 return NGX_AGAIN-2;
53 }
54 }
55 }
56
57 prev = NULL((void*)0);
58 iov = NULL((void*)0);
2
Null pointer value stored to 'iov'
59 size = 0;
60
61 vec.elts = iovs;
62 vec.nelts = 0;
63 vec.size = sizeof(struct iovec);
64 vec.nalloc = NGX_IOVS16;
65 vec.pool = c->pool;
66
67 /* coalesce the neighbouring bufs */
68
69 while (chain) {
3
Loop condition is true. Entering loop body
70 if (prev == chain->buf->last) {
4
Taking true branch
71 iov->iov_len += chain->buf->end - chain->buf->last;
5
Access to field 'iov_len' results in a dereference of a null pointer (loaded from variable 'iov')
72
73 } else {
74 if (vec.nelts >= IOV_MAX1024) {
75 break;
76 }
77
78 iov = ngx_array_push(&vec);
79 if (iov == NULL((void*)0)) {
80 return NGX_ERROR-1;
81 }
82
83 iov->iov_base = (void *) chain->buf->last;
84 iov->iov_len = chain->buf->end - chain->buf->last;
85 }
86
87 size += chain->buf->end - chain->buf->last;
88 prev = chain->buf->end;
89 chain = chain->next;
90 }
91
92 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
93 "readv: %d, last:%d", vec.nelts, iov->iov_len);
94
95 rev = c->read;
96
97 do {
98 n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
99
100 if (n >= 0) {
101 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
102 rev->available -= n;
103
104 /*
105 * rev->available may be negative here because some additional
106 * bytes may be received between kevent() and recv()
107 */
108
109 if (rev->available <= 0) {
110 if (!rev->pending_eof) {
111 rev->ready = 0;
112 }
113
114 if (rev->available < 0) {
115 rev->available = 0;
116 }
117 }
118
119 if (n == 0) {
120
121 /*
122 * on FreeBSD recv() may return 0 on closed socket
123 * even if kqueue reported about available data
124 */
125
126#if 0
127 ngx_log_error(NGX_LOG_ALERT, c->log, 0,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "readv() returned 0 while kevent() reported " "%d available bytes"
, rev->available)
128 "readv() returned 0 while kevent() reported "if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "readv() returned 0 while kevent() reported " "%d available bytes"
, rev->available)
129 "%d available bytes", rev->available)if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "readv() returned 0 while kevent() reported " "%d available bytes"
, rev->available)
;
130#endif
131
132 rev->eof = 1;
133 rev->available = 0;
134 }
135
136 return n;
137 }
138
139 if (n < size) {
140 rev->ready = 0;
141 }
142
143 if (n == 0) {
144 rev->eof = 1;
145 }
146
147 return n;
148 }
149
150 err = ngx_socket_errno(*__error());
151
152 if (err == NGX_EAGAIN35 || err == NGX_EINTR4) {
153 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
154 "readv() not ready");
155 n = NGX_AGAIN-2;
156
157 } else {
158 n = ngx_connection_error(c, err, "readv() failed");
159 break;
160 }
161
162 } while (err == NGX_EINTR4);
163
164 rev->ready = 0;
165
166 if (n == NGX_ERROR-1) {
167 c->read->error = 1;
168 }
169
170 return n;
171}
172
173#else /* ! NGX_HAVE_KQUEUE */
174
175ssize_t
176ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
177{
178 u_char *prev;
179 ssize_t n, size;
180 ngx_err_t err;
181 ngx_array_t vec;
182 ngx_event_t *rev;
183 struct iovec *iov, iovs[NGX_IOVS16];
184
185 prev = NULL((void*)0);
186 iov = NULL((void*)0);
187 size = 0;
188
189 vec.elts = iovs;
190 vec.nelts = 0;
191 vec.size = sizeof(struct iovec);
192 vec.nalloc = NGX_IOVS16;
193 vec.pool = c->pool;
194
195 /* coalesce the neighbouring bufs */
196
197 while (chain) {
198 if (prev == chain->buf->last) {
199 iov->iov_len += chain->buf->end - chain->buf->last;
200
201 } else {
202 if (vec.nelts >= IOV_MAX1024) {
203 break;
204 }
205
206 iov = ngx_array_push(&vec);
207 if (iov == NULL((void*)0)) {
208 return NGX_ERROR-1;
209 }
210
211 iov->iov_base = (void *) chain->buf->last;
212 iov->iov_len = chain->buf->end - chain->buf->last;
213 }
214
215 size += chain->buf->end - chain->buf->last;
216 prev = chain->buf->end;
217 chain = chain->next;
218 }
219
220 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
221 "readv: %d:%d", vec.nelts, iov->iov_len);
222
223 rev = c->read;
224
225 do {
226 n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
227
228 if (n == 0) {
229 rev->ready = 0;
230 rev->eof = 1;
231
232 return n;
233
234 } else if (n > 0) {
235
236 if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT0x00000020)) {
237 rev->ready = 0;
238 }
239
240 return n;
241 }
242
243 err = ngx_socket_errno(*__error());
244
245 if (err == NGX_EAGAIN35 || err == NGX_EINTR4) {
246 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
247 "readv() not ready");
248 n = NGX_AGAIN-2;
249
250 } else {
251 n = ngx_connection_error(c, err, "readv() failed");
252 break;
253 }
254
255 } while (err == NGX_EINTR4);
256
257 rev->ready = 0;
258
259 if (n == NGX_ERROR-1) {
260 c->read->error = 1;
261 }
262
263 return n;
264}
265
266#endif /* NGX_HAVE_KQUEUE */