You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Color.FromHex accepts "#+F+F+F" as #0F0F0F and throws FormatException (not ArgumentException) for non-hex characters #313
Semantics.Color/Color.Conversions.csFromHex (L49-L70) checks only the string's length, then parses each channel with ParseByte (L99-L100): Convert.ToByte(hex.Substring(index, 2), 16). Convert.ToByte(string, 16) has two quirks that leak through:
A leading + is accepted, so Color.FromHex("#+F+F+F").ToHex() returns "#0F0F0F" and invalid input is accepted without complaint. The same applies to "+F" inside any 6- or 8-digit string.
A non-hex character throws FormatException, so FromHex("#GGGGGG") and FromHex("#0x0x0x") both throw it. FromHex("#-1-1-1") throws ArgumentException instead. The exception type therefore depends on which bad character appears.
The XML docs for FromHex list only ArgumentNullException and ArgumentException, and CLAUDE.md says to throw ArgumentException for validation failures, not FormatException. A caller that validates user or theme input with catch (ArgumentException) crashes on #GGGGGG and silently accepts #+F+F+F.
All of these were reproduced by compiling Semantics.Color into a scratch console app.
Suggested fix
After length normalisation, check that every character is [0-9A-Fa-f], and throw ArgumentException(..., nameof(hex)) if one is not.
Parse each channel with byte.Parse(span, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture), which rejects signs.
Add tests: #+F+F+F, #GGGGGG, #0x0x0x and #-1-1-1 all throw ArgumentException, and valid 3/6/8-digit inputs in either case still round-trip.
Priority: Medium. Invalid input such as #+F+F+F is accepted silently. The exception type depends on which bad character appears, and it contradicts both the XML docs and the CLAUDE.md rule to throw ArgumentException for validation failures. Callers that validate theme or user input with catch (ArgumentException) crash.
Area / suggested assignment:Semantics.Color (Color.Conversions.FromHex / ParseByte). @matt-edmondson
Notes:byte.Parse(span, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture) plus an explicit character check is a small fix. The listed test cases cover every path.
Activity
matt-edmondson commentedon Sep 28, 2026
Triage
#+F+F+Fis accepted silently. The exception type depends on which bad character appears, and it contradicts both the XML docs and the CLAUDE.md rule to throwArgumentExceptionfor validation failures. Callers that validate theme or user input withcatch (ArgumentException)crash.Semantics.Color(Color.Conversions.FromHex/ParseByte). @matt-edmondson$matches before a trailing newline) #311 (Ibanregex$and a trailing newline): both are validation that accepts malformed input. Worth sweeping otherConvert.To*(…, 16)call sites for the same leak.Notes:
byte.Parse(span, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture)plus an explicit character check is a small fix. The listed test cases cover every path.Generated by Claude Code
[patch] Reject non-hex characters in Color.FromHex with ArgumentExcep…