Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

HTTP/2 Data padding is not counted toward the connection flow-control window. This deadlocks connections with peers that pad.

Aperta
#9,772 6 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Amir-Golmoradi ci sta già lavorando.

Dal 8/10/2026.

  • #9786 di @Amir-Golmoradi — chiusa senza merge

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
67/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
kotlin
Ambito
networking

Direzione di ricerca

Start with Http2Reader.readData, Http2Connection.updateConnectionFlowControl, and Http2Stream.FramingSource.receive to trace how DATA frame bytes reach connection-level accounting. Add a regression test in Http2ConnectionTest that sends padded DATA frames and reads the stream-0 WINDOW_UPDATE; done when its increment accounts for the full padded payload, as RFC 9113 requires.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug
Summary

Http2Reader does not count DATA frame padding toward the connection-level flow-control window. When the peer pads its DATA frames, the server's view of the connection window drains faster than the client's counter grows, the server's window reaches zero before the client reaches its next WINDOW_UPDATE threshold, and the connection deadlocks. PING/PONG keeps working, so the connection stays in the pool and every subsequent call on it times out.

Observed on 5.5.0; the code is unchanged on main.

Where

Http2Reader.readData reads the pad-length byte, computes the body length without padding, calls handler.data(..., dataLength) with the body length only, and then skips the padding:
https://github.com/lysine-dev/okhttp/blob/e9eae50d36e938603811a41f9e2ab04182bcb515/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/http2/Http2Reader.kt#L198-L202

Http2Connection.updateConnectionFlowControl is therefore only ever fed the body length, both through the stream path (Http2Stream.FramingSource.receive) and the unknown-stream path:
https://github.com/lysine-dev/okhttp/blob/e9eae50d36e938603811a41f9e2ab04182bcb515/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/http2/Http2Connection.kt#L189
https://github.com/lysine-dev/okhttp/blob/e9eae50d36e938603811a41f9e2ab04182bcb515/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/http2/Http2Stream.kt#L517

The pad-length byte and the padding bytes are consumed from the socket but never credited back to the peer.

Spec

RFC 9113 §6.1: "The entire DATA frame payload is included in flow control, including the Pad Length and Padding fields if present."
https://www.rfc-editor.org/rfc/rfc9113.html#section-6.1

Go's net/http2 fixed the same bug in 2016 and refunds padding immediately on receipt (golang/go#16556, https://go.googlesource.com/net/+/35028a49ca5a73b486af60cd20ac21cd6b67bfdb). Google's quiche fixed a padding flow-control leak that stalled Envoy connections (envoyproxy/envoy#32401, https://quiche.googlesource.com/quiche/+/9e875938052443c7f51b25012093be59e20598ac). Netty charges data.readableBytes() + padding.

How it shows up in practice

Google Front End pads every response DATA frame with a random 0–255 bytes. A production client of ours talking to an API behind GFE deadlocked every long-lived connection at the same point. Measured with a FlowControlListener on the pool:

response body ~250 B
DATA frame on the wire ~372 B average, uniform 247–503 B (`DATA END_STREAM
fraction the client counts ~0.665
client window 16 MiB advertised, WINDOW_UPDATE of 8 MiB once 8 MiB has been counted
server bytes sent at the freeze 24.0 MiB (16 MiB initial + one 8 MiB grant)
WindowCounter at the freeze total 15.7–16.7 MiB, acknowledged 8,388,6xx: below the threshold for the second grant
responses per connection before the freeze ~67,000

After the freeze the only inbound frames were PINGs and the server's own WINDOW_UPDATEs for our request bytes. No HEADERS or DATA, no GOAWAY, no RST_STREAM. Http2Connection.isHealthy() kept returning true, so the connection was reused for every call until the server eventually closed it.

Failing test

The Http2Writer used by the test peer cannot write padded frames, so the test writes DATA frames by hand: a 9-byte frame header with FLAG_PADDED, one pad-length byte, the body, then the padding. Send enough frames for the padded total to exceed half the client window, then read the WINDOW_UPDATE the client sends on stream 0. Expected: the increment equals the padded bytes received. Actual on 5.5.0: the increment equals the body bytes only. (I can turn this into a test in Http2ConnectionTest if that helps.)

Workaround

Restricting the affected client to HTTP/1.1 removes the problem entirely.

Lingua principale
Kotlin
Stelle
47.1k
Fork
9.3k
Merge medio
18h 18m
PR unite (30g)
15

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di lysine-dev/okhttp

Tutte le issue di lysine-dev/okhttp

Issue simili

Altre issue su Kotlin

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.