From ddf5b5b35140d2f6b3936cc74d6b6054c71bba30 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Tue, 23 Sep 2025 14:55:40 -0700
Subject: [PATCH 1/5] Always dispose PEReader in ResourceUpdater
---
.../managed/Microsoft.NET.HostModel/ResourceUpdater.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
index e4791a6bb14e99..94ff0be384dba6 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
@@ -333,10 +333,11 @@ public void Dispose()
public void Dispose(bool disposing)
{
- if (disposing && !leaveOpen)
+ if (disposing)
{
_reader.Dispose();
- stream.Dispose();
+ if (!leaveOpen)
+ stream.Dispose();
}
}
}
From 7c9e8003cef4a6e3e007d5e5e624480cb30f392c Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Tue, 23 Sep 2025 15:00:02 -0700
Subject: [PATCH 2/5] Practice good Dispose hygene
---
.../managed/Microsoft.NET.HostModel/ResourceUpdater.cs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
index 94ff0be384dba6..ea3d396307ce2b 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
@@ -13,7 +13,7 @@ namespace Microsoft.NET.HostModel
///
/// Provides methods for modifying the embedded native resources in a PE image.
///
- public class ResourceUpdater : IDisposable
+ public sealed class ResourceUpdater : IDisposable
{
private readonly FileStream stream;
private readonly PEReader _reader;
@@ -325,19 +325,21 @@ private static void ThrowExceptionForInvalidUpdate()
"Update handle is invalid. This instance may not be used for further updates");
}
- public void Dispose()
+ void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
- public void Dispose(bool disposing)
+ private void Dispose(bool disposing)
{
if (disposing)
{
_reader.Dispose();
if (!leaveOpen)
+ {
stream.Dispose();
+ }
}
}
}
From 4fce069835934ba95d0b9955418bd78a0c16939d Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Tue, 23 Sep 2025 16:23:08 -0700
Subject: [PATCH 3/5] Revert Dispose visibility changes
---
.../managed/Microsoft.NET.HostModel/ResourceUpdater.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
index ea3d396307ce2b..40a3d78a8bcf36 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
@@ -325,13 +325,13 @@ private static void ThrowExceptionForInvalidUpdate()
"Update handle is invalid. This instance may not be used for further updates");
}
- void IDisposable.Dispose()
+ public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
- private void Dispose(bool disposing)
+ public void Dispose(bool disposing)
{
if (disposing)
{
From 83225a7474947af5984a3e31d14dfc715e3323ea Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Wed, 24 Sep 2025 13:21:22 -0700
Subject: [PATCH 4/5] Add unit test to validate dispose behavior
---
.../ResourceUpdaterTests.cs | 21 ++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs
index 30e3efdf1027db..2f25839507bbfa 100644
--- a/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs
+++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs
@@ -23,7 +23,7 @@ class TempFile : IDisposable
public TempFile()
{
_path = Path.GetTempFileName();
- Stream = new FileStream(_path, FileMode.Open);
+ Stream = new FileStream(_path, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
public void Dispose()
@@ -169,6 +169,25 @@ void AddResource_AddTwoSameUShortTypeWithDifferName()
}
}
+ [Fact]
+ void DisposeWithLeaveOpenDisposesPEReader()
+ {
+ using var tempFile = GetCurrentAssemblyMemoryStream();
+ PEReader? peReader = null;
+
+ using (var updater = new ResourceUpdater(tempFile.Stream, leaveOpen: true))
+ {
+ FieldInfo? readerField = typeof(ResourceUpdater).GetField("_reader", BindingFlags.Instance | BindingFlags.NonPublic);
+ Assert.NotNull(readerField);
+ peReader = Assert.IsType(readerField.GetValue(updater));
+ _ = peReader.PEHeaders;
+ }
+
+ Assert.NotNull(peReader);
+
+ Assert.Throws(() => _ = peReader!.PEHeaders);
+ }
+
[Fact]
void AddResourcesFromPEImage()
{
From 7ffeea1594e03b1c8b6fe8a9430ddd2909614111 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Thu, 25 Sep 2025 13:02:45 -0700
Subject: [PATCH 5/5] Make Dispose(bool) private
---
.../managed/Microsoft.NET.HostModel/ResourceUpdater.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
index 40a3d78a8bcf36..1873e38956038e 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
@@ -331,7 +331,7 @@ public void Dispose()
GC.SuppressFinalize(this);
}
- public void Dispose(bool disposing)
+ private void Dispose(bool disposing)
{
if (disposing)
{