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') |
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 | ssize_t | |||
14 | ngx_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) { | |||
| ||||
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); | |||
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) { | |||
83 | n = chain->buf->end - chain->buf->last; | |||
84 | ||||
85 | if (limit) { | |||
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) { | |||
96 | iov->iov_len += n; | |||
| ||||
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 | } |