googleapis / googleapis/google-http-java-client

Core: LowLevelHttpResponse not disconnected when HttpResponse construction throws RuntimeException

Offen Anfängerfreundlich
#2,177 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
Java
Sterne
1.4k
Forks
473
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

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:
```java
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():

```java
} 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.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Start in google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java, focusing on HttpRequest.execute() and its finally block. Reproduce the failure with a LowLevelHttpResponse whose getContentEncoding() throws, then run testExecute_disconnectOnResponseConstructionFailure. Done means the low-level response is disconnected when response construction fails and the regression test passes.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
java
Bereich
networking
Issue-Typ
Bug
Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Aktivitätsstatus
Ruhig
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
84/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.