Bug Summary

File:os/unix/ngx_writev_chain.c
Location:line 157, 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
13ngx_chain_t *
14ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
15{
16 ssize_t n, sent;
17 off_t send, prev_send;
18 ngx_chain_t *cl;
19 ngx_event_t *wev;
20 ngx_iovec_t vec;
21 struct iovec iovs[NGX_IOVS_PREALLOCATE64];
22
23 wev = c->write;
24
25 if (!wev->ready) {
1
Taking false branch
26 return in;
27 }
28
29#if (NGX_HAVE_KQUEUE)
30
31 if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) && wev->pending_eof) {
32 (void) ngx_connection_error(c, wev->kq_errno,
33 "kevent() reported about an closed connection");
34 wev->error = 1;
35 return NGX_CHAIN_ERROR(ngx_chain_t *) -1;
36 }
37
38#endif
39
40 /* the maximum limit size is the maximum size_t value - the page size */
41
42 if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE9223372036854775807LL - ngx_pagesize)) {
2
Assuming 'limit' is not equal to 0
3
Taking false branch
43 limit = NGX_MAX_SIZE_T_VALUE9223372036854775807LL - ngx_pagesize;
44 }
45
46 send = 0;
47
48 vec.iovs = iovs;
49 vec.nalloc = NGX_IOVS_PREALLOCATE64;
50
51 for ( ;; ) {
4
Loop condition is true. Entering loop body
12
Loop condition is true. Entering loop body
19
Loop condition is true. Entering loop body
52 prev_send = send;
53
54 /* create the iovec and coalesce the neighbouring bufs */
55
56 cl = ngx_output_chain_to_iovec(&vec, in, limit - send, c->log);
20
Calling 'ngx_output_chain_to_iovec'
57
58 if (cl == NGX_CHAIN_ERROR(ngx_chain_t *) -1) {
5
Taking false branch
13
Taking false branch
59 return NGX_CHAIN_ERROR(ngx_chain_t *) -1;
60 }
61
62 if (cl && cl->buf->in_file) {
63 ngx_log_error(NGX_LOG_ALERT, c->log, 0,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
64 "file buf in writev "if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
65 "t:%d r:%d f:%d %p %p-%p %p %O-%O",if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
66 cl->buf->temporary,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
67 cl->buf->recycled,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
68 cl->buf->in_file,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
69 cl->buf->start,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
70 cl->buf->pos,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
71 cl->buf->last,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
72 cl->buf->file,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
73 cl->buf->file_pos,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
74 cl->buf->file_last)if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "file buf in writev " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, cl->buf->temporary, cl->buf->recycled, cl->buf
->in_file, cl->buf->start, cl->buf->pos, cl->
buf->last, cl->buf->file, cl->buf->file_pos, cl
->buf->file_last)
;
75
76 ngx_debug_point();
77
78 return NGX_CHAIN_ERROR(ngx_chain_t *) -1;
79 }
80
81 send += vec.size;
82
83 n = ngx_writev(c, &vec);
84
85 if (n == NGX_ERROR-1) {
6
Taking false branch
14
Taking false branch
86 return NGX_CHAIN_ERROR(ngx_chain_t *) -1;
87 }
88
89 sent = (n == NGX_AGAIN-2) ? 0 : n;
7
'?' condition is false
15
'?' condition is false
90
91 c->sent += sent;
92
93 in = ngx_chain_update_sent(in, sent);
94
95 if (send - prev_send != sent) {
8
Taking false branch
16
Taking false branch
96 wev->ready = 0;
97 return in;
98 }
99
100 if (send >= limit || in == NULL((void*)0)) {
9
Assuming 'send' is < 'limit'
10
Assuming 'in' is not equal to null
11
Taking false branch
17
Assuming 'in' is not equal to null
18
Taking false branch
101 return in;
102 }
103 }
104}
105
106
107ngx_chain_t *
108ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, size_t limit,
109 ngx_log_t *log)
110{
111 size_t total, size;
112 u_char *prev;
113 ngx_uint_t n;
114 struct iovec *iov;
115
116 iov = NULL((void*)0);
21
Null pointer value stored to 'iov'
117 prev = NULL((void*)0);
118 total = 0;
119 n = 0;
120
121 for ( /* void */ ; in && total < limit; in = in->next) {
22
Assuming 'total' is < 'limit'
23
Loop condition is true. Entering loop body
122
123 if (ngx_buf_special(in->buf)((in->buf->flush || in->buf->last_buf || in->buf
->sync) && !(in->buf->temporary || in->buf
->memory || in->buf->mmap) && !in->buf->
in_file)
) {
124 continue;
125 }
126
127 if (in->buf->in_file) {
24
Taking false branch
128 break;
129 }
130
131 if (!ngx_buf_in_memory(in->buf)(in->buf->temporary || in->buf->memory || in->
buf->mmap)
) {
25
Taking false branch
132 ngx_log_error(NGX_LOG_ALERT, log, 0,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
133 "bad buf in output chain "if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
134 "t:%d r:%d f:%d %p %p-%p %p %O-%O",if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
135 in->buf->temporary,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
136 in->buf->recycled,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
137 in->buf->in_file,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
138 in->buf->start,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
139 in->buf->pos,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
140 in->buf->last,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
141 in->buf->file,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
142 in->buf->file_pos,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
143 in->buf->file_last)if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "bad buf in output chain " "t:%d r:%d f:%d %p %p-%p %p %O-%O"
, in->buf->temporary, in->buf->recycled, in->buf
->in_file, in->buf->start, in->buf->pos, in->
buf->last, in->buf->file, in->buf->file_pos, in
->buf->file_last)
;
144
145 ngx_debug_point();
146
147 return NGX_CHAIN_ERROR(ngx_chain_t *) -1;
148 }
149
150 size = in->buf->last - in->buf->pos;
151
152 if (size > limit - total) {
26
Taking false branch
153 size = limit - total;
154 }
155
156 if (prev == in->buf->pos) {
27
Taking true branch
157 iov->iov_len += size;
28
Access to field 'iov_len' results in a dereference of a null pointer (loaded from variable 'iov')
158
159 } else {
160 if (n == vec->nalloc) {
161 break;
162 }
163
164 iov = &vec->iovs[n++];
165
166 iov->iov_base = (void *) in->buf->pos;
167 iov->iov_len = size;
168 }
169
170 prev = in->buf->pos + size;
171 total += size;
172 }
173
174 vec->count = n;
175 vec->size = total;
176
177 return in;
178}
179
180
181ssize_t
182ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec)
183{
184 ssize_t n;
185 ngx_err_t err;
186
187eintr:
188
189 n = writev(c->fd, vec->iovs, vec->count);
190
191 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
192 "writev: %z of %uz", n, vec->size);
193
194 if (n == -1) {
195 err = ngx_errno(*__errno_location ());
196
197 switch (err) {
198 case NGX_EAGAIN11:
199 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
200 "writev() not ready");
201 return NGX_AGAIN-2;
202
203 case NGX_EINTR4:
204 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
205 "writev() was interrupted");
206 goto eintr;
207
208 default:
209 c->write->error = 1;
210 ngx_connection_error(c, err, "writev() failed");
211 return NGX_ERROR-1;
212 }
213 }
214
215 return n;
216}