From 31968837e51516e1df3fdad4833d78e0c668a5cf Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Tue, 22 Aug 2023 12:46:57 +0500 Subject: [PATCH] Fix JSON corruption when saving (#100) This PR fixes an issue that caused guild data JSON files to be corrupted upon saving. As it turns out `File.OpenWrite(string)` does not clear the file before writing to it. That means, if a file contains `{"MyKey": "MyValue"}` and I write `{}` to it using `File.OpenWrite(string)`, the contents of the file will be `{}MyKey": "MyValue"}`. This is a malformed JSON and will cause an error upon next bot startup. In addition, this PR blacklists the `File.OpenWrite` method using `CodeAnalysis/BannedSymbols.txt` to prevent its accidental use in the future. Signed-off-by: Octol1ttle --- CodeAnalysis/BannedSymbols.txt | 1 + src/Services/GuildDataService.cs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index f664b89..0a1ec81 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -17,3 +17,4 @@ M:Humanizer.InflectorExtensions.Kebaberize(System.String);Humanizer's .Kebaberiz P:System.DateTime.Now;Use System.DateTime.UtcNow instead. P:System.DateTimeOffset.Now;Use System.DateTimeOffset.UtcNow instead. P:System.DateTimeOffset.DateTime;Use System.DateTimeOffset.UtcDateTime instead. +M:System.IO.File.OpenWrite(System.String);File.OpenWrite(string) does not clear the file before writing to it. Use File.Create(string) instead. diff --git a/src/Services/GuildDataService.cs b/src/Services/GuildDataService.cs index 26147d2..796b598 100644 --- a/src/Services/GuildDataService.cs +++ b/src/Services/GuildDataService.cs @@ -48,15 +48,15 @@ public sealed class GuildDataService : IHostedService var tasks = new List(); foreach (var data in _datas.Values) { - await using var settingsStream = File.OpenWrite(data.SettingsPath); + await using var settingsStream = File.Create(data.SettingsPath); tasks.Add(JsonSerializer.SerializeAsync(settingsStream, data.Settings, cancellationToken: ct)); - await using var eventsStream = File.OpenWrite(data.ScheduledEventsPath); + await using var eventsStream = File.Create(data.ScheduledEventsPath); tasks.Add(JsonSerializer.SerializeAsync(eventsStream, data.ScheduledEvents, cancellationToken: ct)); foreach (var memberData in data.MemberData.Values) { - await using var memberDataStream = File.OpenWrite($"{data.MemberDataPath}/{memberData.Id}.json"); + await using var memberDataStream = File.Create($"{data.MemberDataPath}/{memberData.Id}.json"); tasks.Add(JsonSerializer.SerializeAsync(memberDataStream, memberData, cancellationToken: ct)); } }