Core: LowLevelHttpResponse not disconnected when HttpResponse construction throws RuntimeException

Aperta Adatta ai principianti
#2,177 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
84/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Tranquilla
Stack tecnologico
java
Ambito
networking

Direzione di ricerca

Inizia in google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java, concentrandoti su HttpRequest.execute() e sul relativo blocco finally. Riproduci il problema con un LowLevelHttpResponse il cui getContentEncoding() genera un'eccezione, quindi esegui testExecute_disconnectOnResponseConstructionFailure. Il lavoro è completato quando la risposta di basso livello viene disconnessa se la costruzione della risposta non riesce e il test di regressione passa.

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

Descrizione

Environment details:

  1. Core — HttpRequest.execute() in google-http-client
  2. OS type and version: Any (not OS-specific)
  3. Java version: Any (reproduces on Java 8+)
  4. google-http-client version(s): reproducible on current main

Steps to reproduce:

  1. Implement a LowLevelHttpResponse whose getContentEncoding() throws a RuntimeException.
  2. Execute an HttpRequest against that transport.
  3. Catch the RuntimeException from execute().
  4. Observe disconnect() was never called on the low-level response.

Code example:

MockLowLevelHttpResponse failingResponse = new MockLowLevelHttpResponse() {
  @Override
  public String getContentEncoding() {
    throw new RuntimeException("simulated failure");
  }
};

HttpTransport transport = new MockHttpTransport() {
  @Override
  public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
    return new MockLowLevelHttpRequest().setResponse(failingResponse);
  }
};

HttpRequest req = transport.createRequestFactory()
    .buildGetRequest(new GenericUrl("http://example.com"));

try {
  req.execute();
} catch (RuntimeException e) {
  // failingResponse.isDisconnected() == false  <-- BUG: socket leaked
}

Stack trace:
None — silent resource leak, not a crash. The RuntimeException propagates as expected; the
bug is that execute()'s finally block never calls LowLevelHttpResponse#disconnect() here.

External references:

  • HttpRequest#execute(): google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java

Any additional information:
Under sustained error conditions, leaked connections accumulate until the pool is exhausted,
risking DoS/thread starvation. Pre-existing bug, unrelated to security hardening — found
opportunistically during a security audit of this file.

Proposed fix — in execute()'s finally block, add a guarded disconnect():

} finally {
  if (!responseConstructed && lowLevelHttpResponse != null) {
    try {
      InputStream c = lowLevelHttpResponse.getContent();
      if (c != null) c.close();
    } catch (IOException ignored) {}
    try {
      lowLevelHttpResponse.disconnect();
    } catch (IOException ignored) {}
  }
}

Regression test testExecute_disconnectOnResponseConstructionFailure included in the
accompanying PR.

Lingua principale
Java
Stelle
1.4k
Fork
473
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Guida per i contributori

Apri la guida per i contributori

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 googleapis/google-http-java-client

Tutte le issue di googleapis/google-http-java-client

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.