Skip to content

Commit abd88d5

Browse files
committed
fix(patch): add MD5 verification for full-replacement files to prevent stale content
1 parent d0108f1 commit abd88d5

1 file changed

Lines changed: 32 additions & 1 deletion

File tree

Hi3Helper.Plugin.Wuwa/Management/WuwaGameInstaller.Patch.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,22 @@ await Parallel.ForEachAsync(downloadEntries,
10521052
var fi = new FileInfo(existingPath);
10531053
if (fi.Length == (long)entry.Size)
10541054
{
1055+
// Size matches — verify MD5 to ensure the content is
1056+
// actually the new version and not a stale file.
1057+
if (!string.IsNullOrEmpty(entry.Md5) && fi.Length <= Md5CheckSizeThreshold)
1058+
{
1059+
await using var existFs = File.OpenRead(existingPath);
1060+
string existMd5 = await WuwaUtils.ComputeMd5HexAsync(existFs, ct)
1061+
.ConfigureAwait(false);
1062+
if (!string.Equals(existMd5, entry.Md5, StringComparison.OrdinalIgnoreCase))
1063+
{
1064+
SharedStatic.InstanceLogger.LogDebug(
1065+
"[Patch::RunAsync] Full-replacement file has correct size but MD5 mismatch, downloading: {Dest}",
1066+
entry.Dest);
1067+
goto DownloadFile;
1068+
}
1069+
}
1070+
10551071
SharedStatic.InstanceLogger.LogDebug(
10561072
"[Patch::RunAsync] Full-replacement file already exists with correct size, skipping: {Dest}",
10571073
entry.Dest);
@@ -1064,6 +1080,8 @@ await Parallel.ForEachAsync(downloadEntries,
10641080
}
10651081
}
10661082

1083+
DownloadFile:
1084+
10671085
// Ensure subdirectory exists
10681086
string? dir = Path.GetDirectoryName(outputPath);
10691087
if (!string.IsNullOrEmpty(dir))
@@ -1126,7 +1144,7 @@ await _owner.TryDownloadWholeFileWithFallbacksAsync(
11261144
string filePath = Path.Combine(patchTempPath, relativePath);
11271145

11281146
// Full-replacement files may have been skipped during download because
1129-
// they already exist in the install directory with the correct size.
1147+
// they already exist in the install directory with the correct size and MD5.
11301148
// Check both temp and install locations.
11311149
if (!File.Exists(filePath) && !isKrpdiff)
11321150
{
@@ -1136,6 +1154,19 @@ await _owner.TryDownloadWholeFileWithFallbacksAsync(
11361154
var installFi = new FileInfo(installFilePath);
11371155
if (installFi.Length == (long)entry.Size)
11381156
{
1157+
// Also verify MD5 to catch stale files with matching size.
1158+
if (!string.IsNullOrEmpty(entry.Md5) && installFi.Length <= Md5CheckSizeThreshold)
1159+
{
1160+
await using var installFs = File.OpenRead(installFilePath);
1161+
string installMd5 = await WuwaUtils.ComputeMd5HexAsync(installFs, token)
1162+
.ConfigureAwait(false);
1163+
if (!string.Equals(installMd5, entry.Md5, StringComparison.OrdinalIgnoreCase))
1164+
{
1165+
throw new InvalidOperationException(
1166+
$"Full-replacement file was skipped during download but MD5 does not match in install dir: {entry.Dest} (expected={entry.Md5}, computed={installMd5})");
1167+
}
1168+
}
1169+
11391170
SharedStatic.InstanceLogger.LogDebug(
11401171
"[Patch::RunAsync] Verification: full-replacement file verified in install dir (skipped download): {Dest}",
11411172
entry.Dest);

0 commit comments

Comments
 (0)