mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-08-29 10:09:43 +02:00
[CmdPal] Harden JS numeric color/int parsing against out-of-range input
ReadByte/ReadInt guarded only on ValueKind == Number, then called JsonElement.GetByte()/GetInt32(), which throw FormatException for out-of-range or fractional values coming from untrusted extension JSON. A single bad tag color would escape the WinRT-visible Tags getter and degrade the entire list item to Error, losing title, subtitle, icon and every valid tag. Switch to TryGetByte/TryGetInt32 with the existing defaults so malformed components fall back instead of throwing. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d243b1e9-40fb-4aed-aa60-beb5e80f7d91
This commit is contained in:
committed by
Michael Jolley
parent
d04f2ae54d
commit
72807b5916
@@ -634,9 +634,10 @@ internal static class JSModelMapper
|
||||
|
||||
private static byte ReadByte(JsonElement element, string camel, string pascal, byte defaultValue = 0)
|
||||
{
|
||||
if (TryGetAnyCase(element, camel, pascal, out var prop) && prop.ValueKind == JsonValueKind.Number)
|
||||
if (TryGetAnyCase(element, camel, pascal, out var prop) && prop.ValueKind == JsonValueKind.Number &&
|
||||
prop.TryGetByte(out var value))
|
||||
{
|
||||
return prop.GetByte();
|
||||
return value;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
@@ -645,9 +646,10 @@ internal static class JSModelMapper
|
||||
private static int ReadInt(JsonElement element, string name, int defaultValue)
|
||||
{
|
||||
if (element.ValueKind == JsonValueKind.Object &&
|
||||
element.TryGetProperty(name, out var prop) && prop.ValueKind == JsonValueKind.Number)
|
||||
element.TryGetProperty(name, out var prop) && prop.ValueKind == JsonValueKind.Number &&
|
||||
prop.TryGetInt32(out var value))
|
||||
{
|
||||
return prop.GetInt32();
|
||||
return value;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
|
||||
@@ -391,6 +391,53 @@ public partial class JSAdapterRemediationTests
|
||||
Assert.IsFalse(withoutAccent.AccentColor.HasValue);
|
||||
}
|
||||
|
||||
// p3-12: a tag whose color components are out of byte range or fractional must
|
||||
// not throw out of the WinRT-visible Tags getter. Every numeric component that
|
||||
// does not fit is dropped to its default, and the surrounding item metadata
|
||||
// (title, subtitle, other tags) is preserved rather than collapsing to Error.
|
||||
[TestMethod]
|
||||
public void Tags_OutOfRangeOrFractionalColorComponentsDefaultInsteadOfThrowing()
|
||||
{
|
||||
using var fake = new JSFakeExtension();
|
||||
var element = ParseElement(new JsonObject
|
||||
{
|
||||
["title"] = "Item With Bad Tag Color",
|
||||
["subtitle"] = "Still Here",
|
||||
["tags"] = new JsonArray
|
||||
{
|
||||
new JsonObject
|
||||
{
|
||||
["text"] = "over",
|
||||
["foreground"] = new JsonObject
|
||||
{
|
||||
// 256 overflows a byte and 1.5 is fractional; both would throw
|
||||
// from JsonElement.GetByte, so they must fall back to defaults.
|
||||
["r"] = 256,
|
||||
["g"] = 1.5,
|
||||
["b"] = 12,
|
||||
},
|
||||
},
|
||||
new JsonObject { ["text"] = "clean" },
|
||||
},
|
||||
});
|
||||
|
||||
var adapter = new JSListItemAdapter(element, fake.Connection);
|
||||
|
||||
var tags = adapter.Tags;
|
||||
Assert.AreEqual(2, tags.Length);
|
||||
Assert.AreEqual("over", tags[0].Text);
|
||||
Assert.AreEqual("clean", tags[1].Text);
|
||||
|
||||
var foreground = tags[0].Foreground;
|
||||
Assert.IsTrue(foreground.HasValue);
|
||||
Assert.AreEqual(0, foreground.Color.R);
|
||||
Assert.AreEqual(0, foreground.Color.G);
|
||||
Assert.AreEqual(12, foreground.Color.B);
|
||||
|
||||
Assert.AreEqual("Item With Bad Tag Color", adapter.Title);
|
||||
Assert.AreEqual("Still Here", adapter.Subtitle);
|
||||
}
|
||||
|
||||
private static async Task<string> SubmitAndReadFormId(JSFormContentProxy form, TaskCompletionSource<string> captured)
|
||||
{
|
||||
await Task.Run(() => form.SubmitForm("{}", "{}"));
|
||||
|
||||
Reference in New Issue
Block a user