Bug Summary

File:os/unix/ngx_readv_chain.c
Location:line 96, 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
13ssize_t
14ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
15{
16 u_char *prev;
17 ssize_t n, size;
18 ngx_err_t err;
19 ngx_array_t vec;
20 ngx_event_t *rev;
21 struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE64];
22
23 rev = c->read;
24
25#if (NGX_HAVE_KQUEUE)
26
27 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
28 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
29 "readv: eof:%d, avail:%d, err:%d",
30 rev->pending_eof, rev->available, rev->kq_errno);
31
32 if (rev->available == 0) {
33 if (rev->pending_eof) {
34 rev->ready = 0;
35 rev->eof = 1;
36
37 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"
)
38 "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"
)
;
39
40 if (rev->kq_errno) {
41 rev->error = 1;
42 ngx_set_socket_errno(rev->kq_errno)(*__errno_location ()) = rev->kq_errno;
43 return NGX_ERROR-1;
44 }
45
46 return 0;
47
48 } else {
49 return NGX_AGAIN-2;
50 }
51 }
52 }
53
54#endif
55
56#if (NGX_HAVE_EPOLLRDHUP1)
57
58 if (ngx_event_flags & NGX_USE_EPOLL_EVENT0x00000040) {
1
Taking false branch
59 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
60 "readv: eof:%d, avail:%d",
61 rev->pending_eof, rev->available);
62
63 if (!rev->available && !rev->pending_eof) {
64 return NGX_AGAIN-2;
65 }
66 }
67
68#endif
69
70 prev = NULL((void*)0);
71 iov = NULL((void*)0);
2
Null pointer value stored to 'iov'
72 size = 0;
73
74 vec.elts = iovs;
75 vec.nelts = 0;
76 vec.size = sizeof(struct iovec);
77 vec.nalloc = NGX_IOVS_PREALLOCATE64;
78 vec.pool = c->pool;
79
80 /* coalesce the neighbouring bufs */
81
82 while (chain) {
3
Loop condition is true. Entering loop body
83 n = chain->buf->end - chain->buf->last;
84
85 if (limit) {
4
Assuming 'limit' is 0
5
Taking false branch
86 if (size >= limit) {
87 break;
88 }
89
90 if (size + n > limit) {
91 n = (ssize_t) (limit - size);
92 }
93 }
94
95 if (prev == chain->buf->last) {
6
Taking true branch
96 iov->iov_len += n;
7
Access to field 'iov_len' results in a dereference of a null pointer (loaded from variable 'iov')
97
98 } else {
99 if (vec.nelts >= IOV_MAX1024) {
100 break;
101 }
102
103 iov = ngx_array_push(&vec);
104 if (iov == NULL((void*)0)) {
105 return NGX_ERROR-1;
106 }
107
108 iov->iov_base = (void *) chain->buf->last;
109 iov->iov_len = n;
110 }
111
112 size += n;
113 prev = chain->buf->end;
114 chain = chain->next;
115 }
116
117 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
118 "readv: %ui, last:%uz", vec.nelts, iov->iov_len);
119
120 do {
121 n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
122
123 if (n == 0) {
124 rev->ready = 0;
125 rev->eof = 1;
126
127#if (NGX_HAVE_KQUEUE)
128
129 /*
130 * on FreeBSD readv() may return 0 on closed socket
131 * even if kqueue reported about available data
132 */
133
134 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
135 rev->available = 0;
136 }
137
138#endif
139
140 return 0;
141 }
142
143 if (n > 0) {
144
145#if (NGX_HAVE_KQUEUE)
146
147 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
148 rev->available -= n;
149
150 /*
151 * rev->available may be negative here because some additional
152 * bytes may be received between kevent() and readv()
153 */
154
155 if (rev->available <= 0) {
156 if (!rev->pending_eof) {
157 rev->ready = 0;
158 }
159
160 rev->available = 0;
161 }
162
163 return n;
164 }
165
166#endif
167
168#if (NGX_HAVE_EPOLLRDHUP1)
169
170 if ((ngx_event_flags & NGX_USE_EPOLL_EVENT0x00000040)
171 && ngx_use_epoll_rdhup)
172 {
173 if (n < size) {
174 if (!rev->pending_eof) {
175 rev->ready = 0;
176 }
177
178 rev->available = 0;
179 }
180
181 return n;
182 }
183
184#endif
185
186 if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT0x00000020)) {
187 rev->ready = 0;
188 }
189
190 return n;
191 }
192
193 err = ngx_socket_errno(*__errno_location ());
194
195 if (err == NGX_EAGAIN11 || err == NGX_EINTR4) {
196 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
197 "readv() not ready");
198 n = NGX_AGAIN-2;
199
200 } else {
201 n = ngx_connection_error(c, err, "readv() failed");
202 break;
203 }
204
205 } while (err == NGX_EINTR4);
206
207 rev->ready = 0;
208
209 if (n == NGX_ERROR-1) {
210 c->read->error = 1;
211 }
212
213 return n;
214}