getsentry / getsentry/sentry-java

ManifestVersionReader leaks a ZipFile Inflater per JAR (openStream never closed)

未关闭
#6,120 2 条评论 0 个 reaction 已指派 1 人 已被 @0xadam-brown 认领 在 GitHub 查看
Platform: Java Type: Bug
主要语言
Kotlin
星标
1.4k
派生
478
平均合并
2 天 23 小时
30 天内合并 PR
67

描述

## 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.

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。