Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent loss of modifier when comparing two similar pointer chains #416

Merged
merged 2 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading