File: | out/../deps/nghttp2/lib/nghttp2_buf.c |
Warning: | line 389, column 26 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
32 | void 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 | ||||
40 | int 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 | ||||
45 | void 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 | ||||
54 | int 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 | ||||
80 | void nghttp2_buf_reset(nghttp2_buf *buf) { | |||
81 | buf->pos = buf->last = buf->mark = buf->begin; | |||
82 | } | |||
83 | ||||
84 | void 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 | ||||
91 | static 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)); | |||
96 | if (*chain == NULL((void*)0)) { | |||
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
| |||
104 | nghttp2_mem_free(mem, *chain); | |||
105 | return NGHTTP2_ERR_NOMEM; | |||
106 | } | |||
107 | ||||
108 | return 0; | |||
109 | } | |||
110 | ||||
111 | static 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 | ||||
116 | int 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 | ||||
121 | int 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 | ||||
127 | int 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 | ||||
158 | int 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 | ||||
184 | void 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 | ||||
202 | int 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 | ||||
229 | int 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 | ||||
269 | void 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 | ||||
279 | void 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 | ||||
291 | size_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 | ||||
303 | static int bufs_alloc_chain(nghttp2_bufs *bufs) { | |||
304 | int rv; | |||
305 | nghttp2_buf_chain *chain; | |||
306 | ||||
307 | if (bufs->cur->next) { | |||
308 | bufs->cur = bufs->cur->next; | |||
309 | ||||
310 | return 0; | |||
311 | } | |||
312 | ||||
313 | if (bufs->max_chunk == bufs->chunk_used) { | |||
314 | return NGHTTP2_ERR_BUFFER_ERROR; | |||
315 | } | |||
316 | ||||
317 | rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem); | |||
318 | if (rv
| |||
319 | return rv; | |||
320 | } | |||
321 | ||||
322 | DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",do { } while (0) | |||
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; | |||
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); | |||
331 | ||||
332 | return 0; | |||
333 | } | |||
334 | ||||
335 | int 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 | ||||
363 | static 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) { | |||
370 | return 0; | |||
371 | } | |||
372 | ||||
373 | rv = bufs_alloc_chain(bufs); | |||
374 | if (rv
| |||
375 | return rv; | |||
376 | } | |||
377 | ||||
378 | return 0; | |||
379 | } | |||
380 | ||||
381 | int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) { | |||
382 | int rv; | |||
383 | ||||
384 | rv = bufs_ensure_addb(bufs); | |||
| ||||
385 | if (rv
| |||
386 | return rv; | |||
387 | } | |||
388 | ||||
389 | *bufs->cur->buf.last++ = b; | |||
| ||||
390 | ||||
391 | return 0; | |||
392 | } | |||
393 | ||||
394 | int 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 | ||||
407 | int 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 | ||||
420 | int 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 | ||||
433 | ssize_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 | ||||
468 | size_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 | ||||
486 | void 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 | ||||
519 | int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); } | |||
520 | ||||
521 | int 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 | } |