getsentry / getsentry/sentry-java
ManifestVersionReader leaks a ZipFile Inflater per JAR (openStream never closed)
- Lingua principale
- Kotlin
- Stelle
- 1.4k
- Fork
- 478
- Merge medio
- 2g 23h
- PR unite (30g)
- 67
Descrizione
## Description
`ManifestVersionReader.readManifestFiles()` enumerates every `META-INF/MANIFEST.MF` on the classpath and passes `URL.openStream()` into `new Manifest(InputStream)` **without closing the stream**.
`java.util.jar.Manifest(InputStream)` reads the stream and does not close it. For `jar:` URLs that stream is a `ZipFileInflaterInputStream`. Closing it is what calls `ZipFile$CleanableResource.releaseInflater()`. If it is never closed, each JAR leaves a live `java.util.zip.Inflater` (~64 KiB zlib window).
This still matches [main](https://github.com/getsentry/sentry-java/blob/main/sentry/src/main/java/io/sentry/internal/ManifestVersionReader.java) and 8.41.0 / 8.52.0.
## Call site
```java
final Enumeration resources =
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
try {
final Manifest manifest = new Manifest(resources.nextElement().openStream());
// ...
} catch (Exception e) {
// ignore
}
}
```
Triggered from `ManifestVersionDetector.checkForMixedVersions()` → `InitUtil.shouldInit()` → `Sentry.init()`.
## Observed
Compose Desktop / packaged JVM app with ~80 JARs on the classpath (`sentry-java` **8.41.0**):
- `GC.class_histogram`: **168** live `java.util.zip.Inflater`
- async-profiler `event=java.util.zip.Inflater.` from process start: **79 / 174** constructors (45%) are
```
java.util.zip.Inflater.
java.util.zip.ZipFile$CleanableResource.getInflater
java.util.zip.ZipFile$ZipFileInflaterInputStream.
java.util.zip.ZipFile.getInputStream
java.util.jar.JarFile.getBytes
java.util.jar.JarFile.checkForSpecialAttributes
java.util.jar.JarFile.isMultiRelease
java.util.jar.JarFile.getEntry
sun.net.www.protocol.jar.URLJarFile.getEntry
sun.net.www.protocol.jar.JarURLConnection.connect
sun.net.www.protocol.jar.JarURLConnection.getInputStream
java.net.URL.openStream
io.sentry.internal.ManifestVersionReader.readManifestFiles
io.sentry.ManifestVersionDetector.checkForMixedVersions
io.sentry.util.InitUtil.shouldInit
io.sentry.Sentry.init
```
## Suggested fix
```java
try (InputStream is = resources.nextElement().openStream()) {
final Manifest manifest = new Manifest(is);
// existing attribute handling
} catch (Exception e) {
// ignore
}
```
`Manifest` does not take ownership of the stream, so try-with-resources is required even on the success path.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.