[Libwebsockets] lib/roles/http/parsers.c header copy possible overflow

UV 20 sas2016spss at gmail.com
Thu Aug 26 20:42:40 CEST 2021


Hi, I am using v4.2-stable and found the following:

In the header copy function lws_hdr_copy() line 574, 577, 579 (see the code
at then end of this email), *dst is written with new separator in buffer
and dst++, but the variable len for remaining buffer length doesn't
decrease like line 569. So the checking of the remaining buffer at line 562
doesn't prevent it from writing outside of the buffer anymore.

If the allocated buffer size is large enough to hold all new separator(s),
this problem won't be triggered. But I don't know how big the buffer I need
to allocate, I used lws_hdr_total_length()+1 as length to allocate the
buffer before copying the header. This can trigger the overflow.

Since lws_hdr_total_length() is supposed to tell the total size when the
header will be written to a buffer including separators. But its criteria
of adding separator(s)  at line 493 - 494 is different from the actual
separators adding code in the header copy function lws_hdr_copy() between
line 572 to 580.  This can cause lws_hdr_total_length() reports a length
less than the size that's actually needed.

The above two factors combined actually caused a crash in my environment.
Please take a look. Thanks.

  int *lws_hdr_total_length*(struct lws *wsi, enum lws_token_indexes h)
 479 {
 480     int n;
 481     int len = 0;
 482
 483     if (!wsi->http.ah)
 484         return 0;
 485
 486     n = wsi->http.ah->frag_index[h];
 487     if (!n)
 488         return 0;
 489     do {
 490         len += wsi->http.ah->frags[n].len;
 491         n = wsi->http.ah->frags[n].nfrag;
 492

* 493         if (n && h != WSI_TOKEN_HTTP_COOKIE) 494             ++len;*
 495
 496     } while (n);
 497
 498     return len;


  int *lws_hdr_copy*(struct lws *wsi, char *dst, int len,
 533                  enum lws_token_indexes h)
 534 {
 535     int toklen = lws_hdr_total_length(wsi, h);
 536     int n;
 537     int comma;
 538
 539     *dst = '\0';
 540     if (!toklen)
 541         return 0;
 542
 543     if (toklen >= len)
 544         return -1;
 545
 546     if (!wsi->http.ah)
 547         return -1;
 548
 549     n = wsi->http.ah->frag_index[h];
 550     if (h == WSI_TOKEN_HTTP_URI_ARGS)
 551         lwsl_err("%s: WSI_TOKEN_HTTP_URI_ARGS start frag %d\n",
__func__, n);
 552
 553
 554     if (!n)
 555         return 0;
 556     do {
 557         comma = (wsi->http.ah->frags[n].nfrag) ? 1 : 0;
 558
 559         if (h == WSI_TOKEN_HTTP_URI_ARGS)
 560             lwsl_notice("%s: WSI_TOKEN_HTTP_URI_ARGS '%.*s'\n",
__func__, (int)wsi->http.ah->frags[n].len,
&wsi->http.ah->data[wsi->http.ah->frags     [n].offset]);
 561
 562         if (wsi->http.ah->frags[n].len + comma *>= len*) {
 563             lwsl_notice("blowout len\n");
 564             return -1;
 565         }
 566         strncpy(dst,
&wsi->http.ah->data[wsi->http.ah->frags[n].offset],
 567                 wsi->http.ah->frags[n].len);

* 568         dst += wsi->http.ah->frags[n].len; 569         len -=
wsi->http.ah->frags[n].len;*
 570         n = wsi->http.ah->frags[n].nfrag;
 571








* 572         if (comma) { 573             if (h == WSI_TOKEN_HTTP_COOKIE
|| h == WSI_TOKEN_HTTP_SET_COOKIE) 574                 *dst++ = ';'; 575
          else 576                 if (h == WSI_TOKEN_HTTP_URI_ARGS) 577
                  *dst++ = '&'; 578                 else 579
      *dst++ = ','; 580         }*
 581
 582     } while (n);
 583     *dst = '\0';
 584
 585     if (h == WSI_TOKEN_HTTP_URI_ARGS)
 586         lwsl_err("%s: WSI_TOKEN_HTTP_URI_ARGS toklen %d\n", __func__,
(int)toklen);
 587
 588     return toklen;
 589 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://libwebsockets.org/pipermail/libwebsockets/attachments/20210826/75fa12d5/attachment.htm>


More information about the Libwebsockets mailing list