cloudflare/quiche · critical

The provided buffer is too large

Error message

The provided buffer is too large

What it means

Defensive size guard in the H3 FFI wrapper quiche_h3_send_body. body_len is size_t but bytes sent are returned as ssize_t; a body length above ssize_t::MAX cannot be represented in the return value, so the wrapper panics instead of returning an ambiguous value.

Solutions

  1. Pass the actual body buffer length, <= SSIZE_MAX
  2. Validate or chunk large bodies before sending
  3. Fix signed-length bugs at the call site

Example fix

// before
quiche_h3_send_body(h3, conn, id, body, (size_t)len, fin);
// after
if (len < 0 || (size_t)len > SSIZE_MAX) return -1;
quiche_h3_send_body(h3, conn, id, body, (size_t)len, fin);
Defensive patterns

Strategy: validation

Validate before calling

if (body_len < 0 || (size_t)body_len > SSIZE_MAX) return -1;

Prevention

When it happens

Trigger: Calling quiche_h3_send_body() with body_len > SSIZE_MAX (typically a negative C length cast to size_t).

Common situations: Sign/overflow errors in C HTTP/3 applications, untrusted body sizes, fuzzing of the h3 FFI boundary.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of cloudflare/quiche@9f96daa2c2 (2026-09-08). Data as JSON: /api/errors/558b983e292f92d0. Report an issue: GitHub.

Appendix: source

Thrown at quiche/src/h3/ffi.rs:308

        quic_conn,
        stream_id,
        &headers,
        is_trailer_section,
        fin,
    ) {
        Ok(_) => 0,

        Err(e) => e.to_c() as c_int,
    }
}

#[no_mangle]
pub extern "C" fn quiche_h3_send_body(
    conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
    body: *const u8, body_len: size_t, fin: bool,
) -> ssize_t {
    if body_len > <ssize_t>::MAX as usize {
        panic!("The provided buffer is too large");
    }

    let body = unsafe { slice::from_raw_parts(body, body_len) };

    match conn.send_body(quic_conn, stream_id, body, fin) {
        Ok(v) => v as ssize_t,

        Err(e) => e.to_c(),
    }
}

#[no_mangle]
pub extern "C" fn quiche_h3_recv_body(
    conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
    out: *mut u8, out_len: size_t,
) -> ssize_t {
    if out_len > <ssize_t>::MAX as usize {
        panic!("The provided buffer is too large");

View on GitHub (pinned to 9f96daa2c2)