[Dynamic instrumentation] DEBUG-3321 Fix malformed local var sig parsing in PDB reader#8532
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2bbdd9790
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (TryReadLocalVariablesCount(ref blobReader, out var variableCount)) | ||
| { | ||
| return variableCount; |
There was a problem hiding this comment.
Validate the full local signature before returning a count
When a malformed LocalVarSig still has a valid count byte (for example, 07 01 but no following type entry), this branch returns a positive count. GetLocalSymbols then continues to signature.Value.DecodeLocalSignature(...) outside this protected block and still throws BadImageFormatException, so the PDB metadata path remains non-best-effort for truncated signatures past the count. Consider validating/decoding the full local signature under the guarded path before trusting the count.
Useful? React with 👍 / 👎.
BenchmarksBenchmark execution time: 2026-04-29 14:28:17 Comparing candidate commit 9c34a41 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 27 metrics, 0 unstable metrics, 63 known flaky benchmarks, 24 flaky benchmarks without significant changes.
|
607c657 to
2855f6c
Compare
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8532) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:
Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard. Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph). Duration chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (73ms) : 70, 76
master - mean (76ms) : 72, 79
section Bailout
This PR (8532) - mean (77ms) : 74, 79
master - mean (79ms) : 75, 82
section CallTarget+Inlining+NGEN
This PR (8532) - mean (1,074ms) : 1019, 1128
master - mean (1,081ms) : 1024, 1138
FakeDbCommand (.NET Core 3.1)gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (115ms) : 110, 121
master - mean (118ms) : 112, 125
section Bailout
This PR (8532) - mean (115ms) : 112, 118
master - mean (115ms) : 112, 118
section CallTarget+Inlining+NGEN
This PR (8532) - mean (777ms) : 754, 800
master - mean (780ms) : 755, 805
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (105ms) : 99, 110
master - mean (104ms) : 98, 111
section Bailout
This PR (8532) - mean (102ms) : 99, 105
master - mean (103ms) : 98, 108
section CallTarget+Inlining+NGEN
This PR (8532) - mean (941ms) : 912, 970
master - mean (939ms) : 900, 977
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (101ms) : 97, 104
master - mean (101ms) : 96, 105
section Bailout
This PR (8532) - mean (105ms) : 100, 111
master - mean (105ms) : 99, 110
section CallTarget+Inlining+NGEN
This PR (8532) - mean (825ms) : 785, 865
master - mean (824ms) : 783, 864
HttpMessageHandler (.NET Framework 4.8)gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (204ms) : 195, 213
master - mean (204ms) : 194, 214
section Bailout
This PR (8532) - mean (207ms) : 199, 216
master - mean (207ms) : 199, 215
section CallTarget+Inlining+NGEN
This PR (8532) - mean (1,203ms) : 1154, 1252
master - mean (1,208ms) : 1156, 1259
HttpMessageHandler (.NET Core 3.1)gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (295ms) : 278, 311
master - mean (293ms) : 280, 306
section Bailout
This PR (8532) - mean (296ms) : 278, 314
master - mean (294ms) : 283, 305
section CallTarget+Inlining+NGEN
This PR (8532) - mean (967ms) : 930, 1003
master - mean (966ms) : 929, 1002
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (288ms) : 273, 302
master - mean (286ms) : 272, 299
section Bailout
This PR (8532) - mean (290ms) : 271, 310
master - mean (286ms) : 273, 299
section CallTarget+Inlining+NGEN
This PR (8532) - mean (1,167ms) : 1125, 1208
master - mean (1,158ms) : 1114, 1202
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8532) - mean (286ms) : 273, 300
master - mean (283ms) : 273, 292
section Bailout
This PR (8532) - mean (287ms) : 275, 299
master - mean (281ms) : 273, 289
section CallTarget+Inlining+NGEN
This PR (8532) - mean (1,046ms) : 995, 1096
master - mean (1,040ms) : 991, 1089
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2855f6c to
9c34a41
Compare
Summary of changes
Harden
DatadogMetadataReaderso malformed or truncated local variable signatures are treated as best-effort misses instead of throwing.Add focused regression tests for both valid and truncated local signatures in DatadogMetadataReaderTests.
Reason for change
Some customer assemblies appear to contain malformed local variable signature metadata.
In the debugger metadata path, that could surface as Failed to obtain local variable names from PDB with
BadImageFormatException, even though local names are best-effort metadata.Implementation details
The local signature parser now validates the blob shape before reading the compressed local count.
Invalid or truncated signatures now fall back to 0 locals instead of propagating an exception through the debugger local-name lookup flow.
Test coverage
Added unit coverage for:
a valid local variable signature
a truncated local variable signature
in
DatadogMetadataReaderTests