Skip to content

Commit

Permalink
Fix: jump table limit determination
Browse files Browse the repository at this point in the history
A subtle case where the jump table computation is as follows:
```
lim = idx
if (lim >= N_Cases)
    goto skip
goto jmptable[idx]
```

This resolves #1346.
  • Loading branch information
uxmal committed May 31, 2024
1 parent 5b432eb commit e16d9bd
Show file tree
Hide file tree
Showing 3 changed files with 365 additions and 87 deletions.
48 changes: 44 additions & 4 deletions src/Decompiler/Scanning/BackwardSlicer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -606,9 +606,10 @@ public bool Step()
if (sr.Stop)
{
this.GuardInstrAddress = addr;
var jtFormat = slicer.Simplify(this.JumpTableFormat!);
BackwardSlicer.trace.Verbose(" Was asked to stop, stopping.");
BackwardSlicer.trace.Verbose(" index: {0} ({1})", this.JumpTableIndex!, this.JumpTableIndexInterval);
BackwardSlicer.trace.Verbose(" expr: {0}", this.JumpTableFormat!);
BackwardSlicer.trace.Verbose(" expr: {0}", jtFormat);
BackwardSlicer.trace.Verbose(" addr: {0} (of range check instr)", this.GuardInstrAddress);
return false;
}
Expand Down Expand Up @@ -737,6 +738,29 @@ public SlicerResult VisitArrayAccess(ArrayAccess acc, BackwardSlicerContext ctx)
// Ignore writes to memory.
return null;
}
// Check if we're assigning the condition variable with the index variable.
if (Live.TryGetValue(id, out var dstCtx) &&
Live.TryGetValue(ass.Src, out var srcCtx))
{
if (dstCtx.Type == ContextType.Condition && srcCtx.Type == ContextType.Jumptable)
{
this.JumpTableIndex = ass.Src;
return new SlicerResult
{
LiveExprs = Live,
Stop = true,
};
}
if (dstCtx.Type == ContextType.Jumptable && srcCtx.Type == ContextType.Condition)
{
this.JumpTableIndex = id;
return new SlicerResult
{
LiveExprs = Live,
Stop = true,
};
}
}
this.assignLhs = ass.Dst;
// var killedRegs = Live.Where(de => de.Key is Identifier i && id.Storage.Covers(i.Storage)).ToList();
var killedRegs = Live.Where(de => de.Key is Identifier i && i.Storage.Domain == id.Storage.Domain).ToList();
Expand Down Expand Up @@ -952,10 +976,12 @@ private SlicerResult FoundBoundaryCheck(BinaryExpression binExp, bool commute, E
this.JumpTableIndexToUse = eIndex;
this.JumpTableIndexInterval = interval;
BackwardSlicer.trace.Verbose(" Found range of {0}: {1}", liveKey, JumpTableIndexInterval);
bool stop = Live.ContainsKey(liveKey);
return new SlicerResult
{
SrcExpr = binExp,
Stop = true
LiveExprs = new() { { liveKey, BackwardSlicerContext.Cond(RangeOf(liveKey)) } },
Stop = stop
};
}

Expand Down Expand Up @@ -1109,7 +1135,7 @@ public SlicerResult VisitMemoryAccess(MemoryAccess access, BackwardSlicerContext
public SlicerResult VisitMkSequence(MkSequence seq, BackwardSlicerContext ctx)
{
var srExprs = seq.Expressions
.Select(e => e.Accept(this, ctx))
.Select(e => e.Accept(this, ctx)!)
.ToArray();
var srLast = srExprs[^1]!;
if (RangeOf(srLast.SrcExpr!) == ctx.BitRange)
Expand All @@ -1123,15 +1149,29 @@ public SlicerResult VisitMkSequence(MkSequence seq, BackwardSlicerContext ctx)
}
else
{
var liveExprs = FuseLiveExpr(srExprs);
return new SlicerResult
{
LiveExprs = srExprs[1]!.LiveExprs,
LiveExprs = liveExprs,
SrcExpr = new MkSequence(seq.DataType, srExprs.Select(s => s!.SrcExpr).ToArray()!),
Stop = srExprs.Any(s => s!.Stop)
};
}
}

private Dictionary<Expression, BackwardSlicerContext> FuseLiveExpr(SlicerResult[] srExprs)
{
var result = new Dictionary<Expression, BackwardSlicerContext>();
foreach (var sr in srExprs)
{
foreach (var (k, v) in sr.LiveExprs)
{
result[k] = v;
}
}
return result;
}

public SlicerResult? VisitNop(RtlNop rtlNop)
{
return null;
Expand Down
Loading

0 comments on commit e16d9bd

Please sign in to comment.