Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ internal static bool TryExtractBaggage(string? baggageString, out IEnumerable<Ke
// key = ( lcalpha / DIGIT ) 0*255 ( keychar )
// keychar = lcalpha / DIGIT / "_" / "-"/ "*" / "/" / "@"
// lcalpha = %x61-7A ; a-z
// DIGIT = %x30-39 ; 0-9
//
// value = 0*255(chr) nblk-chr
// nblk-chr = %x21-2B / %x2D-3C / %x3E-7E
Expand Down Expand Up @@ -421,26 +422,28 @@ private static bool IsInvalidBaggageKey(ReadOnlySpan<char> span)
}
#endif

// https://www.w3.org/TR/trace-context-2/#key
// key = ( lcalpha / DIGIT ) 0*255 ( keychar )
// keychar = lcalpha / DIGIT / "_" / "-"/ "*" / "/" / "@"
// lcalpha = %x61-7A ; a-z
// DIGIT = %x30-39 ; 0-9

#if NET
private const string TraceStateKeyValidChars = "*-/@_abcdefghijklmnopqrstuvwxyz";
private const string TraceStateKeyValidChars = "*-/0123456789@_abcdefghijklmnopqrstuvwxyz";
private static readonly SearchValues<char> s_validTraceStateChars = SearchValues.Create(TraceStateKeyValidChars);

private static bool IsInvalidTraceStateKey(ReadOnlySpan<char> key) => key.IsEmpty || (key[0] < 'a' || key[0] > 'z') || key.ContainsAnyExcept(s_validTraceStateChars);
private static bool IsInvalidTraceStateKey(ReadOnlySpan<char> key) => key.IsEmpty || ((uint)('z' - key[0]) > (uint)('z' - 'a') && (uint)('9' - key[0]) > (uint)('9' - '0')) || key.ContainsAnyExcept(s_validTraceStateChars);

private const string TraceStateValueValidChars = "!\"#$%&'()*+-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
private static readonly SearchValues<char> s_validTraceStateValueChars = SearchValues.Create(TraceStateValueValidChars);

private static bool IsInvalidTraceStateValue(ReadOnlySpan<char> value) => value.IsEmpty || value.ContainsAnyExcept(s_validTraceStateValueChars);
#else
private static ulong[] ValidTraceStateKeyCharsMask = [0x0000A40000000000, 0x07FFFFFE80000001];
private static ulong[] ValidTraceStateKeyCharsMask = [0x03FFA40000000000, 0x07FFFFFE80000001];

private static bool IsInvalidTraceStateKey(ReadOnlySpan<char> key)
{
if (key.IsEmpty || (key[0] < 'a' || key[0] > 'z')) // Key has to start with a lowercase letter
if (key.IsEmpty || ((uint)('z' - key[0]) > (uint)('z' - 'a') && (uint)('9' - key[0]) > (uint)('9' - '0'))) // Key has to start with a lowercase letter or digit
{
return true; // invalid key character, skip current entry
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@ public static IEnumerable<object[]> W3CTestData()
yield return new object[] { "state=1", "state=1", new[] { new KeyValuePair<string, string>("b1", "v1") }, "b1 = v1", new[] { new KeyValuePair<string, string>("b1", "v1") } };

// Invalid trace state
yield return new object[] { "PassThroughW3CState=1", null, null, null, null }; // trace state key has to be lowercase
yield return new object[] { "PassThroughW3CState=1", null, null, null, null }; // trace state key has to be lowercase or digit

// Invalid trace state
yield return new object[] { "1start=1", null, null, null, null }; // trace state key has to start with lowercase
// valid trace state, the key can have digits https://www.w3.org/TR/trace-context-2/#key
yield return new object[] { "1start=1", "1start=1", null, null, null }; // trace state key has to start with lowercase or digit

// valid trace state, the key can have digits https://www.w3.org/TR/trace-context-2/#key
yield return new object[] { "123@456=1", "123@456=1", null, null, null }; // trace state key has to start with lowercase or digit

// Tabs is not allowed in trace state values. use only the valid entry
yield return new object[] { "start=1, end=\t1", "start=1", null, null, null }; // trace state key has to start with lowercase
yield return new object[] { "start=1, end=\t1", "start=1", null, null, null }; // trace state key has to start with lowercase or digit

// multiple trace states
yield return new object[] { "start=1, end=1", "start=1, end=1", null, null, null }; // trace state key has to start with lowercase
yield return new object[] { "start=1, end=1", "start=1, end=1", null, null, null }; // trace state key has to start with lowercase or digit

// trace state longer than the max limit
yield return new object[] { $"{new string('a', 255)}=1", null, null, null, null }; // trace state length max is 256
Expand Down
Loading