Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: infinite loop in parse_header_data() when HTTP/3 header length exceeds 65535 #69

Merged
merged 1 commit into from
Dec 16, 2024

Conversation

plumplumli
Copy link
Contributor

Issue Description

When using QPACK for encoding and decoding in HTTP/3, lsquic encounters infinite loop during the process of decoding client request headers.

Loop Description

Infinite loop occurs in parse_header_data(). Loop is as follows:

  1. get_dst(): Unable to store Huffman decoding results due to insufficient buffer space.
  2. lsqpack_huff_decode(): Returns status code HUFF_DEC_END_DST, indicating the buffer is full.
  3. header_out_grow_buf(): Attempts to calculate the required buffer growth size but restricts it to a maximum limit.
  4. h1h_prepare_decode(): Fails to grow the buffer because the size remains unchanged.
  5. get_dst(): Unable to store Huffman decoding results due to insufficient buffer space.
    ...... loop continues.

Loop Reason

During the decoding of HTTP/3 request header, if the buffer space is insufficient, a buffer expansion is triggered. However, even if the required expansion size exceeds 65535 bytes, the header_out_grow_buf() restricts the buffer size to 65535 bytes, resulting in no additional space being allocated. This causes the decoding process to enter a infinite loop.

@plumplumli
Copy link
Contributor Author

Reproduction Steps

Use the http_client from lsquic to send a custom request header that exceeds 65535 bytes. The specific steps are as follows:

  1. Set the client request header buffer length to exceed 65535 bytes.
    struct

  2. Send a custom request header that exceeds 65535 bytes.
    func

Reproduction Results

  1. CPU usage of a single core remains at 100%.
    cpu

  2. pstack trace during the infinite loop process.
    h1h_prepare_decode() -> header_out_grow_buf() -> parse_header_data() -> ......

@litespeedtech
Copy link
Owner

Thanks. just curious, why the screen shot shows that nginx has 100% CPU? nginx is patched to use ls-qpack?

@plumplumli
Copy link
Contributor Author

Yes, we try to integrate lsquic and ls-qpack into Nginx.

@litespeedtech
Copy link
Owner

Yes, we try to integrate lsquic and ls-qpack into Nginx.

Interesting. :-)
Since latest Nginx has built-in HTTP3 support, it is not good enough? or due to other reasons.

@plumplumli
Copy link
Contributor Author

Yes, the QUIC implementation in Nginx is currently not fully mature, as it only supports the Reno congestion control algorithm. Additionally, LSQUIC supports both GQUIC and IETF QUIC.

@litespeedtech litespeedtech merged commit f75312d into litespeedtech:master Dec 16, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants