Files
isphere-ai-bridge/scripts/extract-frmP2PChat-il-risk.ps1
2026-07-11 20:58:26 +08:00

119 lines
4.1 KiB
PowerShell

param(
[string]$IlFile = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPlatformClient.exe.il",
[string]$OutDir = "runs/offline-chat-window"
)
$ErrorActionPreference = "Stop"
$repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")
function Resolve-RepoPath([string]$PathValue) {
if ([System.IO.Path]::IsPathRooted($PathValue)) {
return $PathValue
}
return (Join-Path $repo $PathValue)
}
$ilFull = Resolve-RepoPath $IlFile
$outFull = Resolve-RepoPath $OutDir
if (-not (Test-Path -LiteralPath $ilFull)) {
throw "IL file not found: $ilFull"
}
New-Item -ItemType Directory -Force -Path $outFull | Out-Null
$lines = Get-Content -LiteralPath $ilFull
$endIndex = $null
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match 'end of method frmP2PChat::\.ctor') {
$endIndex = $i
break
}
}
if ($null -eq $endIndex) {
throw "frmP2PChat::.ctor end marker not found"
}
$startIndex = $null
for ($i = $endIndex; $i -ge 0; $i--) {
if ($lines[$i] -match '^\s*\.method\s+public\s+hidebysig\s+specialname\s+rtspecialname') {
$startIndex = $i
break
}
}
if ($null -eq $startIndex) {
throw "frmP2PChat::.ctor method start not found before line $($endIndex + 1)"
}
$ctorIlFile = Join-Path $outFull "frmP2PChat-ctor.il.txt"
$riskCsvFile = Join-Path $outFull "frmP2PChat-ctor-null-risk.csv"
$riskMdFile = Join-Path $outFull "frmP2PChat-ctor-null-risk.md"
$ctorLines = New-Object System.Collections.Generic.List[string]
for ($i = $startIndex; $i -le $endIndex; $i++) {
$ctorLines.Add(("{0}: {1}" -f ($i + 1), $lines[$i]))
}
$ctorLines | Set-Content -LiteralPath $ctorIlFile -Encoding UTF8
$riskRows = New-Object System.Collections.Generic.List[object]
foreach ($entry in $ctorLines) {
if ($entry -notmatch '\b(callvirt|ldfld)\b') {
continue
}
$offset = $null
if ($entry -match '(IL_[0-9a-fA-F]{4})') {
$offset = $matches[1].ToLowerInvariant().Replace("il_", "IL_")
}
$op = if ($entry -match '\b(callvirt|ldfld)\b') { $matches[1] } else { $null }
$target = ($entry -replace '^.*?\b(callvirt|ldfld)\b\s+', '').Trim()
$riskRows.Add([pscustomobject]@{
source_line = [int]($entry -replace '^(\d+):.*$', '$1')
il_offset = $offset
opcode = $op
target = $target
null_risk = if ($op -eq "callvirt") { "receiver_null_possible" } else { "instance_field_owner_null_possible" }
evidence = $entry.Trim()
})
}
$riskRows | Sort-Object source_line | Export-Csv -LiteralPath $riskCsvFile -NoTypeInformation -Encoding UTF8
$topEvidence = $riskRows |
Where-Object {
$_.target -match 'Connection::add_OnConnectError|Connection::add_OnReConnectOk|P2PChat::get_OtherJid|Jid::getBareJid|IMPPManager::get_UserInfo|UCChatSendMessageBox::GetChatRichTextBox|UCChatSendMessageBox::GetReceiptCheckBox|MessageCenter::add_OnTcpMessageArrived|RosterManager::UpdateStrangerStatus|BaseConfig::VisualPhoneEnable'
} |
Select-Object -First 40
$md = New-Object System.Collections.Generic.List[string]
$md.Add("# frmP2PChat constructor IL NullRisk")
$md.Add("")
$md.Add("- Source IL: $ilFull")
$md.Add("- Constructor source lines: $($startIndex + 1)-$($endIndex + 1)")
$md.Add("- Constructor line count: $($ctorLines.Count)")
$md.Add("- callvirt / ldfld risk rows: $($riskRows.Count)")
$md.Add("")
$md.Add("## High-signal risks")
$md.Add("")
$md.Add("| source_line | il_offset | opcode | target |")
$md.Add("|---:|---|---|---|")
foreach ($row in $topEvidence) {
$target = ($row.target -replace '\|', '\\|')
$md.Add("| $($row.source_line) | $($row.il_offset) | $($row.opcode) | $target |")
}
$md.Add("")
$md.Add("## Files")
$md.Add("")
$md.Add("- Full constructor IL: $ctorIlFile")
$md.Add("- Full NullRisk CSV: $riskCsvFile")
$md | Set-Content -LiteralPath $riskMdFile -Encoding UTF8
[pscustomobject]@{
ok = $true
il_file = $ilFull
ctor_line_start = $startIndex + 1
ctor_line_end = $endIndex + 1
ctor_line_count = $ctorLines.Count
risk_count = $riskRows.Count
ctor_il_file = $ctorIlFile
risk_csv_file = $riskCsvFile
risk_md_file = $riskMdFile
} | ConvertTo-Json -Compress