[Fuzz] Add Fuzz testing for RegistryPreview (#37607)

* Add fuzz test cases

* add fuzz tests framework in registrypreview

* add registrypreview fuzzing code

* add annotations and change net7.0--net8.0

* merge main into code

* add registry fuzz sln

* change fuzzing tests scope

* remove unuse annotations

* fix typos

* change public parser to internel and private

* fix linelower error and modify filenametext to registryContent

* Revert "fix linelower error and modify filenametext to registryContent"

This reverts commit e8269b8af2.

* add fuzz tests in sln

* modify typos

* clean code

Co-authored-by: leileizhang <leilzh@microsoft.com>

* add annotations

---------

Co-authored-by: leileizhang <leilzh@microsoft.com>
This commit is contained in:
chenmy77
2025-03-13 10:23:02 +08:00
committed by GitHub
parent 2b7307d32e
commit a00f56e317
7 changed files with 465 additions and 62 deletions

View File

@@ -0,0 +1,124 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RegistryPreviewUILib
{
internal static class ParseHelper
{
private const string ERRORIMAGE = "ms-appx:///Assets/RegistryPreview/error32.png";
/// <summary>
/// Checks a Key line for the closing bracket and treat it as an error if it cannot be found
/// </summary>
internal static void CheckKeyLineForBrackets(ref string registryLine, ref string imageName)
{
// following the current behavior of the registry editor, find the last ] and treat everything else as ignorable
int lastBracket = registryLine.LastIndexOf(']');
if (lastBracket == -1)
{
// since we don't have a last bracket yet, add an extra space and continue processing
registryLine += " ";
imageName = ERRORIMAGE;
}
else
{
// having found the last ] and there is text after it, drop the rest of the string on the floor
if (lastBracket < registryLine.Length - 1)
{
registryLine = registryLine.Substring(0, lastBracket + 1);
}
if (CheckForKnownGoodBranches(registryLine) == false)
{
imageName = ERRORIMAGE;
}
}
}
/// <summary>
/// Make sure the root of a full path start with one of the five "hard coded" roots. Throw an error for the branch if it doesn't.
/// </summary>
private static bool CheckForKnownGoodBranches(string key)
{
if ((key.StartsWith("[HKEY_CLASSES_ROOT]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_CURRENT_USER]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_USERS]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_LOCAL_MACHINE]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_CURRENT_CONFIG]", StringComparison.InvariantCultureIgnoreCase) == false)
&&
(key.StartsWith(@"[HKEY_CLASSES_ROOT\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_CURRENT_USER\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_USERS\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_LOCAL_MACHINE\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_CURRENT_CONFIG\", StringComparison.InvariantCultureIgnoreCase) == false)
&&
(key.StartsWith("[HKCR]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKCU]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKU]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKLM]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKCC]", StringComparison.InvariantCultureIgnoreCase) == false)
&&
(key.StartsWith(@"[HKCR\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKCU\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKU\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKLM\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKCC\", StringComparison.InvariantCultureIgnoreCase) == false))
{
return false;
}
return true;
}
/// <summary>
/// Rip the first and last character off a string,
/// checking that the string is at least 2 characters long to avoid errors
/// </summary>
internal static string StripFirstAndLast(string line)
{
if (line.Length > 1)
{
line = line.Remove(line.Length - 1, 1);
line = line.Remove(0, 1);
}
return line;
}
/// <summary>
/// Replace any escaped characters in the REG file with their counterparts, for the UX
/// </summary>
internal static string StripEscapedCharacters(string value)
{
value = value.Replace("\\\\", "\\"); // Replace \\ with \ in the UI
value = value.Replace("\\\"", "\""); // Replace \" with " in the UI
return value;
}
// special case for when the registryLine begins with a @ - make some tweaks and
// let the regular processing handle the rest.
internal static string ProcessRegistryLine(string registryLine)
{
if (registryLine.StartsWith("@=-", StringComparison.InvariantCulture))
{
// REG file has a callout to delete the @ Value which won't work *but* the Registry Editor will
// clear the value of the @ Value instead, so it's still a valid line.
registryLine = registryLine.Replace("@=-", "\"(Default)\"=\"\"");
}
else if (registryLine.StartsWith("@=", StringComparison.InvariantCulture))
{
// This is the Value called "(Default)" so we tweak the line for the UX
registryLine = registryLine.Replace("@=", "\"(Default)\"=");
}
return registryLine;
}
}
}

View File

@@ -967,12 +967,7 @@ namespace RegistryPreviewUILib
/// </summary>
private string StripFirstAndLast(string line)
{
if (line.Length > 1)
{
line = line.Remove(line.Length - 1, 1);
line = line.Remove(0, 1);
}
line = ParseHelper.StripFirstAndLast(line);
return line;
}
@@ -1040,27 +1035,7 @@ namespace RegistryPreviewUILib
/// </summary>
private void CheckKeyLineForBrackets(ref string registryLine, ref string imageName)
{
// following the current behavior of the registry editor, find the last ] and treat everything else as ignorable
int lastBracket = registryLine.LastIndexOf(']');
if (lastBracket == -1)
{
// since we don't have a last bracket yet, add an extra space and continue processing
registryLine += " ";
imageName = ERRORIMAGE;
}
else
{
// having found the last ] and there is text after it, drop the rest of the string on the floor
if (lastBracket < registryLine.Length - 1)
{
registryLine = registryLine.Substring(0, lastBracket + 1);
}
if (CheckForKnownGoodBranches(registryLine) == false)
{
imageName = ERRORIMAGE;
}
}
ParseHelper.CheckKeyLineForBrackets(ref registryLine, ref imageName);
}
/// <summary>
@@ -1079,41 +1054,6 @@ namespace RegistryPreviewUILib
return value.TrimEnd();
}
/// <summary>
/// Make sure the root of a full path start with one of the five "hard coded" roots. Throw an error for the branch if it doesn't.
/// </summary>
private bool CheckForKnownGoodBranches(string key)
{
if ((key.StartsWith("[HKEY_CLASSES_ROOT]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_CURRENT_USER]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_USERS]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_LOCAL_MACHINE]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKEY_CURRENT_CONFIG]", StringComparison.InvariantCultureIgnoreCase) == false)
&&
(key.StartsWith(@"[HKEY_CLASSES_ROOT\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_CURRENT_USER\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_USERS\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_LOCAL_MACHINE\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKEY_CURRENT_CONFIG\", StringComparison.InvariantCultureIgnoreCase) == false)
&&
(key.StartsWith("[HKCR]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKCU]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKU]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKLM]", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith("[HKCC]", StringComparison.InvariantCultureIgnoreCase) == false)
&&
(key.StartsWith(@"[HKCR\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKCU\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKU\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKLM\", StringComparison.InvariantCultureIgnoreCase) == false &&
key.StartsWith(@"[HKCC\", StringComparison.InvariantCultureIgnoreCase) == false))
{
return false;
}
return true;
}
/// <summary>
/// Turns the Open Key button in the command bar on/off, depending on if a key is selected
/// </summary>