Hello,
scan-build found a 28-step path where an unitialized value could be used in
h2s_htx_bck_make_req_headers().
Here is a shortened version:
4378 idx = htx_get_head(htx); // returns the SL that we skip
4379 while ((idx = htx_get_next(htx, idx)) != -1) {
4380 blk = htx_get_blk(htx, idx);
4381 type = htx_get_blk_type(blk);
4382
4383 if (type == HTX_BLK_UNUSED)
4384 continue;
4385
4386 if (type != HTX_BLK_HDR)
// (here, assume condition is true, so control leaves the loop...)
4387 break;
4388
4389 if (unlikely(hdr >= sizeof(list)/sizeof(list[0]) - 1))
4390 goto fail;
4391
// (... and list will not be initialized.)
4392 list[hdr].n = htx_get_blk_name(htx, blk);
4393 list[hdr].v = htx_get_blk_value(htx, blk);
4394 hdr++;
4395 }
...
4450 /* look for the Host header and place it in :authority */
4451 auth = ist2(NULL, 0);
4452 for (hdr = 0; hdr < sizeof(list)/sizeof(list[0]); hdr++) {
4453 if (isteq(list[hdr].n, ist("")))
// (here, assume the condition is false, so control keeps in this block...)
4454 break; // end
4455
4456 if (isteq(list[hdr].n, ist("host"))) {
4457 auth = list[hdr].v;
// (... auth receives an uninitialized value from list ...)
4458 break;
4459 }
4460 }
4461 }
4462 else {
4463 /* for CONNECT, :authority is taken from the path */
4464 auth = path;
4465 }
4466
// (... and here auth is evaluated, but it contains whatever uninitialized
// data that list had, because its initialization has been jumped over.)
4467 if (auth.ptr && !hpack_encode_header(&outbuf, ist(":authority"),
auth)) {
4468 /* output full */
4469 if (b_space_wraps(&h2c->mbuf))
4470 goto realign_again;
4471 goto full;
4472 }
While this feels like a convoluted or unlikely scenario, the path leading
to the use of uninitialized value seems to be correctly unearthed by
scan-build. Also, there might be a chance that this path invokes undefined
behavior, leading to further surprises.
Does this make sense?
Cheers,
--
Ricardo Nabinger Sanchez http://www.taghos.com.br/