Bug Summary

File:out/../deps/nghttp2/lib/nghttp2_buf.c
Warning:line 389, column 26
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nghttp2_buf.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _U_= -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D BUILDING_NGHTTP2 -D NGHTTP2_STATICLIB -D HAVE_CONFIG_H -I ../deps/nghttp2/lib/includes -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c ../deps/nghttp2/lib/nghttp2_buf.c
1/*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2014 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25#include "nghttp2_buf.h"
26
27#include <stdio.h>
28
29#include "nghttp2_helper.h"
30#include "nghttp2_debug.h"
31
32void nghttp2_buf_init(nghttp2_buf *buf) {
33 buf->begin = NULL((void*)0);
34 buf->end = NULL((void*)0);
35 buf->pos = NULL((void*)0);
36 buf->last = NULL((void*)0);
37 buf->mark = NULL((void*)0);
38}
39
40int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) {
41 nghttp2_buf_init(buf);
42 return nghttp2_buf_reserve(buf, initial, mem);
43}
44
45void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) {
46 if (buf == NULL((void*)0)) {
47 return;
48 }
49
50 nghttp2_mem_free(mem, buf->begin);
51 buf->begin = NULL((void*)0);
52}
53
54int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
55 uint8_t *ptr;
56 size_t cap;
57
58 cap = nghttp2_buf_cap(buf)((size_t)((buf)->end - (buf)->begin));
59
60 if (cap >= new_cap) {
61 return 0;
62 }
63
64 new_cap = nghttp2_max(new_cap, cap * 2)((new_cap) > (cap * 2) ? (new_cap) : (cap * 2));
65
66 ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
67 if (ptr == NULL((void*)0)) {
68 return NGHTTP2_ERR_NOMEM;
69 }
70
71 buf->pos = ptr + (buf->pos - buf->begin);
72 buf->last = ptr + (buf->last - buf->begin);
73 buf->mark = ptr + (buf->mark - buf->begin);
74 buf->begin = ptr;
75 buf->end = ptr + new_cap;
76
77 return 0;
78}
79
80void nghttp2_buf_reset(nghttp2_buf *buf) {
81 buf->pos = buf->last = buf->mark = buf->begin;
82}
83
84void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
85 buf->begin = buf->pos = buf->last = buf->mark = buf->end = begin;
86 if (len) {
87 buf->end += len;
88 }
89}
90
91static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length,
92 nghttp2_mem *mem) {
93 int rv;
94
95 *chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
10
Value assigned to 'chain'
96 if (*chain == NULL((void*)0)) {
11
Assuming the condition is false
12
Taking false branch
97 return NGHTTP2_ERR_NOMEM;
98 }
99
100 (*chain)->next = NULL((void*)0);
101
102 rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem);
103 if (rv
12.1
'rv' is equal to 0
!= 0) {
13
Taking false branch
104 nghttp2_mem_free(mem, *chain);
105 return NGHTTP2_ERR_NOMEM;
106 }
107
108 return 0;
109}
110
111static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) {
112 nghttp2_buf_free(&chain->buf, mem);
113 nghttp2_mem_free(mem, chain);
114}
115
116int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
117 nghttp2_mem *mem) {
118 return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem);
119}
120
121int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
122 size_t max_chunk, size_t offset, nghttp2_mem *mem) {
123 return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset,
124 mem);
125}
126
127int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
128 size_t max_chunk, size_t chunk_keep, size_t offset,
129 nghttp2_mem *mem) {
130 int rv;
131 nghttp2_buf_chain *chain;
132
133 if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
134 return NGHTTP2_ERR_INVALID_ARGUMENT;
135 }
136
137 rv = buf_chain_new(&chain, chunk_length, mem);
138 if (rv != 0) {
139 return rv;
140 }
141
142 bufs->mem = mem;
143 bufs->offset = offset;
144
145 bufs->head = chain;
146 bufs->cur = bufs->head;
147
148 nghttp2_buf_shift_right(&bufs->cur->buf, offset)do { (&bufs->cur->buf)->pos += offset; (&bufs
->cur->buf)->last += offset; } while (0)
;
149
150 bufs->chunk_length = chunk_length;
151 bufs->chunk_used = 1;
152 bufs->max_chunk = max_chunk;
153 bufs->chunk_keep = chunk_keep;
154
155 return 0;
156}
157
158int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
159 int rv;
160 nghttp2_buf_chain *chain;
161
162 if (chunk_length < bufs->offset) {
163 return NGHTTP2_ERR_INVALID_ARGUMENT;
164 }
165
166 rv = buf_chain_new(&chain, chunk_length, bufs->mem);
167 if (rv != 0) {
168 return rv;
169 }
170
171 nghttp2_bufs_free(bufs);
172
173 bufs->head = chain;
174 bufs->cur = bufs->head;
175
176 nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset)do { (&bufs->cur->buf)->pos += bufs->offset; (
&bufs->cur->buf)->last += bufs->offset; } while
(0)
;
177
178 bufs->chunk_length = chunk_length;
179 bufs->chunk_used = 1;
180
181 return 0;
182}
183
184void nghttp2_bufs_free(nghttp2_bufs *bufs) {
185 nghttp2_buf_chain *chain, *next_chain;
186
187 if (bufs == NULL((void*)0)) {
188 return;
189 }
190
191 for (chain = bufs->head; chain;) {
192 next_chain = chain->next;
193
194 buf_chain_del(chain, bufs->mem);
195
196 chain = next_chain;
197 }
198
199 bufs->head = NULL((void*)0);
200}
201
202int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
203 nghttp2_mem *mem) {
204 nghttp2_buf_chain *chain;
205
206 chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
207 if (chain == NULL((void*)0)) {
208 return NGHTTP2_ERR_NOMEM;
209 }
210
211 chain->next = NULL((void*)0);
212
213 nghttp2_buf_wrap_init(&chain->buf, begin, len);
214
215 bufs->mem = mem;
216 bufs->offset = 0;
217
218 bufs->head = chain;
219 bufs->cur = bufs->head;
220
221 bufs->chunk_length = len;
222 bufs->chunk_used = 1;
223 bufs->max_chunk = 1;
224 bufs->chunk_keep = 1;
225
226 return 0;
227}
228
229int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
230 size_t veclen, nghttp2_mem *mem) {
231 size_t i = 0;
232 nghttp2_buf_chain *cur_chain;
233 nghttp2_buf_chain *head_chain;
234 nghttp2_buf_chain **dst_chain = &head_chain;
235
236 if (veclen == 0) {
237 return nghttp2_bufs_wrap_init(bufs, NULL((void*)0), 0, mem);
238 }
239
240 head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
241 if (head_chain == NULL((void*)0)) {
242 return NGHTTP2_ERR_NOMEM;
243 }
244
245 for (i = 0; i < veclen; ++i) {
246 cur_chain = &head_chain[i];
247 cur_chain->next = NULL((void*)0);
248 nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
249
250 *dst_chain = cur_chain;
251 dst_chain = &cur_chain->next;
252 }
253
254 bufs->mem = mem;
255 bufs->offset = 0;
256
257 bufs->head = head_chain;
258 bufs->cur = bufs->head;
259
260 /* We don't use chunk_length since no allocation is expected. */
261 bufs->chunk_length = 0;
262 bufs->chunk_used = veclen;
263 bufs->max_chunk = veclen;
264 bufs->chunk_keep = veclen;
265
266 return 0;
267}
268
269void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
270 if (bufs == NULL((void*)0)) {
271 return;
272 }
273
274 if (bufs->head) {
275 nghttp2_mem_free(bufs->mem, bufs->head);
276 }
277}
278
279void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
280 nghttp2_buf_chain *ci;
281
282 for (ci = bufs->cur; ci; ci = ci->next) {
283 if (nghttp2_buf_len(&ci->buf)((size_t)((&ci->buf)->last - (&ci->buf)->
pos))
== 0) {
284 return;
285 } else {
286 bufs->cur = ci;
287 }
288 }
289}
290
291size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
292 nghttp2_buf_chain *ci;
293 size_t len;
294
295 len = 0;
296 for (ci = bufs->head; ci; ci = ci->next) {
297 len += nghttp2_buf_len(&ci->buf)((size_t)((&ci->buf)->last - (&ci->buf)->
pos))
;
298 }
299
300 return len;
301}
302
303static int bufs_alloc_chain(nghttp2_bufs *bufs) {
304 int rv;
305 nghttp2_buf_chain *chain;
306
307 if (bufs->cur->next) {
5
Assuming field 'next' is null
6
Taking false branch
308 bufs->cur = bufs->cur->next;
309
310 return 0;
311 }
312
313 if (bufs->max_chunk == bufs->chunk_used) {
7
Assuming field 'max_chunk' is not equal to field 'chunk_used'
8
Taking false branch
314 return NGHTTP2_ERR_BUFFER_ERROR;
315 }
316
317 rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem);
9
Calling 'buf_chain_new'
14
Returning from 'buf_chain_new'
318 if (rv
14.1
'rv' is equal to 0
!= 0) {
15
Taking false branch
319 return rv;
320 }
321
322 DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",do { } while (0)
16
Loop condition is false. Exiting loop
323 bufs->chunk_length, bufs, bufs->chunk_used)do { } while (0);
324
325 ++bufs->chunk_used;
326
327 bufs->cur->next = chain;
328 bufs->cur = chain;
17
The value of 'chain' is assigned to field 'cur'
329
330 nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset)do { (&bufs->cur->buf)->pos += bufs->offset; (
&bufs->cur->buf)->last += bufs->offset; } while
(0)
;
18
Loop condition is false. Exiting loop
331
332 return 0;
333}
334
335int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
336 int rv;
337 size_t nwrite;
338 nghttp2_buf *buf;
339 const uint8_t *p;
340
341 p = data;
342
343 while (len) {
344 buf = &bufs->cur->buf;
345
346 nwrite = nghttp2_min(nghttp2_buf_avail(buf), len)((((size_t)((buf)->end - (buf)->last))) < (len) ? ((
(size_t)((buf)->end - (buf)->last))) : (len))
;
347 if (nwrite == 0) {
348 rv = bufs_alloc_chain(bufs);
349 if (rv != 0) {
350 return rv;
351 }
352 continue;
353 }
354
355 buf->last = nghttp2_cpymem(buf->last, p, nwrite);
356 p += nwrite;
357 len -= nwrite;
358 }
359
360 return 0;
361}
362
363static int bufs_ensure_addb(nghttp2_bufs *bufs) {
364 int rv;
365 nghttp2_buf *buf;
366
367 buf = &bufs->cur->buf;
368
369 if (nghttp2_buf_avail(buf)((size_t)((buf)->end - (buf)->last)) > 0) {
2
Assuming the condition is false
3
Taking false branch
370 return 0;
371 }
372
373 rv = bufs_alloc_chain(bufs);
4
Calling 'bufs_alloc_chain'
19
Returning from 'bufs_alloc_chain'
374 if (rv
19.1
'rv' is equal to 0
!= 0) {
20
Taking false branch
375 return rv;
376 }
377
378 return 0;
379}
380
381int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
382 int rv;
383
384 rv = bufs_ensure_addb(bufs);
1
Calling 'bufs_ensure_addb'
21
Returning from 'bufs_ensure_addb'
385 if (rv
21.1
'rv' is equal to 0
!= 0) {
22
Taking false branch
386 return rv;
387 }
388
389 *bufs->cur->buf.last++ = b;
23
Dereference of null pointer
390
391 return 0;
392}
393
394int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
395 int rv;
396
397 rv = bufs_ensure_addb(bufs);
398 if (rv != 0) {
399 return rv;
400 }
401
402 *bufs->cur->buf.last = b;
403
404 return 0;
405}
406
407int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
408 int rv;
409
410 rv = bufs_ensure_addb(bufs);
411 if (rv != 0) {
412 return rv;
413 }
414
415 *bufs->cur->buf.last++ |= b;
416
417 return 0;
418}
419
420int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
421 int rv;
422
423 rv = bufs_ensure_addb(bufs);
424 if (rv != 0) {
425 return rv;
426 }
427
428 *bufs->cur->buf.last |= b;
429
430 return 0;
431}
432
433ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
434 size_t len;
435 nghttp2_buf_chain *chain;
436 nghttp2_buf *buf;
437 uint8_t *res;
438 nghttp2_buf resbuf;
439
440 len = 0;
441
442 for (chain = bufs->head; chain; chain = chain->next) {
443 len += nghttp2_buf_len(&chain->buf)((size_t)((&chain->buf)->last - (&chain->buf
)->pos))
;
444 }
445
446 if (len == 0) {
447 res = NULL((void*)0);
448 return 0;
449 }
450
451 res = nghttp2_mem_malloc(bufs->mem, len);
452 if (res == NULL((void*)0)) {
453 return NGHTTP2_ERR_NOMEM;
454 }
455
456 nghttp2_buf_wrap_init(&resbuf, res, len);
457
458 for (chain = bufs->head; chain; chain = chain->next) {
459 buf = &chain->buf;
460 resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf)((size_t)((buf)->last - (buf)->pos)));
461 }
462
463 *out = res;
464
465 return (ssize_t)len;
466}
467
468size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
469 size_t len;
470 nghttp2_buf_chain *chain;
471 nghttp2_buf *buf;
472 nghttp2_buf resbuf;
473
474 len = nghttp2_bufs_len(bufs);
475
476 nghttp2_buf_wrap_init(&resbuf, out, len);
477
478 for (chain = bufs->head; chain; chain = chain->next) {
479 buf = &chain->buf;
480 resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf)((size_t)((buf)->last - (buf)->pos)));
481 }
482
483 return len;
484}
485
486void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
487 nghttp2_buf_chain *chain, *ci;
488 size_t k;
489
490 k = bufs->chunk_keep;
491
492 for (ci = bufs->head; ci; ci = ci->next) {
493 nghttp2_buf_reset(&ci->buf);
494 nghttp2_buf_shift_right(&ci->buf, bufs->offset)do { (&ci->buf)->pos += bufs->offset; (&ci->
buf)->last += bufs->offset; } while (0)
;
495
496 if (--k == 0) {
497 break;
498 }
499 }
500
501 if (ci) {
502 chain = ci->next;
503 ci->next = NULL((void*)0);
504
505 for (ci = chain; ci;) {
506 chain = ci->next;
507
508 buf_chain_del(ci, bufs->mem);
509
510 ci = chain;
511 }
512
513 bufs->chunk_used = bufs->chunk_keep;
514 }
515
516 bufs->cur = bufs->head;
517}
518
519int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
520
521int nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
522 nghttp2_buf_chain *chain;
523
524 chain = bufs->cur->next;
525
526 return chain && nghttp2_buf_len(&chain->buf)((size_t)((&chain->buf)->last - (&chain->buf
)->pos))
;
527}