Repository navigation
Fix issue 15213: Bitmap finalized during Image.Save(Stream, ImageFormat) leaks native GDI+ memory - #15254
Open
SimonZhao888 wants to merge 3 commits into
Open
Fix issue 15213: Bitmap finalized during Image.Save(Stream, ImageFormat) leaks native GDI+ memory#15254SimonZhao888 wants to merge 3 commits into
SimonZhao888 wants to merge 3 commits into
Conversation
added 2 commits
October 12, 2026 16:22
…at) leaks native GDI+ memory
SimonZhao888
requested review from
LeafShi1 and
ricardobossan
and
a balanced review from Copilot
October 12, 2026 08:43
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The regression test baseline can be contaminated by pending finalizers from earlier tests.
1 open finding
What changed in this PR
Prevents premature Image finalization during native GDI+ stream saves.
Changes:
- Keeps
IImagealive throughGdipSaveImageToStream. - Adds native-memory regression coverage.
| File | Description |
|---|---|
CoreImageExtensions.cs |
Extends image lifetime through native save. |
ImageTests.cs |
Tests memory growth across collections. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #15254 +/- ##
=============================================
Coverage 37.84861% 37.84861%
=============================================
Files 246 246
Lines 9789 9789
Branches 1031 1031
=============================================
Hits 3705 3705
Misses 5920 5920
Partials 164 164
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
LeafShi1
approved these changes
Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #15213
Root Cause
When
Image.Save(Stream, ImageFormat)executes the internal stream-saving path, theImageobject is not guaranteed to remain alive during the call to the nativeGdipSaveImageToStreamfunction. Under specific timing conditions, the JIT compiler or Garbage Collector (GC) may trigger finalization of theImageobject prematurely, creating a race condition with the native save operation; this results in the failure to release—or the loss of—underlying GDI+ image resources, manifesting as a native memory leak (where significant memory remains unrecovered).Proposed changes
Within
CoreImageExtensions.Save(this IImage image, Stream stream, ...)ofSystem.Private.Windows.GdiPlus, wrapGdipSaveImageToStreamin a try/finally block and callGC.KeepAlive(image)in the finally block.Customer Impact
The correction avoids abnormal native memory growth in
Save(Stream, ImageFormat)under high-pressure/specific GC timings, reducing memory risks and potential stability issues in long-duration or batch image processing scenarios.The impact on existing behavioral compatibility is minimal (only extending object survival to the end of the method), and should not change functional results or introduce visible behavioral differences.
Regression?
Risk
Screenshots
Before
After
Test methodology
Test environment(s)
Microsoft Reviewers: Open in CodeFlow