-
Notifications
You must be signed in to change notification settings - Fork 0
feat: harden updater error handling and input validation #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,11 @@ namespace KeePassAutoReload.Updater | |
| { | ||
| internal static class Program | ||
| { | ||
| internal const int ExitSuccess = 0; | ||
| internal const int ExitInvalidArguments = 1; | ||
| internal const int ExitUpdateFailed = 2; | ||
| internal const int ExitRestartFailed = 3; | ||
|
|
||
| internal static int Main(string[] args) | ||
| { | ||
| int processId = 0; | ||
|
|
@@ -22,7 +27,11 @@ internal static int Main(string[] args) | |
|
|
||
| if (string.Equals(current, "--process-id", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| int.TryParse(value, out processId); | ||
| if (!int.TryParse(value, out processId) || processId < 0) | ||
| { | ||
| Console.Error.WriteLine("Invalid process ID."); | ||
| return ExitInvalidArguments; | ||
| } | ||
| } | ||
| else if (string.Equals(current, "--source", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
|
|
@@ -41,7 +50,25 @@ internal static int Main(string[] args) | |
| if (string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(destination)) | ||
| { | ||
| Console.Error.WriteLine("Usage: KeePassAutoReload.Updater --source <path> --destination <path> [--process-id <pid>] [--restart <path>]"); | ||
| return 1; | ||
| return ExitInvalidArguments; | ||
| } | ||
|
|
||
| if (!source.EndsWith(".new", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| Console.Error.WriteLine("Source file must have a .new extension."); | ||
| return ExitInvalidArguments; | ||
| } | ||
|
|
||
| if (!destination.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| Console.Error.WriteLine("Destination file must have a .dll extension."); | ||
| return ExitInvalidArguments; | ||
| } | ||
|
|
||
| if (!File.Exists(source)) | ||
| { | ||
| Console.Error.WriteLine("Source file does not exist: " + source); | ||
| return ExitInvalidArguments; | ||
| } | ||
|
|
||
| try | ||
|
|
@@ -63,20 +90,30 @@ internal static int Main(string[] args) | |
|
|
||
| Thread.Sleep(1000); | ||
|
|
||
| string destinationDirectory = Path.GetDirectoryName(destination); | ||
| if (!string.IsNullOrWhiteSpace(destinationDirectory) && !Directory.Exists(destinationDirectory)) | ||
| { | ||
| Directory.CreateDirectory(destinationDirectory); | ||
| } | ||
|
|
||
| File.Copy(source, destination, overwrite: true); | ||
| File.Delete(source); | ||
|
|
||
| if (!string.IsNullOrWhiteSpace(restart) && File.Exists(restart)) | ||
| if (string.IsNullOrWhiteSpace(restart)) return ExitSuccess; | ||
|
|
||
| if (!File.Exists(restart)) | ||
| { | ||
| Process.Start(restart); | ||
| Console.Error.WriteLine("KeePass executable not found: " + restart); | ||
| return ExitRestartFailed; | ||
| } | ||
|
|
||
| return 0; | ||
| Process.Start(restart); | ||
| return ExitSuccess; | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Console.Error.WriteLine("Update failed: " + ex.Message); | ||
| return 2; | ||
| return ExitUpdateFailed; | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
90
to
119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. File Operation Robustness and Error Handling The file operations ( Recommendation:
Example: try {
File.Copy(source, destination, overwrite: true);
} catch (IOException ioEx) {
Console.Error.WriteLine($"File copy failed: {ioEx.Message}");
return ExitUpdateFailed;
} |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,16 @@ public static bool TryScheduleUpdate( | |
| if (string.IsNullOrWhiteSpace(newPluginPath)) throw new ArgumentException("newPluginPath"); | ||
| if (string.IsNullOrWhiteSpace(updaterExePath)) throw new ArgumentException("updaterExePath"); | ||
| if (starter == null) throw new ArgumentNullException("starter"); | ||
| if (keepassProcessId < 0) throw new ArgumentOutOfRangeException("keepassProcessId"); | ||
|
|
||
| if (!pluginPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) | ||
| throw new ArgumentException("pluginPath must end with .dll", "pluginPath"); | ||
| if (!newPluginPath.EndsWith(".new", StringComparison.OrdinalIgnoreCase)) | ||
| throw new ArgumentException("newPluginPath must end with .new", "newPluginPath"); | ||
| if (!updaterExePath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) | ||
| throw new ArgumentException("updaterExePath must end with .exe", "updaterExePath"); | ||
| if (!string.IsNullOrWhiteSpace(keepassExecutablePath) && !keepassExecutablePath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) | ||
| throw new ArgumentException("keepassExecutablePath must end with .exe", "keepassExecutablePath"); | ||
|
|
||
| if (!File.Exists(newPluginPath)) return false; | ||
| if (!File.Exists(updaterExePath)) return false; | ||
|
Comment on lines
49
to
50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Insufficient Error Reporting for File Existence Checks The method returns Example improvement: if (!File.Exists(newPluginPath)) return Result.NewPluginMissing;
if (!File.Exists(updaterExePath)) return Result.UpdaterExeMissing; |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argument Value Validation Weakness
The argument parsing logic assumes that every flag is followed by a value, but does not check if the value is another flag (e.g.,
--source --destination ...). This can lead to incorrect assignments and subtle bugs if the user omits a value or provides flags in an unexpected order.Recommendation:
Add a check to ensure that
valuedoes not start with--before assigning it to a variable. For example: