Skip to content

Commit c25c6b1

Browse files
author
Max Charlamb
committed
allow dec/hex strings. If string doesn't parse as a int, treat as string
1 parent 878c8c2 commit c25c6b1

File tree

3 files changed

+71
-9
lines changed

3 files changed

+71
-9
lines changed

src/coreclr/tools/cdac-build-tool/JsonConverter/GlobalValueJsonConverter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ public override void Write(Utf8JsonWriter writer, DataDescriptorModel.GlobalValu
1818
switch (value.Kind)
1919
{
2020
case DataDescriptorModel.GlobalValue.KindEnum.Direct:
21-
// no type: just write value as a JSON number.
22-
writer.WriteNumberValue(value.NumericValue);
21+
// no type: just write value as a number.
22+
// we always write as a string containing a hex number
23+
writer.WriteStringValue($"0x{value.NumericValue:x}");
2324
break;
2425
case DataDescriptorModel.GlobalValue.KindEnum.Indirect:
2526
// pointer data index. write as a 1-element array containing a decimal number

src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,14 @@ internal sealed class FieldDescriptorConverter : JsonConverter<FieldDescriptor>
171171
// 2. [number, string] - offset is given as the number, type name is given as the string
172172
public override FieldDescriptor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
173173
{
174-
if (TryGetInt32FromTokenFlexible(ref reader, out int offset))
174+
if (TryGetInt32FromToken(ref reader, out int offset))
175175
return new FieldDescriptor { Offset = offset };
176176
if (reader.TokenType != JsonTokenType.StartArray)
177177
throw new JsonException();
178178
reader.Read();
179179
// [number, string]
180180
// ^ we're here
181-
if (!TryGetInt32FromTokenFlexible(ref reader, out offset))
181+
if (!TryGetInt32FromToken(ref reader, out offset))
182182
throw new JsonException();
183183
reader.Read(); // string
184184
if (reader.TokenType != JsonTokenType.String)
@@ -303,7 +303,7 @@ private static bool TryGetStringFromToken(ref Utf8JsonReader reader, out string
303303
return false;
304304
}
305305

306-
// Somewhat flexible parsing of numbers, allowing signed or unsigned json number tokens.
306+
// Somewhat flexible parsing of numbers, allowing json number tokens or strings as decimal or hex, possibly negated.
307307
private static bool TryGetUInt64FromToken(ref Utf8JsonReader reader, out ulong value)
308308
{
309309
if (reader.TokenType == JsonTokenType.Number)
@@ -316,12 +316,39 @@ private static bool TryGetUInt64FromToken(ref Utf8JsonReader reader, out ulong v
316316
return true;
317317
}
318318
}
319+
if (reader.TokenType == JsonTokenType.String)
320+
{
321+
var s = reader.GetString();
322+
if (s == null)
323+
{
324+
value = 0u;
325+
return false;
326+
}
327+
if (ulong.TryParse(s, out value))
328+
return true;
329+
if (long.TryParse(s, out long signedValue))
330+
{
331+
value = (ulong)signedValue;
332+
return true;
333+
}
334+
if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase) &&
335+
ulong.TryParse(s.AsSpan(2), System.Globalization.NumberStyles.HexNumber, null, out value))
336+
{
337+
return true;
338+
}
339+
if (s.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) &&
340+
ulong.TryParse(s.AsSpan(3), System.Globalization.NumberStyles.HexNumber, null, out ulong negValue))
341+
{
342+
value = ~negValue + 1; // two's complement
343+
return true;
344+
}
345+
}
319346
value = 0;
320347
return false;
321348
}
322349

323-
// Somewhat flexible parsing of numbers, allowing json number tokens or strings as decimal or hex, possibly negatated.
324-
private static bool TryGetInt32FromTokenFlexible(ref Utf8JsonReader reader, out int value)
350+
// Somewhat flexible parsing of numbers, allowing json number tokens or strings as decimal or hex, possibly negated.
351+
private static bool TryGetInt32FromToken(ref Utf8JsonReader reader, out int value)
325352
{
326353
if (reader.TokenType == JsonTokenType.Number)
327354
{

src/native/managed/cdacreader/tests/ContractDescriptor/ParserTests.cs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,20 @@ public void ParsesGlobals()
128128
"globalPtr": [2],
129129
"globalTypedInt": [3, "uint8"],
130130
"globalTypedPtr": [[4], "uintptr"],
131+
"globalHex": "0x1234",
131132
"globalNegative": -2,
132133
"globalTypedNegative": [-5, "int32"],
133134
"globalString": "Hello",
134135
"globalTypedString": ["World", "string"],
135136
"globalIntLarge": 18446744073709551615,
136-
"globalIntLargeNegative": -9223372036854775808
137+
"globalIntLargeNegative": -9223372036854775808,
138+
"globalStringyInt": "17",
139+
"globalStringyNegative": "-2",
140+
"globalNegativeHex": "-0xff",
141+
"globalBigStringyInt": "0x123456789abcdef",
142+
"globalStringyPtr": ["0x1234"],
143+
"globalTypedStringyInt": ["0x1234", "int"],
144+
"globalTypedStringyPtr": [["0x1234"], "int"]
137145
}
138146
}
139147
"""u8;
@@ -143,7 +151,7 @@ public void ParsesGlobals()
143151
Assert.Empty(descriptor.Contracts);
144152
Assert.Empty(descriptor.Types);
145153

146-
Assert.Equal(10, descriptor.Globals.Count);
154+
Assert.Equal(18, descriptor.Globals.Count);
147155

148156
Assert.Equal((ulong)1, descriptor.Globals["globalInt"].NumericValue);
149157
AssertDirect(descriptor.Globals["globalInt"]);
@@ -159,6 +167,9 @@ public void ParsesGlobals()
159167
AssertIndirect(descriptor.Globals["globalTypedPtr"]);
160168
Assert.Equal("uintptr", descriptor.Globals["globalTypedPtr"].Type);
161169

170+
Assert.Equal((ulong)0x1234, descriptor.Globals["globalHex"].NumericValue);
171+
AssertDirect(descriptor.Globals["globalHex"]);
172+
162173
Assert.Equal(unchecked((ulong)-2), descriptor.Globals["globalNegative"].NumericValue);
163174
AssertDirect(descriptor.Globals["globalNegative"]);
164175

@@ -179,6 +190,29 @@ public void ParsesGlobals()
179190
Assert.Equal(unchecked((ulong)long.MinValue), descriptor.Globals["globalIntLargeNegative"].NumericValue);
180191
AssertDirect(descriptor.Globals["globalIntLargeNegative"]);
181192

193+
Assert.Equal((ulong)17, descriptor.Globals["globalStringyInt"].NumericValue);
194+
AssertDirect(descriptor.Globals["globalStringyInt"]);
195+
196+
Assert.Equal(unchecked((ulong)-2), descriptor.Globals["globalStringyNegative"].NumericValue);
197+
AssertDirect(descriptor.Globals["globalStringyNegative"]);
198+
199+
Assert.Equal(unchecked((ulong)-0xff), descriptor.Globals["globalNegativeHex"].NumericValue);
200+
AssertDirect(descriptor.Globals["globalNegativeHex"]);
201+
202+
Assert.Equal((ulong)0x123456789abcdef, descriptor.Globals["globalBigStringyInt"].NumericValue);
203+
AssertDirect(descriptor.Globals["globalBigStringyInt"]);
204+
205+
Assert.Equal((ulong)0x1234, descriptor.Globals["globalStringyPtr"].NumericValue);
206+
AssertIndirect(descriptor.Globals["globalStringyPtr"]);
207+
208+
Assert.Equal((ulong)0x1234, descriptor.Globals["globalTypedStringyInt"].NumericValue);
209+
AssertDirect(descriptor.Globals["globalTypedStringyInt"]);
210+
Assert.Equal("int", descriptor.Globals["globalTypedStringyInt"].Type);
211+
212+
Assert.Equal((ulong)0x1234, descriptor.Globals["globalTypedStringyPtr"].NumericValue);
213+
AssertIndirect(descriptor.Globals["globalTypedStringyPtr"]);
214+
Assert.Equal("int", descriptor.Globals["globalTypedStringyPtr"].Type);
215+
182216
void AssertIndirect(ContractDescriptorParser.GlobalDescriptor descriptor)
183217
=> Assert.Equal(ContractDescriptorParser.GlobalDescriptor.KindEnum.Indirect, descriptor.Kind);
184218

0 commit comments

Comments
 (0)