Skip to content

Commit

Permalink
prevent loss of modifier when comparing two similar pointer chains (#416
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Jamiras authored Oct 7, 2023
1 parent 5140617 commit e0a81c0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,13 @@ public bool PointerChainMatches(MemoryAccessorExpressionBase that)

var memoryValue = that as MemoryValueExpression;
if (memoryValue != null)
return PointerChainMatches(memoryValue.MemoryAccessors.Last().MemoryAccessor);
{
var memoryAcessorExpression = memoryValue.MemoryAccessors.Last();
if (memoryAcessorExpression.ModifyingOperator != RequirementOperator.None)
return false;

return PointerChainMatches(memoryAcessorExpression.MemoryAccessor);
}

return (_pointerChain == null || _pointerChain.Count == 0);
}
Expand Down
72 changes: 54 additions & 18 deletions Source/Parser/Expressions/Trigger/RequirementConditionExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,68 @@ protected override bool Equals(ExpressionBase obj)
public override ErrorExpression BuildTrigger(TriggerBuilderContext context)
{
ErrorExpression error;
var comparison = Comparison;
var left = Left;
var right = MemoryAccessorExpressionBase.ReduceToSimpleExpression(Right);

var memoryValue = Left as MemoryValueExpression;
var rightAccessor = right as MemoryAccessorExpression;
if (rightAccessor != null && rightAccessor.HasPointerChain)
{
if (rightAccessor.PointerChainMatches(left as MemoryAccessorExpressionBase))
{
rightAccessor = rightAccessor.Clone();
rightAccessor.ClearPointerChain();
}
else
{
var leftMemoryValue = left as MemoryValueExpression;
if (leftMemoryValue != null && leftMemoryValue.MemoryAccessors.All(m => m.ModifyingOperator != RequirementOperator.None))
{
// all elements on left side are modified, so we'd need a 0 placeholder for the comparison
// attempt to avoid that by making the right value the AddSource element.
//
// A / 2 > B -> - A / 2 + B < 0
//
// move the left side to the right side and invert
var newLeft = new MemoryValueExpression();
newLeft = newLeft.Combine(right, MathematicOperation.Add) as MemoryValueExpression;
left = newLeft.Combine(left, MathematicOperation.Subtract);
comparison = ComparisonExpression.ReverseComparisonOperation(comparison);
}
else
{
// move the right side to the left side and compare to zero.
//
// A > B / 2 -> - B / 2 + A > 0
//
var newLeft = new MemoryValueExpression();
newLeft = newLeft.Combine(left, MathematicOperation.Add) as MemoryValueExpression;
left = newLeft.Combine(right, MathematicOperation.Subtract);
}

if (comparison == ComparisonOperation.LessThan || comparison == ComparisonOperation.LessThanOrEqual)
{
// can't comare "<0" or "<=0". invert comparison
var newLeft = new MemoryValueExpression();
left = ((MemoryValueExpression)left).InvertAndMigrateAccessorsTo(newLeft);
comparison = ComparisonExpression.ReverseComparisonOperation(comparison);
}

right = new IntegerConstantExpression(0);
rightAccessor = null;
}
}

var memoryValue = left as MemoryValueExpression;
if (memoryValue != null)
{
error = memoryValue.BuildTrigger(context, right);
}
else
{
var trigger = Left as ITriggerExpression;
var trigger = left as ITriggerExpression;
if (trigger == null)
return new ErrorExpression(string.Format("Cannot compare {0} in a trigger", Left.Type), Left);
return new ErrorExpression(string.Format("Cannot compare {0} in a trigger", left.Type), left);

error = trigger.BuildTrigger(context);
}
Expand All @@ -94,29 +144,15 @@ public override ErrorExpression BuildTrigger(TriggerBuilderContext context)

var lastRequirement = context.LastRequirement;

var rightAccessor = right as MemoryAccessorExpression;
if (rightAccessor != null)
{
if (rightAccessor.HasPointerChain)
{
if (!rightAccessor.PointerChainMatches(Left as MemoryAccessorExpressionBase))
return new ErrorExpression("Cannot compare values with different pointer chains", this);

rightAccessor = rightAccessor.Clone();
rightAccessor.ClearPointerChain();
}

lastRequirement.Right = FieldFactory.CreateField(rightAccessor);
}
else
{
lastRequirement.Right = FieldFactory.CreateField(right);
}

if (lastRequirement.Right.Type == FieldType.None)
return new ErrorExpression(string.Format("Cannot compare {0} in a trigger", Right.Type), Right);

lastRequirement.Operator = ConvertToRequirementOperator(Comparison);
lastRequirement.Operator = ConvertToRequirementOperator(comparison);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public void TestAppendString(string input)
[TestCase("byte(0x1234) - byte(0x2345) == 4294967295", "B:0xH002345=0_0xH001234=4294967295")] // don't invert very high positive value
[TestCase("byte(0x1234) - byte(0x2345) <= -1", "A:1=0_0xH001234<=0xH002345")]
[TestCase("dword(0x1234) - prev(dword(0x1234)) >= 0x1000", "A:4096=0_d0xX001234<=0xX001234")]
[TestCase("word(dword(0x7f6f10) + 0xB00) > word(dword(0x7f6f10) + 0xB02)", "I:0xX7f6f10_0x 000b00>0x 000b02")]
[TestCase("word(dword(0x7f6f10) + 0xB00) > word(dword(0x7f6f10) + 0xB02) / 2", "I:0xX7f6f10_B:0x 000b02/2_I:0xX7f6f10_0x 000b00>0")] // cannot share addaddress if one value is modified
[TestCase("word(dword(0x7f6f10) + 0xB00) / 2 > word(dword(0x7f6f10) + 0xB02)", "I:0xX7f6f10_B:0x 000b02_I:0xX7f6f10_A:0x 000b00/2_0>0")] // cannot share addaddress if one value is modified
public void TestBuildTrigger(string input, string expected)
{
var clause = TriggerExpressionTests.Parse<RequirementConditionExpression>(input);
Expand Down

0 comments on commit e0a81c0

Please sign in to comment.