public void Test_FlagTools_Create_OF_Add() { Context ctx = this.CreateContext(); { uint nBits = 8; ulong a = 10; ulong b = 20; BitVecExpr aExpr = ctx.MkBV(a, nBits); BitVecExpr bExpr = ctx.MkBV(b, nBits); BoolExpr resultExpr = ToolsFlags.Create_OF_Add(aExpr, bExpr, nBits, ctx).Simplify() as BoolExpr; Assert.IsTrue(AsmTestTools.Calc_OF_Add(nBits, a, b) ? resultExpr.IsTrue : resultExpr.IsFalse); } }
public void Test_BitTricks_Min_Signed() { Tools tools = this.CreateTools(); tools.StateConfig.Set_All_Reg_Off(); tools.StateConfig.RAX = true; tools.StateConfig.RBX = true; tools.StateConfig.RDX = true; return; // this trick does not seem to be correct?! string line1 = "sub rax, rbx"; // Will not work if overflow here! string line2 = "cqo"; // rdx1 = (rax0 > rbx0) ? -1 : 0 string line3 = "and rdx, rax"; // rdx2 = (rax0 > rbx0) ? 0 : (rax0 - rbx0) string line4 = "add rbx, rdx"; // rbx1 = (rax0 > rbx0) ? (rbx0 + 0) : (rbx0 + rax0 - rbx0) { // forward State state = this.CreateState(tools); Context ctx = state.Ctx; if (true) { ulong rax_value = 0x61a4292198602827; ulong rbx_value = 0x8739140220c24080; StateUpdate updateState = new StateUpdate("!PREVKEY", "!NEXTKEY", state.Tools); updateState.Set(Rn.RAX, rax_value); updateState.Set(Rn.RBX, rbx_value); state.Update_Forward(updateState); if (LogToDisplay) { Console.WriteLine("Initially, we know:\n" + state); } } BitVecExpr rax0 = state.Create(Rn.RAX); BitVecExpr rbx0 = state.Create(Rn.RBX); { state.Solver.Assert(state.Ctx.MkNot(ToolsFlags.Create_OF_Sub(rax0, rbx0, rax0.SortSize, ctx))); // this code only works when there is no overflow in line1 } { // line 1 state = Runner.SimpleStep_Forward(line1, state); // retrieve the overflow after line 1, OF has to be zero for the code to work state.Solver.AssertAndTrack(ctx.MkNot(state.Create(Flags.OF)), ctx.MkBoolConst("OF-ZERO")); Assert.AreEqual(Status.SATISFIABLE, state.Solver.Check()); if (LogToDisplay) { Console.WriteLine("After \"" + line1 + "\", we know:\n" + state); } } { // line 2 state = Runner.SimpleStep_Forward(line2, state); // if (logToDisplay) Console.WriteLine("After \"" + line2 + "\", we know:\n" + state); BoolExpr t2 = ctx.MkEq(state.Create(Rn.RDX), ctx.MkITE(ctx.MkBVSGT(rax0, rbx0), ctx.MkBV(0xFFFF_FFFF_FFFF_FFFF, 64), ctx.MkBV(0, 64))); // Assert.AreEqual(Tv5.ONE, ToolsZ3.GetTv5(t2, state.Solver, state.Ctx)); } { state = Runner.SimpleStep_Forward(line3, state); // if (logToDisplay) Console.WriteLine("After \"" + line3 + "\", we know:\n" + state); // BoolExpr t2 = ctx.MkEq(state.Get(Rn.RDX), ctx.MkITE(ctx.MkBVSGT(rax0, rbx0), ctx.MkBV(0, 64), ctx.MkBVSub(rax0, rbx0))); // Assert.AreEqual(Tv5.ONE, ToolsZ3.GetTv5(t2, state.Solver, state.Ctx)); } { state = Runner.SimpleStep_Forward(line4, state); if (LogToDisplay) { Console.WriteLine("After \"" + line4 + "\", we know:\n" + state); } } // ebx is minimum of ebx and eax BitVecExpr rbx1 = state.Create(Rn.RBX); BoolExpr t = ctx.MkEq(rbx1, ctx.MkITE(ctx.MkBVSGT(rax0, rbx0), rbx0, rax0)); if (false) { state.Solver.Push(); state.Solver.AssertAndTrack(t, ctx.MkBoolConst("MIN_RAX_RBX")); Status s = state.Solver.Check(); if (LogToDisplay) { Console.WriteLine("Status A = " + s + "; expected " + Status.SATISFIABLE); } if (s == Status.UNSATISFIABLE) { if (LogToDisplay) { Console.WriteLine("UnsatCore has " + state.Solver.UnsatCore.Length + " elements"); } foreach (BoolExpr b in state.Solver.UnsatCore) { if (LogToDisplay) { Console.WriteLine("UnsatCore=" + b); } } if (LogToDisplay) { Console.WriteLine(state.Solver); } Assert.Fail(); } state.Solver.Pop(); } if (true) { state.Solver.Push(); state.Solver.Assert(ctx.MkNot(t), ctx.MkBoolConst("NOT_MIN_RAX_RBX")); Status s = state.Solver.Check(); if (LogToDisplay) { Console.WriteLine("Status B = " + s + "; expected " + Status.UNSATISFIABLE); } if (s == Status.SATISFIABLE) { if (LogToDisplay) { Console.WriteLine("Model=" + state.Solver.Model); } Assert.Fail(); } state.Solver.Pop(); } Assert.AreEqual(Tv.ONE, ToolsZ3.GetTv(t, state.Solver, state.Ctx)); } }